diff --git a/RELEASES.md b/RELEASES.md index 21134d50bdcc8..fc76fbc95bd3b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,80 @@ +Version 1.31.0 (2018-12-06) +========================== + +Language +-------- +- 🎉 [This version marks the release of the 2018 edition of Rust.][54057] 🎉 +- [New lifetime elision rules now allow for eliding lifetimes in functions and + impl headers.][54778] E.g. `impl<'a> Reader for BufReader<'a> {}` can now be + `impl Reader for BufReader<'_> {}`. Lifetimes are still required to be defined + in structs. +- [You can now define and use `const` functions.][54835] These are currently + a strict minimal subset of the [const fn RFC][RFC-911]. Refer to the + [language reference][const-reference] for what exactly is available. +- [You can now use tool lints, which allow you to scope lints from external + tools using attributes.][54870] E.g. `#[allow(clippy::filter_map)]`. +- [`#[no_mangle]` and `#[export_name]` attributes can now be located anywhere in + a crate, not just in exported functions.][54451] +- [You can now use parentheses in pattern matches.][54497] + +Compiler +-------- +- [Updated musl to 1.1.20][54430] + +Libraries +--------- +- [You can now convert `num::NonZero*` types to their raw equivalvents using the + `From` trait.][54240] E.g. `u8` now implements `From`. +- [You can now convert a `&Option` into `Option<&T>` and `&mut Option` + into `Option<&mut T>` using the `From` trait.][53218] +- [You can now multiply (`*`) a `time::Duration` by a `u32`.][52813] + + +Stabilized APIs +--------------- +- [`slice::align_to`] +- [`slice::align_to_mut`] +- [`slice::chunks_exact`] +- [`slice::chunks_exact_mut`] +- [`slice::rchunks`] +- [`slice::rchunks_mut`] +- [`slice::rchunks_exact`] +- [`slice::rchunks_exact_mut`] +- [`Option::replace`] + +Cargo +----- +- [Cargo will now download crates in parallel using HTTP/2.][cargo/6005] +- [You can now rename packages in your Cargo.toml][cargo/6319] We have a guide + on [how to use the `package` key in your dependencies.][cargo-rename-reference] + +[52813]: https://github.com/rust-lang/rust/pull/52813/ +[53218]: https://github.com/rust-lang/rust/pull/53218/ +[53555]: https://github.com/rust-lang/rust/issues/53555/ +[54057]: https://github.com/rust-lang/rust/pull/54057/ +[54240]: https://github.com/rust-lang/rust/pull/54240/ +[54430]: https://github.com/rust-lang/rust/pull/54430/ +[54451]: https://github.com/rust-lang/rust/pull/54451/ +[54497]: https://github.com/rust-lang/rust/pull/54497/ +[54778]: https://github.com/rust-lang/rust/pull/54778/ +[54835]: https://github.com/rust-lang/rust/pull/54835/ +[54870]: https://github.com/rust-lang/rust/pull/54870/ +[RFC-911]: https://github.com/rust-lang/rfcs/pull/911 +[`Option::replace`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.replace +[`slice::align_to_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.align_to_mut +[`slice::align_to`]: https://doc.rust-lang.org/std/primitive.slice.html#method.align_to +[`slice::chunks_exact_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.chunks_exact_mut +[`slice::chunks_exact`]: https://doc.rust-lang.org/std/primitive.slice.html#method.chunks_exact +[`slice::rchunks_exact_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut +[`slice::rchunks_exact`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_exact +[`slice::rchunks_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks_mut +[`slice::rchunks`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rchunks +[cargo/6005]: https://github.com/rust-lang/cargo/pull/6005/ +[cargo/6319]: https://github.com/rust-lang/cargo/pull/6319/ +[cargo-rename-reference]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml +[const-reference]: https://doc.rust-lang.org/reference/items/functions.html#const-functions + + Version 1.30.0 (2018-10-25) ========================== diff --git a/src/Cargo.lock b/src/Cargo.lock index 98529bdab3ffd..8533fde98e4af 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -253,7 +253,7 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -323,7 +323,7 @@ dependencies = [ name = "clippy" version = "0.0.212" dependencies = [ - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy-mini-macro-test 0.2.0", "clippy_dev 0.0.1", "clippy_lints 0.0.212", @@ -357,7 +357,7 @@ dependencies = [ name = "clippy_lints" version = "0.0.212" dependencies = [ - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -617,12 +617,13 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.11.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -724,7 +725,7 @@ name = "failure_derive" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1288,7 +1289,7 @@ name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1315,7 +1316,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1565,7 +1566,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.13" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1644,23 +1645,23 @@ name = "quote" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "racer" -version = "2.1.9" +version = "2.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1782,10 +1783,10 @@ dependencies = [ [[package]] name = "rls" -version = "0.130.5" +version = "1.31.6" dependencies = [ "cargo 0.32.0", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy_lints 0.0.212", "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1797,20 +1798,20 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-analysis 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-analysis 0.16.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", "rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "rustc_tools_util 0.1.0", - "rustfmt-nightly 0.99.6", + "rustfmt-nightly 1.0.0", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1821,7 +1822,7 @@ dependencies = [ [[package]] name = "rls-analysis" -version = "0.16.1" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1836,7 +1837,7 @@ dependencies = [ [[package]] name = "rls-blacklist" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1867,9 +1868,10 @@ dependencies = [ [[package]] name = "rls-vfs" -version = "0.4.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1916,15 +1918,20 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-graphviz" +version = "297.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1934,7 +1941,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1942,8 +1949,9 @@ dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1953,33 +1961,34 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_target" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1987,29 +1996,29 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "274.0.0" +version = "297.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-arena 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2507,12 +2516,12 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.99.6" +version = "1.0.0" dependencies = [ "assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2522,9 +2531,9 @@ dependencies = [ "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-workspace-hack 1.0.0", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2601,7 +2610,7 @@ name = "serde_derive" version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2744,7 +2753,7 @@ name = "strum_macros" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2774,7 +2783,17 @@ name = "syn" version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2792,7 +2811,7 @@ name = "synstructure" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3191,7 +3210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" "checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010" -"checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" +"checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum chalk-engine 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9adbe0fe1d6e937c3ee0571739a78f53c1de22f59df616060e868cf13c6c4ce5" @@ -3218,7 +3237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08459503c415173da1ce6b41036a37b8bfdd86af46d45abb9964d4c61fe670ef" "checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142" "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a" -"checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b" +"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" @@ -3320,7 +3339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -3328,7 +3347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" -"checksum racer 2.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5eeddfffd44c83eb03eedf5eb336e9c75303534fe28728a9f6b39a6e6f07ccff" +"checksum racer 2.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "344a53b68d889ab5f44d0617f2bbe1f696abe6a730bd41fa619cfc6fa83a6078" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" @@ -3341,20 +3360,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rls-analysis 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a625690e3bf1204ce27b50f71e508ee788214b2d51e26e4e5db884a83627673" -"checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2" +"checksum rls-analysis 0.16.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2a1d3a2a8c03e380331aefb8b5e3e06f3065602fbaa6657ba0ac649dc99d8537" +"checksum rls-blacklist 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ce1fdac03e138c4617ff87b194e1ff57a39bb985a044ccbd8673d30701e411" "checksum rls-data 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a209ce46bb52813cbe0786a7baadc0c1a3f5543ef93f179eda3b841ed72cf2e" "checksum rls-rustc 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9dba7390427aefa953608429701e3665192ca810ba8ae09301e001b7c7bed0" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" -"checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f" -"checksum rustc-ap-arena 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "866fda692855b38f9d6562f0e952c75c6ebe4032d7dd63c608a88e7c4d3f8087" -"checksum rustc-ap-rustc_cratesio_shim 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6c2343e11a97b4eb3bee29cd5f9314ea409a87baee5d3fec8d1516d1633412e" -"checksum rustc-ap-rustc_data_structures 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b88f905f7ab99bf14220a3a87eff60ec143af8136fd0ca8573641c78be532ec8" -"checksum rustc-ap-rustc_errors 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86fda6cf42e0355b7ecf40f14888340c20b7b864c9d37f6ffca85fe87200652" -"checksum rustc-ap-rustc_target 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fa8622299beac8c40270e8536a7b0509ca80f227a2b56550019a325fa5a60c0" -"checksum rustc-ap-serialize 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d16cc3d014af9a524c0bed6ca806c3170e39d5987180f0f8ce8fb7df5113576c" -"checksum rustc-ap-syntax 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a29f280f04f4f45e1bdd773ab5e667b36e757bfbbd01193c330815b9e76d05a" -"checksum rustc-ap-syntax_pos 274.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2ea27b65311571c7614deb393691eb18c5e41fd4fd9d8490304e128e1358646" +"checksum rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "72d56425bd5aa86d9d4372b76f0381d3b4bda9c0220e71956c9fcc929f45c1f1" +"checksum rustc-ap-arena 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b69fd4a0e8a3ecd99b497965d05f6f04dd2e4601a6146a841dbe4c8e77c2b30c" +"checksum rustc-ap-graphviz 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8136418dbc491bab74aa0565eaa2086754a7a81a5e74a1d84d6168d18e889e7" +"checksum rustc-ap-rustc_cratesio_shim 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a972feda82332d1d05b1ba5a097e915cd9c9c8f1af2bd7b08af09fb88c753d5f" +"checksum rustc-ap-rustc_data_structures 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "582584c6c48b0ece4b8aef3f9bb59d94d17c5665612bc87a71f509e45a3113b5" +"checksum rustc-ap-rustc_errors 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd852096944d0ac6af1aefa9639a2ae6dede217606ce97f88ff0dcc8c86d6ff6" +"checksum rustc-ap-rustc_target 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98301a272ecfeec29d2d4e97b07238707c2b89d86fc3a4a5f31a00728f14e288" +"checksum rustc-ap-serialize 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f13510e617e2e322e3297038fd6a7346f2297124af9e10e33a627c5d544e9d" +"checksum rustc-ap-syntax 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0792f5a9ccfc5ec13bb5b0472fa49e145481029c39f6bf5b1a36decc99c3328f" +"checksum rustc-ap-syntax_pos 297.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0df9f97f41650d23b14f92f7267f8c61089655efb4533d82bf8991f99245198d" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" @@ -3390,6 +3410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7" "checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a" diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md index 296422744fa40..61e5b3d0133ff 100644 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ b/src/doc/rustdoc/src/the-doc-attribute.md @@ -186,6 +186,9 @@ mod bar { Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere. +One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will +not eagerly inline it as a module unless you add `#[doc(inline)}`. + ## `#[doc(hidden)]` Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index c42fb7019c771..509068843d193 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -319,10 +319,9 @@ use cmp; use fmt; use iter_private::TrustedRandomAccess; -use ops::{self, Try}; +use ops::Try; use usize; use intrinsics; -use mem; #[stable(feature = "rust1", since = "1.0.0")] pub use self::iterator::Iterator; @@ -673,7 +672,12 @@ impl Iterator for StepBy where I: Iterator { #[inline] fn next(&mut self) -> Option { - ::spec_next(self) + if self.first_take { + self.first_take = false; + self.iter.next() + } else { + self.iter.nth(self.step) + } } #[inline] @@ -733,78 +737,6 @@ impl Iterator for StepBy where I: Iterator { } } -// hidden trait for specializing iterator methods -// could be generalized but is currently only used for StepBy -trait StepBySpecIterator { - type Item; - fn spec_next(&mut self) -> Option; -} - -impl StepBySpecIterator for StepBy -where - I: Iterator, -{ - type Item = I::Item; - - #[inline] - default fn spec_next(&mut self) -> Option { - if self.first_take { - self.first_take = false; - self.iter.next() - } else { - self.iter.nth(self.step) - } - } -} - -impl StepBySpecIterator for StepBy> -where - T: Step, -{ - #[inline] - fn spec_next(&mut self) -> Option { - self.first_take = false; - if !(self.iter.start < self.iter.end) { - return None; - } - // add 1 to self.step to get original step size back - // it was decremented for the general case on construction - if let Some(n) = self.iter.start.add_usize(self.step+1) { - let next = mem::replace(&mut self.iter.start, n); - Some(next) - } else { - let last = self.iter.start.clone(); - self.iter.start = self.iter.end.clone(); - Some(last) - } - } -} - -impl StepBySpecIterator for StepBy> -where - T: Step, -{ - #[inline] - fn spec_next(&mut self) -> Option { - self.first_take = false; - self.iter.compute_is_empty(); - if self.iter.is_empty.unwrap_or_default() { - return None; - } - // add 1 to self.step to get original step size back - // it was decremented for the general case on construction - if let Some(n) = self.iter.start.add_usize(self.step+1) { - self.iter.is_empty = Some(!(n <= self.iter.end)); - let next = mem::replace(&mut self.iter.start, n); - Some(next) - } else { - let last = self.iter.start.clone(); - self.iter.is_empty = Some(true); - Some(last) - } - } -} - // StepBy can only make the iterator shorter, so the len will still fit. #[stable(feature = "iterator_step_by", since = "1.28.0")] impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 2476c07cbd9ca..ec09071b3d0f0 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1618,6 +1618,13 @@ fn test_range_step() { assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX))); } +#[test] +fn test_step_by_skip() { + assert_eq!((0..640).step_by(128).skip(1).collect::>(), [128, 256, 384, 512]); + assert_eq!((0..=50).step_by(10).nth(3), Some(30)); + assert_eq!((200..=255u8).step_by(10).nth(3), Some(230)); +} + #[test] fn test_range_inclusive_step() { assert_eq!((0..=50).step_by(10).collect::>(), [0, 10, 20, 30, 40, 50]); diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 95b73d5f87b39..dcc0f8545e5d7 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -298,6 +298,9 @@ pub trait Visitor<'v> : Sized { fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) { walk_fn(self, fk, fd, b, s, id) } + fn visit_use(&mut self, path: &'v Path, id: NodeId, hir_id: HirId) { + walk_use(self, path, id, hir_id) + } fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) } @@ -471,8 +474,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { } } ItemKind::Use(ref path, _) => { - visitor.visit_id(item.id); - visitor.visit_path(path, item.hir_id); + visitor.visit_use(path, item.id, item.hir_id); } ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => { @@ -554,6 +556,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { walk_list!(visitor, visit_attribute, &item.attrs); } +pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, + path: &'v Path, + item_id: NodeId, + hir_id: HirId) { + visitor.visit_id(item_id); + visitor.visit_path(path, hir_id); +} + pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V, enum_definition: &'v EnumDef, generics: &'v Generics, @@ -652,6 +662,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { visitor.visit_ident(segment.ident); + if let Some(id) = segment.id { + visitor.visit_id(id); + } if let Some(ref args) = segment.args { visitor.visit_generic_args(path_span, args); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 99a1cf3c78757..b6621e0962cf6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -143,8 +143,12 @@ pub struct LoweringContext<'a> { } pub trait Resolver { - /// Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc. - fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool); + /// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc. + fn resolve_hir_path( + &mut self, + path: &ast::Path, + is_value: bool, + ) -> hir::Path; /// Obtain the resolution for a node id fn get_resolution(&mut self, id: NodeId) -> Option; @@ -163,7 +167,6 @@ pub trait Resolver { span: Span, crate_root: Option<&str>, components: &[&str], - params: Option>, is_value: bool, ) -> hir::Path; } @@ -1064,6 +1067,9 @@ impl<'a> LoweringContext<'a> { } fn lower_attr(&mut self, attr: &Attribute) -> Attribute { + // Note that we explicitly do not walk the path. Since we don't really + // lower attributes (we use the AST version) there is nowhere to keep + // the HirIds. We don't actually need HIR version of attributes anyway. Attribute { id: attr.id, style: attr.style, @@ -1677,6 +1683,7 @@ impl<'a> LoweringContext<'a> { num_lifetimes, parenthesized_generic_args, itctx.reborrow(), + None, ) }) .collect(), @@ -1720,6 +1727,7 @@ impl<'a> LoweringContext<'a> { 0, ParenthesizedGenericArgs::Warn, itctx.reborrow(), + None, )); let qpath = hir::QPath::TypeRelative(ty, segment); @@ -1746,8 +1754,8 @@ impl<'a> LoweringContext<'a> { &mut self, def: Def, p: &Path, - ident: Option, param_mode: ParamMode, + explicit_owner: Option, ) -> hir::Path { hir::Path { def, @@ -1761,9 +1769,9 @@ impl<'a> LoweringContext<'a> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), + explicit_owner, ) }) - .chain(ident.map(|ident| hir::PathSegment::from_ident(ident))) .collect(), span: p.span, } @@ -1771,7 +1779,7 @@ impl<'a> LoweringContext<'a> { fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path { let def = self.expect_full_def(id); - self.lower_path_extra(def, p, None, param_mode) + self.lower_path_extra(def, p, param_mode, None) } fn lower_path_segment( @@ -1782,6 +1790,7 @@ impl<'a> LoweringContext<'a> { expected_lifetimes: usize, parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext<'_>, + explicit_owner: Option, ) -> hir::PathSegment { let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args { let msg = "parenthesized parameters may only be used with a trait"; @@ -1852,8 +1861,17 @@ impl<'a> LoweringContext<'a> { } } + let def = self.expect_full_def(segment.id); + let id = if let Some(owner) = explicit_owner { + self.lower_node_id_with_owner(segment.id, owner) + } else { + self.lower_node_id(segment.id) + }; + hir::PathSegment::new( segment.ident, + Some(id.node_id), + Some(def), generic_args, infer_types, ) @@ -2936,6 +2954,12 @@ impl<'a> LoweringContext<'a> { attrs: &hir::HirVec, ) -> hir::ItemKind { let path = &tree.prefix; + let segments = prefix + .segments + .iter() + .chain(path.segments.iter()) + .cloned() + .collect(); match tree.kind { UseTreeKind::Simple(rename, id1, id2) => { @@ -2943,12 +2967,7 @@ impl<'a> LoweringContext<'a> { // First apply the prefix to the path let mut path = Path { - segments: prefix - .segments - .iter() - .chain(path.segments.iter()) - .cloned() - .collect(), + segments, span: path.span, }; @@ -2968,9 +2987,18 @@ impl<'a> LoweringContext<'a> { // for later let ret_def = defs.next().unwrap_or(Def::Err); + // Here, we are looping over namespaces, if they exist for the definition + // being imported. We only handle type and value namespaces because we + // won't be dealing with macros in the rest of the compiler. + // Essentially a single `use` which imports two names is desugared into + // two imports. for (def, &new_node_id) in defs.zip([id1, id2].iter()) { let vis = vis.clone(); let name = name.clone(); + let mut path = path.clone(); + for seg in &mut path.segments { + seg.id = self.sess.next_node_id(); + } let span = path.span; self.resolver.definitions().create_def_with_parent( parent_def_index, @@ -2983,7 +3011,8 @@ impl<'a> LoweringContext<'a> { self.with_hir_id_owner(new_node_id, |this| { let new_id = this.lower_node_id(new_node_id); - let path = this.lower_path_extra(def, &path, None, ParamMode::Explicit); + let path = + this.lower_path_extra(def, &path, ParamMode::Explicit, None); let item = hir::ItemKind::Use(P(path), hir::UseKind::Single); let vis_kind = match vis.node { hir::VisibilityKind::Public => hir::VisibilityKind::Public, @@ -2991,9 +3020,14 @@ impl<'a> LoweringContext<'a> { hir::VisibilityKind::Inherited => hir::VisibilityKind::Inherited, hir::VisibilityKind::Restricted { ref path, id: _, hir_id: _ } => { let id = this.next_id(); + let mut path = path.clone(); + for seg in path.segments.iter_mut() { + if seg.id.is_some() { + seg.id = Some(this.next_id().node_id); + } + } hir::VisibilityKind::Restricted { - path: path.clone(), - // We are allocating a new NodeId here + path, id: id.node_id, hir_id: id.hir_id, } @@ -3016,19 +3050,15 @@ impl<'a> LoweringContext<'a> { }); } - let path = P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit)); + let path = + P(self.lower_path_extra(ret_def, &path, ParamMode::Explicit, None)); hir::ItemKind::Use(path, hir::UseKind::Single) } UseTreeKind::Glob => { let path = P(self.lower_path( id, &Path { - segments: prefix - .segments - .iter() - .chain(path.segments.iter()) - .cloned() - .collect(), + segments, span: path.span, }, ParamMode::Explicit, @@ -3036,19 +3066,17 @@ impl<'a> LoweringContext<'a> { hir::ItemKind::Use(path, hir::UseKind::Glob) } UseTreeKind::Nested(ref trees) => { + // Nested imports are desugared into simple imports. + let prefix = Path { - segments: prefix - .segments - .iter() - .chain(path.segments.iter()) - .cloned() - .collect(), + segments, span: prefix.span.to(path.span), }; - // Add all the nested PathListItems in the HIR + // Add all the nested PathListItems to the HIR. for &(ref use_tree, id) in trees { self.allocate_hir_id_counter(id, &use_tree); + let LoweredNodeId { node_id: new_id, hir_id: new_hir_id, @@ -3056,10 +3084,26 @@ impl<'a> LoweringContext<'a> { let mut vis = vis.clone(); let mut name = name.clone(); - let item = - self.lower_use_tree(use_tree, &prefix, new_id, &mut vis, &mut name, &attrs); + let mut prefix = prefix.clone(); + + // Give the segments new ids since they are being cloned. + for seg in &mut prefix.segments { + seg.id = self.sess.next_node_id(); + } + // Each `use` import is an item and thus are owners of the + // names in the path. Up to this point the nested import is + // the current owner, since we want each desugared import to + // own its own names, we have to adjust the owner before + // lowering the rest of the import. self.with_hir_id_owner(new_id, |this| { + let item = this.lower_use_tree(use_tree, + &prefix, + new_id, + &mut vis, + &mut name, + attrs); + let vis_kind = match vis.node { hir::VisibilityKind::Public => hir::VisibilityKind::Public, hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar), @@ -3068,7 +3112,6 @@ impl<'a> LoweringContext<'a> { let id = this.next_id(); hir::VisibilityKind::Restricted { path: path.clone(), - // We are allocating a new NodeId here id: id.node_id, hir_id: id.hir_id, } @@ -3081,7 +3124,7 @@ impl<'a> LoweringContext<'a> { hir::Item { id: new_id, hir_id: new_hir_id, - name: name, + name, attrs: attrs.clone(), node: item, vis, @@ -3095,7 +3138,7 @@ impl<'a> LoweringContext<'a> { // the stability of `use a::{};`, to avoid it showing up as // a re-export by accident when `pub`, e.g. in documentation. let def = self.expect_full_def_from_use(id).next().unwrap_or(Def::Err); - let path = P(self.lower_path_extra(def, &prefix, None, ParamMode::Explicit)); + let path = P(self.lower_path_extra(def, &prefix, ParamMode::Explicit, None)); *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited); hir::ItemKind::Use(path, hir::UseKind::ListStem) } @@ -3646,6 +3689,7 @@ impl<'a> LoweringContext<'a> { 0, ParenthesizedGenericArgs::Err, ImplTraitContext::disallowed(), + None, ); let args = args.iter().map(|x| self.lower_expr(x)).collect(); hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args) @@ -4499,8 +4543,14 @@ impl<'a> LoweringContext<'a> { } else { self.lower_node_id(id) }; + let def = self.expect_full_def(id); hir::VisibilityKind::Restricted { - path: P(self.lower_path(id, path, ParamMode::Explicit)), + path: P(self.lower_path_extra( + def, + path, + ParamMode::Explicit, + explicit_owner, + )), id: lowered_id.node_id, hir_id: lowered_id.hir_id, } @@ -4807,8 +4857,17 @@ impl<'a> LoweringContext<'a> { params: Option>, is_value: bool ) -> hir::Path { - self.resolver - .resolve_str_path(span, self.crate_root, components, params, is_value) + let mut path = self.resolver + .resolve_str_path(span, self.crate_root, components, is_value); + path.segments.last_mut().unwrap().args = params; + + + for seg in path.segments.iter_mut() { + if let Some(id) = seg.id { + seg.id = Some(self.lower_node_id(id).node_id); + } + } + path } fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::Ty { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index bd12a5e0cb4d8..4fbcd83adb555 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -210,17 +210,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { None => format!("{:?}", node) }; - if hir_id == ::hir::DUMMY_HIR_ID { - debug!("Maybe you forgot to lower the node id {:?}?", id); - } + let forgot_str = if hir_id == ::hir::DUMMY_HIR_ID { + format!("\nMaybe you forgot to lower the node id {:?}?", id) + } else { + String::new() + }; bug!("inconsistent DepNode for `{}`: \ - current_dep_node_owner={}, hir_id.owner={}", + current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", node_str, self.definitions .def_path(self.current_dep_node_owner) .to_string_no_crate(), - self.definitions.def_path(hir_id.owner).to_string_no_crate()) + self.current_dep_node_owner, + self.definitions.def_path(hir_id.owner).to_string_no_crate(), + hir_id.owner, + forgot_str) } } @@ -392,6 +397,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment) { + if let Some(id) = path_segment.id { + self.insert(id, Node::PathSegment(path_segment)); + } + intravisit::walk_path_segment(self, path_span, path_segment); + } + fn visit_ty(&mut self, ty: &'hir Ty) { self.insert(ty.id, Node::Ty(ty)); diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 087efbd4a22dd..896a6163eba64 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -88,7 +88,7 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { walk(self); if owner_def_index == CRATE_DEF_INDEX { - return + return; } // There's always at least one entry for the owning item itself @@ -129,13 +129,16 @@ impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> { local_id, self.hir_map.node_to_string(node_id))); } - self.errors.push(format!( "ItemLocalIds not assigned densely in {}. \ - Max ItemLocalId = {}, missing IDs = {:?}", + Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), max, - missing_items)); + missing_items, + self.hir_ids_seen + .values() + .map(|n| format!("({:?} {})", n, self.hir_map.node_to_string(*n))) + .collect::>())); } } } @@ -155,6 +158,7 @@ impl<'a, 'hir: 'a> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { self.errors.push(format!("HirIdValidator: No HirId assigned for NodeId {}: {:?}", node_id, self.hir_map.node_to_string(node_id))); + return; } if owner != stable_id.owner { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f5f9bcd3b5ea5..7a20146130d94 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -204,7 +204,7 @@ impl<'hir> Map<'hir> { if let Some(entry) = self.map[id.as_usize()] { self.dep_graph.read_index(entry.dep_node); } else { - bug!("called `HirMap::read()` with invalid `NodeId`") + bug!("called `HirMap::read()` with invalid `NodeId`: {:?}", id) } } @@ -344,6 +344,7 @@ impl<'hir> Map<'hir> { Node::AnonConst(_) | Node::Expr(_) | Node::Stmt(_) | + Node::PathSegment(_) | Node::Ty(_) | Node::TraitRef(_) | Node::Pat(_) | @@ -884,6 +885,7 @@ impl<'hir> Map<'hir> { Some(Node::AnonConst(constant)) => self.body(constant.body).value.span, Some(Node::Expr(expr)) => expr.span, Some(Node::Stmt(stmt)) => stmt.span, + Some(Node::PathSegment(seg)) => seg.ident.span, Some(Node::Ty(ty)) => ty.span, Some(Node::TraitRef(tr)) => tr.path.span, Some(Node::Binding(pat)) => pat.span, @@ -1098,6 +1100,7 @@ impl<'a> print::State<'a> { Node::AnonConst(a) => self.print_anon_const(&a), Node::Expr(a) => self.print_expr(&a), Node::Stmt(a) => self.print_stmt(&a), + Node::PathSegment(a) => self.print_path_segment(&a), Node::Ty(a) => self.print_type(&a), Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | @@ -1215,6 +1218,9 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { Some(Node::Stmt(_)) => { format!("stmt {}{}", map.node_to_pretty_string(id), id_str) } + Some(Node::PathSegment(_)) => { + format!("path segment {}{}", map.node_to_pretty_string(id), id_str) + } Some(Node::Ty(_)) => { format!("type {}{}", map.node_to_pretty_string(id), id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d5de6197a2e48..a2095ff40c040 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -347,6 +347,13 @@ impl fmt::Display for Path { pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, + // `id` and `def` are optional. We currently only use these in save-analysis, + // any path segments without these will not have save-analysis info and + // therefore will not have 'jump to def' in IDEs, but otherwise will not be + // affected. (In general, we don't bother to get the defs for synthesized + // segments, only for segments which have come from the AST). + pub id: Option, + pub def: Option, /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. Note that @@ -367,14 +374,24 @@ impl PathSegment { pub fn from_ident(ident: Ident) -> PathSegment { PathSegment { ident, + id: None, + def: None, infer_types: true, args: None, } } - pub fn new(ident: Ident, args: GenericArgs, infer_types: bool) -> Self { + pub fn new( + ident: Ident, + id: Option, + def: Option, + args: GenericArgs, + infer_types: bool, + ) -> Self { PathSegment { ident, + id, + def, infer_types, args: if args.is_empty() { None @@ -2511,6 +2528,7 @@ pub enum Node<'hir> { AnonConst(&'hir AnonConst), Expr(&'hir Expr), Stmt(&'hir Stmt), + PathSegment(&'hir PathSegment), Ty(&'hir Ty), TraitRef(&'hir TraitRef), Binding(&'hir Pat), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index ad2fa48610b0e..e69d32ad1deaf 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1633,6 +1633,17 @@ impl<'a> State<'a> { Ok(()) } + pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> { + if segment.ident.name != keywords::CrateRoot.name() && + segment.ident.name != keywords::DollarCrate.name() { + self.print_ident(segment.ident)?; + segment.with_generic_args(|generic_args| { + self.print_generic_args(generic_args, segment.infer_types, false) + })?; + } + Ok(()) + } + pub fn print_qpath(&mut self, qpath: &hir::QPath, colons_before_params: bool) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index a48bd4eeb09a3..b220634d0d903 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -174,6 +174,8 @@ impl_stable_hash_for!(struct hir::Path { impl_stable_hash_for!(struct hir::PathSegment { ident -> (ident.name), + id, + def, infer_types, args }); diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index de8f57ee79666..0ee03bc4c6e00 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -251,6 +251,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { dir: RelationDir) -> RelateResult<'tcx, Generalization<'tcx>> { + debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir); // Determine the ambient variance within which `ty` appears. // The surrounding equation is: // @@ -273,8 +274,15 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { root_ty: ty, }; - let ty = generalize.relate(&ty, &ty)?; + let ty = match generalize.relate(&ty, &ty) { + Ok(ty) => ty, + Err(e) => { + debug!("generalize: failure {:?}", e); + return Err(e); + } + }; let needs_wf = generalize.needs_wf; + debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); Ok(Generalization { ty, needs_wf }) } } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 854960492c9bd..c7b5ddb83410f 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -74,6 +74,9 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> let infcx = self.fields.infcx; let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); + + debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); + match (&a.sty, &b.sty) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 5db850f1588b6..0215b0380bdf3 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -388,22 +388,38 @@ where // rule might not apply (but another rule might). For now, we err // on the side of adding too few edges into the graph. + // Compute the bounds we can derive from the trait definition. + // These are guaranteed to apply, no matter the inference + // results. + let trait_bounds: Vec<_> = self.verify_bound + .projection_declared_bounds_from_trait(projection_ty) + .collect(); + // Compute the bounds we can derive from the environment. This // is an "approximate" match -- in some cases, these bounds // may not apply. - let approx_env_bounds = self.verify_bound + let mut approx_env_bounds = self.verify_bound .projection_approx_declared_bounds_from_env(projection_ty); debug!( "projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds ); - // Compute the bounds we can derive from the trait definition. - // These are guaranteed to apply, no matter the inference - // results. - let trait_bounds: Vec<_> = self.verify_bound - .projection_declared_bounds_from_trait(projection_ty) - .collect(); + // Remove outlives bounds that we get from the environment but + // which are also deducable from the trait. This arises (cc + // #55756) in cases where you have e.g. `>::Item: + // 'a` in the environment but `trait Foo<'b> { type Item: 'b + // }` in the trait definition. + approx_env_bounds.retain(|bound| { + match bound.0.sty { + ty::Projection(projection_ty) => { + self.verify_bound.projection_declared_bounds_from_trait(projection_ty) + .all(|r| r != bound.1) + } + + _ => panic!("expected only projection types from env, not {:?}", bound.0), + } + }); // If declared bounds list is empty, the only applicable rule is // OutlivesProjectionComponent. If there are inference variables, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7e2532bb1c4e8..ebb495fdfcee6 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1020,9 +1020,12 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { } fn visit_pat(&mut self, p: &'a ast::Pat) { - run_lints!(self, check_pat, p); + let mut visit_subpats = true; + run_lints!(self, check_pat, p, &mut visit_subpats); self.check_id(p.id); - ast_visit::walk_pat(self, p); + if visit_subpats { + ast_visit::walk_pat(self, p); + } } fn visit_expr(&mut self, e: &'a ast::Expr) { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5ac0c0d32dcdc..c1e439ce607d4 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -341,7 +341,7 @@ pub trait EarlyLintPass: LintPass { fn check_block_post(&mut self, _: &EarlyContext<'_>, _: &ast::Block) { } fn check_stmt(&mut self, _: &EarlyContext<'_>, _: &ast::Stmt) { } fn check_arm(&mut self, _: &EarlyContext<'_>, _: &ast::Arm) { } - fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat) { } + fn check_pat(&mut self, _: &EarlyContext<'_>, _: &ast::Pat, _: &mut bool) { } fn check_expr(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { } fn check_expr_post(&mut self, _: &EarlyContext<'_>, _: &ast::Expr) { } fn check_ty(&mut self, _: &EarlyContext<'_>, _: &ast::Ty) { } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index bfc03923f6011..caa627441ceb6 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -364,33 +364,54 @@ macro_rules! make_mir_visitor { self.visit_assign(block, place, rvalue, location); } StatementKind::FakeRead(_, ref $($mutability)* place) => { - self.visit_place(place, - PlaceContext::Inspect, - location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); } StatementKind::EndRegion(_) => {} StatementKind::Validate(_, ref $($mutability)* places) => { for operand in places { - self.visit_place(& $($mutability)* operand.place, - PlaceContext::Validate, location); + self.visit_place( + & $($mutability)* operand.place, + PlaceContext::NonUse(NonUseContext::Validate), + location + ); self.visit_ty(& $($mutability)* operand.ty, TyContext::Location(location)); } } StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => { - self.visit_place(place, PlaceContext::Store, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); } StatementKind::StorageLive(ref $($mutability)* local) => { - self.visit_local(local, PlaceContext::StorageLive, location); + self.visit_local( + local, + PlaceContext::NonUse(NonUseContext::StorageLive), + location + ); } StatementKind::StorageDead(ref $($mutability)* local) => { - self.visit_local(local, PlaceContext::StorageDead, location); + self.visit_local( + local, + PlaceContext::NonUse(NonUseContext::StorageDead), + location + ); } StatementKind::InlineAsm { ref $($mutability)* outputs, ref $($mutability)* inputs, asm: _ } => { for output in & $($mutability)* outputs[..] { - self.visit_place(output, PlaceContext::AsmOutput, location); + self.visit_place( + output, + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), + location + ); } for input in & $($mutability)* inputs[..] { self.visit_operand(input, location); @@ -412,7 +433,11 @@ macro_rules! make_mir_visitor { place: &$($mutability)* Place<'tcx>, rvalue: &$($mutability)* Rvalue<'tcx>, location: Location) { - self.visit_place(place, PlaceContext::Store, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); self.visit_rvalue(rvalue, location); } @@ -459,7 +484,11 @@ macro_rules! make_mir_visitor { TerminatorKind::Drop { ref $($mutability)* location, target, unwind } => { - self.visit_place(location, PlaceContext::Drop, source_location); + self.visit_place( + location, + PlaceContext::MutatingUse(MutatingUseContext::Drop), + source_location + ); self.visit_branch(block, target); unwind.map(|t| self.visit_branch(block, t)); } @@ -468,7 +497,11 @@ macro_rules! make_mir_visitor { ref $($mutability)* value, target, unwind } => { - self.visit_place(location, PlaceContext::Drop, source_location); + self.visit_place( + location, + PlaceContext::MutatingUse(MutatingUseContext::Drop), + source_location + ); self.visit_operand(value, source_location); self.visit_branch(block, target); unwind.map(|t| self.visit_branch(block, t)); @@ -484,7 +517,11 @@ macro_rules! make_mir_visitor { self.visit_operand(arg, source_location); } if let Some((ref $($mutability)* destination, target)) = *destination { - self.visit_place(destination, PlaceContext::Call, source_location); + self.visit_place( + destination, + PlaceContext::MutatingUse(MutatingUseContext::Call), + source_location + ); self.visit_branch(block, target); } cleanup.map(|t| self.visit_branch(block, t)); @@ -552,14 +589,28 @@ macro_rules! make_mir_visitor { Rvalue::Ref(ref $($mutability)* r, bk, ref $($mutability)* path) => { self.visit_region(r, location); - self.visit_place(path, PlaceContext::Borrow { - region: *r, - kind: bk - }, location); + let ctx = match bk { + BorrowKind::Shared => PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow(*r) + ), + BorrowKind::Shallow => PlaceContext::NonMutatingUse( + NonMutatingUseContext::ShallowBorrow(*r) + ), + BorrowKind::Unique => PlaceContext::NonMutatingUse( + NonMutatingUseContext::UniqueBorrow(*r) + ), + BorrowKind::Mut { .. } => + PlaceContext::MutatingUse(MutatingUseContext::Borrow(*r)), + }; + self.visit_place(path, ctx, location); } Rvalue::Len(ref $($mutability)* path) => { - self.visit_place(path, PlaceContext::Inspect, location); + self.visit_place( + path, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); } Rvalue::Cast(_cast_kind, @@ -584,7 +635,11 @@ macro_rules! make_mir_visitor { } Rvalue::Discriminant(ref $($mutability)* place) => { - self.visit_place(place, PlaceContext::Inspect, location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), + location + ); } Rvalue::NullaryOp(_op, ref $($mutability)* ty) => { @@ -632,10 +687,18 @@ macro_rules! make_mir_visitor { location: Location) { match *operand { Operand::Copy(ref $($mutability)* place) => { - self.visit_place(place, PlaceContext::Copy, location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); } Operand::Move(ref $($mutability)* place) => { - self.visit_place(place, PlaceContext::Move, location); + self.visit_place( + place, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move), + location + ); } Operand::Constant(ref $($mutability)* constant) => { self.visit_constant(constant, location); @@ -648,7 +711,11 @@ macro_rules! make_mir_visitor { _variance: & $($mutability)* ty::Variance, user_ty: & $($mutability)* UserTypeProjection<'tcx>, location: Location) { - self.visit_place(place, PlaceContext::Validate, location); + self.visit_place( + place, + PlaceContext::NonUse(NonUseContext::AscribeUserTy), + location + ); self.visit_user_type_projection(user_ty); } @@ -693,9 +760,9 @@ macro_rules! make_mir_visitor { ref $($mutability)* elem, } = *proj; let context = if context.is_mutating_use() { - PlaceContext::Projection(Mutability::Mut) + PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { - PlaceContext::Projection(Mutability::Not) + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) }; self.visit_place(base, context, location); self.visit_projection_elem(elem, location); @@ -713,7 +780,11 @@ macro_rules! make_mir_visitor { self.visit_ty(ty, TyContext::Location(location)); } ProjectionElem::Index(ref $($mutability)* local) => { - self.visit_local(local, PlaceContext::Copy, location); + self.visit_local( + local, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); } ProjectionElem::ConstantIndex { offset: _, min_length: _, @@ -896,125 +967,146 @@ pub enum TyContext { } #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum PlaceContext<'tcx> { - // Appears as LHS of an assignment - Store, +pub enum NonMutatingUseContext<'tcx> { + /// Being inspected in some way, like loading a len. + Inspect, + /// Consumed as part of an operand. + Copy, + /// Consumed as part of an operand. + Move, + /// Shared borrow. + SharedBorrow(Region<'tcx>), + /// Shallow borrow. + ShallowBorrow(Region<'tcx>), + /// Unique borrow. + UniqueBorrow(Region<'tcx>), + /// Used as base for another place, e.g. `x` in `x.y`. Will not mutate the place. + /// For example, the projection `x.y` is not marked as a mutation in these cases: + /// + /// z = x.y; + /// f(&x.y); + /// + Projection, +} - // Can often be treated as a Store, but needs to be separate because - // ASM is allowed to read outputs as well, so a Store-AsmOutput sequence - // cannot be simplified the way a Store-Store can be. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum MutatingUseContext<'tcx> { + /// Appears as LHS of an assignment. + Store, + /// Can often be treated as a `Store`, but needs to be separate because + /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence + /// cannot be simplified the way a `Store`-`Store` can be. AsmOutput, - - // Dest of a call + /// Destination of a call. Call, - - // Being dropped + /// Being dropped. Drop, + /// Mutable borrow. + Borrow(Region<'tcx>), + /// Used as base for another place, e.g. `x` in `x.y`. Could potentially mutate the place. + /// For example, the projection `x.y` is marked as a mutation in these cases: + /// + /// x.y = ...; + /// f(&mut x.y); + /// + Projection, +} - // Being inspected in some way, like loading a len - Inspect, - - // Being borrowed - Borrow { region: Region<'tcx>, kind: BorrowKind }, - - // Used as base for another place, e.g. `x` in `x.y`. - // - // The `Mutability` argument specifies whether the projection is being performed in order to - // (potentially) mutate the place. For example, the projection `x.y` is marked as a mutation - // in these cases: - // - // x.y = ...; - // f(&mut x.y); - // - // But not in these cases: - // - // z = x.y; - // f(&x.y); - Projection(Mutability), - - // Consumed as part of an operand - Copy, - Move, - - // Starting and ending a storage live range +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum NonUseContext { + /// Starting a storage live range. StorageLive, + /// Ending a storage live range. StorageDead, - - // Validation command + /// User type annotation assertions for NLL. + AscribeUserTy, + /// Validation command. Validate, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum PlaceContext<'tcx> { + NonMutatingUse(NonMutatingUseContext<'tcx>), + MutatingUse(MutatingUseContext<'tcx>), + NonUse(NonUseContext), +} + impl<'tcx> PlaceContext<'tcx> { - /// Returns true if this place context represents a drop. + /// Returns `true` if this place context represents a drop. pub fn is_drop(&self) -> bool { match *self { - PlaceContext::Drop => true, + PlaceContext::MutatingUse(MutatingUseContext::Drop) => true, + _ => false, + } + } + + /// Returns `true` if this place context represents a borrow. + pub fn is_borrow(&self) -> bool { + match *self { + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) | + PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) => true, _ => false, } } - /// Returns true if this place context represents a storage live or storage dead marker. + /// Returns `true` if this place context represents a storage live or storage dead marker. pub fn is_storage_marker(&self) -> bool { match *self { - PlaceContext::StorageLive | PlaceContext::StorageDead => true, + PlaceContext::NonUse(NonUseContext::StorageLive) | + PlaceContext::NonUse(NonUseContext::StorageDead) => true, _ => false, } } - /// Returns true if this place context represents a storage live marker. + /// Returns `true` if this place context represents a storage live marker. pub fn is_storage_live_marker(&self) -> bool { match *self { - PlaceContext::StorageLive => true, + PlaceContext::NonUse(NonUseContext::StorageLive) => true, _ => false, } } - /// Returns true if this place context represents a storage dead marker. + /// Returns `true` if this place context represents a storage dead marker. pub fn is_storage_dead_marker(&self) -> bool { match *self { - PlaceContext::StorageDead => true, + PlaceContext::NonUse(NonUseContext::StorageDead) => true, _ => false, } } - /// Returns true if this place context represents a use that potentially changes the value. + /// Returns `true` if this place context represents a use that potentially changes the value. pub fn is_mutating_use(&self) -> bool { match *self { - PlaceContext::Store | PlaceContext::AsmOutput | PlaceContext::Call | - PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | - PlaceContext::Projection(Mutability::Mut) | - PlaceContext::Drop => true, - - PlaceContext::Inspect | - PlaceContext::Borrow { kind: BorrowKind::Shared, .. } | - PlaceContext::Borrow { kind: BorrowKind::Shallow, .. } | - PlaceContext::Borrow { kind: BorrowKind::Unique, .. } | - PlaceContext::Projection(Mutability::Not) | - PlaceContext::Copy | PlaceContext::Move | - PlaceContext::StorageLive | PlaceContext::StorageDead | - PlaceContext::Validate => false, + PlaceContext::MutatingUse(..) => true, + _ => false, } } - /// Returns true if this place context represents a use that does not change the value. + /// Returns `true` if this place context represents a use that does not change the value. pub fn is_nonmutating_use(&self) -> bool { match *self { - PlaceContext::Inspect | - PlaceContext::Borrow { kind: BorrowKind::Shared, .. } | - PlaceContext::Borrow { kind: BorrowKind::Shallow, .. } | - PlaceContext::Borrow { kind: BorrowKind::Unique, .. } | - PlaceContext::Projection(Mutability::Not) | - PlaceContext::Copy | PlaceContext::Move => true, - - PlaceContext::Borrow { kind: BorrowKind::Mut { .. }, .. } | PlaceContext::Store | - PlaceContext::AsmOutput | - PlaceContext::Call | PlaceContext::Projection(Mutability::Mut) | - PlaceContext::Drop | PlaceContext::StorageLive | PlaceContext::StorageDead | - PlaceContext::Validate => false, + PlaceContext::NonMutatingUse(..) => true, + _ => false, } } + /// Returns `true` if this place context represents a use. pub fn is_use(&self) -> bool { - self.is_mutating_use() || self.is_nonmutating_use() + match *self { + PlaceContext::NonUse(..) => false, + _ => true, + } + } + + /// Returns `true` if this place context represents an assignment statement. + pub fn is_place_assignment(&self) -> bool { + match *self { + PlaceContext::MutatingUse(MutatingUseContext::Store) | + PlaceContext::MutatingUse(MutatingUseContext::Call) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) => true, + _ => false, + } } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 8bceebb23950c..c7e5d89007418 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -693,7 +693,12 @@ fn do_normalize_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, predicates: Vec>) -> Result>, ErrorReported> { - debug!("do_normalize_predicates({:?})", predicates); + debug!( + "do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})", + predicates, + region_context, + cause, + ); let span = cause.span; tcx.infer_ctxt().enter(|infcx| { // FIXME. We should really... do something with these region diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 49f3717935493..2ea16823cc65d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1522,6 +1522,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map(|v| v.get(tcx)) } + /// Determines whether can we safely cache the result + /// of selecting an obligation. This is almost always 'true', + /// except when dealing with certain ParamCandidates. + /// + /// Ordinarily, a ParamCandidate will contain no inference variables, + /// since it was usually produced directly from a DefId. However, + /// certain cases (currently only librustdoc's blanket impl finder), + /// a ParamEnv may be explicitly constructed with inference types. + /// When this is the case, we do *not* want to cache the resulting selection + /// candidate. This is due to the fact that it might not always be possible + /// to equate the obligation's trait ref and the candidate's trait ref, + /// if more constraints end up getting added to an inference variable. + /// + /// Because of this, we always want to re-run the full selection + /// process for our obligation the next time we see it, since + /// we might end up picking a different SelectionCandidate (or none at all) + fn can_cache_candidate(&self, + result: &SelectionResult<'tcx, SelectionCandidate<'tcx>> + ) -> bool { + match result { + Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => { + !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer())) + }, + _ => true + } + } + fn insert_candidate_cache( &mut self, param_env: ty::ParamEnv<'tcx>, @@ -1531,6 +1558,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) { let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; + + if !self.can_cache_candidate(&candidate) { + debug!("insert_candidate_cache(trait_ref={:?}, candidate={:?} -\ + candidate is not cacheable", trait_ref, candidate); + return; + + } + if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index 1602ef3c5b795..a63cbe70df611 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -15,7 +15,7 @@ use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::graph::dominators::Dominators; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc::mir::{self, Location, TerminatorKind}; -use rustc::mir::visit::{Visitor, PlaceContext}; +use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::traversal; use rustc::ty; use rustc::ty::layout::LayoutOf; @@ -116,7 +116,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { self.not_ssa(index); } } else { - self.visit_place(place, PlaceContext::Store, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); } self.visit_rvalue(rvalue, location); @@ -142,7 +146,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { // is not guaranteed to be statically dominated by the // definition of x, so x must always be in an alloca. if let mir::Operand::Move(ref place) = args[0] { - self.visit_place(place, PlaceContext::Drop, location); + self.visit_place( + place, + PlaceContext::MutatingUse(MutatingUseContext::Drop), + location + ); } } } @@ -160,7 +168,8 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { if let mir::Place::Projection(ref proj) = *place { // Allow uses of projections that are ZSTs or from scalar fields. let is_consume = match context { - PlaceContext::Copy | PlaceContext::Move => true, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true, _ => false }; if is_consume { @@ -190,7 +199,11 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { // A deref projection only reads the pointer, never needs the place. if let mir::ProjectionElem::Deref = proj.elem { - return self.visit_place(&proj.base, PlaceContext::Copy, location); + return self.visit_place( + &proj.base, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); } } @@ -202,16 +215,14 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { context: PlaceContext<'tcx>, location: Location) { match context { - PlaceContext::Call => { + PlaceContext::MutatingUse(MutatingUseContext::Call) => { self.assign(local, location); } - PlaceContext::StorageLive | - PlaceContext::StorageDead | - PlaceContext::Validate => {} + PlaceContext::NonUse(_) => {} - PlaceContext::Copy | - PlaceContext::Move => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => { // Reads from uninitialized variables (e.g. in dead code, after // optimizations) require locals to be in (uninitialized) memory. // NB: there can be uninitialized reads of a local visited after @@ -227,15 +238,19 @@ impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { } } - PlaceContext::Inspect | - PlaceContext::Store | - PlaceContext::AsmOutput | - PlaceContext::Borrow { .. } | - PlaceContext::Projection(..) => { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | + PlaceContext::MutatingUse(MutatingUseContext::Store) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | + PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) | + PlaceContext::MutatingUse(MutatingUseContext::Projection) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => { self.not_ssa(local); } - PlaceContext::Drop => { + PlaceContext::MutatingUse(MutatingUseContext::Drop) => { let ty = mir::Place::Local(local).ty(self.fx.mir, self.fx.cx.tcx); let ty = self.fx.monomorphize(&ty.to_ty(self.fx.cx.tcx)); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 19f9168cf0a0e..7291e27048280 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -40,6 +40,8 @@ use rustc::util::nodemap::FxHashSet; use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::ast; +use syntax::ptr::P; +use syntax::ast::Expr; use syntax::attr; use syntax::source_map::Spanned; use syntax::edition::Edition; @@ -47,6 +49,7 @@ use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_a use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; use syntax::errors::{Applicability, DiagnosticBuilder}; +use syntax::print::pprust::expr_to_string; use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::intravisit::FnKind; @@ -1477,21 +1480,48 @@ impl LintPass for EllipsisInclusiveRangePatterns { } impl EarlyLintPass for EllipsisInclusiveRangePatterns { - fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) { - use self::ast::{PatKind, RangeEnd, RangeSyntax}; + fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat, visit_subpats: &mut bool) { + use self::ast::{PatKind, RangeEnd, RangeSyntax::DotDotDot}; + + /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span + /// corresponding to the ellipsis. + fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(&P, &P, Span)> { + match &pat.node { + PatKind::Range(a, b, Spanned { span, node: RangeEnd::Included(DotDotDot), .. }) => { + Some((a, b, *span)) + } + _ => None, + } + } - if let PatKind::Range( - _, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) } - ) = pat.node { + let (parenthesise, endpoints) = match &pat.node { + PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)), + _ => (false, matches_ellipsis_pat(pat)), + }; + + if let Some((start, end, join)) = endpoints { let msg = "`...` range patterns are deprecated"; - let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg); - err.span_suggestion_short_with_applicability( - span, "use `..=` for an inclusive range", "..=".to_owned(), - // FIXME: outstanding problem with precedence in ref patterns: - // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285 - Applicability::MaybeIncorrect - ); - err.emit() + let suggestion = "use `..=` for an inclusive range"; + if parenthesise { + *visit_subpats = false; + let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg); + err.span_suggestion_with_applicability( + pat.span, + suggestion, + format!("&({}..={})", expr_to_string(&start), expr_to_string(&end)), + Applicability::MachineApplicable, + ); + err.emit(); + } else { + let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg); + err.span_suggestion_short_with_applicability( + join, + suggestion, + "..=".to_owned(), + Applicability::MachineApplicable, + ); + err.emit(); + }; } } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 9ccfecd46fdb2..049bcc3010be1 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -397,12 +397,12 @@ impl EarlyLintPass for UnusedParens { self.check_unused_parens_expr(cx, &value, msg, followed_by_block); } - fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat) { + fn check_pat(&mut self, cx: &EarlyContext, p: &ast::Pat, _: &mut bool) { use ast::PatKind::{Paren, Range}; // The lint visitor will visit each subpattern of `p`. We do not want to lint any range // pattern no matter where it occurs in the pattern. For something like `&(a..=b)`, there // is a recursive `check_pat` on `a` and `b`, but we will assume that if there are - // unnecessry parens they serve a purpose of readability. + // unnecessary parens they serve a purpose of readability. if let Paren(ref pat) = p.node { match pat.node { Range(..) => {} diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index ab44ebc052f30..db56ce4627410 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -12,7 +12,9 @@ use borrow_check::place_ext::PlaceExt; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::MoveData; use rustc::mir::traversal; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{ + PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext +}; use rustc::mir::{self, Location, Mir, Place, Local}; use rustc::ty::{Region, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -116,7 +118,7 @@ impl LocalsStateAtExit { impl<'tcx> Visitor<'tcx> for HasStorageDead { fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { - if ctx == PlaceContext::StorageDead { + if ctx == PlaceContext::NonUse(NonUseContext::StorageDead) { self.0.insert(*local); } } @@ -266,7 +268,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { // Watch out: the use of TMP in the borrow itself // doesn't count as an activation. =) - if borrow_data.reserve_location == location && context == PlaceContext::Store { + if borrow_data.reserve_location == location && + context == PlaceContext::MutatingUse(MutatingUseContext::Store) + { return; } @@ -287,10 +291,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { borrow_data.activation_location = match context { // The use of TMP in a shared borrow does not // count as an actual activation. - PlaceContext::Borrow { kind: mir::BorrowKind::Shared, .. } - | PlaceContext::Borrow { kind: mir::BorrowKind::Shallow, .. } => { - TwoPhaseActivation::NotActivated - } + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) => + TwoPhaseActivation::NotActivated, _ => { // Double check: This borrow is indeed a two-phase borrow (that is, // we are 'transitioning' from `NotActivated` to `ActivatedAt`) and diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 33bd009c8b565..f1ebddfd6d658 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -35,7 +35,7 @@ use rustc::infer::outlives::env::RegionBoundPairs; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc::mir::tcx::PlaceTy; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; @@ -472,9 +472,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } Place::Projection(ref proj) => { let base_context = if context.is_mutating_use() { - PlaceContext::Projection(Mutability::Mut) + PlaceContext::MutatingUse(MutatingUseContext::Projection) } else { - PlaceContext::Projection(Mutability::Not) + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) }; let base_ty = self.sanitize_place(&proj.base, location, base_context); if let PlaceTy::Ty { ty } = base_ty { @@ -488,7 +488,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { self.sanitize_projection(base_ty, &proj.elem, place, location) } }; - if let PlaceContext::Copy = context { + if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { let tcx = self.tcx(); let trait_ref = ty::TraitRef { def_id: tcx.lang_items().copy_trait().unwrap(), diff --git a/src/librustc_mir/borrow_check/used_muts.rs b/src/librustc_mir/borrow_check/used_muts.rs index dbe19bc47859f..dad87ed65a7d4 100644 --- a/src/librustc_mir/borrow_check/used_muts.rs +++ b/src/librustc_mir/borrow_check/used_muts.rs @@ -14,7 +14,6 @@ use rustc::mir::{Local, Location, Place}; use rustc_data_structures::fx::FxHashSet; use borrow_check::MirBorrowckCtxt; -use util::collect_writes::is_place_assignment; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable @@ -46,7 +45,7 @@ impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'c return; } - if is_place_assignment(&place_context) { + if place_context.is_place_assignment() { // Propagate the Local assigned at this Location as a used mutable local variable for moi in &self.mbcx.move_data.loc_map[location] { let mpi = &self.mbcx.move_data.moves[*moi].path; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index ae881bad58dcd..edd15c39fed3e 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -19,7 +19,7 @@ use rustc::hir::Node; use rustc::hir::def_id::DefId; use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc::mir::*; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; use syntax::ast; use syntax::symbol::Symbol; @@ -152,7 +152,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { place: &Place<'tcx>, context: PlaceContext<'tcx>, location: Location) { - if let PlaceContext::Borrow { .. } = context { + if context.is_borrow() { if util::is_disaligned(self.tcx, self.mir, self.param_env, place) { let source_info = self.source_info; let lint_root = @@ -193,9 +193,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } ty::Adt(adt, _) => { if adt.is_union() { - if context == PlaceContext::Store || - context == PlaceContext::AsmOutput || - context == PlaceContext::Drop + if context == PlaceContext::MutatingUse(MutatingUseContext::Store) || + context == PlaceContext::MutatingUse(MutatingUseContext::Drop) || + context == PlaceContext::MutatingUse( + MutatingUseContext::AsmOutput + ) { let elem_ty = match elem { &ProjectionElem::Field(_, ty) => ty, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 626baf207eebc..51644a6bba236 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -16,7 +16,7 @@ use rustc::hir::def::Def; use rustc::mir::{Constant, Location, Place, Mir, Operand, Rvalue, Local}; use rustc::mir::{NullOp, UnOp, StatementKind, Statement, BasicBlock, LocalKind}; use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem}; -use rustc::mir::visit::{Visitor, PlaceContext}; +use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext}; use rustc::mir::interpret::{ ConstEvalErr, EvalErrorKind, Scalar, GlobalId, EvalResult }; @@ -529,17 +529,18 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // Constants must have at most one write // FIXME(oli-obk): we could be more powerful here, if the multiple writes // only occur in independent execution paths - Store => if self.found_assignment[local] { + MutatingUse(MutatingUseContext::Store) => if self.found_assignment[local] { self.can_const_prop[local] = false; } else { self.found_assignment[local] = true }, // Reading constants is allowed an arbitrary number of times - Copy | Move | - StorageDead | StorageLive | - Validate | - Projection(_) | - Inspect => {}, + NonMutatingUse(NonMutatingUseContext::Copy) | + NonMutatingUse(NonMutatingUseContext::Move) | + NonMutatingUse(NonMutatingUseContext::Inspect) | + NonMutatingUse(NonMutatingUseContext::Projection) | + MutatingUse(MutatingUseContext::Projection) | + NonUse(_) => {}, _ => self.can_const_prop[local] = false, } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index f4efe33da7080..629211a7b554d 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -23,7 +23,7 @@ //! move analysis runs after promotion on broken MIR. use rustc::mir::*; -use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; +use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; use rustc::ty::TyCtxt; use syntax_pos::Span; @@ -53,6 +53,7 @@ pub enum TempState { impl TempState { pub fn is_promotable(&self) -> bool { + debug!("is_promotable: self={:?}", self); if let TempState::Defined { uses, .. } = *self { uses > 0 } else { @@ -88,6 +89,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { &index: &Local, context: PlaceContext<'tcx>, location: Location) { + debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location); // We're only interested in temporaries if self.mir.local_kind(index) != LocalKind::Temp { return; @@ -95,17 +97,22 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { // Ignore drops, if the temp gets promoted, // then it's constant and thus drop is noop. - // Storage live ranges are also irrelevant. - if context.is_drop() || context.is_storage_marker() { + // Non-uses are also irrelevent. + if context.is_drop() || !context.is_use() { + debug!( + "visit_local: context.is_drop={:?} context.is_use={:?}", + context.is_drop(), context.is_use(), + ); return; } let temp = &mut self.temps[index]; + debug!("visit_local: temp={:?}", temp); if *temp == TempState::Undefined { match context { - PlaceContext::Store | - PlaceContext::AsmOutput | - PlaceContext::Call => { + PlaceContext::MutatingUse(MutatingUseContext::Store) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | + PlaceContext::MutatingUse(MutatingUseContext::Call) => { *temp = TempState::Defined { location, uses: 0 @@ -117,10 +124,8 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { } else if let TempState::Defined { ref mut uses, .. } = *temp { // We always allow borrows, even mutable ones, as we need // to promote mutable borrows of some ZSTs e.g. `&mut []`. - let allowed_use = match context { - PlaceContext::Borrow {..} => true, - _ => context.is_nonmutating_use() - }; + let allowed_use = context.is_borrow() || context.is_nonmutating_use(); + debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { *uses += 1; return; diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 78547abf9d9d3..c78fb51961819 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -26,7 +26,7 @@ use rustc::ty::cast::CastTy; use rustc::ty::query::Providers; use rustc::mir::*; use rustc::mir::traversal::ReversePostorder; -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext}; use rustc::middle::lang_items; use rustc_target::spec::abi::Abi; use syntax::ast::LitKind; @@ -84,7 +84,7 @@ impl<'a, 'tcx> Qualif { } /// What kind of item we are in. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Mode { Const, Static, @@ -271,7 +271,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // This must be an explicit assignment. _ => { // Catch more errors in the destination. - self.visit_place(dest, PlaceContext::Store, location); + self.visit_place( + dest, + PlaceContext::MutatingUse(MutatingUseContext::Store), + location + ); self.statement_like(); } } @@ -383,6 +387,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { // Collect all the temps we need to promote. let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len()); + debug!("qualify_const: promotion_candidates={:?}", self.promotion_candidates); for candidate in &self.promotion_candidates { match *candidate { Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => { @@ -414,6 +419,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { &local: &Local, _: PlaceContext<'tcx>, _: Location) { + debug!("visit_local: local={:?}", local); let kind = self.mir.local_kind(local); match kind { LocalKind::ReturnPointer => { @@ -435,6 +441,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } if !self.temp_promotion_state[local].is_promotable() { + debug!("visit_local: (not promotable) local={:?}", local); self.add(Qualif::NOT_PROMOTABLE); } @@ -451,6 +458,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { place: &Place<'tcx>, context: PlaceContext<'tcx>, location: Location) { + debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location); match *place { Place::Local(ref local) => self.visit_local(local, context, location), Place::Promoted(_) => bug!("promoting already promoted MIR"), @@ -557,6 +565,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { + debug!("visit_operand: operand={:?} location={:?}", operand, location); self.super_operand(operand, location); match *operand { @@ -591,6 +600,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { + debug!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); // Recurse through operands and places. if let Rvalue::Ref(region, kind, ref place) = *rvalue { let mut is_reborrow = false; @@ -604,10 +614,17 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } if is_reborrow { - self.super_place(place, PlaceContext::Borrow { - region, - kind - }, location); + let ctx = match kind { + BorrowKind::Shared => + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(region)), + BorrowKind::Shallow => + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(region)), + BorrowKind::Unique => + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(region)), + BorrowKind::Mut { .. } => + PlaceContext::MutatingUse(MutatingUseContext::Borrow(region)), + }; + self.super_place(place, ctx, location); } else { self.super_rvalue(rvalue, location); } @@ -696,6 +713,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } } + debug!("visit_rvalue: forbidden_mut={:?}", forbidden_mut); if forbidden_mut { self.add(Qualif::NOT_CONST); } else { @@ -709,15 +727,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } place = &proj.base; } + debug!("visit_rvalue: place={:?}", place); if let Place::Local(local) = *place { if self.mir.local_kind(local) == LocalKind::Temp { + debug!("visit_rvalue: local={:?}", local); if let Some(qualif) = self.local_qualif[local] { // `forbidden_mut` is false, so we can safely ignore // `MUTABLE_INTERIOR` from the local's qualifications. // This allows borrowing fields which don't have // `MUTABLE_INTERIOR`, from a type that does, e.g.: // `let _: &'static _ = &(Cell::new(1), 2).1;` + debug!("visit_rvalue: qualif={:?}", qualif); if (qualif - Qualif::MUTABLE_INTERIOR).is_empty() { + debug!("visit_rvalue: candidate={:?}", candidate); self.promotion_candidates.push(candidate); } } @@ -815,6 +837,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { bb: BasicBlock, kind: &TerminatorKind<'tcx>, location: Location) { + debug!("visit_terminator_kind: bb={:?} kind={:?} location={:?}", bb, kind, location); if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind { self.visit_operand(func, location); @@ -967,6 +990,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { let candidate = Candidate::Argument { bb, index: i }; if is_shuffle && i == 2 { if this.qualif.is_empty() { + debug!("visit_terminator_kind: candidate={:?}", candidate); this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, @@ -983,6 +1007,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { return } if this.qualif.is_empty() { + debug!("visit_terminator_kind: candidate={:?}", candidate); this.promotion_candidates.push(candidate); } else { this.tcx.sess.span_err(this.span, @@ -1056,6 +1081,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { dest: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { + debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location); self.visit_rvalue(rvalue, location); // Check the allowed const fn argument forms. @@ -1104,10 +1130,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } fn visit_source_info(&mut self, source_info: &SourceInfo) { + debug!("visit_source_info: source_info={:?}", source_info); self.span = source_info.span; } fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>, location: Location) { + debug!("visit_statement: bb={:?} statement={:?} location={:?}", bb, statement, location); self.nest(|this| { this.visit_source_info(&statement.source_info); match statement.kind { @@ -1131,6 +1159,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { bb: BasicBlock, terminator: &Terminator<'tcx>, location: Location) { + debug!("visit_terminator: bb={:?} terminator={:?} location={:?}", bb, terminator, location); self.nest(|this| this.super_terminator(bb, terminator, location)); } } @@ -1197,6 +1226,7 @@ impl MirPass for QualifyAndPromoteConstants { hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut, }; + debug!("run_pass: mode={:?}", mode); if mode == Mode::Fn || mode == Mode::ConstFn { // This is ugly because Qualifier holds onto mir, // which can't be mutated until its scope ends. @@ -1239,6 +1269,7 @@ impl MirPass for QualifyAndPromoteConstants { // In `const` and `static` everything without `StorageDead` // is `'static`, we don't have to create promoted MIR fragments, // just remove `Drop` and `StorageDead` on "promoted" locals. + debug!("run_pass: promoted_temps={:?}", promoted_temps); for block in mir.basic_blocks_mut() { block.statements.retain(|statement| { match statement.kind { diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index a6e0932bf0ace..c20d40af50151 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -331,8 +331,10 @@ struct DeclMarker { impl<'tcx> Visitor<'tcx> for DeclMarker { fn visit_local(&mut self, local: &Local, ctx: PlaceContext<'tcx>, _: Location) { - // ignore these altogether, they get removed along with their otherwise unused decls. - if ctx != PlaceContext::StorageLive && ctx != PlaceContext::StorageDead { + // Ignore storage markers altogether, they get removed along with their otherwise unused + // decls. + // FIXME: Extend this to all non-uses. + if !ctx.is_storage_marker() { self.locals.insert(*local); } } diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index b123a846596e5..949b8f74f71e9 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -39,7 +39,7 @@ use rustc::ty; use rustc::ty::TyCtxt; use rustc::mir::*; -use rustc::mir::visit::{Visitor, PlaceContext}; +use rustc::mir::visit::{Visitor, PlaceContext, NonUseContext}; use transform::{MirPass, MirSource}; use util::patch::MirPatch; use rustc_data_structures::indexed_vec::{IndexVec}; @@ -316,8 +316,8 @@ impl<'tcx> Visitor<'tcx> for RestoreDataCollector { location: Location) { let local_use = &mut self.locals_use[*local]; match context { - PlaceContext::StorageLive => local_use.alive = Some(location), - PlaceContext::StorageDead => local_use.dead = Some(location), + PlaceContext::NonUse(NonUseContext::StorageLive) => local_use.alive = Some(location), + PlaceContext::NonUse(NonUseContext::StorageDead) => local_use.dead = Some(location), _ => { local_use.use_count += 1; if local_use.first_use.is_none() { diff --git a/src/librustc_mir/util/collect_writes.rs b/src/librustc_mir/util/collect_writes.rs index 23f753f8569bb..3e1d0852deedf 100644 --- a/src/librustc_mir/util/collect_writes.rs +++ b/src/librustc_mir/util/collect_writes.rs @@ -43,24 +43,8 @@ impl<'tcx> Visitor<'tcx> for FindLocalAssignmentVisitor { return; } - if is_place_assignment(&place_context) { + if place_context.is_place_assignment() { self.locations.push(location); } } } - -/// Returns true if this place context represents an assignment statement -crate fn is_place_assignment(place_context: &PlaceContext) -> bool { - match *place_context { - PlaceContext::Store | PlaceContext::Call | PlaceContext::AsmOutput => true, - PlaceContext::Drop - | PlaceContext::Inspect - | PlaceContext::Borrow { .. } - | PlaceContext::Projection(..) - | PlaceContext::Copy - | PlaceContext::Move - | PlaceContext::StorageLive - | PlaceContext::StorageDead - | PlaceContext::Validate => false, - } -} diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 420ca4efde37d..d16094e8238de 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -33,7 +33,9 @@ //! generator yield points, all pre-existing references are invalidated, so this //! doesn't matter). -use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::visit::{ + PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext, NonUseContext, +}; use rustc::mir::Local; use rustc::mir::*; use rustc::ty::{item_path, TyCtxt}; @@ -161,10 +163,10 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { /////////////////////////////////////////////////////////////////////////// // DEFS - PlaceContext::Store | + PlaceContext::MutatingUse(MutatingUseContext::Store) | // This is potentially both a def and a use... - PlaceContext::AsmOutput | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | // We let Call define the result in both the success and // unwind cases. This is not really correct, however it @@ -172,12 +174,12 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { // generate MIR. To do things properly, we would apply // the def in call only to the input from the success // path and not the unwind path. -nmatsakis - PlaceContext::Call | + PlaceContext::MutatingUse(MutatingUseContext::Call) | // Storage live and storage dead aren't proper defines, but we can ignore // values that come before them. - PlaceContext::StorageLive | - PlaceContext::StorageDead => Some(DefUse::Def), + PlaceContext::NonUse(NonUseContext::StorageLive) | + PlaceContext::NonUse(NonUseContext::StorageDead) => Some(DefUse::Def), /////////////////////////////////////////////////////////////////////////// // REGULAR USES @@ -186,18 +188,23 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { // purposes of NLL, these are special in that **all** the // lifetimes appearing in the variable must be live for each regular use. - PlaceContext::Projection(..) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) | + PlaceContext::MutatingUse(MutatingUseContext::Projection) | // Borrows only consider their local used at the point of the borrow. // This won't affect the results since we use this analysis for generators // and we only care about the result at suspension points. Borrows cannot // cross suspension points so this behavior is unproblematic. - PlaceContext::Borrow { .. } | - - PlaceContext::Inspect | - PlaceContext::Copy | - PlaceContext::Move | - PlaceContext::Validate => + PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) | + + PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | + PlaceContext::NonUse(NonUseContext::AscribeUserTy) | + PlaceContext::NonUse(NonUseContext::Validate) => Some(DefUse::Use), /////////////////////////////////////////////////////////////////////////// @@ -208,7 +215,7 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>) -> Option { // uses in drop are special because `#[may_dangle]` // attributes can affect whether lifetimes must be live. - PlaceContext::Drop => + PlaceContext::MutatingUse(MutatingUseContext::Drop) => Some(DefUse::Drop), } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 023a7477cee1b..b3a70c79df144 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,7 +16,7 @@ use macros::{InvocationData, ParentScope, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; -use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; +use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding}; use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -114,7 +114,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // This particular use tree use_tree: &ast::UseTree, id: NodeId, - parent_prefix: &[Ident], + parent_prefix: &[Segment], nested: bool, // The whole `use` item parent_scope: ParentScope<'a>, @@ -126,7 +126,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { parent_prefix, use_tree, nested); let mut prefix_iter = parent_prefix.iter().cloned() - .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident)).peekable(); + .chain(use_tree.prefix.segments.iter().map(|seg| seg.into())).peekable(); // On 2015 edition imports are resolved as crate-relative by default, // so prefixes are prepended with crate root segment if necessary. @@ -134,8 +134,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // appears, so imports in braced groups can have roots prepended independently. let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false }; let crate_root = if !self.session.rust_2018() && - prefix_iter.peek().map_or(is_glob, |ident| !ident.is_path_segment_keyword()) { - Some(Ident::new(keywords::CrateRoot.name(), use_tree.prefix.span.shrink_to_lo())) + prefix_iter.peek().map_or(is_glob, |seg| !seg.ident.is_path_segment_keyword()) + { + Some(Segment::from_ident(Ident::new( + keywords::CrateRoot.name(), + use_tree.prefix.span.shrink_to_lo(), + ))) } else { None }; @@ -143,9 +147,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let prefix = crate_root.into_iter().chain(prefix_iter).collect::>(); debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix); - let empty_for_self = |prefix: &[Ident]| { + let empty_for_self = |prefix: &[Segment]| { prefix.is_empty() || - prefix.len() == 1 && prefix[0].name == keywords::CrateRoot.name() + prefix.len() == 1 && prefix[0].ident.name == keywords::CrateRoot.name() }; match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { @@ -156,7 +160,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if nested { // Correctly handle `self` - if source.name == keywords::SelfValue.name() { + if source.ident.name == keywords::SelfValue.name() { type_ns_only = true; if empty_for_self(&module_path) { @@ -172,20 +176,20 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // Replace `use foo::self;` with `use foo;` source = module_path.pop().unwrap(); if rename.is_none() { - ident = source; + ident = source.ident; } } } else { // Disallow `self` - if source.name == keywords::SelfValue.name() { + if source.ident.name == keywords::SelfValue.name() { resolve_error(self, use_tree.span, ResolutionError::SelfImportsOnlyAllowedWithin); } // Disallow `use $crate;` - if source.name == keywords::DollarCrate.name() && module_path.is_empty() { - let crate_root = self.resolve_crate_root(source); + if source.ident.name == keywords::DollarCrate.name() && module_path.is_empty() { + let crate_root = self.resolve_crate_root(source.ident); let crate_name = match crate_root.kind { ModuleKind::Def(_, name) => name, ModuleKind::Block(..) => unreachable!(), @@ -195,11 +199,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // while the current crate doesn't have a valid `crate_name`. if crate_name != keywords::Invalid.name() { // `crate_name` should not be interpreted as relative. - module_path.push(Ident { - name: keywords::CrateRoot.name(), - span: source.span, + module_path.push(Segment { + ident: Ident { + name: keywords::CrateRoot.name(), + span: source.ident.span, + }, + id: Some(self.session.next_node_id()), }); - source.name = crate_name; + source.ident.name = crate_name; } if rename.is_none() { ident.name = crate_name; @@ -220,7 +227,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let subclass = SingleImport { target: ident, - source, + source: source.ident, result: PerNS { type_ns: Cell::new(Err(Undetermined)), value_ns: Cell::new(Err(Undetermined)), @@ -291,7 +298,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // `a::b::c::{self as _}`, so that their prefixes are correctly // resolved and checked for privacy/stability/etc. if items.is_empty() && !empty_for_self(&prefix) { - let new_span = prefix[prefix.len() - 1].span; + let new_span = prefix[prefix.len() - 1].ident.span; let tree = ast::UseTree { prefix: ast::Path::from_ident( Ident::new(keywords::SelfValue.name(), new_span) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 728023908678d..263d23d133e1c 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {CrateLint, PathResult}; +use {CrateLint, PathResult, Segment}; use macros::ParentScope; -use syntax::ast::Ident; use syntax::symbol::keywords; use syntax_pos::Span; @@ -23,20 +22,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { pub(crate) fn make_path_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); match (path.get(0), path.get(1)) { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) if fst.name == keywords::CrateRoot.name() && - !snd.is_path_segment_keyword() => {} + (Some(fst), Some(snd)) if fst.ident.name == keywords::CrateRoot.name() && + !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018 - (Some(fst), _) if self.session.rust_2018() && !fst.is_path_segment_keyword() => { + (Some(fst), _) if self.session.rust_2018() && !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. - path.insert(0, keywords::Invalid.ident()); + path.insert(0, Segment::from_ident(keywords::Invalid.ident())); } _ => return None, } @@ -57,11 +56,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_missing_self_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. - path[0].name = keywords::SelfValue.name(); + path[0].ident.name = keywords::SelfValue.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -81,11 +80,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_missing_crate_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. - path[0].name = keywords::Crate.name(); + path[0].ident.name = keywords::Crate.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -112,11 +111,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_missing_super_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. - path[0].name = keywords::Super.name(); + path[0].ident.name = keywords::Super.name(); let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -139,9 +138,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { fn make_external_crate_suggestion( &mut self, span: Span, - mut path: Vec, + mut path: Vec, parent_scope: &ParentScope<'b>, - ) -> Option<(Vec, Option)> { + ) -> Option<(Vec, Option)> { if !self.session.rust_2018() { return None; } @@ -155,7 +154,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. - path[0].name = name; + path[0].ident.name = name; let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0387b53bff968..4eb8a285aeccb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,7 +58,6 @@ use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; -use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; @@ -629,6 +628,43 @@ impl<'a> PathSource<'a> { } } +// A minimal representation of a path segment. We use this in resolve because +// we synthesize 'path segments' which don't have the rest of an AST or HIR +// PathSegment. +#[derive(Clone, Copy, Debug)] +pub struct Segment { + ident: Ident, + id: Option, +} + +impl Segment { + fn from_path(path: &Path) -> Vec { + path.segments.iter().map(|s| s.into()).collect() + } + + fn from_ident(ident: Ident) -> Segment { + Segment { + ident, + id: None, + } + } + + fn names_to_string(segments: &[Segment]) -> String { + names_to_string(&segments.iter() + .map(|seg| seg.ident) + .collect::>()) + } +} + +impl<'a> From<&'a ast::PathSegment> for Segment { + fn from(seg: &'a ast::PathSegment) -> Segment { + Segment { + ident: seg.ident, + id: Some(seg.id), + } + } +} + struct UsePlacementFinder { target_module: NodeId, span: Option, @@ -1033,7 +1069,7 @@ pub struct ModuleData<'a> { resolutions: RefCell>>>, single_segment_macro_resolutions: RefCell, Option<&'a NameBinding<'a>>)>>, - multi_segment_macro_resolutions: RefCell, Span, MacroKind, ParentScope<'a>, + multi_segment_macro_resolutions: RefCell, Span, MacroKind, ParentScope<'a>, Option)>>, builtin_attrs: RefCell)>>, @@ -1613,7 +1649,11 @@ impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { - fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { + fn resolve_hir_path( + &mut self, + path: &ast::Path, + is_value: bool, + ) -> hir::Path { self.resolve_hir_path_cb(path, is_value, |resolver, span, error| resolve_error(resolver, span, error)) } @@ -1623,33 +1663,22 @@ impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { span: Span, crate_root: Option<&str>, components: &[&str], - args: Option>, is_value: bool ) -> hir::Path { - let mut segments = iter::once(keywords::CrateRoot.ident()) + let segments = iter::once(keywords::CrateRoot.ident()) .chain( crate_root.into_iter() .chain(components.iter().cloned()) .map(Ident::from_str) - ).map(hir::PathSegment::from_ident).collect::>(); + ).map(|i| self.new_ast_path_segment(i)).collect::>(); - if let Some(args) = args { - let ident = segments.last().unwrap().ident; - *segments.last_mut().unwrap() = hir::PathSegment { - ident, - args: Some(args), - infer_types: true, - }; - } - let mut path = hir::Path { + let path = ast::Path { span, - def: Def::Err, - segments: segments.into(), + segments, }; - self.resolve_hir_path(&mut path, is_value); - path + self.resolve_hir_path(&path, is_value) } fn get_resolution(&mut self, id: NodeId) -> Option { @@ -1675,23 +1704,27 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { use std::iter; let mut errored = false; - let mut path = if path_str.starts_with("::") { - hir::Path { + let path = if path_str.starts_with("::") { + ast::Path { span, - def: Def::Err, - segments: iter::once(keywords::CrateRoot.ident()).chain({ - path_str.split("::").skip(1).map(Ident::from_str) - }).map(hir::PathSegment::from_ident).collect(), + segments: iter::once(keywords::CrateRoot.ident()) + .chain({ + path_str.split("::").skip(1).map(Ident::from_str) + }) + .map(|i| self.new_ast_path_segment(i)) + .collect(), } } else { - hir::Path { + ast::Path { span, - def: Def::Err, - segments: path_str.split("::").map(Ident::from_str) - .map(hir::PathSegment::from_ident).collect(), + segments: path_str + .split("::") + .map(Ident::from_str) + .map(|i| self.new_ast_path_segment(i)) + .collect(), } }; - self.resolve_hir_path_cb(&mut path, is_value, |_, _, _| errored = true); + let path = self.resolve_hir_path_cb(&path, is_value, |_, _, _| errored = true); if errored || path.def == Def::Err { Err(()) } else { @@ -1700,30 +1733,60 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { } /// resolve_hir_path, but takes a callback in case there was an error - fn resolve_hir_path_cb(&mut self, path: &mut hir::Path, is_value: bool, error_callback: F) + fn resolve_hir_path_cb( + &mut self, + path: &ast::Path, + is_value: bool, + error_callback: F, + ) -> hir::Path where F: for<'c, 'b> FnOnce(&'c mut Resolver, Span, ResolutionError<'b>) { let namespace = if is_value { ValueNS } else { TypeNS }; - let hir::Path { ref segments, span, ref mut def } = *path; - let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); + let span = path.span; + let segments = &path.segments; + let path = Segment::from_path(&path); // FIXME (Manishearth): Intra doc links won't get warned of epoch changes - match self.resolve_path_without_parent_scope(&path, Some(namespace), true, span, - CrateLint::No) { + let def = match self.resolve_path_without_parent_scope( + &path, + Some(namespace), + true, + span, + CrateLint::No, + ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => - *def = module.def().unwrap(), + module.def().unwrap(), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => - *def = path_res.base_def(), + path_res.base_def(), PathResult::NonModule(..) => { let msg = "type-relative paths are not supported in this context"; error_callback(self, span, ResolutionError::FailedToResolve(msg)); + Def::Err } PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) | PathResult::Indeterminate => unreachable!(), PathResult::Failed(span, msg, _) => { error_callback(self, span, ResolutionError::FailedToResolve(&msg)); + Def::Err } + }; + + let segments: Vec<_> = segments.iter().map(|seg| { + let mut hir_seg = hir::PathSegment::from_ident(seg.ident); + hir_seg.def = Some(self.def_map.get(&seg.id).map_or(Def::Err, |p| p.base_def())); + hir_seg + }).collect(); + hir::Path { + span, + def, + segments: segments.into(), } } + + fn new_ast_path_segment(&self, ident: Ident) -> ast::PathSegment { + let mut seg = ast::PathSegment::from_ident(ident); + seg.id = self.session.next_node_id(); + seg + } } impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { @@ -2056,7 +2119,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { if !module.no_implicit_prelude { if ns == TypeNS { - if let Some(binding) = self.extern_prelude_get(ident, !record_used, false) { + if let Some(binding) = self.extern_prelude_get(ident, !record_used) { return Some(LexicalScopeBinding::Item(binding)); } } @@ -2531,9 +2594,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let mut new_val = None; let mut new_id = None; if let Some(trait_ref) = opt_trait_ref { - let path: Vec<_> = trait_ref.path.segments.iter() - .map(|seg| seg.ident) - .collect(); + let path: Vec<_> = Segment::from_path(&trait_ref.path); let def = self.smart_resolve_path_fragment( trait_ref.ref_id, None, @@ -3029,21 +3090,25 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { source: PathSource, crate_lint: CrateLint ) -> PathResolution { - let segments = &path.segments.iter() - .map(|seg| seg.ident) - .collect::>(); - self.smart_resolve_path_fragment(id, qself, segments, path.span, source, crate_lint) + self.smart_resolve_path_fragment( + id, + qself, + &Segment::from_path(path), + path.span, + source, + crate_lint, + ) } fn smart_resolve_path_fragment(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], span: Span, source: PathSource, crate_lint: CrateLint) -> PathResolution { - let ident_span = path.last().map_or(span, |ident| ident.span); + let ident_span = path.last().map_or(span, |ident| ident.ident.span); let ns = source.namespace(); let is_expected = &|def| source.is_expected(def); let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false }; @@ -3052,18 +3117,18 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let report_errors = |this: &mut Self, def: Option| { // Make the base error. let expected = source.descr_expected(); - let path_str = names_to_string(path); - let item_str = path.last().unwrap(); + let path_str = Segment::names_to_string(path); + let item_str = path.last().unwrap().ident; let code = source.error_code(def.is_some()); let (base_msg, fallback_label, base_span) = if let Some(def) = def { (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str), format!("not a {}", expected), span) } else { - let item_span = path.last().unwrap().span; + let item_span = path.last().unwrap().ident.span; let (mod_prefix, mod_str) = if path.len() == 1 { (String::new(), "this scope".to_string()) - } else if path.len() == 2 && path[0].name == keywords::CrateRoot.name() { + } else if path.len() == 2 && path[0].ident.name == keywords::CrateRoot.name() { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; @@ -3074,7 +3139,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { module.def(), _ => None, }.map_or(String::new(), |def| format!("{} ", def.kind_name())); - (mod_prefix, format!("`{}`", names_to_string(mod_path))) + (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path))) }; (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str), format!("not found in {}", mod_str), @@ -3085,7 +3150,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // Emit help message for fake-self from other languages like `this`(javascript) if ["this", "my"].contains(&&*item_str.as_str()) - && this.self_value_is_available(path[0].span, span) { + && this.self_value_is_available(path[0].ident.span, span) { err.span_suggestion_with_applicability( span, "did you mean", @@ -3120,7 +3185,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } // Try to lookup the name in more relaxed fashion for better error reporting. - let ident = *path.last().unwrap(); + let ident = path.last().unwrap().ident; let candidates = this.lookup_import_candidates(ident.name, ns, is_expected); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = @@ -3147,7 +3212,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } if path.len() == 1 && this.self_type_is_available(span) { if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) { - let self_is_available = this.self_value_is_available(path[0].span, span); + let self_is_available = this.self_value_is_available(path[0].ident.span, span); match candidate { AssocSuggestion::Field => { err.span_suggestion_with_applicability( @@ -3382,7 +3447,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // or `::A::B`. If `B` should be resolved in value namespace then // it needs to be added to the trait map. if ns == ValueNS { - let item_name = *path.last().unwrap(); + let item_name = path.last().unwrap().ident; let traits = self.get_traits_containing_item(item_name, ns); self.trait_map.insert(id, traits); } @@ -3452,7 +3517,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_qpath_anywhere(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], primary_ns: Namespace, span: Span, defer_to_typeck: bool, @@ -3474,10 +3539,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } if primary_ns != MacroNS && - (self.macro_names.contains(&path[0].modern()) || - self.builtin_macros.get(&path[0].name).cloned() + (self.macro_names.contains(&path[0].ident.modern()) || + self.builtin_macros.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang) || - self.macro_use_prelude.get(&path[0].name).cloned() + self.macro_use_prelude.get(&path[0].ident.name).cloned() .and_then(NameBinding::macro_kind) == Some(MacroKind::Bang)) { // Return some dummy definition, it's enough for error reporting. return Some( @@ -3491,7 +3556,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_qpath(&mut self, id: NodeId, qself: Option<&QSelf>, - path: &[Ident], + path: &[Segment], ns: Namespace, span: Span, global_by_default: bool, @@ -3580,8 +3645,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { PathResult::Failed(..) if (ns == TypeNS || path.len() > 1) && self.primitive_type_table.primitive_types - .contains_key(&path[0].name) => { - let prim = self.primitive_type_table.primitive_types[&path[0].name]; + .contains_key(&path[0].ident.name) => { + let prim = self.primitive_type_table.primitive_types[&path[0].ident.name]; PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) } PathResult::Module(ModuleOrUniformRoot::Module(module)) => @@ -3596,8 +3661,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; if path.len() > 1 && !global_by_default && result.base_def() != Def::Err && - path[0].name != keywords::CrateRoot.name() && - path[0].name != keywords::DollarCrate.name() { + path[0].ident.name != keywords::CrateRoot.name() && + path[0].ident.name != keywords::DollarCrate.name() { let unqualified_result = { match self.resolve_path_without_parent_scope( &[*path.last().unwrap()], @@ -3623,7 +3688,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_path_without_parent_scope( &mut self, - path: &[Ident], + path: &[Segment], opt_ns: Option, // `None` indicates a module path in import record_used: bool, path_span: Span, @@ -3638,7 +3703,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn resolve_path( &mut self, - path: &[Ident], + path: &[Segment], opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, record_used: bool, @@ -3660,8 +3725,19 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { crate_lint, ); - for (i, &ident) in path.iter().enumerate() { - debug!("resolve_path ident {} {:?}", i, ident); + for (i, &Segment { ident, id }) in path.iter().enumerate() { + debug!("resolve_path ident {} {:?} {:?}", i, ident, id); + let record_segment_def = |this: &mut Self, def| { + if record_used { + if let Some(id) = id { + if !this.def_map.contains_key(&id) { + assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); + this.record_def(id, PathResolution::new(def)); + } + } + } + }; + let is_last = i == path.len() - 1; let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS }; let name = ident.name; @@ -3721,7 +3797,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } else { format!("`{}`", name) }; - let msg = if i == 1 && path[0].name == keywords::CrateRoot.name() { + let msg = if i == 1 && path[0].ident.name == keywords::CrateRoot.name() { format!("global paths cannot start with {}", name_str) } else { format!("{} in paths can only be used in start position", name_str) @@ -3745,6 +3821,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // we found a local variable or type param Some(LexicalScopeBinding::Def(def)) if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => { + record_segment_def(self, def); return PathResult::NonModule(PathResolution::with_unresolved_segments( def, path.len() - 1 )); @@ -3762,6 +3839,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); if let Some(next_module) = binding.module() { module = Some(ModuleOrUniformRoot::Module(next_module)); + record_segment_def(self, def); } else if def == Def::ToolMod && i + 1 != path.len() { let def = Def::NonMacroAttr(NonMacroAttrKind::Tool); return PathResult::NonModule(PathResolution::new(def)); @@ -3811,7 +3889,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } else if i == 0 { format!("use of undeclared type or module `{}`", ident) } else { - format!("could not find `{}` in `{}`", ident, path[i - 1]) + format!("could not find `{}` in `{}`", ident, path[i - 1].ident) }; return PathResult::Failed(ident.span, msg, is_last); } @@ -3831,7 +3909,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { fn lint_if_path_starts_with_module( &self, crate_lint: CrateLint, - path: &[Ident], + path: &[Segment], path_span: Span, second_binding: Option<&NameBinding>, ) { @@ -3848,7 +3926,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { }; let first_name = match path.get(0) { - Some(ident) => ident.name, + Some(ident) => ident.ident.name, None => return, }; @@ -3860,7 +3938,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { match path.get(1) { // If this import looks like `crate::...` it's already good - Some(ident) if ident.name == keywords::Crate.name() => return, + Some(Segment { ident, .. }) if ident.name == keywords::Crate.name() => return, // Otherwise go below to see if it's an extern crate Some(_) => {} // If the path has length one (and it's `CrateRoot` most likely) @@ -4054,7 +4132,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } fn lookup_typo_candidate(&mut self, - path: &[Ident], + path: &[Segment], ns: Namespace, filter_fn: FilterFn, span: Span) @@ -4119,7 +4197,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } - let name = path[path.len() - 1].name; + let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. names.sort_by_cached_key(|name| name.as_str()); match find_best_match_for_name(names.iter(), &name.as_str(), None) { @@ -4647,7 +4725,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { // On 2015 visibilities are resolved as crate-relative by default, // add starting root segment if necessary. let segments = path.make_root().iter().chain(path.segments.iter()) - .map(|seg| seg.ident) + .map(|seg| Segment { ident: seg.ident, id: Some(seg.id) }) .collect::>(); let def = self.smart_resolve_path_fragment( id, @@ -4956,7 +5034,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { self.name_already_seen.insert(name, span); } - fn extern_prelude_get(&mut self, ident: Ident, speculative: bool, skip_feature_gate: bool) + fn extern_prelude_get(&mut self, ident: Ident, speculative: bool) -> Option<&'a NameBinding<'a>> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. @@ -4964,13 +5042,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| { if let Some(binding) = entry.extern_crate_item { - if !speculative && !skip_feature_gate && entry.introduced_by_item && - !self.session.features_untracked().extern_crate_item_prelude { - emit_feature_err(&self.session.parse_sess, "extern_crate_item_prelude", - ident.span, GateIssue::Language, - "use of extern prelude names introduced \ - with `extern crate` items is unstable"); - } Some(binding) } else { let crate_id = if !speculative { @@ -4990,12 +5061,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { } } -fn is_self_type(path: &[Ident], namespace: Namespace) -> bool { - namespace == TypeNS && path.len() == 1 && path[0].name == keywords::SelfType.name() +fn is_self_type(path: &[Segment], namespace: Namespace) -> bool { + namespace == TypeNS && path.len() == 1 && path[0].ident.name == keywords::SelfType.name() } -fn is_self_value(path: &[Ident], namespace: Namespace) -> bool { - namespace == ValueNS && path.len() == 1 && path[0].name == keywords::SelfValue.name() +fn is_self_value(path: &[Segment], namespace: Namespace) -> bool { + namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfValue.name() } fn names_to_string(idents: &[Ident]) -> String { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2877e6a436795..df73befa324f0 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -10,8 +10,8 @@ use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; use {CrateLint, Resolver, ResolutionError, Weak}; -use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; -use {is_known_tool, names_to_string, resolve_error}; +use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding}; +use {is_known_tool, resolve_error}; use ModuleOrUniformRoot; use Namespace::{self, *}; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; @@ -470,13 +470,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> { force: bool, ) -> Result { let path_span = path.span; - let mut path = path.segments.iter().map(|s| s.ident).collect::>(); + let mut path = Segment::from_path(path); // Possibly apply the macro helper hack if kind == MacroKind::Bang && path.len() == 1 && - path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) { - let root = Ident::new(keywords::DollarCrate.name(), path[0].span); - path.insert(0, root); + path[0].ident.span.ctxt().outer().expn_info() + .map_or(false, |info| info.local_inner_macros) { + let root = Ident::new(keywords::DollarCrate.name(), path[0].ident.span); + path.insert(0, Segment::from_ident(root)); } if path.len() > 1 { @@ -501,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { def } else { let binding = self.early_resolve_ident_in_lexical_scope( - path[0], MacroNS, Some(kind), false, parent_scope, false, force, path_span + path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span ); match binding { Ok(..) => {} @@ -511,7 +512,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { if trace { parent_scope.module.single_segment_macro_resolutions.borrow_mut() - .push((path[0], kind, parent_scope.clone(), binding.ok())); + .push((path[0].ident, kind, parent_scope.clone(), binding.ok())); } binding.map(|binding| binding.def_ignoring_ambiguity()) @@ -737,8 +738,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } WhereToResolve::ExternPrelude => { if use_prelude { - match self.extern_prelude_get(ident, !record_used, - innermost_result.is_some()) { + match self.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::PRELUDE)), None => Err(Determinacy::determined( self.graph_root.unresolved_invocations.borrow().is_empty() @@ -905,7 +905,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // but its `Def` should coincide with a crate passed with `--extern` // (otherwise there would be ambiguity) and we can skip feature error in this case. if ns != TypeNS || !use_prelude || - self.extern_prelude_get(ident, true, false).is_none() { + self.extern_prelude_get(ident, true).is_none() { let msg = "imports can only refer to extern crate names \ passed with `--extern` on stable channel"; let mut err = feature_err(&self.session.parse_sess, "uniform_paths", @@ -945,7 +945,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; - let check_consistency = |this: &mut Self, path: &[Ident], span, + let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind, initial_def, def| { if let Some(initial_def) = initial_def { if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() { @@ -964,7 +964,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { // less informative error if the privacy error is reported elsewhere. if this.privacy_errors.is_empty() { let msg = format!("cannot determine resolution for the {} `{}`", - kind.descr(), names_to_string(path)); + kind.descr(), Segment::names_to_string(path)); let msg_note = "import resolution is stuck, try simplifying macro imports"; this.session.struct_span_err(span, &msg).note(msg_note).emit(); } @@ -973,7 +973,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> { let macro_resolutions = mem::replace(&mut *module.multi_segment_macro_resolutions.borrow_mut(), Vec::new()); - for (path, path_span, kind, parent_scope, initial_def) in macro_resolutions { + for (mut path, path_span, kind, parent_scope, initial_def) in macro_resolutions { + // FIXME: Path resolution will ICE if segment IDs present. + for seg in &mut path { seg.id = None; } match self.resolve_path(&path, Some(MacroNS), &parent_scope, true, path_span, CrateLint::No) { PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { @@ -1004,7 +1006,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> { initial_binding.def_ignoring_ambiguity() }); let def = binding.def_ignoring_ambiguity(); - check_consistency(self, &[ident], ident.span, kind, initial_def, def); + let seg = Segment::from_ident(ident); + check_consistency(self, &[seg], ident.span, kind, initial_def, def); } Err(..) => { assert!(initial_binding.is_none()); @@ -1050,7 +1053,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> { } }; let ident = Ident::new(Symbol::intern(name), span); - self.lookup_typo_candidate(&[ident], MacroNS, is_macro, span) + self.lookup_typo_candidate(&[Segment::from_ident(ident)], MacroNS, is_macro, span) }); if let Some(suggestion) = suggestion { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e744fae7cafff..b4490ea05f5a4 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -14,7 +14,7 @@ use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak}; use Namespace::{self, TypeNS, MacroNS}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; -use Resolver; +use {Resolver, Segment}; use {names_to_string, module_to_string}; use {resolve_error, ResolutionError}; use macros::ParentScope; @@ -89,7 +89,7 @@ crate struct ImportDirective<'a> { pub root_span: Span, pub parent_scope: ParentScope<'a>, - pub module_path: Vec, + pub module_path: Vec, /// The resolution of `module_path`. pub imported_module: Cell>>, pub subclass: ImportDirectiveSubclass<'a>, @@ -167,7 +167,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { match uniform_root_kind { UniformRootKind::ExternPrelude => { return if let Some(binding) = - self.extern_prelude_get(ident, !record_used, false) { + self.extern_prelude_get(ident, !record_used) { Ok(binding) } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { // Macro-expanded `extern crate` items can add names to extern prelude. @@ -367,7 +367,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> { // Add an import directive to the current module. pub fn add_import_directive(&mut self, - module_path: Vec, + module_path: Vec, subclass: ImportDirectiveSubclass<'a>, span: Span, id: NodeId, @@ -657,9 +657,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { self.throw_unresolved_import_error(empty_vec, None); } if !seen_spans.contains(&span) { - let path = import_path_to_string(&import.module_path[..], - &import.subclass, - span); + let path = import_path_to_string( + &import.module_path.iter().map(|seg| seg.ident).collect::>(), + &import.subclass, + span, + ); error_vec.push((span, path, err, note)); seen_spans.insert(span); prev_root_id = import.root_id; @@ -727,7 +729,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { /// If successful, the resolved bindings are written into the module. fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { debug!("(resolving import for module) resolving import `{}::...` in `{}`", - names_to_string(&directive.module_path), + Segment::names_to_string(&directive.module_path), module_to_string(self.current_module).unwrap_or_else(|| "???".to_string())); self.current_module = directive.parent_scope.module; @@ -852,7 +854,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { ) { Some(( span, - format!("did you mean `{}`?", names_to_string(&suggested_path[..])), + format!("did you mean `{}`?", Segment::names_to_string(&suggested_path)), note, )) } else { @@ -874,7 +876,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = directive.module_path.clone(); - full_path.push(keywords::Invalid.ident()); + full_path.push(Segment::from_ident(keywords::Invalid.ident())); self.lint_if_path_starts_with_module( directive.crate_lint(), &full_path, @@ -1065,7 +1067,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = directive.module_path.clone(); - full_path.push(ident); + full_path.push(Segment::from_ident(ident)); self.per_ns(|this, ns| { if let Ok(binding) = result[ns].get() { this.lint_if_path_starts_with_module( @@ -1211,7 +1213,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let resolutions = imported_module.parent.expect("parent should exist") .resolutions.borrow(); let enum_path_segment_index = directive.module_path.len() - 1; - let enum_ident = directive.module_path[enum_path_segment_index]; + let enum_ident = directive.module_path[enum_path_segment_index].ident; let enum_resolution = resolutions.get(&(enum_ident, TypeNS)) .expect("resolution should exist"); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 01859d683e0f8..15c8861eb3f1f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -34,12 +34,10 @@ use std::env; use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; use syntax::parse::token; -use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ bounds_to_string, generic_params_to_string, - path_to_string, ty_to_string }; use syntax::ptr::P; @@ -94,7 +92,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> { // we only write one macro def per unique macro definition, and // one macro use per unique callsite span. // mac_defs: FxHashSet, - macro_calls: FxHashSet, + // macro_calls: FxHashSet, } impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { @@ -110,7 +108,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { span: span_utils, cur_scope: CRATE_NODE_ID, // mac_defs: FxHashSet::default(), - macro_calls: FxHashSet::default(), + // macro_calls: FxHashSet::default(), } } @@ -219,95 +217,21 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.dumper.compilation_opts(data); } - // Return all non-empty prefixes of a path. - // For each prefix, we return the span for the last segment in the prefix and - // a str representation of the entire prefix. - fn process_path_prefixes(&self, path: &ast::Path) -> Vec<(Span, String)> { - let segments = &path.segments[if path.is_global() { 1 } else { 0 }..]; - - let mut result = Vec::with_capacity(segments.len()); - let mut segs = Vec::with_capacity(segments.len()); - - for (i, seg) in segments.iter().enumerate() { - segs.push(seg.clone()); - let sub_path = ast::Path { - span: seg.ident.span, // span for the last segment - segments: segs, - }; - let qualname = if i == 0 && path.is_global() { - format!("::{}", path_to_string(&sub_path)) - } else { - path_to_string(&sub_path) - }; - result.push((seg.ident.span, qualname)); - segs = sub_path.segments; - } - - result - } - fn write_sub_paths(&mut self, path: &ast::Path) { - let sub_paths = self.process_path_prefixes(path); - for (span, _) in sub_paths { - let span = self.span_from_span(span); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::null_id(), - }); + for seg in &path.segments { + if let Some(data) = self.save_ctxt.get_path_segment_data(seg) { + self.dumper.dump_ref(data); + } } } // As write_sub_paths, but does not process the last ident in the path (assuming it // will be processed elsewhere). See note on write_sub_paths about global. fn write_sub_paths_truncated(&mut self, path: &ast::Path) { - let sub_paths = self.process_path_prefixes(path); - let len = sub_paths.len(); - if len <= 1 { - return; - } - - for (span, _) in sub_paths.into_iter().take(len - 1) { - let span = self.span_from_span(span); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::null_id(), - }); - } - } - - // As write_sub_paths, but expects a path of the form module_path::trait::method - // Where trait could actually be a struct too. - fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) { - let sub_paths = self.process_path_prefixes(path); - let len = sub_paths.len(); - if len <= 1 { - return; - } - let sub_paths = &sub_paths[..(len - 1)]; - - // write the trait part of the sub-path - let (ref span, _) = sub_paths[len - 2]; - let span = self.span_from_span(*span); - self.dumper.dump_ref(Ref { - kind: RefKind::Type, - ref_id: ::null_id(), - span, - }); - - // write the other sub-paths - if len <= 2 { - return; - } - let sub_paths = &sub_paths[..len - 2]; - for &(ref span, _) in sub_paths { - let span = self.span_from_span(*span); - self.dumper.dump_ref(Ref { - kind: RefKind::Mod, - span, - ref_id: ::null_id(), - }); + for seg in &path.segments[..path.segments.len() - 1] { + if let Some(data) = self.save_ctxt.get_path_segment_data(seg) { + self.dumper.dump_ref(data); + } } } @@ -323,7 +247,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.visit_pat(&arg.pat); let mut collector = PathCollector::new(); collector.visit_pat(&arg.pat); - let span_utils = self.span.clone(); for (id, ident, ..) in collector.collected_idents { let hir_id = self.tcx.hir.node_to_hir_id(id); @@ -331,10 +254,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { Some(s) => s.to_string(), None => continue, }; - let sub_span = span_utils.span_for_last_ident(ident.span); - if !self.span.filter_generated(sub_span, ident.span) { + if !self.span.filter_generated(ident.span) { let id = ::id_from_node_id(id, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for variable")); + let span = self.span_from_span(ident.span); self.dumper.dump_def( &Access { @@ -373,7 +295,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ) { debug!("process_method: {}:{}", id, ident); - if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident.name, span) { + if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) { let sig_str = ::make_signature(&sig.decl, &generics); if body.is_some() { self.nest_tables( @@ -382,7 +304,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ); } - self.process_generic_params(&generics, span, &method_data.qualname, id); + self.process_generic_params(&generics, &method_data.qualname, id); method_data.value = sig_str; method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt); @@ -415,7 +337,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn process_generic_params( &mut self, generics: &'l ast::Generics, - full_span: Span, prefix: &str, id: NodeId, ) { @@ -427,7 +348,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let name = escape(self.span.snippet(param_ss)); // Append $id to name to make sure each one is unique. let qualname = format!("{}::{}${}", prefix, name, id); - if !self.span.filter_generated(Some(param_ss), full_span) { + if !self.span.filter_generated(param_ss) { let id = ::id_from_node_id(param.id, &self.save_ctxt); let span = self.span_from_span(param_ss); @@ -471,7 +392,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname), ); - self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); + self.process_generic_params(ty_params, &fn_data.qualname, item.id); self.dumper.dump_def(&access_from!(self.save_ctxt, item), fn_data); } @@ -505,8 +426,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { fn process_assoc_const( &mut self, id: ast::NodeId, - name: ast::Name, - span: Span, + ident: ast::Ident, typ: &'l ast::Ty, expr: Option<&'l ast::Expr>, parent_id: DefId, @@ -515,11 +435,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ) { let qualname = format!("::{}", self.tcx.node_path_str(id)); - let sub_span = self.span.sub_span_after_keyword(span, keywords::Const); - - if !self.span.filter_generated(sub_span, span) { - let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for variable")); + if !self.span.filter_generated(ident.span) { + let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt); + let span = self.span_from_span(ident.span); self.dumper.dump_def( &access_from!(self.save_ctxt, vis, id), @@ -527,7 +445,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { kind: DefKind::Const, id: ::id_from_node_id(id, &self.save_ctxt), span, - name: name.to_string(), + name: ident.name.to_string(), qualname, value: ty_to_string(&typ), parent: Some(::id_from_def_id(parent_id)), @@ -558,13 +476,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let (kind, keyword) = match item.node { - ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct), - ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union), + let kind = match item.node { + ast::ItemKind::Struct(_, _) => DefKind::Struct, + ast::ItemKind::Union(_, _) => DefKind::Union, _ => unreachable!(), }; - let sub_span = self.span.sub_span_after_keyword(item.span, keyword); let (value, fields) = match item.node { ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) | ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => { @@ -595,8 +512,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { _ => (String::new(), vec![]), }; - if !self.span.filter_generated(sub_span, item.span) { - let span = self.span_from_span(sub_span.expect("No span found for struct")); + if !self.span.filter_generated(item.ident.span) { + let span = self.span_from_span(item.ident.span); self.dumper.dump_def( &access_from!(self.save_ctxt, item), Def { @@ -621,7 +538,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.visit_ty(&field.ty); } - self.process_generic_params(ty_params, item.span, &qualname, item.id); + self.process_generic_params(ty_params, &qualname, item.id); } fn process_enum( @@ -642,10 +559,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { for variant in &enum_definition.variants { let name = variant.node.ident.name.to_string(); let qualname = format!("{}::{}", enum_data.qualname, name); + let name_span = variant.node.ident.span; match variant.node.data { ast::VariantData::Struct(ref fields, _) => { - let sub_span = self.span.span_for_first_ident(variant.span); let fields_str = fields .iter() .enumerate() @@ -655,9 +572,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .collect::>() .join(", "); let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); - if !self.span.filter_generated(sub_span, variant.span) { - let span = self - .span_from_span(sub_span.expect("No span found for struct variant")); + if !self.span.filter_generated(name_span) { + let span = self.span_from_span(name_span); let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); @@ -684,7 +600,6 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } ref v => { - let sub_span = self.span.span_for_first_ident(variant.span); let mut value = format!("{}::{}", enum_data.name, name); if let &ast::VariantData::Tuple(ref fields, _) = v { value.push('('); @@ -695,9 +610,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .join(", ")); value.push(')'); } - if !self.span.filter_generated(sub_span, variant.span) { - let span = - self.span_from_span(sub_span.expect("No span found for tuple variant")); + if !self.span.filter_generated(name_span) { + let span = self.span_from_span(name_span); let id = ::id_from_node_id(variant.node.data.id(), &self.save_ctxt); let parent = Some(::id_from_node_id(item.id, &self.save_ctxt)); @@ -731,7 +645,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.visit_ty(&field.ty); } } - self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id); + self.process_generic_params(ty_params, &enum_data.qualname, item.id); self.dumper.dump_def(&access, enum_data); } @@ -744,18 +658,20 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { impl_items: &'l [ast::ImplItem], ) { if let Some(impl_data) = self.save_ctxt.get_item_data(item) { - if let super::Data::RelationData(rel, imp) = impl_data { - self.dumper.dump_relation(rel); - self.dumper.dump_impl(imp); - } else { - span_bug!(item.span, "unexpected data kind: {:?}", impl_data); + if !self.span.filter_generated(item.span) { + if let super::Data::RelationData(rel, imp) = impl_data { + self.dumper.dump_relation(rel); + self.dumper.dump_impl(imp); + } else { + span_bug!(item.span, "unexpected data kind: {:?}", impl_data); + } } } self.visit_ty(&typ); if let &Some(ref trait_ref) = trait_ref { self.process_path(trait_ref.ref_id, &trait_ref.path); } - self.process_generic_params(type_parameters, item.span, "", item.id); + self.process_generic_params(type_parameters, "", item.id); for impl_item in impl_items { let map = &self.tcx.hir; self.process_impl_item(impl_item, map.local_def_id(item.id)); @@ -779,10 +695,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { val.push_str(": "); val.push_str(&bounds_to_string(trait_refs)); } - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Trait); - if !self.span.filter_generated(sub_span, item.span) { + if !self.span.filter_generated(item.ident.span) { let id = ::id_from_node_id(item.id, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for trait")); + let span = self.span_from_span(item.ident.span); let children = methods .iter() .map(|i| ::id_from_node_id(i.id, &self.save_ctxt)) @@ -815,21 +730,18 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let trait_ref = &trait_ref.trait_ref; if let Some(id) = self.lookup_def_id(trait_ref.ref_id) { - let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span); - if !self.span.filter_generated(sub_span, trait_ref.path.span) { - let span = self.span_from_span(sub_span.expect("No span found for trait ref")); + let sub_span = trait_ref.path.segments.last().unwrap().ident.span; + if !self.span.filter_generated(sub_span) { + let span = self.span_from_span(sub_span); self.dumper.dump_ref(Ref { kind: RefKind::Type, - span, + span: span.clone(), ref_id: ::id_from_def_id(id), }); - } - if !self.span.filter_generated(sub_span, trait_ref.path.span) { - let sub_span = self.span_from_span(sub_span.expect("No span for inheritance")); self.dumper.dump_relation(Relation { kind: RelationKind::SuperTrait, - span: sub_span, + span, from: ::id_from_def_id(id), to: ::id_from_node_id(item.id, &self.save_ctxt), }); @@ -838,7 +750,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } // walk generics and methods - self.process_generic_params(generics, item.span, &qualname, item.id); + self.process_generic_params(generics, &qualname, item.id); for method in methods { let map = &self.tcx.hir; self.process_trait_item(method, map.local_def_id(item.id)) @@ -861,8 +773,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } fn process_path(&mut self, id: NodeId, path: &'l ast::Path) { - debug!("process_path {:?}", path); - if generated_code(path.span) { + if self.span.filter_generated(path.span) { return; } self.dump_path_ref(id, path); @@ -891,29 +802,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } } - // Modules or types in the path prefix. - match self.save_ctxt.get_path_def(id) { - HirDef::Method(did) => { - let ti = self.tcx.associated_item(did); - if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument { - self.write_sub_path_trait_truncated(path); - } - } - HirDef::Fn(..) | - HirDef::Const(..) | - HirDef::Static(..) | - HirDef::StructCtor(..) | - HirDef::VariantCtor(..) | - HirDef::AssociatedConst(..) | - HirDef::Local(..) | - HirDef::Upvar(..) | - HirDef::Struct(..) | - HirDef::Union(..) | - HirDef::Variant(..) | - HirDef::TyAlias(..) | - HirDef::AssociatedTy(..) => self.write_sub_paths_truncated(path), - _ => {} - } + self.write_sub_paths_truncated(path); } fn process_struct_lit( @@ -924,9 +813,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { variant: &'l ty::VariantDef, base: &'l Option>, ) { - self.write_sub_paths_truncated(path); - if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) { + self.write_sub_paths_truncated(path); down_cast_data!(struct_lit_data, RefData, ex.span); if !generated_code(ex.span) { self.dumper.dump_ref(struct_lit_data); @@ -988,12 +876,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { }; let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id)); - for &Spanned { node: ref field, span } in fields { - let sub_span = self.span.span_for_first_ident(span); + for &Spanned { node: ref field, .. } in fields { if let Some(index) = self.tcx.find_field_index(field.ident, variant) { - if !self.span.filter_generated(sub_span, span) { - let span = - self.span_from_span(sub_span.expect("No span fund for var ref")); + if !self.span.filter_generated(field.ident.span) { + let span = self.span_from_span(field.ident.span); self.dumper.dump_ref(Ref { kind: RefKind::Variable, span, @@ -1034,7 +920,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { value.push_str(": "); value.push_str(&typ); - if !self.span.filter_generated(Some(ident.span), ident.span) { + if !self.span.filter_generated(ident.span) { let qualname = format!("{}${}", ident.to_string(), id); let id = ::id_from_node_id(id, &self.save_ctxt); let span = self.span_from_span(ident.span); @@ -1109,14 +995,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { None => String::new(), }; - // Get the span only for the name of the variable (I hope the path - // is only ever a variable name, but who knows?). - let sub_span = self.span.span_for_last_ident(ident.span); // Rust uses the id of the pattern for var lookups, so we'll use it too. - if !self.span.filter_generated(sub_span, ident.span) { + if !self.span.filter_generated(ident.span) { let qualname = format!("{}${}", ident.to_string(), id); let id = ::id_from_node_id(id, &self.save_ctxt); - let span = self.span_from_span(sub_span.expect("No span found for variable")); + let span = self.span_from_span(ident.span); self.dumper.dump_def( &Access { @@ -1149,18 +1032,20 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { /// If the span is not macro-generated, do nothing, else use callee and /// callsite spans to record macro definition and use data, using the /// mac_uses and mac_defs sets to prevent multiples. - fn process_macro_use(&mut self, span: Span) { - let source_span = span.source_callsite(); - if !self.macro_calls.insert(source_span) { - return; - } + fn process_macro_use(&mut self, _span: Span) { + // FIXME if we're not dumping the defs (see below), there is no point + // dumping refs either. + // let source_span = span.source_callsite(); + // if !self.macro_calls.insert(source_span) { + // return; + // } - let data = match self.save_ctxt.get_macro_use_data(span) { - None => return, - Some(data) => data, - }; + // let data = match self.save_ctxt.get_macro_use_data(span) { + // None => return, + // Some(data) => data, + // }; - self.dumper.macro_use(data); + // self.dumper.macro_use(data); // FIXME write the macro def // let mut hasher = DefaultHasher::new(); @@ -1190,8 +1075,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ast::TraitItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( trait_item.id, - trait_item.ident.name, - trait_item.span, + trait_item.ident, &ty, expr.as_ref().map(|e| &**e), trait_id, @@ -1214,11 +1098,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id)); - let sub_span = self.span - .sub_span_after_keyword(trait_item.span, keywords::Type); - if !self.span.filter_generated(sub_span, trait_item.span) { - let span = self.span_from_span(sub_span.expect("No span found for assoc type")); + if !self.span.filter_generated(trait_item.ident.span) { + let span = self.span_from_span(trait_item.ident.span); let id = ::id_from_node_id(trait_item.id, &self.save_ctxt); self.dumper.dump_def( @@ -1263,8 +1145,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ast::ImplItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( impl_item.id, - impl_item.ident.name, - impl_item.span, + impl_item.ident, &ty, Some(expr), impl_id, @@ -1328,7 +1209,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { .map(::id_from_def_id); match use_tree.kind { - ast::UseTreeKind::Simple(..) => { + ast::UseTreeKind::Simple(alias, ..) => { let ident = use_tree.ident(); let path = ast::Path { segments: prefix.segments @@ -1339,24 +1220,22 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { span: path.span, }; - let sub_span = self.span.span_for_last_ident(path.span); - let alias_span = self.span.sub_span_after_keyword(use_tree.span, keywords::As); - let ref_id = self.lookup_def_id(id); - - if !self.span.filter_generated(sub_span, path.span) { - let span = self.span_from_span(sub_span.expect("No span found for use")); - let alias_span = alias_span.map(|sp| self.span_from_span(sp)); + let sub_span = path.segments.last().unwrap().ident.span; + if !self.span.filter_generated(sub_span) { + let ref_id = self.lookup_def_id(id).map(|id| ::id_from_def_id(id)); + let alias_span = alias.map(|i| self.span_from_span(i.span)); + let span = self.span_from_span(sub_span); self.dumper.import(&access, Import { kind: ImportKind::Use, - ref_id: ref_id.map(|id| ::id_from_def_id(id)), + ref_id, span, alias_span, name: ident.to_string(), value: String::new(), parent, }); + self.write_sub_paths_truncated(&path); } - self.write_sub_paths_truncated(&path); } ast::UseTreeKind::Glob => { let path = ast::Path { @@ -1377,22 +1256,26 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { Vec::new() }; - let sub_span = self.span.sub_span_of_token(use_tree.span, - token::BinOp(token::Star)); - if !self.span.filter_generated(sub_span, use_tree.span) { - let span = - self.span_from_span(sub_span.expect("No span found for use glob")); - self.dumper.import(&access, Import { - kind: ImportKind::GlobUse, - ref_id: None, - span, - alias_span: None, - name: "*".to_owned(), - value: names.join(", "), - parent, - }); + // Otherwise it's a span with wrong macro expansion info, which + // we don't want to track anyway, since it's probably macro-internal `use` + if let Some(sub_span) = + self.span.sub_span_of_token(use_tree.span, token::BinOp(token::Star)) + { + if !self.span.filter_generated(use_tree.span) { + let span = self.span_from_span(sub_span); + + self.dumper.import(&access, Import { + kind: ImportKind::GlobUse, + ref_id: None, + span, + alias_span: None, + name: "*".to_owned(), + value: names.join(", "), + parent, + }); + self.write_sub_paths(&path); + } } - self.write_sub_paths(&path); } ast::UseTreeKind::Nested(ref nested_items) => { let prefix = ast::Path { @@ -1471,11 +1354,9 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc self.process_use_tree(use_tree, item.id, item, &prefix); } ExternCrate(_) => { - let alias_span = self.span.span_for_last_ident(item.span); - - if !self.span.filter_generated(alias_span, item.span) { - let span = - self.span_from_span(alias_span.expect("No span found for extern crate")); + let name_span = item.ident.span; + if !self.span.filter_generated(name_span) { + let span = self.span_from_span(name_span); let parent = self.save_ctxt.tcx.hir.opt_local_def_id(item.id) .and_then(|id| self.save_ctxt.tcx.parent_def_id(id)) .map(::id_from_def_id); @@ -1518,9 +1399,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc Ty(ref ty, ref ty_params) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let value = ty_to_string(&ty); - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); - if !self.span.filter_generated(sub_span, item.span) { - let span = self.span_from_span(sub_span.expect("No span found for typedef")); + if !self.span.filter_generated(item.ident.span) { + let span = self.span_from_span(item.ident.span); let id = ::id_from_node_id(item.id, &self.save_ctxt); self.dumper.dump_def( @@ -1543,15 +1423,14 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } self.visit_ty(&ty); - self.process_generic_params(ty_params, item.span, &qualname, item.id); + self.process_generic_params(ty_params, &qualname, item.id); } Existential(ref _bounds, ref ty_params) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); // FIXME do something with _bounds let value = String::new(); - let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type); - if !self.span.filter_generated(sub_span, item.span) { - let span = self.span_from_span(sub_span.expect("No span found for typedef")); + if !self.span.filter_generated(item.ident.span) { + let span = self.span_from_span(item.ident.span); let id = ::id_from_node_id(item.id, &self.save_ctxt); self.dumper.dump_def( @@ -1573,7 +1452,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc ); } - self.process_generic_params(ty_params, item.span, &qualname, item.id); + self.process_generic_params(ty_params, &qualname, item.id); } Mac(_) => (), _ => visit::walk_item(self, item), @@ -1606,14 +1485,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } if let Some(id) = self.lookup_def_id(t.id) { - if let Some(sub_span) = self.span.sub_span_for_type_name(t.span) { - let span = self.span_from_span(sub_span); - self.dumper.dump_ref(Ref { - kind: RefKind::Type, - span, - ref_id: ::id_from_def_id(id), - }); - } + let sub_span = path.segments.last().unwrap().ident.span; + let span = self.span_from_span(sub_span); + self.dumper.dump_ref(Ref { + kind: RefKind::Type, + span, + ref_id: ::id_from_def_id(id), + }); } self.write_sub_paths_truncated(path); @@ -1753,11 +1631,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(fn_data, DefData, item.span); - self.nest_tables( - item.id, - |v| v.process_formals(&decl.inputs, &fn_data.qualname), - ); - self.process_generic_params(generics, item.span, &fn_data.qualname, item.id); + self.process_generic_params(generics, &fn_data.qualname, item.id); self.dumper.dump_def(&access, fn_data); } diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index e14ac73ee1020..d2354f38e2685 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -93,7 +93,7 @@ impl<'b, O: DumpOutput + 'b> JsonDumper { self.result.compilation = Some(data); } - pub fn macro_use(&mut self, data: MacroRef) { + pub fn _macro_use(&mut self, data: MacroRef) { if self.config.pub_only || self.config.reachable_only { return; } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4b43a1a6270f8..82c4795a29d4b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -57,12 +57,10 @@ use std::env; use std::fs::File; use std::path::{Path, PathBuf}; -use syntax::ast::{self, Attribute, NodeId, PatKind}; +use syntax::ast::{self, Attribute, DUMMY_NODE_ID, NodeId, PatKind}; use syntax::source_map::Spanned; use syntax::parse::lexer::comments::strip_doc_comment_decoration; -use syntax::parse::token; use syntax::print::pprust; -use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{arg_to_string, ty_to_string}; use syntax::source_map::MacroAttribute; @@ -162,14 +160,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); match item.node { ast::ForeignItemKind::Fn(ref decl, ref generics) => { - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Fn); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::ForeignFunction, id: id_from_node_id(item.id, self), - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), name: item.ident.to_string(), qualname, value: make_signature(decl, generics), @@ -181,13 +177,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Static(ref ty, m) => { - let keyword = if m { keywords::Mut } else { keywords::Static }; - let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); - filter!(self.span_utils, sub_span, item.span, None); + ast::ForeignItemKind::Static(ref ty, _) => { + filter!(self.span_utils, item.ident.span); let id = ::id_from_node_id(item.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(item.ident.span); Some(Data::DefData(Def { kind: DefKind::ForeignStatic, @@ -214,13 +208,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { match item.node { ast::ItemKind::Fn(ref decl, .., ref generics, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Fn); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::Function, id: id_from_node_id(item.id, self), - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), name: item.ident.to_string(), qualname, value: make_signature(decl, generics), @@ -232,19 +224,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Static(ref typ, mt, _) => { + ast::ItemKind::Static(ref typ, ..) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let keyword = match mt { - ast::Mutability::Mutable => keywords::Mut, - ast::Mutability::Immutable => keywords::Static, - }; - - let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(item.ident.span); Some(Data::DefData(Def { kind: DefKind::Static, @@ -263,12 +249,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ItemKind::Const(ref typ, _) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Const); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(item.ident.span); Some(Data::DefData(Def { kind: DefKind::Const, @@ -291,16 +275,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let cm = self.tcx.sess.source_map(); let filename = cm.span_to_filename(m.inner); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Mod); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::Mod, id: id_from_node_id(item.id, self), name: item.ident.to_string(), qualname, - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), value: filename.to_string(), parent: None, children: m.items @@ -316,9 +298,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ItemKind::Enum(ref def, _) => { let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); - let sub_span = self.span_utils - .sub_span_after_keyword(item.span, keywords::Enum); - filter!(self.span_utils, sub_span, item.span, None); + filter!(self.span_utils, item.ident.span); let variants_str = def.variants .iter() .map(|v| v.node.ident.to_string()) @@ -328,7 +308,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Some(Data::DefData(Def { kind: DefKind::Enum, id: id_from_node_id(item.id, self), - span: self.span_from_span(sub_span.unwrap()), + span: self.span_from_span(item.ident.span), name, qualname, value, @@ -349,11 +329,11 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if generated_code(path.span) { return None; } - let sub_span = self.span_utils.sub_span_for_type_name(path.span); - filter!(self.span_utils, sub_span, typ.span, None); + let sub_span = path.segments.last().unwrap().ident.span; + filter!(self.span_utils, sub_span); let impl_id = self.next_impl_id(); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(sub_span); let type_data = self.lookup_ref_id(typ.id); type_data.map(|type_data| { @@ -402,15 +382,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if let Some(ident) = field.ident { let name = ident.to_string(); let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); - let sub_span = self.span_utils - .sub_span_before_token(field.span, token::Colon); - filter!(self.span_utils, sub_span, field.span, None); + filter!(self.span_utils, ident.span); let def_id = self.tcx.hir.local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); let id = id_from_node_id(field.id, self); - let span = self.span_from_span(sub_span.unwrap()); + let span = self.span_from_span(ident.span); Some(Def { kind: DefKind::Field, @@ -433,7 +411,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // FIXME would be nice to take a MethodItem here, but the ast provides both // trait and impl flavours, so the caller must do the disassembly. - pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> Option { + pub fn get_method_data(&self, id: ast::NodeId, ident: ast::Ident, span: Span) -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. let (qualname, parent_scope, decl_id, docs, attributes) = @@ -459,7 +437,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname.push_str(&self.tcx.item_path_str(def_id)); self.tcx .associated_items(def_id) - .find(|item| item.ident.name == name) + .find(|item| item.ident.name == ident.name) .map(|item| decl_id = Some(item.def_id)); } qualname.push_str(">"); @@ -512,16 +490,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }, }; - let qualname = format!("{}::{}", qualname, name); + let qualname = format!("{}::{}", qualname, ident.name); - let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); - filter!(self.span_utils, sub_span, span, None); + filter!(self.span_utils, ident.span); Some(Def { kind: DefKind::Method, id: id_from_node_id(id, self), - span: self.span_from_span(sub_span.unwrap()), - name: name.to_string(), + span: self.span_from_span(ident.span), + name: ident.name.to_string(), qualname, // FIXME you get better data here by using the visitor. value: String::new(), @@ -540,9 +517,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if generated_code(span) { return None; } - let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span)); - filter!(self.span_utils, sub_span, span, None); - let span = self.span_from_span(sub_span.unwrap()); + let sub_span = trait_ref.path.segments.last().unwrap().ident.span; + filter!(self.span_utils, sub_span); + let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Type, span, @@ -574,9 +551,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); let index = self.tcx.find_field_index(ident, variant).unwrap(); - let sub_span = self.span_utils.span_for_last_ident(expr.span); - filter!(self.span_utils, sub_span, expr.span, None); - let span = self.span_from_span(sub_span.unwrap()); + filter!(self.span_utils, ident.span); + let span = self.span_from_span(ident.span); return Some(Data::RefData(Ref { kind: RefKind::Variable, span, @@ -593,9 +569,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ExprKind::Struct(ref path, ..) => { match self.tables.expr_ty_adjusted(&hir_node).sty { ty::Adt(def, _) if !def.is_enum() => { - let sub_span = self.span_utils.span_for_last_ident(path.span); - filter!(self.span_utils, sub_span, path.span, None); - let span = self.span_from_span(sub_span.unwrap()); + let sub_span = path.segments.last().unwrap().ident.span; + filter!(self.span_utils, sub_span); + let span = self.span_from_span(sub_span); Some(Data::RefData(Ref { kind: RefKind::Type, span, @@ -624,7 +600,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ty::TraitContainer(_) => (None, Some(method_id)), }; let sub_span = seg.ident.span; - filter!(self.span_utils, Some(sub_span), expr.span, None); + filter!(self.span_utils, sub_span); let span = self.span_from_span(sub_span); Some(Data::RefData(Ref { kind: RefKind::Function, @@ -656,6 +632,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Node::Visibility(&Spanned { node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.def, + Node::PathSegment(seg) => match seg.def { + Some(def) => def, + None => HirDef::Err, + }, Node::Expr(&hir::Expr { node: hir::ExprKind::Struct(ref qpath, ..), .. @@ -709,12 +689,26 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option { + path.segments + .last() + .and_then(|seg| { + self.get_path_segment_data(seg) + .or_else(|| self.get_path_segment_data_with_id(seg, id)) + }) + } + + pub fn get_path_segment_data(&self, path_seg: &ast::PathSegment) -> Option { + self.get_path_segment_data_with_id(path_seg, path_seg.id) + } + + fn get_path_segment_data_with_id( + &self, + path_seg: &ast::PathSegment, + id: NodeId, + ) -> Option { // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`. - fn fn_type(path: &ast::Path) -> bool { - if path.segments.len() != 1 { - return false; - } - if let Some(ref generic_args) = path.segments[0].args { + fn fn_type(seg: &ast::PathSegment) -> bool { + if let Some(ref generic_args) = seg.args { if let ast::GenericArgs::Parenthesized(_) = **generic_args { return true; } @@ -722,17 +716,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { false } - if path.segments.is_empty() { + if id == DUMMY_NODE_ID { return None; } let def = self.get_path_def(id); - let last_seg = &path.segments[path.segments.len() - 1]; - let sub_span = last_seg.ident.span; - filter!(self.span_utils, Some(sub_span), path.span, None); + let span = path_seg.ident.span; + filter!(self.span_utils, span); + let span = self.span_from_span(span); + match def { HirDef::Upvar(id, ..) | HirDef::Local(id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Variable, span, @@ -743,23 +737,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Const(..) | HirDef::AssociatedConst(..) | HirDef::VariantCtor(..) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(def.def_id()), }) } - HirDef::Trait(def_id) if fn_type(path) => { - // Function type bounds are desugared in the parser, so we have to - // special case them here. - let fn_span = self.span_utils.span_for_first_ident(path.span); - fn_span.map(|span| { - Ref { - kind: RefKind::Type, - span: self.span_from_span(span), - ref_id: id_from_def_id(def_id), - } + HirDef::Trait(def_id) if fn_type(path_seg) => { + Some(Ref { + kind: RefKind::Type, + span, + ref_id: id_from_def_id(def_id), }) } HirDef::Struct(def_id) | @@ -774,7 +762,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { HirDef::Trait(def_id) | HirDef::Existential(def_id) | HirDef::TyParam(def_id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Type, span, @@ -785,7 +772,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // This is a reference to a tuple struct where the def_id points // to an invisible constructor function. That is not a very useful // def, so adjust to point to the tuple struct itself. - let span = self.span_from_span(sub_span); let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); Some(Ref { kind: RefKind::Type, @@ -804,7 +790,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } else { None }; - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Function, span, @@ -812,7 +797,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Fn(def_id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Function, span, @@ -820,7 +804,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }) } HirDef::Mod(def_id) => { - let span = self.span_from_span(sub_span); Some(Ref { kind: RefKind::Mod, span, @@ -843,15 +826,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { field_ref: &ast::Field, variant: &ty::VariantDef, ) -> Option { - let index = self.tcx.find_field_index(field_ref.ident, variant).unwrap(); - // We don't really need a sub-span here, but no harm done - let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span); - filter!(self.span_utils, sub_span, field_ref.ident.span, None); - let span = self.span_from_span(sub_span.unwrap()); - Some(Ref { - kind: RefKind::Variable, - span, - ref_id: id_from_def_id(variant.fields[index].did), + filter!(self.span_utils, field_ref.ident.span); + self.tcx.find_field_index(field_ref.ident, variant).map(|index| { + let span = self.span_from_span(field_ref.ident.span); + Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(variant.fields[index].did), + } }) } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 47677a751712e..06b4f33b5db3e 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -16,7 +16,6 @@ use std::cell::Cell; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; -use syntax::symbol::keywords; use syntax_pos::*; #[derive(Clone)] @@ -67,131 +66,6 @@ impl<'a> SpanUtils<'a> { lexer::StringReader::retokenize(&self.sess.parse_sess, span) } - // Re-parses a path and returns the span for the last identifier in the path - pub fn span_for_last_ident(&self, span: Span) -> Option { - let mut result = None; - - let mut toks = self.retokenise_span(span); - let mut bracket_count = 0; - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return result; - } - if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { - result = Some(ts.sp); - } - - bracket_count += match ts.tok { - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shr) => -2, - _ => 0, - } - } - } - - // Return the span for the first identifier in the path. - pub fn span_for_first_ident(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut bracket_count = 0; - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } - if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) { - return Some(ts.sp); - } - - bracket_count += match ts.tok { - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shr) => -2, - _ => 0, - } - } - } - - // Return the span for the last ident before a `<` and outside any - // angle brackets, or the last span. - pub fn sub_span_for_type_name(&self, span: Span) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - let mut result = None; - - // We keep track of the following two counts - the depth of nesting of - // angle brackets, and the depth of nesting of square brackets. For the - // angle bracket count, we only count tokens which occur outside of any - // square brackets (i.e. bracket_count == 0). The intuition here is - // that we want to count angle brackets in the type, but not any which - // could be in expression context (because these could mean 'less than', - // etc.). - let mut angle_count = 0; - let mut bracket_count = 0; - loop { - let next = toks.real_token(); - - if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0 - && bracket_count == 0 && prev.tok.is_ident() - { - result = Some(prev.sp); - } - - if bracket_count == 0 { - angle_count += match prev.tok { - token::Lt => 1, - token::Gt => -1, - token::BinOp(token::Shl) => 2, - token::BinOp(token::Shr) => -2, - _ => 0, - }; - } - - bracket_count += match prev.tok { - token::OpenDelim(token::Bracket) => 1, - token::CloseDelim(token::Bracket) => -1, - _ => 0, - }; - - if next.tok == token::Eof { - break; - } - prev = next; - } - #[cfg(debug_assertions)] { - if angle_count != 0 || bracket_count != 0 { - let loc = self.sess.source_map().lookup_char_pos(span.lo()); - span_bug!( - span, - "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}", - self.snippet(span), - loc.file.name, - loc.line - ); - } - } - if result.is_none() && prev.tok.is_ident() { - return Some(prev.sp); - } - result - } - - pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option { - let mut toks = self.retokenise_span(span); - let mut prev = toks.real_token(); - loop { - if prev.tok == token::Eof { - return None; - } - let next = toks.real_token(); - if next.tok == tok { - return Some(prev.sp); - } - prev = next; - } - } - pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option { let mut toks = self.retokenise_span(span); loop { @@ -205,28 +79,6 @@ impl<'a> SpanUtils<'a> { } } - pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option { - self.sub_span_after(span, |t| t.is_keyword(keyword)) - } - - fn sub_span_after bool>(&self, span: Span, f: F) -> Option { - let mut toks = self.retokenise_span(span); - loop { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } - if f(ts.tok) { - let ts = toks.real_token(); - if ts.tok == token::Eof { - return None; - } else { - return Some(ts.sp); - } - } - } - } - // // Return the name for a macro definition (identifier after first `!`) // pub fn span_for_macro_def_name(&self, span: Span) -> Option { // let mut toks = self.retokenise_span(span); @@ -271,42 +123,24 @@ impl<'a> SpanUtils<'a> { /// /// Used to filter out spans of minimal value, /// such as references to macro internal variables. - pub fn filter_generated(&self, sub_span: Option, parent: Span) -> bool { - if !generated_code(parent) { - // Edge case - this occurs on generated code with incorrect expansion info. - return sub_span.is_none() + pub fn filter_generated(&self, span: Span) -> bool { + if generated_code(span) { + return true; } - // If sub_span is none, filter out generated code. - let sub_span = match sub_span { - Some(ss) => ss, - None => return true, - }; //If the span comes from a fake source_file, filter it. - if !self.sess + !self.sess .source_map() - .lookup_char_pos(parent.lo()) + .lookup_char_pos(span.lo()) .file .is_real_file() - { - return true; - } - - // Otherwise, a generated span is deemed invalid if it is not a sub-span of the root - // callsite. This filters out macro internal variables and most malformed spans. - !parent.source_callsite().contains(sub_span) } } macro_rules! filter { - ($util: expr, $span: expr, $parent: expr, None) => { - if $util.filter_generated($span, $parent) { + ($util: expr, $parent: expr) => { + if $util.filter_generated($parent) { return None; } }; - ($util: expr, $span: ident, $parent: expr) => { - if $util.filter_generated($span, $parent) { - return; - } - }; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index eb52a013b0566..b33b21478ca4b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1591,6 +1591,7 @@ fn predicates_defined_on<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, ) -> ty::GenericPredicates<'tcx> { + debug!("predicates_defined_on({:?})", def_id); let explicit = tcx.explicit_predicates_of(def_id); let span = tcx.def_span(def_id); let predicates = explicit.predicates.into_iter().chain( diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 132da8f5cea8d..30e304375fe0e 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -14,6 +14,7 @@ use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{Kind, Subst, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; use rustc::util::nodemap::FxHashMap; use super::explicit::ExplicitPredicatesMap; @@ -245,6 +246,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } +#[derive(Debug)] pub struct IgnoreSelfTy(bool); /// We also have to check the explicit predicates @@ -270,10 +272,18 @@ pub fn check_explicit_predicates<'tcx>( explicit_map: &mut ExplicitPredicatesMap<'tcx>, ignore_self_ty: IgnoreSelfTy, ) { - debug!("def_id = {:?}", &def_id); - debug!("substs = {:?}", &substs); - debug!("explicit_map = {:?}", explicit_map); - debug!("required_predicates = {:?}", required_predicates); + debug!( + "check_explicit_predicates(def_id={:?}, \ + substs={:?}, \ + explicit_map={:?}, \ + required_predicates={:?}, \ + ignore_self_ty={:?})", + def_id, + substs, + explicit_map, + required_predicates, + ignore_self_ty, + ); let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id); for outlives_predicate in explicit_predicates.iter() { @@ -302,13 +312,23 @@ pub fn check_explicit_predicates<'tcx>( // // Note that we do this check for self **before** applying `substs`. In the // case that `substs` come from a `dyn Trait` type, our caller will have - // included `Self = dyn Trait<'x, X>` as the value for `Self`. If we were + // included `Self = usize` as the value for `Self`. If we were // to apply the substs, and not filter this predicate, we might then falsely // conclude that e.g. `X: 'x` was a reasonable inferred requirement. - if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.is_self() && ignore_self_ty.0 { - debug!("skipping self ty = {:?}", &ty); - continue; + // + // Another similar case is where we have a inferred + // requirement like `::Foo: 'b`. We presently + // ignore such requirements as well (cc #54467)-- though + // conceivably it might be better if we could extract the `Foo + // = X` binding from the object type (there must be such a + // binding) and thus infer an outlives requirement that `X: + // 'b`. + if ignore_self_ty.0 { + if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { + if ty.has_self_ty() { + debug!("skipping self ty = {:?}", &ty); + continue; + } } } diff --git a/src/librustc_typeck/outlives/mod.rs b/src/librustc_typeck/outlives/mod.rs index cca77b20d9b30..1eb53ffc730f6 100644 --- a/src/librustc_typeck/outlives/mod.rs +++ b/src/librustc_typeck/outlives/mod.rs @@ -67,6 +67,9 @@ fn inferred_outlives_of<'a, 'tcx>( } err.emit(); } + + debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates); + predicates } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 858685ef00e37..8246c7bab27af 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -50,6 +50,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { name: Option, ) -> Vec where F: Fn(DefId) -> Def { + debug!("get_blanket_impls(def_id={:?}, ...)", def_id); let mut impls = Vec::new(); if self.cx .tcx @@ -78,6 +79,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { } self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { self.cx.tcx.infer_ctxt().enter(|infcx| { + debug!("get_blanet_impls: Considering impl for trait '{:?}' {:?}", + trait_def_id, impl_def_id); let t_generics = infcx.tcx.generics_of(impl_def_id); let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) .expect("Cannot get impl trait"); @@ -104,8 +107,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { drop(obligations); debug!( - "invoking predicate_may_hold: {:?}", - trait_ref, + "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", + param_env, trait_ref, ty ); let may_apply = match infcx.evaluate_obligation( &traits::Obligation::new( @@ -117,6 +120,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { Ok(eval_result) => eval_result.may_apply(), Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no }; + debug!("get_blanket_impls: found applicable impl: {}\ + for trait_ref={:?}, ty={:?}", + may_apply, trait_ref, ty); + if !may_apply { return } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bed3f7f99ae02..4281ccf5f67ee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3491,13 +3491,16 @@ impl Clean> for doctree::Import { // forcefully don't inline if this is not public or if the // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. - let denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| { + let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| { a.name() == "doc" && match a.meta_item_list() { Some(l) => attr::list_contains_name(&l, "no_inline") || attr::list_contains_name(&l, "hidden"), None => false, } }); + // Also check whether imports were asked to be inlined, in case we're trying to re-export a + // crate in Rust 2018+ + let please_inline = self.attrs.lists("doc").has_word("inline"); let path = self.path.clean(cx); let inner = if self.glob { if !denied { @@ -3510,6 +3513,16 @@ impl Clean> for doctree::Import { Import::Glob(resolve_use_source(cx, path)) } else { let name = self.name; + if !please_inline { + match path.def { + Def::Mod(did) => if !did.is_local() && did.index == CRATE_DEF_INDEX { + // if we're `pub use`ing an extern crate root, don't inline it unless we + // were specifically asked for it + denied = true; + } + _ => {} + } + } if !denied { let mut visited = FxHashSet::default(); if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) { @@ -4012,6 +4025,8 @@ where F: Fn(DefId) -> Def { def: def_ctor(def_id), segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment { ident: ast::Ident::from_str(&s), + id: None, + def: None, args: None, infer_types: false, }).collect()) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8f9c3fa4b7f20..d6b0127e44d01 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -186,6 +186,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { segments.push(hir::PathSegment::new( real_name.unwrap_or(last.ident), + None, + None, self.generics_to_path_params(generics.clone()), false, )); diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 90ab349159915..bb795a33746e2 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -481,7 +481,8 @@ mod tests { let (a, b) = ($a, $b); if a != b { let (a, b) = if a > b {(a, b)} else {(b, a)}; - assert!(a - Duration::new(0, 100) <= b); + assert!(a - Duration::new(0, 1000) <= b, + "{:?} is not almost equal to {:?}", a, b); } }) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9ed628e2ed337..ee82b9860058a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -129,6 +129,8 @@ pub struct PathSegment { /// The identifier portion of this path segment. pub ident: Ident, + pub id: NodeId, + /// Type/lifetime parameters attached to this path. They come in /// two flavors: `Path` and `Path(A,B) -> C`. /// `None` means that no parameter list is supplied (`Path`), @@ -140,7 +142,7 @@ pub struct PathSegment { impl PathSegment { pub fn from_ident(ident: Ident) -> Self { - PathSegment { ident, args: None } + PathSegment { ident, id: DUMMY_NODE_ID, args: None } } pub fn crate_root(span: Span) -> Self { PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span)) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 6210003a40da4..7928ec1606b1d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -329,7 +329,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } else { None }; - segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), args }); + segments.push(ast::PathSegment { + ident: last_ident.with_span_pos(span), + id: ast::DUMMY_NODE_ID, + args, + }); let mut path = ast::Path { span, segments }; if global { if let Some(seg) = path.make_root() { @@ -366,7 +370,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } else { None }; - path.segments.push(ast::PathSegment { ident, args }); + path.segments.push(ast::PathSegment { ident, id: ast::DUMMY_NODE_ID, args }); (ast::QSelf { ty: self_type, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2cd4fd92bc81e..55e9c3c298c5d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -501,9 +501,6 @@ declare_features! ( // Allows `const _: TYPE = VALUE` (active, underscore_const_names, "1.31.0", Some(54912), None), - - // `extern crate foo as bar;` puts `bar` into extern prelude. - (active, extern_crate_item_prelude, "1.31.0", Some(54658), None), ); declare_features! ( @@ -689,6 +686,8 @@ declare_features! ( // impl Iterator for &mut Iterator // impl Debug for Foo<'_> (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), + // `extern crate foo as bar;` puts `bar` into extern prelude. + (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1591,6 +1590,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + ast::ItemKind::Static(..) | ast::ItemKind::Const(_,_) => { if i.ident.name == "_" { gate_feature_post!(&self, underscore_const_names, i.span, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 18d5970462f63..bec193548e176 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -468,8 +468,9 @@ pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { pub fn noop_fold_path(Path { segments, span }: Path, fld: &mut T) -> Path { Path { - segments: segments.move_map(|PathSegment { ident, args }| PathSegment { + segments: segments.move_map(|PathSegment { ident, id, args }| PathSegment { ident: fld.fold_ident(ident), + id: fld.new_id(id), args: args.map(|args| args.map(|args| fld.fold_generic_args(args))), }), span: fld.new_span(span) @@ -1234,6 +1235,7 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::MethodCall( PathSegment { ident: folder.fold_ident(seg.ident), + id: folder.new_id(seg.id), args: seg.args.map(|args| { args.map(|args| folder.fold_generic_args(args)) }), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 964d7fcab2052..be448f960df3f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2134,7 +2134,7 @@ impl<'a> Parser<'a> { ParenthesisedArgs { inputs, output, span }.into() }; - PathSegment { ident, args } + PathSegment { ident, args, id: ast::DUMMY_NODE_ID } } else { // Generic arguments are not found. PathSegment::from_ident(ident) diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 8469f0aa6645d..85d1f3df05b1d 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -95,7 +95,7 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, TypeckTables")] +#[rustc_clean(cfg="cfail2", except="HirBody, MirValidated, TypeckTables")] #[rustc_clean(cfg="cfail3")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs index 23c00c3bce1d8..dd1c2bd51260b 100644 --- a/src/test/mir-opt/end_region_1.rs +++ b/src/test/mir-opt/end_region_1.rs @@ -22,7 +22,7 @@ fn main() { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _2: &'10_1rs i32; +// let _2: &'11_1rs i32; // ... // let _1: i32; // ... @@ -31,10 +31,10 @@ fn main() { // _1 = const 3i32; // FakeRead(ForLet, _1); // StorageLive(_2); -// _2 = &'10_1rs _1; +// _2 = &'11_1rs _1; // FakeRead(ForLet, _2); // _0 = (); -// EndRegion('10_1rs); +// EndRegion('11_1rs); // StorageDead(_2); // StorageDead(_1); // return; diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs index 08de5320a2b32..6b0a28b811007 100644 --- a/src/test/mir-opt/end_region_2.rs +++ b/src/test/mir-opt/end_region_2.rs @@ -27,9 +27,9 @@ fn main() { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _7: &'23_3rs bool; +// let _7: &'26_3rs bool; // ... -// let _3: &'23_1rs bool; +// let _3: &'26_1rs bool; // ... // let _2: bool; // ... @@ -47,7 +47,7 @@ fn main() { // _2 = const true; // FakeRead(ForLet, _2); // StorageLive(_3); -// _3 = &'23_1rs _2; +// _3 = &'26_1rs _2; // FakeRead(ForLet, _3); // StorageLive(_5); // _5 = _2; @@ -59,7 +59,7 @@ fn main() { // bb4: { // _0 = (); // StorageDead(_5); -// EndRegion('23_1rs); +// EndRegion('26_1rs); // StorageDead(_3); // StorageDead(_2); // return; @@ -68,12 +68,12 @@ fn main() { // _4 = (); // StorageDead(_5); // StorageLive(_7); -// _7 = &'23_3rs _2; +// _7 = &'26_3rs _2; // FakeRead(ForLet, _7); // _1 = (); -// EndRegion('23_3rs); +// EndRegion('26_3rs); // StorageDead(_7); -// EndRegion('23_1rs); +// EndRegion('26_1rs); // StorageDead(_3); // StorageDead(_2); // goto -> bb1; diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs index 189154332b85a..d8d48358e53fc 100644 --- a/src/test/mir-opt/end_region_3.rs +++ b/src/test/mir-opt/end_region_3.rs @@ -28,9 +28,9 @@ fn main() { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _7: &'26_3rs bool; +// let _7: &'30_3rs bool; // ... -// let _3: &'26_1rs bool; +// let _3: &'30_1rs bool; // ... // let mut _1: bool; // ... @@ -48,7 +48,7 @@ fn main() { // bb2: { // _1 = const true; // StorageLive(_3); -// _3 = &'26_1rs _1; +// _3 = &'30_1rs _1; // FakeRead(ForLet, _3); // StorageLive(_5); // _5 = _1; @@ -60,7 +60,7 @@ fn main() { // bb4: { // _0 = (); // StorageDead(_5); -// EndRegion('26_1rs); +// EndRegion('30_1rs); // StorageDead(_3); // StorageDead(_1); // return; @@ -69,12 +69,12 @@ fn main() { // _4 = (); // StorageDead(_5); // StorageLive(_7); -// _7 = &'26_3rs _1; +// _7 = &'30_3rs _1; // FakeRead(ForLet, _7); // _2 = (); -// EndRegion('26_3rs); +// EndRegion('30_3rs); // StorageDead(_7); -// EndRegion('26_1rs); +// EndRegion('30_1rs); // StorageDead(_3); // goto -> bb1; // } diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index d5701669d2bdd..359ed07a9c095 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -32,9 +32,9 @@ fn foo(i: i32) { // START rustc.main.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // ... -// let _6: &'26_4rs i32; +// let _6: &'31_4rs i32; // ... -// let _3: &'26_2rs i32; +// let _3: &'31_2rs i32; // ... // let _2: i32; // ... @@ -50,7 +50,7 @@ fn foo(i: i32) { // _2 = const 0i32; // FakeRead(ForLet, _2); // StorageLive(_3); -// _3 = &'26_2rs _2; +// _3 = &'31_2rs _2; // FakeRead(ForLet, _3); // StorageLive(_5); // _5 = (*_3); @@ -62,18 +62,18 @@ fn foo(i: i32) { // bb2: { // StorageDead(_5); // StorageLive(_6); -// _6 = &'26_4rs _2; +// _6 = &'31_4rs _2; // FakeRead(ForLet, _6); // _0 = (); -// EndRegion('26_4rs); +// EndRegion('31_4rs); // StorageDead(_6); -// EndRegion('26_2rs); +// EndRegion('31_2rs); // StorageDead(_3); // StorageDead(_2); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('26_2rs); +// EndRegion('31_2rs); // drop(_1) -> bb1; // } // bb4: { diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index 7a5d71ee21b93..3b632e198cd66 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -33,16 +33,16 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _1: D; // ... // let mut _2: (); -// let mut _3: [closure@NodeId(18) d:&'14s D]; -// let mut _4: &'14s D; +// let mut _3: [closure@NodeId(28) d:&'18s D]; +// let mut _4: &'18s D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); -// _4 = &'14s _1; -// _3 = [closure@NodeId(18)] { d: move _4 }; +// _4 = &'18s _1; +// _3 = [closure@NodeId(28)] { d: move _4 }; // StorageDead(_4); // _2 = const foo(move _3) -> [return: bb2, unwind: bb3]; // } @@ -50,13 +50,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb2: { -// EndRegion('14s); +// EndRegion('18s); // StorageDead(_3); // _0 = (); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('14s); +// EndRegion('18s); // drop(_1) -> bb1; // } // bb4: { @@ -67,11 +67,11 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'14s D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(28) d:&'18s D]) -> i32 { // let mut _0: i32; // // bb0: { -// _0 = ((*(_1.0: &'14s D)).0: i32); +// _0 = ((*(_1.0: &'18s D)).0: i32); // return; // } // END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index b9162f85fa71e..03c7de02ec111 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -33,16 +33,16 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _1: D; // ... // let mut _2: (); -// let mut _3: [closure@NodeId(22) d:&'19s D]; -// let mut _4: &'19s D; +// let mut _3: [closure@NodeId(33) d:&'24s D]; +// let mut _4: &'24s D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); -// _4 = &'19s _1; -// _3 = [closure@NodeId(22)] { d: move _4 }; +// _4 = &'24s _1; +// _3 = [closure@NodeId(33)] { d: move _4 }; // StorageDead(_4); // _2 = const foo(move _3) -> [return: bb2, unwind: bb3]; // } @@ -50,13 +50,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb2: { -// EndRegion('19s); +// EndRegion('24s); // StorageDead(_3); // _0 = (); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('19s); +// EndRegion('24s); // drop(_1) -> bb1; // } // bb4: { @@ -66,17 +66,17 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(33) d:&'24s D]) -> i32 { // let mut _0: i32; // ... -// let _2: &'16_0rs D; +// let _2: &'21_0rs D; // ... // bb0: { // StorageLive(_2); -// _2 = &'16_0rs (*(_1.0: &'19s D)); +// _2 = &'21_0rs (*(_1.0: &'24s D)); // FakeRead(ForLet, _2); // _0 = ((*_2).0: i32); -// EndRegion('16_0rs); +// EndRegion('21_0rs); // StorageDead(_2); // return; // } diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 4deea75e56b04..56e3e0aa6f7a9 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -33,13 +33,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let _1: D; // ... // let mut _2: (); -// let mut _3: [closure@NodeId(22) d:D]; +// let mut _3: [closure@NodeId(33) d:D]; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_3); -// _3 = [closure@NodeId(22)] { d: move _1 }; +// _3 = [closure@NodeId(33)] { d: move _1 }; // _2 = const foo(move _3) -> [return: bb2, unwind: bb4]; // } // bb1: { @@ -67,17 +67,17 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(33) d:D]) -> i32 { // let mut _0: i32; // ... -// let _2: &'16_0rs D; +// let _2: &'21_0rs D; // ... // bb0: { // StorageLive(_2); -// _2 = &'16_0rs (_1.0: D); +// _2 = &'21_0rs (_1.0: D); // FakeRead(ForLet, _2); // _0 = ((*_2).0: i32); -// EndRegion('16_0rs); +// EndRegion('21_0rs); // StorageDead(_2); // drop(_1) -> [return: bb2, unwind: bb1]; // } diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index 6f899a0db15d9..0a54dcaa0d33f 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -31,37 +31,37 @@ fn foo(f: F) where F: FnOnce() -> i32 { // fn main() -> () { // let mut _0: (); // ... -// let _2: &'21_1rs D; +// let _2: &'26_1rs D; // ... // let _1: D; // ... // let mut _3: (); -// let mut _4: [closure@NodeId(22) r:&'19s D]; +// let mut _4: [closure@NodeId(33) r:&'24s D]; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // FakeRead(ForLet, _1); // StorageLive(_2); -// _2 = &'21_1rs _1; +// _2 = &'26_1rs _1; // FakeRead(ForLet, _2); // StorageLive(_4); -// _4 = [closure@NodeId(22)] { r: _2 }; +// _4 = [closure@NodeId(33)] { r: _2 }; // _3 = const foo(move _4) -> [return: bb2, unwind: bb3]; // } // bb1: { // resume; // } // bb2: { -// EndRegion('19s); +// EndRegion('24s); // StorageDead(_4); // _0 = (); -// EndRegion('21_1rs); +// EndRegion('26_1rs); // StorageDead(_2); // drop(_1) -> [return: bb4, unwind: bb1]; // } // bb3: { -// EndRegion('19s); -// EndRegion('21_1rs); +// EndRegion('24s); +// EndRegion('26_1rs); // drop(_1) -> bb1; // } // bb4: { @@ -72,11 +72,11 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.main.SimplifyCfg-qualify-consts.after.mir // START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'19s D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(33) r:&'24s D]) -> i32 { // let mut _0: i32; // // bb0: { -// _0 = ((*(_1.0: &'21_1rs D)).0: i32); +// _0 = ((*(_1.0: &'26_1rs D)).0: i32); // return; // } // } diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs index b43f25e6f548c..ef2d949d3074e 100644 --- a/src/test/mir-opt/end_region_9.rs +++ b/src/test/mir-opt/end_region_9.rs @@ -41,7 +41,7 @@ fn main() { // fn main() -> () { // let mut _0: (); // ... -// let mut _4: &'33_0rs i32; +// let mut _4: &'37_0rs i32; // ... // let _2: i32; // ... @@ -79,14 +79,14 @@ fn main() { // bb5: { // _0 = (); // StorageDead(_7); -// EndRegion('33_0rs); +// EndRegion('37_0rs); // StorageDead(_4); // StorageDead(_2); // StorageDead(_1); // return; // } // bb6: { -// _4 = &'33_0rs _2; +// _4 = &'37_0rs _2; // _6 = (); // StorageDead(_7); // _1 = const true; diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs index 75cfb5c2f6239..3dbc73caf65d8 100644 --- a/src/test/mir-opt/end_region_cyclic.rs +++ b/src/test/mir-opt/end_region_cyclic.rs @@ -45,24 +45,24 @@ fn query() -> bool { true } // scope 1 { // } // scope 2 { -// let _2: S<'36_0rs>; +// let _2: S<'49_0rs>; // } // let mut _1: (); -// let mut _3: std::cell::Cell>>; -// let mut _4: std::option::Option<&'36_0rs S<'36_0rs>>; +// let mut _3: std::cell::Cell>>; +// let mut _4: std::option::Option<&'49_0rs S<'49_0rs>>; // let mut _5: (); -// let mut _6: &'17s std::cell::Cell>>; -// let mut _7: std::option::Option<&'36_0rs S<'36_0rs>>; -// let mut _8: &'36_0rs S<'36_0rs>; -// let mut _9: &'36_0rs S<'36_0rs>; +// let mut _6: &'25s std::cell::Cell>>; +// let mut _7: std::option::Option<&'49_0rs S<'49_0rs>>; +// let mut _8: &'49_0rs S<'49_0rs>; +// let mut _9: &'49_0rs S<'49_0rs>; // let mut _10: (); // let mut _11: bool; // let mut _12: !; // let mut _13: (); -// let mut _14: &'34s std::cell::Cell>>; -// let mut _15: std::option::Option<&'36_0rs S<'36_0rs>>; -// let mut _16: &'36_0rs S<'36_0rs>; -// let mut _17: &'36_0rs S<'36_0rs>; +// let mut _14: &'47s std::cell::Cell>>; +// let mut _15: std::option::Option<&'49_0rs S<'49_0rs>>; +// let mut _16: &'49_0rs S<'49_0rs>; +// let mut _17: &'49_0rs S<'49_0rs>; // bb0: { // goto -> bb1; // } @@ -73,7 +73,7 @@ fn query() -> bool { true } // StorageLive(_2); // StorageLive(_3); // StorageLive(_4); -// _4 = std::option::Option<&'36_0rs S<'36_0rs>>::None; +// _4 = std::option::Option<&'49_0rs S<'49_0rs>>::None; // _3 = const >::new(move _4) -> [return: bb4, unwind: bb3]; // } // bb3: { @@ -81,22 +81,22 @@ fn query() -> bool { true } // } // bb4: { // StorageDead(_4); -// _2 = S<'36_0rs> { r: move _3 }; +// _2 = S<'49_0rs> { r: move _3 }; // StorageDead(_3); // FakeRead(ForLet, _2); // StorageLive(_6); -// _6 = &'17s (_2.0: std::cell::Cell>>); +// _6 = &'25s (_2.0: std::cell::Cell>>); // StorageLive(_7); // StorageLive(_8); // StorageLive(_9); -// _9 = &'36_0rs _2; -// _8 = &'36_0rs (*_9); -// _7 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _8,); +// _9 = &'49_0rs _2; +// _8 = &'49_0rs (*_9); +// _7 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _8,); // StorageDead(_8); // _5 = const >::set(move _6, move _7) -> [return: bb5, unwind: bb3]; // } // bb5: { -// EndRegion('17s); +// EndRegion('25s); // StorageDead(_7); // StorageDead(_6); // StorageDead(_9); @@ -109,7 +109,7 @@ fn query() -> bool { true } // bb7: { // _0 = (); // StorageDead(_11); -// EndRegion('36_0rs); +// EndRegion('49_0rs); // StorageDead(_2); // return; // } @@ -117,23 +117,23 @@ fn query() -> bool { true } // _10 = (); // StorageDead(_11); // StorageLive(_14); -// _14 = &'34s (_2.0: std::cell::Cell>>); +// _14 = &'47s (_2.0: std::cell::Cell>>); // StorageLive(_15); // StorageLive(_16); // StorageLive(_17); -// _17 = &'36_0rs _2; -// _16 = &'36_0rs (*_17); -// _15 = std::option::Option<&'36_0rs S<'36_0rs>>::Some(move _16,); +// _17 = &'49_0rs _2; +// _16 = &'49_0rs (*_17); +// _15 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _16,); // StorageDead(_16); // _13 = const >::set(move _14, move _15) -> [return: bb9, unwind: bb3]; // } // bb9: { -// EndRegion('34s); +// EndRegion('47s); // StorageDead(_15); // StorageDead(_14); // StorageDead(_17); // _1 = (); -// EndRegion('36_0rs); +// EndRegion('49_0rs); // StorageDead(_2); // goto -> bb1; // } diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs index 16e2fe046fb69..a5107d304386f 100644 --- a/src/test/mir-opt/end_region_destruction_extents_1.rs +++ b/src/test/mir-opt/end_region_destruction_extents_1.rs @@ -41,16 +41,16 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // Notes on the MIR output below: // -// 1. The `EndRegion('10s)` is allowed to precede the `drop(_3)` +// 1. The `EndRegion('13s)` is allowed to precede the `drop(_3)` // solely because of the #[may_dangle] mentioned above. // -// 2. Regarding the occurrence of `EndRegion('12ds)` *after* `StorageDead(_6)` -// (where we have borrows `&'12ds _6`): Eventually: +// 2. Regarding the occurrence of `EndRegion('15ds)` *after* `StorageDead(_6)` +// (where we have borrows `&'15ds _6`): Eventually: // // i. this code should be rejected (by mir-borrowck), or // // ii. the MIR code generation should be changed so that the -// EndRegion('12ds)` precedes `StorageDead(_6)` in the +// EndRegion('15ds)` precedes `StorageDead(_6)` in the // control-flow. (Note: arielb1 views drop+storagedead as one // unit, and does not see this option as a useful avenue to // explore.), or @@ -66,13 +66,13 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // START rustc.main.QualifyAndPromoteConstants.before.mir // fn main() -> () { // let mut _0: (); -// let mut _1: &'12ds S1; -// let mut _2: D1<'12ds, '10s>; -// let mut _3: &'12ds S1; -// let mut _4: &'12ds S1; +// let mut _1: &'15ds S1; +// let mut _2: D1<'15ds, '13s>; +// let mut _3: &'15ds S1; +// let mut _4: &'15ds S1; // let _5: S1; -// let mut _6: &'10s S1; -// let mut _7: &'10s S1; +// let mut _6: &'13s S1; +// let mut _7: &'13s S1; // let _8: S1; // bb0: { // StorageLive(_2); @@ -80,19 +80,19 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageLive(_4); // StorageLive(_5); // _5 = S1::{{constructor}}(const "ex1",); -// _4 = &'12ds _5; -// _3 = &'12ds (*_4); +// _4 = &'15ds _5; +// _3 = &'15ds (*_4); // StorageLive(_6); // StorageLive(_7); // StorageLive(_8); // _8 = S1::{{constructor}}(const "dang1",); -// _7 = &'10s _8; -// _6 = &'10s (*_7); -// _2 = D1<'12ds, '10s>::{{constructor}}(move _3, move _6); -// EndRegion('10s); +// _7 = &'13s _8; +// _6 = &'13s (*_7); +// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6); +// EndRegion('13s); // StorageDead(_6); // StorageDead(_3); -// _1 = (_2.0: &'12ds S1); +// _1 = (_2.0: &'15ds S1); // drop(_2) -> [return: bb2, unwind: bb1]; // } // bb1: { @@ -104,7 +104,7 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageDead(_8); // StorageDead(_4); // StorageDead(_5); -// EndRegion('12ds); +// EndRegion('15ds); // _0 = (); // return; // } @@ -114,29 +114,29 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // START rustc.main.QualifyAndPromoteConstants.after.mir // fn main() -> (){ // let mut _0: (); -// let mut _1: &'12ds S1; -// let mut _2: D1<'12ds, '10s>; -// let mut _3: &'12ds S1; -// let mut _4: &'12ds S1; +// let mut _1: &'15ds S1; +// let mut _2: D1<'15ds, '13s>; +// let mut _3: &'15ds S1; +// let mut _4: &'15ds S1; // let _5: S1; -// let mut _6: &'10s S1; -// let mut _7: &'10s S1; +// let mut _6: &'13s S1; +// let mut _7: &'13s S1; // let _8: S1; // bb0: { // StorageLive(_2); // StorageLive(_3); // StorageLive(_4); -// _4 = &'12ds (promoted[1]: S1); -// _3 = &'12ds (*_4); +// _4 = &'15ds (promoted[1]: S1); +// _3 = &'15ds (*_4); // StorageLive(_6); // StorageLive(_7); -// _7 = &'10s (promoted[0]: S1); -// _6 = &'10s (*_7); -// _2 = D1<'12ds, '10s>::{{constructor}}(move _3, move _6); -// EndRegion('10s); +// _7 = &'13s (promoted[0]: S1); +// _6 = &'13s (*_7); +// _2 = D1<'15ds, '13s>::{{constructor}}(move _3, move _6); +// EndRegion('13s); // StorageDead(_6); // StorageDead(_3); -// _1 = (_2.0: &'12ds S1); +// _1 = (_2.0: &'15ds S1); // drop(_2) -> [return: bb2, unwind: bb1]; // } // bb1: { @@ -146,7 +146,7 @@ unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> { // StorageDead(_2); // StorageDead(_7); // StorageDead(_4); -// EndRegion('12ds); +// EndRegion('15ds); // _0 = (); // return; // } diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs index aab432ddc8700..ba1712f4ca398 100644 --- a/src/test/mir-opt/inline-closure-borrows-arg.rs +++ b/src/test/mir-opt/inline-closure-borrows-arg.rs @@ -30,7 +30,7 @@ fn foo(_t: T, q: &i32) -> i32 { // ... // bb0: { // ... -// _3 = [closure@NodeId(39)]; +// _3 = [closure@NodeId(53)]; // ... // _4 = &_3; // ... diff --git a/src/test/mir-opt/inline-closure.rs b/src/test/mir-opt/inline-closure.rs index 22e7de31e90cf..9cb0a4dc2bfac 100644 --- a/src/test/mir-opt/inline-closure.rs +++ b/src/test/mir-opt/inline-closure.rs @@ -26,7 +26,7 @@ fn foo(_t: T, q: i32) -> i32 { // ... // bb0: { // ... -// _3 = [closure@NodeId(28)]; +// _3 = [closure@NodeId(39)]; // ... // _4 = &_3; // ... diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index 882579c571086..f1544968adb6a 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -40,35 +40,35 @@ fn main() { // ... // bb0: { // ... -// Validate(Suspend(ReScope(Node(ItemLocalId(10)))), [_1: i32]); +// Validate(Suspend(ReScope(Node(ItemLocalId(13)))), [_1: i32]); // _6 = &ReErased mut _1; -// Validate(Acquire, [(*_6): i32/ReScope(Node(ItemLocalId(10)))]); -// Validate(Suspend(ReScope(Node(ItemLocalId(10)))), [(*_6): i32/ReScope(Node(ItemLocalId(10)))]); +// Validate(Acquire, [(*_6): i32/ReScope(Node(ItemLocalId(13)))]); +// Validate(Suspend(ReScope(Node(ItemLocalId(13)))), [(*_6): i32/ReScope(Node(ItemLocalId(13)))]); // _5 = &ReErased mut (*_6); -// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(10)))]); -// Validate(Release, [_2: (), _3: &ReScope(Node(ItemLocalId(10))) Test, _5: &ReScope(Node(ItemLocalId(10))) mut i32]); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(13)))]); +// Validate(Release, [_2: (), _3: &ReScope(Node(ItemLocalId(13))) Test, _5: &ReScope(Node(ItemLocalId(13))) mut i32]); // _2 = const Test::foo(move _3, move _5) -> bb1; // } // // bb1: { // Validate(Acquire, [_2: ()]); -// EndRegion(ReScope(Node(ItemLocalId(10)))); +// EndRegion(ReScope(Node(ItemLocalId(13)))); // ... // return; // } // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &ReErased [closure@NodeId(50)], _2: &ReErased mut i32) -> i32 { +// fn main::{{closure}}(_1: &ReErased [closure@NodeId(65)], _2: &ReErased mut i32) -> i32 { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(65)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); -// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]); +// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(31), first_statement_index: 0 })), [(*_2): i32]); // _3 = &ReErased (*_2); -// Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]); +// Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(31), first_statement_index: 0 }) (imm)]); // _0 = (*_3); -// EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })); +// EndRegion(ReScope(Remainder { block: ItemLocalId(31), first_statement_index: 0 })); // StorageDead(_3); // return; // } diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs index 07f5b2aa84b7d..ce840397713ad 100644 --- a/src/test/mir-opt/validate_3.rs +++ b/src/test/mir-opt/validate_3.rs @@ -48,27 +48,27 @@ fn main() { // StorageLive(_1); // _1 = Test { x: const 0i32 }; // StorageLive(_2); -// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]); +// Validate(Suspend(ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 })), [_1: Test]); // _2 = &ReErased _1; -// Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); +// Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 }) (imm)]); // StorageLive(_4); // StorageLive(_5); -// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); +// Validate(Suspend(ReScope(Node(ItemLocalId(22)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 }) (imm)]); // _5 = &ReErased ((*_2).0: i32); -// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]); -// Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [(*_5): i32/ReScope(Node(ItemLocalId(18))) (imm)]); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(22))) (imm)]); +// Validate(Suspend(ReScope(Node(ItemLocalId(22)))), [(*_5): i32/ReScope(Node(ItemLocalId(22))) (imm)]); // _4 = &ReErased (*_5); -// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(18))) (imm)]); -// Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(18))) i32]); +// Validate(Acquire, [(*_4): i32/ReScope(Node(ItemLocalId(22))) (imm)]); +// Validate(Release, [_3: (), _4: &ReScope(Node(ItemLocalId(22))) i32]); // _3 = const foo(move _4) -> bb1; // } // bb1: { // Validate(Acquire, [_3: ()]); -// EndRegion(ReScope(Node(ItemLocalId(18)))); +// EndRegion(ReScope(Node(ItemLocalId(22)))); // StorageDead(_4); // StorageDead(_5); // _0 = (); -// EndRegion(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })); +// EndRegion(ReScope(Remainder { block: ItemLocalId(24), first_statement_index: 3 })); // StorageDead(_2); // StorageDead(_1); // return; diff --git a/src/test/mir-opt/validate_4.rs b/src/test/mir-opt/validate_4.rs index 24a4ebd8429df..542ac8a42411f 100644 --- a/src/test/mir-opt/validate_4.rs +++ b/src/test/mir-opt/validate_4.rs @@ -48,11 +48,11 @@ fn main() { // } // END rustc.write_42.EraseRegions.after.mir // START rustc.write_42-{{closure}}.EraseRegions.after.mir -// fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(22)], _2: *mut i32) -> () { +// fn write_42::{{closure}}(_1: &ReErased [closure@NodeId(32)], _2: *mut i32) -> () { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(22)], _2: *mut i32]); -// Validate(Release, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(22)], _2: *mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(32)], _2: *mut i32]); +// Validate(Release, [_1: &ReFree(DefId(0/1:9 ~ validate_4[317d]::write_42[0]::{{closure}}[0]), BrEnv) [closure@NodeId(32)], _2: *mut i32]); // (*_2) = const 23i32; // _0 = (); // return; @@ -76,11 +76,11 @@ fn main() { // } // END rustc.test.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &ReErased [closure@NodeId(60)], _2: &ReErased mut i32) -> bool { +// fn main::{{closure}}(_1: &ReErased [closure@NodeId(80)], _2: &ReErased mut i32) -> bool { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); -// Validate(Release, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(60)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(80)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Release, [_1: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(80)], _2: &ReFree(DefId(0/1:10 ~ validate_4[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); // ... // _0 = const write_42(move _3) -> bb1; diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index b4d4479bab94a..955de0c3bad04 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -46,19 +46,19 @@ fn main() { // } // END rustc.test.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &ReErased [closure@NodeId(46)], _2: &ReErased mut i32) -> bool { +// fn main::{{closure}}(_1: &ReErased [closure@NodeId(62)], _2: &ReErased mut i32) -> bool { // ... // bb0: { -// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(46)], _2: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); +// Validate(Acquire, [_1: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(62)], _2: &ReFree(DefId(0/1:9 ~ validate_5[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]); // StorageLive(_3); // StorageLive(_4); // StorageLive(_5); -// Validate(Suspend(ReScope(Node(ItemLocalId(12)))), [(*_2): i32]); +// Validate(Suspend(ReScope(Node(ItemLocalId(16)))), [(*_2): i32]); // _5 = &ReErased mut (*_2); -// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(12)))]); +// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(16)))]); // _4 = move _5 as *mut i32 (Misc); // _3 = move _4; -// EndRegion(ReScope(Node(ItemLocalId(12)))); +// EndRegion(ReScope(Node(ItemLocalId(16)))); // StorageDead(_4); // StorageDead(_5); // Validate(Release, [_0: bool, _3: *mut i32]); diff --git a/src/test/run-pass/issue-55376.rs b/src/test/run-pass/issue-55376.rs new file mode 100644 index 0000000000000..9c7256fd26fed --- /dev/null +++ b/src/test/run-pass/issue-55376.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that paths in `pub(...)` don't fail HIR verification. + +#![allow(unused_imports)] +#![allow(dead_code)] + +pub(self) use self::my_mod::Foo; + +mod my_mod { + pub(super) use self::Foo as Bar; + pub(in super::my_mod) use self::Foo as Baz; + + pub struct Foo; +} + +fn main() {} diff --git a/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs b/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs new file mode 100644 index 0000000000000..55202de1981be --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub mod asdf { + pub struct SomeStruct; +} + +pub trait SomeTrait {} diff --git a/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs b/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs new file mode 100644 index 0000000000000..1f11cbc4da718 --- /dev/null +++ b/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs @@ -0,0 +1,11 @@ +// 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. + +pub struct SomethingElse; diff --git a/src/test/rustdoc/inline_cross/use_crate.rs b/src/test/rustdoc/inline_cross/use_crate.rs new file mode 100644 index 0000000000000..a98704446ee76 --- /dev/null +++ b/src/test/rustdoc/inline_cross/use_crate.rs @@ -0,0 +1,37 @@ +// 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. + +// aux-build:use_crate.rs +// aux-build:use_crate_2.rs +// build-aux-docs +// edition:2018 +// compile-flags:--extern use_crate --extern use_crate_2 -Z unstable-options + +// During the buildup to Rust 2018, rustdoc would eagerly inline `pub use some_crate;` as if it +// were a module, so we changed it to make `pub use`ing crate roots remain as a `pub use` statement +// in docs... unless you added `#[doc(inline)]`. + +#![crate_name = "local"] + +// @!has-dir local/use_crate +// @has local/index.html +// @has - '//code' 'pub use use_crate' +pub use use_crate; + +// @has-dir local/asdf +// @has local/asdf/index.html +// @has local/index.html '//a/@href' 'asdf/index.html' +pub use use_crate::asdf; + +// @has-dir local/use_crate_2 +// @has local/use_crate_2/index.html +// @has local/index.html '//a/@href' 'use_crate_2/index.html' +#[doc(inline)] +pub use use_crate_2; diff --git a/src/test/rustdoc/issue-55001.rs b/src/test/rustdoc/issue-55001.rs new file mode 100644 index 0000000000000..f6c7f9a3d082c --- /dev/null +++ b/src/test/rustdoc/issue-55001.rs @@ -0,0 +1,31 @@ +// Regression test for issue #55001. Previously, we would incorrectly +// cache certain trait selection results when checking for blanket impls, +// resulting in an ICE when we tried to confirm the cached ParamCandidate +// against an obligation. + +pub struct DefaultAllocator; +pub struct Standard; +pub struct Inner; + +pub trait Rand {} + +pub trait Distribution {} +pub trait Allocator {} + +impl Rand for T where Standard: Distribution {} + +impl Distribution> for Standard +where +DefaultAllocator: Allocator, +Standard: Distribution {} + +impl Distribution for Standard {} + + +pub struct Point +where DefaultAllocator: Allocator +{ + field: N +} + +fn main() {} diff --git a/src/test/rustdoc/src-links-external.rs b/src/test/rustdoc/src-links-external.rs index d3307bb4d42c1..6cc7f1743ad07 100644 --- a/src/test/rustdoc/src-links-external.rs +++ b/src/test/rustdoc/src-links-external.rs @@ -18,6 +18,7 @@ extern crate src_links_external; // @has foo/bar/index.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11' +#[doc(inline)] pub use src_links_external as bar; // @has foo/bar/struct.Foo.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11' diff --git a/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs b/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs index e320ad9713542..25a2a37614778 100644 --- a/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs +++ b/src/test/ui-fulldeps/proc-macro/extern-prelude-extern-crate-proc-macro.rs @@ -1,8 +1,6 @@ // compile-pass // edition:2018 -#![feature(extern_crate_item_prelude)] - extern crate proc_macro; use proc_macro::TokenStream; // OK diff --git a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs deleted file mode 100644 index 27b9a34ff4eb7..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.rs +++ /dev/null @@ -1,46 +0,0 @@ -// edition:2018 - -#![feature(alloc, underscore_imports)] - -extern crate alloc; - -mod in_scope { - fn check() { - let v = alloc::vec![0]; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - type A = alloc::boxed::Box; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - } -} - -mod absolute { - fn check() { - let v = ::alloc::vec![0]; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - type A = ::alloc::boxed::Box; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - } -} - -mod import_in_scope { - use alloc as _; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - use alloc::boxed; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable -} - -mod import_absolute { - use ::alloc; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable - use ::alloc::boxed; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable -} - -extern crate alloc as core; - -mod unrelated_crate_renamed { - type A = core::boxed::Box; - //~^ ERROR use of extern prelude names introduced with `extern crate` items is unstable -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr b/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr deleted file mode 100644 index ac65dcb4d54fc..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-extern_crate_item_prelude.stderr +++ /dev/null @@ -1,75 +0,0 @@ -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:26:9 - | -LL | use alloc as _; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:28:9 - | -LL | use alloc::boxed; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:33:11 - | -LL | use ::alloc; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:35:11 - | -LL | use ::alloc::boxed; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:9:17 - | -LL | let v = alloc::vec![0]; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:11:18 - | -LL | type A = alloc::boxed::Box; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:18:19 - | -LL | let v = ::alloc::vec![0]; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:20:20 - | -LL | type A = ::alloc::boxed::Box; - | ^^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error[E0658]: use of extern prelude names introduced with `extern crate` items is unstable (see issue #54658) - --> $DIR/feature-gate-extern_crate_item_prelude.rs:42:14 - | -LL | type A = core::boxed::Box; - | ^^^^ - | - = help: add #![feature(extern_crate_item_prelude)] to the crate attributes to enable - -error: aborting due to 9 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs index b1154f2076b80..cf91a9714ade0 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-absolute-expanded.rs @@ -1,8 +1,6 @@ // compile-pass // edition:2018 -#![feature(extern_crate_item_prelude)] - macro_rules! define_iso { () => { extern crate std as iso; }} diff --git a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs index c48a65798b6c1..6117e5f6f3cd7 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-cfg.rs @@ -1,7 +1,6 @@ // compile-pass // compile-flags:--cfg my_feature -#![feature(extern_crate_item_prelude)] #![no_std] #[cfg(my_feature)] diff --git a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs index 8c147dfd04a3c..bb4cf6ca99c75 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-pass.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-pass.rs @@ -1,8 +1,6 @@ // compile-pass // aux-build:two_macros.rs -#![feature(extern_crate_item_prelude)] - extern crate two_macros; mod m { diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs index 732f1c4de2fb3..6ff3ab73639c0 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.rs @@ -1,7 +1,5 @@ // aux-build:two_macros.rs -#![feature(extern_crate_item_prelude)] - macro_rules! define_vec { () => { extern crate std as Vec; @@ -16,4 +14,13 @@ mod m { } } +macro_rules! define_other_core { + () => { + extern crate std as core; + //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern` + } +} + +define_other_core!(); + fn main() {} diff --git a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr index 218dfb796f77a..795e1761ccdb3 100644 --- a/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr +++ b/src/test/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr @@ -1,12 +1,21 @@ +error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:19:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | --------------------- in this macro invocation + error[E0659]: `Vec` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:15:9 + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:13:9 | LL | Vec::panic!(); //~ ERROR `Vec` is ambiguous | ^^^ ambiguous name | = note: `Vec` could refer to a struct from prelude note: `Vec` could also refer to the extern crate imported here - --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:7:9 + --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:5:9 | LL | extern crate std as Vec; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,6 +23,6 @@ LL | extern crate std as Vec; LL | define_vec!(); | -------------- in this macro invocation -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs new file mode 100644 index 0000000000000..c5adeaf17fa92 --- /dev/null +++ b/src/test/ui/imports/extern-prelude-extern-crate-shadowing.rs @@ -0,0 +1,12 @@ +// compile-pass +// aux-build:two_macros.rs + +extern crate two_macros as core; + +mod m { + fn check() { + core::m!(); // OK + } +} + +fn main() {} diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed index d16859df79e25..f0aee8a51f18b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.fixed +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.fixed @@ -20,4 +20,10 @@ fn main() { //~^ WARN `...` range patterns are deprecated _ => {} } + + match &despondency { + &(1..=2) => {} + //~^ WARN `...` range patterns are deprecated + _ => {} + } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.rs b/src/test/ui/lint/inclusive-range-pattern-syntax.rs index 9d418aec0858f..97bc04faa774b 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.rs +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.rs @@ -20,4 +20,10 @@ fn main() { //~^ WARN `...` range patterns are deprecated _ => {} } + + match &despondency { + &1...2 => {} + //~^ WARN `...` range patterns are deprecated + _ => {} + } } diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr index de04fed589b23..b13afdbc023d4 100644 --- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr +++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr @@ -10,3 +10,9 @@ note: lint level defined here LL | #![warn(ellipsis_inclusive_range_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: `...` range patterns are deprecated + --> $DIR/inclusive-range-pattern-syntax.rs:25:9 + | +LL | &1...2 => {} + | ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)` + diff --git a/src/test/ui/nll/issue-55288.rs b/src/test/ui/nll/issue-55288.rs new file mode 100644 index 0000000000000..c0f10ee607cf2 --- /dev/null +++ b/src/test/ui/nll/issue-55288.rs @@ -0,0 +1,21 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +// run-pass + +struct Slice(&'static [&'static [u8]]); + +static MAP: Slice = Slice(&[ + b"CloseEvent" as &'static [u8], +]); + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/issue-55756.rs b/src/test/ui/nll/ty-outlives/issue-55756.rs new file mode 100644 index 0000000000000..cda3915849e2d --- /dev/null +++ b/src/test/ui/nll/ty-outlives/issue-55756.rs @@ -0,0 +1,37 @@ +// Regression test for #55756. +// +// In this test, the result of `self.callee` is a projection `>::Guard`. As it may contain a destructor, the dropck +// rules require that this type outlivess the scope of `state`. Unfortunately, +// our region inference is not smart enough to figure out how to +// translate a requirement like +// +// >::guard: 'r +// +// into a requirement that `'0: 'r` -- in particular, it fails to do +// so because it *also* knows that `>::Guard: 'a` +// from the trait definition. Faced with so many choices, the current +// solver opts to do nothing. +// +// Fixed by tweaking the solver to recognize that the constraint from +// the environment duplicates one from the trait. +// +// compile-pass + +#![crate_type="lib"] + +pub trait Database<'a> { + type Guard: 'a; +} + +pub struct Stateful<'a, D: 'a>(&'a D); + +impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> { + pub fn callee<'a>(&'a self) -> >::Guard { + unimplemented!() + } + pub fn caller<'a>(&'a self) -> >::Guard { + let state = self.callee(); + unimplemented!() + } +} diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr index cd5ce3035c683..6fa67a5d4fa30 100644 --- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr +++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr @@ -11,10 +11,10 @@ LL | box 10..=15 => {} | ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)` warning: `...` range patterns are deprecated - --> $DIR/range-inclusive-pattern-precedence.rs:24:11 + --> $DIR/range-inclusive-pattern-precedence.rs:24:9 | LL | &0...9 => {} - | ^^^ help: use `..=` for an inclusive range + | ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)` | note: lint level defined here --> $DIR/range-inclusive-pattern-precedence.rs:19:9 diff --git a/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs new file mode 100644 index 0000000000000..438923e29246c --- /dev/null +++ b/src/test/ui/rfc-2093-infer-outlives/issue-54467.rs @@ -0,0 +1,17 @@ +// Regression test for #54467: +// +// Here, the trait object has an "inferred outlives" requirement that +// `>::Item: 'a`; but since we don't know what +// `Self` is, we were (incorrectly) messing things up, leading to +// strange errors. This test ensures that we do not give compilation +// errors. +// +// compile-pass + +trait MyIterator<'a>: Iterator where Self::Item: 'a { } + +struct MyStruct<'a, A> { + item: Box> +} + +fn main() { } diff --git a/src/test/ui/underscore_const_names_feature_gate.rs b/src/test/ui/underscore_const_names_feature_gate.rs new file mode 100644 index 0000000000000..b2174036dede0 --- /dev/null +++ b/src/test/ui/underscore_const_names_feature_gate.rs @@ -0,0 +1,14 @@ +// Copyright 2012-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. + +const _: () = (); //~ ERROR is unstable +static _: () = (); //~ ERROR is unstable + +fn main() {} diff --git a/src/test/ui/underscore_const_names_feature_gate.stderr b/src/test/ui/underscore_const_names_feature_gate.stderr new file mode 100644 index 0000000000000..c97b3f8d4d3cd --- /dev/null +++ b/src/test/ui/underscore_const_names_feature_gate.stderr @@ -0,0 +1,19 @@ +error[E0658]: naming constants with `_` is unstable (see issue #54912) + --> $DIR/underscore_const_names_feature_gate.rs:11:1 + | +LL | const _: () = (); //~ ERROR is unstable + | ^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(underscore_const_names)] to the crate attributes to enable + +error[E0658]: naming constants with `_` is unstable (see issue #54912) + --> $DIR/underscore_const_names_feature_gate.rs:12:1 + | +LL | static _: () = (); //~ ERROR is unstable + | ^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(underscore_const_names)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index f81964ccbc23c..0a39135ad8a76 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -360,6 +360,8 @@ impl Builder { self.package("lldb-preview", &mut manifest.pkg, TARGETS); manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() }); + manifest.renames.insert("rustfmt".to_owned(), Rename { to: "rustfmt-preview".to_owned() }); + manifest.renames.insert("clippy".to_owned(), Rename { to: "clippy-preview".to_owned() }); let mut pkg = Package { version: self.cached_version("rust") diff --git a/src/tools/clippy b/src/tools/clippy index b1d0343749bdc..246a77ebe8c9d 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit b1d0343749bdc87e5cbbe7f1aeaa9d2a2c9dbc5b +Subproject commit 246a77ebe8c9d640c76a82f3869c5272ba51346d diff --git a/src/tools/rls b/src/tools/rls index 1c755efed6ee2..daa138ce7f222 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 1c755efed6ee265c762f4d3fec73de8a989637a5 +Subproject commit daa138ce7f222559e9a339600b44a715101a3f4d diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 750b25261380b..1cc61cfc2b29a 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 750b25261380b776de2518fd6863fe63f98d2722 +Subproject commit 1cc61cfc2b29ae3f29a924b4c8feb1bcb09aa5fc