"clippy-mini-macro-test 0.2.0",
"clippy_dev 0.0.1",
"clippy_lints 0.0.212",
- "compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "compiletest_rs"
-version = "0.3.18"
+version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tester 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
"byteorder 1.2.7 (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.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"polonius-engine 0.6.2 (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)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_apfloat 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_errors 0.0.0",
"rustc_fs_util 0.0.0",
+ "rustc_macros 0.1.0",
"rustc_target 0.0.0",
"scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"rustc-ap-rustc_cratesio_shim 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-ap-serialize 373.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)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-rayon"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
+ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-rayon-core"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
+ "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (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)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_cratesio_shim 0.0.0",
"serialize 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"rustc_borrowck 0.0.0",
"rustc_codegen_utils 0.0.0",
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
- "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_allocator 0.0.0",
"rustc_borrowck 0.0.0",
"rustc_codegen_utils 0.0.0",
"core 0.0.0",
]
+[[package]]
+name = "rustc_macros"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "rustc_metadata"
version = "0.0.0"
name = "term"
version = "0.0.0"
+[[package]]
+name = "term"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "term"
version = "0.5.1"
"term 0.0.0",
]
+[[package]]
+name = "tester"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
[[package]]
name = "textwrap"
version = "0.10.0"
"checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
"checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
"checksum compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6711d51cb46744dd8305293cc3fbc392aaff7a8f5095a7c4fae1e5113ef07c96"
-"checksum compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0d76d4322a40f6b0db7259d4f2c8a65ed8b0d84fce0bbc61b98cf47f8ec6eec3"
+"checksum compiletest_rs 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "56c799b1f7142badf3b047b4c1f2074cc96b6b784fb2432f2ed9c87da0a03749"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887"
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
"checksum rustc-ap-syntax_pos 373.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4f88a1213562373cee9de5a1d77bbf16dd706030304af041c9733492fcc952"
"checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e"
"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"
-"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
+"checksum rustc-rayon 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d98c51d9cbbe810c8b6693236d3412d8cd60513ff27a3e1b6af483dca0af544"
+"checksum rustc-rayon-core 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "526e7b6d2707a5b9bec3927d424ad70fa3cfc68e0ac1b75e46cdbbc95adc5108"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c5a95edfa0c893236ae4778bb7c4752760e4c0d245e19b5eff33c5aa5eb9dc"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2"
"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
+"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
+"checksum tester 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e812cb26c597f86a49b26dbb58b878bd2a2b4b93fc069dc39499228fe556ff6"
"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
Language
--------
- [You can now use the `cfg(target_vendor)` attribute.][57465] E.g.
- `#[cfg(target_vendor="linux")] fn main() { println!("Hello Linux!"); }`
+ `#[cfg(target_vendor="apple")] fn main() { println!("Hello Apple!"); }`
- [Integer patterns such as in a match expression can now be exhaustive.][56362]
E.g. You can have match statement on a `u8` that covers `0..=255` and
- you would no longer be required to have a `_ => unreachable!()` case.
+ you would no longer be required to have a `_ => unreachable!()` case.
- [You can now have multiple patterns in `if let` and `while let`
expressions.][57532] You can do this with the same syntax as a `match`
expression. E.g.
// Allowed as there is only one `Read` in the module.
pub trait Read {}
```
-- [`extern` functions will now abort by default when panicking.][55982]
- This was previously undefined behaviour.
+- [You may now use `Rc`, `Arc`, and `Pin` as method receivers][56805].
Compiler
--------
are now deprecated in the standard library, and their usage will now produce a warning.
Please use the `str::{trim_start, trim_end, trim_start_matches, trim_end_matches}`
methods instead.
+- The `Error::cause` method has been deprecated in favor of `Error::source` which supports
+ downcasting.
-[57615]: https://github.com/rust-lang/rust/pull/57615/
-[57465]: https://github.com/rust-lang/rust/pull/57465/
-[57532]: https://github.com/rust-lang/rust/pull/57532/
-[57535]: https://github.com/rust-lang/rust/pull/57535/
-[57566]: https://github.com/rust-lang/rust/pull/57566/
+[55982]: https://github.com/rust-lang/rust/pull/55982/
+[56303]: https://github.com/rust-lang/rust/pull/56303/
+[56351]: https://github.com/rust-lang/rust/pull/56351/
+[56362]: https://github.com/rust-lang/rust/pull/56362
+[56642]: https://github.com/rust-lang/rust/pull/56642/
+[56769]: https://github.com/rust-lang/rust/pull/56769/
+[56805]: https://github.com/rust-lang/rust/pull/56805
+[56947]: https://github.com/rust-lang/rust/pull/56947/
+[57049]: https://github.com/rust-lang/rust/pull/57049/
+[57067]: https://github.com/rust-lang/rust/pull/57067/
+[57105]: https://github.com/rust-lang/rust/pull/57105
[57130]: https://github.com/rust-lang/rust/pull/57130/
[57167]: https://github.com/rust-lang/rust/pull/57167/
[57175]: https://github.com/rust-lang/rust/pull/57175/
[57234]: https://github.com/rust-lang/rust/pull/57234/
[57332]: https://github.com/rust-lang/rust/pull/57332/
-[56947]: https://github.com/rust-lang/rust/pull/56947/
-[57049]: https://github.com/rust-lang/rust/pull/57049/
-[57067]: https://github.com/rust-lang/rust/pull/57067/
-[56769]: https://github.com/rust-lang/rust/pull/56769/
-[56642]: https://github.com/rust-lang/rust/pull/56642/
-[56303]: https://github.com/rust-lang/rust/pull/56303/
-[56351]: https://github.com/rust-lang/rust/pull/56351/
-[55982]: https://github.com/rust-lang/rust/pull/55982/
-[56362]: https://github.com/rust-lang/rust/pull/56362
-[57105]: https://github.com/rust-lang/rust/pull/57105
+[57465]: https://github.com/rust-lang/rust/pull/57465/
+[57532]: https://github.com/rust-lang/rust/pull/57532/
+[57535]: https://github.com/rust-lang/rust/pull/57535/
+[57566]: https://github.com/rust-lang/rust/pull/57566/
+[57615]: https://github.com/rust-lang/rust/pull/57615/
[cargo/6484]: https://github.com/rust-lang/cargo/pull/6484/
[`unix::FileExt::read_exact_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.read_exact_at
[`unix::FileExt::write_all_at`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at
- [You can now match against literals in macros with the `literal`
specifier.][56072] This will match against a literal of any type.
E.g. `1`, `'A'`, `"Hello World"`
-- [Self can now be used as a constructor and pattern for unit and tuple structs.][56365] E.g.
+- [Self can now be used as a constructor and pattern for unit and tuple structs.][56365] E.g.
```rust
struct Point(i32, i32);
Language
--------
-- 🎉 [This version marks the release of the 2018 edition of Rust.][54057] 🎉
+- 🎉 [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
# server goes down presumably. See #43333 for more info
CARGO_HTTP_CHECK_REVOKE: false
- # Execute the builds on GCE instead of Hyper-V. Those builders have a 3-4
- # minute startup overhead, but AppVeyor support recommended this as a
- # possible solution for #58160 (spurious 259 exit codes)
- appveyor_build_worker_cloud: gce
-
matrix:
# 32/64 bit MSVC tests
- MSYS_BITS: 64
cmd.arg("-Zexternal-macro-backtrace");
+ // Link crates to the proc macro crate for the target, but use a host proc macro crate
+ // to actually run the macros
+ if env::var_os("RUST_DUAL_PROC_MACROS").is_some() {
+ cmd.arg("-Zdual-proc-macros");
+ }
+
// When we build Rust dylibs they're all intended for intermediate
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
// linking all deps statically into the dylib.
}
}
- // Force all crates compiled by this compiler to (a) be unstable and (b)
- // allow the `rustc_private` feature to link to other unstable crates
- // also in the sysroot.
- if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
- cmd.arg("-Z").arg("force-unstable-if-unmarked");
- }
-
if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
cmd.arg("--remap-path-prefix").arg(&map);
}
}
}
+ // Force all crates compiled by this compiler to (a) be unstable and (b)
+ // allow the `rustc_private` feature to link to other unstable crates
+ // also in the sysroot. We also do this for host crates, since those
+ // may be proc macros, in which case we might ship them.
+ if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
+ cmd.arg("-Z").arg("force-unstable-if-unmarked");
+ }
+
if env::var_os("RUSTC_PARALLEL_COMPILER").is_some() {
cmd.arg("--cfg").arg("parallel_compiler");
}
cputype = 'arm'
if ostype == 'linux-android':
ostype = 'linux-androideabi'
+ elif ostype == 'unknown-freebsd':
+ cputype = subprocess.check_output(
+ ['uname', '-p']).strip().decode(default_encoding)
+ ostype = 'unknown-freebsd'
elif cputype == 'armv6l':
cputype = 'arm'
if ostype == 'linux-android':
cargo.env("RUST_CHECK", "1");
}
+ match mode {
+ Mode::Std | Mode::Test | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTest=> {},
+ Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
+ // Build proc macros both for the host and the target
+ if target != compiler.host && cmd != "check" {
+ cargo.arg("-Zdual-proc-macros");
+ cargo.env("RUST_DUAL_PROC_MACROS", "1");
+ }
+ },
+ }
+
cargo.arg("-j").arg(self.jobs().to_string());
// Remove make-related flags to ensure Cargo can correctly set things up
cargo.env_remove("MAKEFLAGS");
use crate::config::Config;
// The version number
-pub const CFG_RELEASE_NUM: &str = "1.34.0";
+pub const CFG_RELEASE_NUM: &str = "1.35.0";
pub struct GitInfo {
inner: Option<Info>,
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(&builder, &libdir, &libstd_stamp(builder, compiler, target));
+ let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+ add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
}
}
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(&builder, &libdir, &librustc_stamp(builder, compiler, target));
+ let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+ add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
}
}
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(builder, &libdir, &libtest_stamp(builder, compiler, target));
+ let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+ add_to_sysroot(builder, &libdir, &hostdir, &libtest_stamp(builder, compiler, target));
}
}
true);
let libdir = builder.sysroot_libdir(compiler, target);
- add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target));
+ let hostdir = builder.sysroot_libdir(compiler, compiler.host);
+ add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target));
builder.cargo(compiler, Mode::ToolRustc, target, "clean");
}
}
target_compiler.host,
target));
let libdir = builder.sysroot_libdir(target_compiler, target);
- add_to_sysroot(builder, &libdir, &libstd_stamp(builder, compiler, target));
+ let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
+ add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
// The sanitizers are only built in stage1 or above, so the dylibs will
&compiler.host,
target_compiler.host,
target));
- add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
- &libtest_stamp(builder, compiler, target));
+ add_to_sysroot(
+ builder,
+ &builder.sysroot_libdir(target_compiler, target),
+ &builder.sysroot_libdir(target_compiler, compiler.host),
+ &libtest_stamp(builder, compiler, target)
+ );
builder.cargo(target_compiler, Mode::ToolTest, target, "clean");
}
return;
}
- // Ensure that build scripts have a std to link against.
- builder.ensure(Std {
+ // Ensure that build scripts and proc macros have a std / libproc_macro to link against.
+ builder.ensure(Test {
compiler: builder.compiler(self.compiler.stage, builder.config.build),
target: builder.config.build,
});
&compiler.host,
target_compiler.host,
target));
- add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
- &librustc_stamp(builder, compiler, target));
+ add_to_sysroot(
+ builder,
+ &builder.sysroot_libdir(target_compiler, target),
+ &builder.sysroot_libdir(target_compiler, compiler.host),
+ &librustc_stamp(builder, compiler, target)
+ );
builder.cargo(target_compiler, Mode::ToolRustc, target, "clean");
}
}
///
/// For a particular stage this will link the file listed in `stamp` into the
/// `sysroot_dst` provided.
-pub fn add_to_sysroot(builder: &Builder<'_>, sysroot_dst: &Path, stamp: &Path) {
+pub fn add_to_sysroot(
+ builder: &Builder<'_>,
+ sysroot_dst: &Path,
+ sysroot_host_dst: &Path,
+ stamp: &Path
+) {
t!(fs::create_dir_all(&sysroot_dst));
- for path in builder.read_stamp_file(stamp) {
- builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
+ t!(fs::create_dir_all(&sysroot_host_dst));
+ for (path, host) in builder.read_stamp_file(stamp) {
+ if host {
+ builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap()));
+ } else {
+ builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
+ }
}
}
let mut deps = Vec::new();
let mut toplevel = Vec::new();
let ok = stream_cargo(builder, cargo, &mut |msg| {
- let filenames = match msg {
- CargoMessage::CompilerArtifact { filenames, .. } => filenames,
+ let (filenames, crate_types) = match msg {
+ CargoMessage::CompilerArtifact {
+ filenames,
+ target: CargoTarget {
+ crate_types,
+ },
+ ..
+ } => (filenames, crate_types),
_ => return,
};
for filename in filenames {
let filename = Path::new(&*filename);
// If this was an output file in the "host dir" we don't actually
- // worry about it, it's not relevant for us.
+ // worry about it, it's not relevant for us
if filename.starts_with(&host_root_dir) {
+ // Unless it's a proc macro used in the compiler
+ if crate_types.iter().any(|t| t == "proc-macro") {
+ deps.push((filename.to_path_buf(), true));
+ }
continue;
}
// If this was output in the `deps` dir then this is a precise file
// name (hash included) so we start tracking it.
if filename.starts_with(&target_deps_dir) {
- deps.push(filename.to_path_buf());
+ deps.push((filename.to_path_buf(), false));
continue;
}
let candidate = format!("{}.lib", path_to_add);
let candidate = PathBuf::from(candidate);
if candidate.exists() {
- deps.push(candidate);
+ deps.push((candidate, false));
}
}
- deps.push(path_to_add.into());
+ deps.push((path_to_add.into(), false));
}
// Now we want to update the contents of the stamp file, if necessary. First
let mut new_contents = Vec::new();
let mut max = None;
let mut max_path = None;
- for dep in deps.iter() {
+ for (dep, proc_macro) in deps.iter() {
let mtime = mtime(dep);
if Some(mtime) > max {
max = Some(mtime);
max_path = Some(dep.clone());
}
+ new_contents.extend(if *proc_macro { b"h" } else { b"t" });
new_contents.extend(dep.to_str().unwrap().as_bytes());
new_contents.extend(b"\0");
}
if contents_equal && max <= stamp_mtime {
builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
stamp, max, stamp_mtime));
- return deps
+ return deps.into_iter().map(|(d, _)| d).collect()
}
if max > stamp_mtime {
builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
builder.verbose(&format!("updating {:?} as deps changed", stamp));
}
t!(fs::write(&stamp, &new_contents));
- deps
+ deps.into_iter().map(|(d, _)| d).collect()
}
pub fn stream_cargo(
status.success()
}
+#[derive(Deserialize)]
+pub struct CargoTarget<'a> {
+ crate_types: Vec<Cow<'a, str>>,
+}
+
#[derive(Deserialize)]
#[serde(tag = "reason", rename_all = "kebab-case")]
pub enum CargoMessage<'a> {
package_id: Cow<'a, str>,
features: Vec<Cow<'a, str>>,
filenames: Vec<Cow<'a, str>>,
+ target: CargoTarget<'a>,
},
BuildScriptExecuted {
package_id: Cow<'a, str>,
"src/stdsimd",
"src/libproc_macro",
"src/tools/rustc-std-workspace-core",
+ "src/librustc",
+ "src/libsyntax",
];
copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src);
// NOTE: When adding a book here, make sure to ALSO build the book by
// adding a build step in `src/bootstrap/builder.rs`!
book!(
- EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook1;
+ EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2;
EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2;
Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1;
Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1;
ret
}
- fn read_stamp_file(&self, stamp: &Path) -> Vec<PathBuf> {
+ fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> {
if self.config.dry_run {
return Vec::new();
}
if part.is_empty() {
continue
}
- let path = PathBuf::from(t!(str::from_utf8(part)));
- paths.push(path);
+ let host = part[0] as char == 'h';
+ let path = PathBuf::from(t!(str::from_utf8(&part[1..])));
+ paths.push((path, host));
}
paths
}
compile::CargoMessage::CompilerArtifact {
package_id,
features,
- filenames
+ filenames,
+ target: _,
} => {
(package_id, features, filenames)
}
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
-# Ubuntu 16.04 (this container) ships with make 4, but something in the
-# toolchains we build below chokes on that, so go back to make 3
-COPY scripts/make3.sh /scripts/
-RUN sh /scripts/make3.sh
-
-COPY scripts/crosstool-ng.sh /scripts/
-RUN sh /scripts/crosstool-ng.sh
-
-COPY scripts/rustbuild-setup.sh /scripts/
-RUN sh /scripts/rustbuild-setup.sh
-USER rustbuild
-WORKDIR /tmp
-
COPY dist-x86_64-netbsd/build-netbsd-toolchain.sh /tmp/
-RUN ./build-netbsd-toolchain.sh
-
-USER root
+RUN /tmp/build-netbsd-toolchain.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV HOSTS=x86_64-unknown-netbsd
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
- --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
# Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz
-curl $URL/2017-03-17-netbsd-src.tgz | tar xzf -
-curl $URL/2017-03-17-netbsd-gnusrc.tgz | tar xzf -
-curl $URL/2017-03-17-netbsd-sharesrc.tgz | tar xzf -
-curl $URL/2017-03-17-netbsd-syssrc.tgz | tar xzf -
+curl $URL/2018-03-01-netbsd-src.tgz | tar xzf -
+curl $URL/2018-03-01-netbsd-gnusrc.tgz | tar xzf -
+curl $URL/2018-03-01-netbsd-sharesrc.tgz | tar xzf -
+curl $URL/2018-03-01-netbsd-syssrc.tgz | tar xzf -
# Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/amd64/binary/sets/*.tgz
-curl $URL/2017-03-17-netbsd-base.tgz | \
+curl $URL/2018-03-01-netbsd-base.tgz | \
tar xzf - -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib ./lib
-curl $URL/2017-03-17-netbsd-comp.tgz | \
+curl $URL/2018-03-01-netbsd-comp.tgz | \
tar xzf - -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib
cd usr/src
-Subproject commit 419edb885ec1a98c0747b3907003d79e3e6b93a9
+Subproject commit 5f3cc2a5618700efcde3bc00799744f21fa9ad2e
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(stage0), allow_internal_unstable(box_syntax))]
-#[cfg_attr(stage0, allow_internal_unstable)]
+#[allow_internal_unstable(box_syntax)]
macro_rules! vec {
($elem:expr; $n:expr) => (
$crate::vec::from_elem($elem, $n)
/// This method uses a closure to create new values on every push. If
/// you'd rather [`Clone`] a given value, use [`resize`]. If you want
/// to use the [`Default`] trait to generate values, you can pass
- /// [`Default::default()`] as the second argument..
+ /// [`Default::default()`] as the second argument.
///
/// # Examples
///
bench_sums! {
bench_filter_sum,
bench_filter_ref_sum,
- (0i64..1000000).filter(|x| x % 2 == 0)
+ (0i64..1000000).filter(|x| x % 3 == 0)
}
bench_sums! {
bench_filter_chain_sum,
bench_filter_chain_ref_sum,
- (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
+ (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
}
bench_sums! {
assert_eq!(s, 2009900);
});
}
+
+#[bench]
+fn bench_filter_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+ })
+}
+
+#[bench]
+fn bench_filter_ref_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+ })
+}
+
+#[bench]
+fn bench_filter_chain_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+ })
+}
+
+#[bench]
+fn bench_filter_chain_ref_count(b: &mut Bencher) {
+ b.iter(|| {
+ (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+ })
+}
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `saturating_add` method. For example,
/// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
- #[cfg(not(stage0))]
pub fn saturating_add<T>(a: T, b: T) -> T;
/// Computes `a - b`, while saturating at numeric bounds.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `saturating_sub` method. For example,
/// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
- #[cfg(not(stage0))]
pub fn saturating_sub<T>(a: T, b: T) -> T;
/// Returns the value of the discriminant for the variant in 'v',
#[inline]
fn next(&mut self) -> Option<I::Item> {
- for x in &mut self.iter {
- if (self.predicate)(&x) {
- return Some(x);
- }
- }
- None
+ self.try_for_each(Err).err()
}
#[inline]
// Using the branchless version will also simplify the LLVM byte code, thus
// leaving more budget for LLVM optimizations.
#[inline]
- fn count(mut self) -> usize {
- let mut count = 0;
- for x in &mut self.iter {
- count += (self.predicate)(&x) as usize;
- }
- count
+ fn count(self) -> usize {
+ let mut predicate = self.predicate;
+ self.iter.map(|x| predicate(&x) as usize).sum()
}
#[inline]
{
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
- for x in self.iter.by_ref().rev() {
- if (self.predicate)(&x) {
- return Some(x);
- }
- }
- None
+ self.try_rfold((), |_, x| Err(x)).err()
}
#[inline]
#[inline]
fn next(&mut self) -> Option<B> {
- for x in self.iter.by_ref() {
- if let Some(y) = (self.f)(x) {
- return Some(y);
- }
- }
- None
+ self.try_for_each(Err).err()
}
#[inline]
{
#[inline]
fn next_back(&mut self) -> Option<B> {
- for x in self.iter.by_ref().rev() {
- if let Some(y) = (self.f)(x) {
- return Some(y);
- }
- }
- None
+ self.try_rfold((), |_, x| Err(x)).err()
}
#[inline]
/// Entry point of thread panic. For details, see `std::macros`.
#[macro_export]
-#[cfg_attr(not(stage0), allow_internal_unstable(core_panic, __rust_unstable_column))]
-#[cfg_attr(stage0, allow_internal_unstable)]
+#[allow_internal_unstable(core_panic, __rust_unstable_column)]
#[stable(feature = "core", since = "1.6.0")]
macro_rules! panic {
() => (
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(format_args_nl))]
+#[allow_internal_unstable(format_args_nl)]
macro_rules! writeln {
($dst:expr) => (
write!($dst, "\n")
/// [`Pin<P>`]: ../pin/struct.Pin.html
/// [`pin module`]: ../../std/pin/index.html
#[stable(feature = "pin", since = "1.33.0")]
-#[cfg_attr(not(stage0), lang = "unpin")]
+#[lang = "unpin"]
pub auto trait Unpin {}
/// A marker type which does not implement `Unpin`.
}
}
+// FIXME: Reference `MaybeUninit` from these docs, once that is stable.
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
/// This wrapper is 0-cost.
///
+/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
+/// As a consequence, it has *no effect* on the assumptions that the compiler makes
+/// about all values being initialized at their type. In particular, initializing
+/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
+///
/// # Examples
///
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
/// }
/// }
/// ```
+///
+/// [`mem::zeroed`]: fn.zeroed.html
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
Basic usage:
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
-assert_eq!(", stringify!($SelfT), "::max_value().saturating_add(100), ", stringify!($SelfT),
-"::max_value());",
-$EndFeature, "
-```"),
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- #[cfg(stage0)]
- pub fn saturating_add(self, rhs: Self) -> Self {
- match self.checked_add(rhs) {
- Some(x) => x,
- None if rhs >= 0 => Self::max_value(),
- None => Self::min_value(),
- }
- }
-
- }
-
- doc_comment! {
- concat!("Saturating integer addition. Computes `self + rhs`, saturating at the numeric
-bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
```
", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
assert_eq!(", stringify!($SelfT), "::max_value().saturating_add(100), ", stringify!($SelfT),
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline]
- #[cfg(not(stage0))]
pub const fn saturating_add(self, rhs: Self) -> Self {
intrinsics::saturating_add(self, rhs)
}
}
- doc_comment! {
- concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the
-numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27);
-assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringify!($SelfT),
-"::min_value());",
-$EndFeature, "
-```"),
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- #[cfg(stage0)]
- pub fn saturating_sub(self, rhs: Self) -> Self {
- match self.checked_sub(rhs) {
- Some(x) => x,
- None if rhs >= 0 => Self::min_value(),
- None => Self::max_value(),
- }
- }
- }
doc_comment! {
concat!("Saturating integer subtraction. Computes `self - rhs`, saturating at the
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline]
- #[cfg(not(stage0))]
pub const fn saturating_sub(self, rhs: Self) -> Self {
intrinsics::saturating_sub(self, rhs)
}
Basic usage:
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
-assert_eq!(200u8.saturating_add(127), 255);", $EndFeature, "
-```"),
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- #[cfg(stage0)]
- pub fn saturating_add(self, rhs: Self) -> Self {
- match self.checked_add(rhs) {
- Some(x) => x,
- None => Self::max_value(),
- }
- }
- }
-
- doc_comment! {
- concat!("Saturating integer addition. Computes `self + rhs`, saturating at
-the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
```
", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
assert_eq!(200u8.saturating_add(127), 255);", $EndFeature, "
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline]
- #[cfg(not(stage0))]
pub const fn saturating_add(self, rhs: Self) -> Self {
intrinsics::saturating_add(self, rhs)
}
Basic usage:
-```
-", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);
-assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, "
-```"),
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- #[cfg(stage0)]
- pub fn saturating_sub(self, rhs: Self) -> Self {
- match self.checked_sub(rhs) {
- Some(x) => x,
- None => Self::min_value(),
- }
- }
- }
-
- doc_comment! {
- concat!("Saturating integer subtraction. Computes `self - rhs`, saturating
-at the numeric bounds instead of overflowing.
-
-# Examples
-
-Basic usage:
-
```
", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(27), 73);
assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, "
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
#[inline]
- #[cfg(not(stage0))]
pub const fn saturating_sub(self, rhs: Self) -> Self {
intrinsics::saturating_sub(self, rhs)
}
/// # Examples
///
/// Here is an example which increments every integer in a vector.
- /// `We use the checked variant of `add` that returns `None` when the
+ /// We use the checked variant of `add` that returns `None` when the
/// calculation would result in an overflow.
///
/// ```
//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
//! Then we could do the following:
//! ```compile_fail
-//! fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>) {
+//! fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>>) {
//! { let p = rc.as_mut().get_pin_mut(); } // Here we get pinned access to the `T`.
//! let rc_shr: &RefCell<T> = rc.into_ref().get_ref();
//! let b = rc_shr.borrow_mut();
// implementations, are allowed because they all only use `&P`, so they cannot move
// the value behind `pointer`.
#[stable(feature = "pin", since = "1.33.0")]
-#[cfg_attr(not(stage0), lang = "pin")]
+#[lang = "pin"]
#[fundamental]
#[repr(transparent)]
#[derive(Copy, Clone, Hash, Eq, Ord)]
me.make_ascii_lowercase()
}
- /// Return an iterator that escapes each char in `s` with [`char::escape_debug`].
+ /// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
///
/// Note: only extended grapheme codepoints that begin the string will be
/// escaped.
}
}
- /// Return an iterator that escapes each char in `s` with [`char::escape_default`].
+ /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
///
/// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default
///
EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
}
- /// Return an iterator that escapes each char in `s` with [`char::escape_unicode`].
+ /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
///
/// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode
///
/// [`AtomicBool`]: struct.AtomicBool.html
#[cfg(target_has_atomic = "8")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(stage0), rustc_deprecated(
+#[rustc_deprecated(
since = "1.34.0",
reason = "the `new` function is now preferred",
suggestion = "AtomicBool::new(false)",
-))]
-#[cfg_attr(stage0, rustc_deprecated(
- since = "1.34.0",
- reason = "the `new` function is now preferred",
-))]
+)]
pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false);
#[cfg(target_has_atomic = "8")]
/// An atomic integer initialized to `0`.
#[$stable_init_const]
- #[cfg_attr(stage0, rustc_deprecated(
- since = "1.34.0",
- reason = "the `new` function is now preferred",
- ))]
- #[cfg_attr(not(stage0), rustc_deprecated(
+ #[rustc_deprecated(
since = "1.34.0",
reason = "the `new` function is now preferred",
suggestion = $atomic_new,
- ))]
+ )]
pub const $atomic_init: $atomic_type = $atomic_type::new(0);
#[$stable]
scoped-tls = "1.0"
log = { version = "0.4", features = ["release_max_level_info", "std"] }
polonius-engine = "0.6.2"
-rustc-rayon = "0.1.1"
-rustc-rayon-core = "0.1.1"
+rustc-rayon = "0.1.2"
+rustc-rayon-core = "0.1.2"
rustc_apfloat = { path = "../librustc_apfloat" }
rustc_target = { path = "../librustc_target" }
+rustc_macros = { path = "../librustc_macros" }
rustc_data_structures = { path = "../librustc_data_structures" }
errors = { path = "../librustc_errors", package = "rustc_errors" }
serialize = { path = "../libserialize" }
/// Checks any attribute.
fn check_attributes(&self, item: &hir::Item, target: Target) {
if target == Target::Fn || target == Target::Const {
- self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id(item.id));
+ self.tcx.codegen_fn_attrs(self.tcx.hir().local_def_id_from_hir_id(item.hir_id));
} else if let Some(a) = item.attrs.iter().find(|a| a.check_name("target_feature")) {
self.tcx.sess.struct_span_err(a.span, "attribute should be applied to a function")
.span_label(item.span, "not a function")
fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
self.lctx.with_hir_id_owner(item.id, |lctx| {
- let id = hir::TraitItemId { node_id: item.id };
let hir_item = lctx.lower_trait_item(item);
+ let id = hir::TraitItemId { hir_id: hir_item.hir_id };
lctx.trait_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
});
fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
self.lctx.with_hir_id_owner(item.id, |lctx| {
- let id = hir::ImplItemId { node_id: item.id };
let hir_item = lctx.lower_impl_item(item);
+ let id = hir::ImplItemId { hir_id: hir_item.hir_id };
lctx.impl_items.insert(id, hir_item);
lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
});
trace!("exist ty def index: {:#?}", exist_ty_def_index);
let exist_ty_item = hir::Item {
- id: exist_ty_id.node_id,
hir_id: exist_ty_id.hir_id,
ident: keywords::Invalid.ident(),
attrs: Default::default(),
fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
match *vdata {
VariantData::Struct(ref fields, id) => {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
hir::VariantData::Struct(
fields
.enumerate()
.map(|f| self.lower_struct_field(f))
.collect(),
- node_id,
hir_id,
)
},
VariantData::Tuple(ref fields, id) => {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
hir::VariantData::Tuple(
fields
.enumerate()
.map(|f| self.lower_struct_field(f))
.collect(),
- node_id,
hir_id,
)
},
VariantData::Unit(id) => {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);
- hir::VariantData::Unit(node_id, hir_id)
+ hir::VariantData::Unit(hir_id)
},
}
}
}
fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::StructField {
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(f.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(f.id);
hir::StructField {
span: f.span,
- id: node_id,
hir_id,
ident: match f.ident {
Some(ident) => ident,
this.insert_item(
new_id.node_id,
hir::Item {
- id: new_id.node_id,
hir_id: new_id.hir_id,
ident,
attrs: attrs.clone(),
this.insert_item(
new_id,
hir::Item {
- id: new_id,
hir_id: new_hir_id,
ident,
attrs: attrs.clone(),
TraitItemKind::Macro(..) => unimplemented!(),
};
hir::TraitItemRef {
- id: hir::TraitItemId { node_id: i.id },
+ id: hir::TraitItemId { hir_id: self.lower_node_id(i.id).hir_id },
ident: i.ident,
span: i.span,
defaultness: self.lower_defaultness(Defaultness::Default, has_default),
fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
hir::ImplItemRef {
- id: hir::ImplItemId { node_id: i.id },
+ id: hir::ImplItemId { hir_id: self.lower_node_id(i.id).hir_id },
ident: i.ident,
span: i.span,
vis: self.lower_visibility(&i.vis, Some(i.id)),
let node = self.lower_item_kind(i.id, &mut ident, &attrs, &mut vis, &i.node);
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(i.id);
Some(hir::Item {
- id: node_id,
hir_id,
ident,
attrs,
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
let def_id = self.resolver.definitions().local_def_id(node_id);
hir::ForeignItem {
- id: node_id,
hir_id,
ident: i.ident,
attrs: self.lower_attrs(&i.attrs),
let fs = fields
.iter()
.map(|f| {
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
Spanned {
span: f.span,
node: hir::FieldPat {
- id: node_id,
hir_id,
ident: f.node.ident,
pat: self.lower_pat(&f.node.pat),
PatKind::Mac(_) => panic!("Shouldn't exist here"),
};
- let LoweredNodeId { node_id, hir_id } = self.lower_node_id(p.id);
+ let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(p.id);
P(hir::Pat {
- id: node_id,
hir_id,
node,
span: p.span,
let iter = self.str_to_ident("iter");
let next_ident = self.str_to_ident("__next");
- let next_pat = self.pat_ident_binding_mode(
+ let (next_pat, next_pat_nid) = self.pat_ident_binding_mode(
desugared_span,
next_ident,
hir::BindingAnnotation::Mutable,
// `::std::option::Option::Some(val) => next = val`
let pat_arm = {
let val_ident = self.str_to_ident("val");
- let val_pat = self.pat_ident(pat.span, val_ident);
- let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat.id));
- let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat.id));
+ let (val_pat, val_pat_nid) = self.pat_ident(pat.span, val_ident);
+ let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_nid));
+ let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_nid));
let assign = P(self.expr(
pat.span,
hir::ExprKind::Assign(next_expr, val_expr),
};
// `mut iter`
- let iter_pat = self.pat_ident_binding_mode(
+ let (iter_pat, iter_pat_nid) = self.pat_ident_binding_mode(
desugared_span,
iter,
hir::BindingAnnotation::Mutable
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
- let iter = P(self.expr_ident(head_sp, iter, iter_pat.id));
+ let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid));
let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter);
let next_path = &["iter", "Iterator", "next"];
let next_path = P(self.expr_std_path(head_sp, next_path, None, ThinVec::new()));
span: head_sp,
};
- let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
+ let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_nid));
// `let mut __next`
let next_let = self.stmt_let_pat(
// `Ok(val) => #[allow(unreachable_code)] val,`
let ok_arm = {
let val_ident = self.str_to_ident("val");
- let val_pat = self.pat_ident(e.span, val_ident);
+ let (val_pat, val_pat_nid) = self.pat_ident(e.span, val_ident);
let val_expr = P(self.expr_ident_with_attrs(
e.span,
val_ident,
- val_pat.id,
+ val_pat_nid,
ThinVec::from(attrs.clone()),
));
let ok_pat = self.pat_ok(e.span, val_pat);
// return Try::from_error(From::from(err)),`
let err_arm = {
let err_ident = self.str_to_ident("err");
- let err_local = self.pat_ident(e.span, err_ident);
+ let (err_local, err_local_nid) = self.pat_ident(e.span, err_ident);
let from_expr = {
let path = &["convert", "From", "from"];
let from = P(self.expr_std_path(
e.span, path, None, ThinVec::new()));
- let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
+ let err_expr = self.expr_ident(e.span, err_ident, err_local_nid);
self.expr_call(e.span, from, hir_vec![err_expr])
};
ident: Ident,
ex: P<hir::Expr>,
) -> (hir::Stmt, NodeId) {
- let pat = if mutbl {
+ let (pat, pat_nid) = if mutbl {
self.pat_ident_binding_mode(sp, ident, hir::BindingAnnotation::Mutable)
} else {
self.pat_ident(sp, ident)
};
- let pat_id = pat.id;
+
(
self.stmt_let_pat(sp, Some(ex), pat, hir::LocalSource::Normal),
- pat_id,
+ pat_nid,
)
}
self.pat(span, pt)
}
- fn pat_ident(&mut self, span: Span, ident: Ident) -> P<hir::Pat> {
+ fn pat_ident(&mut self, span: Span, ident: Ident) -> (P<hir::Pat>, NodeId) {
self.pat_ident_binding_mode(span, ident, hir::BindingAnnotation::Unannotated)
}
span: Span,
ident: Ident,
bm: hir::BindingAnnotation,
- ) -> P<hir::Pat> {
+ ) -> (P<hir::Pat>, NodeId) {
let LoweredNodeId { node_id, hir_id } = self.next_id();
- P(hir::Pat {
- id: node_id,
- hir_id,
- node: hir::PatKind::Binding(bm, node_id, hir_id, ident.with_span_pos(span), None),
- span,
- })
+ (
+ P(hir::Pat {
+ hir_id,
+ node: hir::PatKind::Binding(bm, node_id, hir_id, ident.with_span_pos(span), None),
+ span,
+ }),
+ node_id
+ )
}
fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
}
fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
- let LoweredNodeId { node_id, hir_id } = self.next_id();
+ let LoweredNodeId { node_id: _, hir_id } = self.next_id();
P(hir::Pat {
- id: node_id,
hir_id,
node: pat,
span,
fn visit_item(&mut self, i: &'hir Item) {
debug!("visit_item: {:?}", i);
debug_assert_eq!(i.hir_id.owner,
- self.definitions.opt_def_index(i.id).unwrap());
+ self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap());
self.with_dep_node_owner(i.hir_id.owner, i, |this| {
this.insert(i.span, i.hir_id, Node::Item(i));
this.with_parent(i.hir_id, |this| {
match node {
Node::Item(item) => {
- let def_id = || self.local_def_id(item.id);
+ let def_id = || self.local_def_id_from_hir_id(item.hir_id);
match item.node {
ItemKind::Static(_, m, _) => Some(Def::Static(def_id(), m == MutMutable)),
}
}
Node::ForeignItem(item) => {
- let def_id = self.local_def_id(item.id);
+ let def_id = self.local_def_id_from_hir_id(item.hir_id);
match item.node {
ForeignItemKind::Fn(..) => Some(Def::Fn(def_id)),
ForeignItemKind::Static(_, m) => Some(Def::Static(def_id, m)),
}
}
Node::Variant(variant) => {
- let def_id = self.local_def_id(variant.node.data.id());
+ let def_id = self.local_def_id_from_hir_id(variant.node.data.hir_id());
Some(Def::Variant(def_id))
}
Node::StructCtor(variant) => {
- let def_id = self.local_def_id(variant.id());
+ let def_id = self.local_def_id_from_hir_id(variant.hir_id());
Some(Def::StructCtor(def_id, def::CtorKind::from_hir(variant)))
}
Node::AnonConst(_) |
}
pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem {
- self.read(id.node_id);
+ self.read_by_hir_id(id.hir_id);
// N.B., intentionally bypass `self.forest.krate()` so that we
// do not trigger a read of the whole krate here
}
pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem {
- self.read(id.node_id);
+ self.read_by_hir_id(id.hir_id);
// N.B., intentionally bypass `self.forest.krate()` so that we
// do not trigger a read of the whole krate here
}
for id in &module.trait_items {
- visitor.visit_trait_item(self.expect_trait_item(id.node_id));
+ visitor.visit_trait_item(self.expect_trait_item_by_hir_id(id.hir_id));
}
for id in &module.impl_items {
- visitor.visit_impl_item(self.expect_impl_item(id.node_id));
+ visitor.visit_impl_item(self.expect_impl_item_by_hir_id(id.hir_id));
}
}
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync};
use rustc_data_structures::thin_vec::ThinVec;
+use rustc_macros::HashStable;
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::{BTreeSet, BTreeMap};
pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable)]
pub struct Lifetime {
pub hir_id: HirId,
pub span: Span,
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct Pat {
- pub id: NodeId,
pub hir_id: HirId,
pub node: PatKind,
pub span: Span,
impl fmt::Debug for Pat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "pat({}: {})", self.id,
+ write!(f, "pat({}: {})", self.hir_id,
print::to_string(print::NO_ANN, |s| s.print_pat(self)))
}
}
/// except `is_shorthand` is true.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct FieldPat {
- pub id: NodeId,
pub hir_id: HirId,
/// The identifier for the field.
pub ident: Ident,
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
pub struct TraitItemId {
- pub node_id: NodeId,
+ pub hir_id: HirId,
}
/// Represents an item declaration within a trait declaration,
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
pub struct ImplItemId {
- pub node_id: NodeId,
+ pub hir_id: HirId,
}
/// Represents anything within an `impl` block
pub span: Span,
pub ident: Ident,
pub vis: Visibility,
- pub id: NodeId,
pub hir_id: HirId,
pub ty: P<Ty>,
pub attrs: HirVec<Attribute>,
/// Id of the whole struct lives in `Item`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub enum VariantData {
- Struct(HirVec<StructField>, NodeId, HirId),
- Tuple(HirVec<StructField>, NodeId, HirId),
- Unit(NodeId, HirId),
+ Struct(HirVec<StructField>, HirId),
+ Tuple(HirVec<StructField>, HirId),
+ Unit(HirId),
}
impl VariantData {
_ => &[],
}
}
- pub fn id(&self) -> NodeId {
- match *self {
- VariantData::Struct(_, id, ..)
- | VariantData::Tuple(_, id, ..)
- | VariantData::Unit(id, ..) => id,
- }
- }
pub fn hir_id(&self) -> HirId {
match *self {
- VariantData::Struct(_, _, hir_id)
- | VariantData::Tuple(_, _, hir_id)
- | VariantData::Unit(_, hir_id) => hir_id,
+ VariantData::Struct(_, hir_id)
+ | VariantData::Tuple(_, hir_id)
+ | VariantData::Unit(hir_id) => hir_id,
}
}
pub fn is_struct(&self) -> bool {
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Item {
pub ident: Ident,
- pub id: NodeId,
pub hir_id: HirId,
pub attrs: HirVec<Attribute>,
pub node: ItemKind,
pub ident: Ident,
pub attrs: HirVec<Attribute>,
pub node: ForeignItemKind,
- pub id: NodeId,
pub hir_id: HirId,
pub span: Span,
pub vis: Visibility,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let hir::TraitItemId {
- node_id
+ hir_id
} = * self;
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
- node_id.hash_stable(hcx, hasher);
+ hir_id.hash_stable(hcx, hasher);
})
}
}
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
let hir::ImplItemId {
- node_id
+ hir_id
} = * self;
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
- node_id.hash_stable(hcx, hasher);
+ hir_id.hash_stable(hcx, hasher);
})
}
}
ident
});
-impl_stable_hash_for!(struct hir::Lifetime {
- hir_id,
- span,
- name
-});
-
impl_stable_hash_for!(struct hir::Path {
span,
def,
});
impl_stable_hash_for!(struct hir::Pat {
- id -> _,
hir_id -> _,
node,
span,
impl_stable_hash_for_spanned!(hir::FieldPat);
impl_stable_hash_for!(struct hir::FieldPat {
- id -> _,
hir_id -> _,
ident -> (ident.name),
pat,
span,
ident -> (ident.name),
vis,
- id,
hir_id,
ty,
attrs
});
impl_stable_hash_for!(enum hir::VariantData {
- Struct(fields, id, hir_id),
- Tuple(fields, id, hir_id),
- Unit(id, hir_id)
+ Struct(fields, hir_id),
+ Tuple(fields, hir_id),
+ Unit(hir_id)
});
impl<'a> HashStable<StableHashingContext<'a>> for hir::Item {
let hir::Item {
ident,
ref attrs,
- id: _,
hir_id: _,
ref node,
ref vis,
ident -> (ident.name),
attrs,
node,
- id,
hir_id,
span,
vis
ReifyFnPointer,
ClosureFnPointer,
UnsafeFnPointer,
+ MutToConstPointer,
Unsize
});
match self {
ty::subst::UnpackedKind::Lifetime(lt) => lt.hash_stable(hcx, hasher),
ty::subst::UnpackedKind::Type(ty) => ty.hash_stable(hcx, hasher),
+ ty::subst::UnpackedKind::Const(ct) => ct.hash_stable(hcx, hasher),
}
}
}
}
}
+impl<'gcx, 'tcx> HashStable<StableHashingContext<'gcx>> for ty::ConstVid<'tcx> {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'gcx>,
+ hasher: &mut StableHasher<W>) {
+ self.index.hash_stable(hcx, hasher);
+ }
+}
+
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
}
}
+impl_stable_hash_for!(
+ impl<'tcx> for enum ty::InferConst<'tcx> [ ty::InferConst ] {
+ Var(vid),
+ Fresh(i),
+ Canonical(debruijn, var),
+ }
+);
+
impl_stable_hash_for!(enum ty::VariantDiscr {
Explicit(def_id),
Relative(distance)
impl_stable_hash_for!(
impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValue ] {
+ Param(param),
+ Infer(infer),
Scalar(val),
Slice(a, b),
ByRef(ptr, alloc),
}
);
+
impl_stable_hash_for!(struct crate::mir::interpret::RawConst<'tcx> {
alloc_id,
ty,
impl_stable_hash_for!(enum ty::GenericParamDefKind {
Lifetime,
Type { has_default, object_lifetime_default, synthetic },
+ Const,
});
impl_stable_hash_for!(
}
}
+impl_stable_hash_for!(struct ty::ParamConst {
+ index,
+ name
+});
+
impl_stable_hash_for!(struct ty::ParamTy {
idx,
name
UnpackedKind::Lifetime(..) => tcx.mk_region(
ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i))
).into(),
+ UnpackedKind::Const(..) => {
+ unimplemented!() // FIXME(const_generics)
+ }
})
.collect()
}
obligations.extend(ok.into_obligations());
}
+ (UnpackedKind::Const(..), UnpackedKind::Const(..)) => {
+ unimplemented!() // FIXME(const_generics)
+ }
+
_ => {
bug!(
"kind mismatch, cannot unify {:?} and {:?}",
opt_values[br.assert_bound_var()] = Some(*original_value);
}
}
+ UnpackedKind::Const(..) => {
+ unimplemented!() // FIXME(const_generics)
+ }
}
}
ty::OutlivesPredicate(t1, r2)
)
),
+ UnpackedKind::Const(..) => {
+ // Consts cannot outlive one another, so we don't expect to
+ // ecounter this branch.
+ span_bug!(cause.span, "unexpected const outlives {:?}", constraint);
+ }
}
)
})
obligations
.extend(self.at(cause, param_env).eq(v1, v2)?.into_obligations());
}
+ (UnpackedKind::Const(..), UnpackedKind::Const(..)) => {
+ unimplemented!() // FIXME(const_generics)
+ }
_ => {
bug!("kind mismatch, cannot unify {:?} and {:?}", value1, value2,);
}
let origin = *variables.var_origin(vid);
let new_var_id = variables.new_var(self.for_universe, false, origin);
- let u = self.tcx().mk_var(new_var_id);
+ let u = self.tcx().mk_ty_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}",
vid, u);
return Ok(u);
) -> SubstsRef<'tcx> {
let generics = self.tcx.generics_of(def_id);
let mut num_supplied_defaults = 0;
- let mut type_params = generics
- .params
- .iter()
- .rev()
- .filter_map(|param| match param.kind {
- ty::GenericParamDefKind::Lifetime => None,
- ty::GenericParamDefKind::Type { has_default, .. } => {
- Some((param.def_id, has_default))
- }
- })
- .peekable();
+ let mut type_params = generics.params.iter().rev().filter_map(|param| match param.kind {
+ ty::GenericParamDefKind::Lifetime => None,
+ ty::GenericParamDefKind::Type { has_default, .. } => Some((param.def_id, has_default)),
+ ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
+ }).peekable();
let has_default = {
let has_default = type_params.peek().map(|(_, has_default)| has_default);
*has_default.unwrap_or(&false)
type_variables
.unsolved_variables()
.into_iter()
- .map(|t| self.tcx.mk_var(t))
+ .map(|t| self.tcx.mk_ty_var(t))
.chain(
(0..int_unification_table.len())
.map(|i| ty::IntVid { index: i as u32 })
}
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
- self.tcx.mk_var(self.next_ty_var_id(false, origin))
+ self.tcx.mk_ty_var(self.next_ty_var_id(false, origin))
}
pub fn next_ty_var_in_universe(
let vid = self.type_variables
.borrow_mut()
.new_var(universe, false, origin);
- self.tcx.mk_var(vid)
+ self.tcx.mk_ty_var(vid)
}
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
- self.tcx.mk_var(self.next_ty_var_id(true, origin))
+ self.tcx.mk_ty_var(self.next_ty_var_id(true, origin))
}
pub fn next_int_var_id(&self) -> IntVid {
TypeVariableOrigin::TypeParameterDefinition(span, param.name),
);
- self.tcx.mk_var(ty_var_id).into()
+ self.tcx.mk_ty_var(ty_var_id).into()
+ }
+ GenericParamDefKind::Const { .. } => {
+ unimplemented!() // FIXME(const_generics)
}
}
}
ty::Projection(projection_ty)
if D::normalization() == NormalizationStrategy::Lazy =>
{
- return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_var(vid)));
+ return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
}
_ => (),
// the universe `_universe`.
let new_var_id = variables.new_var(self.universe, false, origin);
- let u = self.tcx().mk_var(new_var_id);
+ let u = self.tcx().mk_ty_var(new_var_id);
debug!(
"generalize: replacing original vid={:?} with new={:?}",
vid,
substs,
item_def_id: _,
}) => {
- for r in substs.regions() {
- bound_region(r);
+ for k in substs {
+ match k.unpack() {
+ UnpackedKind::Lifetime(lt) => bound_region(lt),
+ UnpackedKind::Type(ty) => types.push(ty),
+ UnpackedKind::Const(_) => {
+ // Const parameters don't impose constraints.
+ }
+ }
}
- types.extend(substs.types());
}
Component::EscapingProjection(more_components) => {
use crate::traits::ObligationCause;
use crate::ty::outlives::Component;
use crate::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
+use crate::ty::subst::UnpackedKind;
impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// Registers that the given region obligation must be resolved
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
debug!("projection_must_outlive: no declared bounds");
- for component_ty in projection_ty.substs.types() {
- self.type_must_outlive(origin.clone(), component_ty, region);
- }
-
- for r in projection_ty.substs.regions() {
- self.delegate
- .push_sub_region_constraint(origin.clone(), region, r);
+ for k in projection_ty.substs {
+ match k.unpack() {
+ UnpackedKind::Lifetime(lt) => {
+ self.delegate.push_sub_region_constraint(origin.clone(), region, lt);
+ }
+ UnpackedKind::Type(ty) => {
+ self.type_must_outlive(origin.clone(), ty, region);
+ }
+ UnpackedKind::Const(_) => {
+ // Const parameters don't impose constraints.
+ }
+ }
}
return;
pub mod bug;
}
-// A private module so that macro-expanded idents like
-// `::rustc::lint::Lint` will also work in `rustc` itself.
-//
-// `libstd` uses the same trick.
-#[doc(hidden)]
-mod rustc {
- pub use crate::lint;
-}
+// Allows macros to refer to this crate as `::rustc`
+extern crate self as rustc;
// FIXME(#27438): right now the unit tests of librustc don't refer to any actual
// functions generated in librustc_data_structures (all
#[macro_export]
macro_rules! declare_tool_lint {
- ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
- declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+ ) => (
+ declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
);
- ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
- report_in_external_macro: $rep: expr) => (
- declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+ report_in_external_macro: $rep:expr
+ ) => (
+ declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
);
- ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+ (
+ $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+ $external:expr
+ ) => (
+ $(#[$attr])*
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: &concat!(stringify!($tool), "::", stringify!($NAME)),
default_level: $crate::lint::$Level,
Node::Item(item) => {
match item.node {
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let def = self.tcx.adt_def(def_id);
self.repr_has_repr_c = def.repr.c();
has_allow_dead_code_or_lang_attr(self.tcx,
impl_item.hir_id,
&impl_item.attrs) {
- self.worklist.push(self.tcx.hir().node_to_hir_id(impl_item_ref.id.node_id));
+ self.worklist.push(impl_item_ref.id.hir_id);
}
}
}
}
fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
- let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id));
+ let field_type = self.tcx.type_of(self.tcx.hir().local_def_id_from_hir_id(field.hir_id));
!field.is_positional()
&& !self.symbol_is_live(field.hir_id)
&& !field_type.is_phantom_data()
use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use crate::session::{config, Session};
use crate::session::config::EntryFnType;
-use syntax::ast::NodeId;
use syntax::attr;
use syntax::entry::EntryPointType;
use syntax_pos::Span;
-use crate::hir::{Item, ItemKind, ImplItem, TraitItem};
+use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem};
use crate::hir::itemlikevisit::ItemLikeVisitor;
use crate::ty::TyCtxt;
use crate::ty::query::Providers;
map: &'a hir_map::Map<'tcx>,
// The top-level function called 'main'
- main_fn: Option<(NodeId, Span)>,
+ main_fn: Option<(HirId, Span)>,
// The function that has attribute named 'main'
- attr_main_fn: Option<(NodeId, Span)>,
+ attr_main_fn: Option<(HirId, Span)>,
// The function that has the attribute 'start' on it
- start_fn: Option<(NodeId, Span)>,
+ start_fn: Option<(HirId, Span)>,
// The functions that one might think are 'main' but aren't, e.g.
// main functions not defined at the top level. For diagnostics.
- non_main_fns: Vec<(NodeId, Span)> ,
+ non_main_fns: Vec<(HirId, Span)> ,
}
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx Item) {
- let def_id = self.map.local_def_id(item.id);
+ let def_id = self.map.local_def_id_from_hir_id(item.hir_id);
let def_key = self.map.def_key(def_id);
let at_root = def_key.parent == Some(CRATE_DEF_INDEX);
find_item(item, self, at_root);
match entry_point_type(item, at_root) {
EntryPointType::MainNamed => {
if ctxt.main_fn.is_none() {
- ctxt.main_fn = Some((item.id, item.span));
+ ctxt.main_fn = Some((item.hir_id, item.span));
} else {
span_err!(ctxt.session, item.span, E0136,
"multiple 'main' functions");
}
},
EntryPointType::OtherMain => {
- ctxt.non_main_fns.push((item.id, item.span));
+ ctxt.non_main_fns.push((item.hir_id, item.span));
},
EntryPointType::MainAttr => {
if ctxt.attr_main_fn.is_none() {
- ctxt.attr_main_fn = Some((item.id, item.span));
+ ctxt.attr_main_fn = Some((item.hir_id, item.span));
} else {
struct_span_err!(ctxt.session, item.span, E0137,
"multiple functions with a #[main] attribute")
},
EntryPointType::Start => {
if ctxt.start_fn.is_none() {
- ctxt.start_fn = Some((item.id, item.span));
+ ctxt.start_fn = Some((item.hir_id, item.span));
} else {
struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions")
.span_label(ctxt.start_fn.unwrap().1, "previous `start` function here")
tcx: TyCtxt<'_, '_, '_>,
visitor: &EntryContext<'_, '_>,
) -> Option<(DefId, EntryFnType)> {
- if let Some((node_id, _)) = visitor.start_fn {
- Some((tcx.hir().local_def_id(node_id), EntryFnType::Start))
- } else if let Some((node_id, _)) = visitor.attr_main_fn {
- Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
- } else if let Some((node_id, _)) = visitor.main_fn {
- Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
+ if let Some((hir_id, _)) = visitor.start_fn {
+ Some((tcx.hir().local_def_id_from_hir_id(hir_id), EntryFnType::Start))
+ } else if let Some((hir_id, _)) = visitor.attr_main_fn {
+ Some((tcx.hir().local_def_id_from_hir_id(hir_id), EntryFnType::Main))
+ } else if let Some((hir_id, _)) = visitor.main_fn {
+ Some((tcx.hir().local_def_id_from_hir_id(hir_id), EntryFnType::Main))
} else {
// No main function
let mut err = struct_err!(tcx.sess, E0601,
use crate::hir::{self, PatKind};
use rustc_data_structures::sync::Lrc;
use std::rc::Rc;
-use syntax::ast;
use syntax::ptr::P;
use syntax_pos::Span;
use crate::util::nodemap::ItemLocalSet;
// The local variable `id` is declared but not initialized.
fn decl_without_init(&mut self,
- id: ast::NodeId,
+ id: hir::HirId,
span: Span);
// The path at `cmt` is being assigned to.
match local.init {
None => {
local.pat.each_binding(|_, hir_id, span, _| {
- let node_id = self.mc.tcx.hir().hir_to_node_id(hir_id);
- self.delegate.decl_without_init(node_id, span);
+ self.delegate.decl_without_init(hir_id, span);
})
}
match self.item_refs.get(&*value.as_str()).cloned() {
// Known lang item with attribute on correct target.
Some((item_index, expected_target)) if actual_target == expected_target => {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
self.collect_item(item_index, def_id);
},
// Known lang item with attribute on incorrect target.
let body = ir.tcx.hir().body(body_id);
for arg in &body.arguments {
+ let is_shorthand = match arg.pat.node {
+ crate::hir::PatKind::Struct(..) => true,
+ _ => false,
+ };
arg.pat.each_binding(|_bm, hir_id, _x, ident| {
debug!("adding argument {:?}", hir_id);
- fn_maps.add_variable(Arg(hir_id, ident.name));
+ let var = if is_shorthand {
+ Local(LocalInfo {
+ id: hir_id,
+ name: ident.name,
+ is_shorthand: true,
+ })
+ } else {
+ Arg(hir_id, ident.name)
+ };
+ fn_maps.add_variable(var);
})
};
ThreadLocal(ty::Region<'tcx>), // value that cannot move, but still restricted in scope
StaticItem,
Upvar(Upvar), // upvar referenced by closure env
- Local(ast::NodeId), // local variable
+ Local(hir::HirId), // local variable
Deref(cmt<'tcx>, PointerKind<'tcx>), // deref of a ptr
Interior(cmt<'tcx>, InteriorKind), // something interior: field, tuple, etc
Downcast(cmt<'tcx>, DefId), // selects a particular enum variant (*1)
pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
pub enum ImmutabilityBlame<'tcx> {
- ImmLocal(ast::NodeId),
+ ImmLocal(hir::HirId),
ClosureEnv(LocalDefId),
- LocalDeref(ast::NodeId),
+ LocalDeref(hir::HirId),
AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
}
Categorization::Deref(ref base_cmt, BorrowedPtr(ty::ImmBorrow, _)) => {
// try to figure out where the immutable reference came from
match base_cmt.cat {
- Categorization::Local(node_id) =>
- Some(ImmutabilityBlame::LocalDeref(node_id)),
+ Categorization::Local(hir_id) =>
+ Some(ImmutabilityBlame::LocalDeref(hir_id)),
Categorization::Interior(ref base_cmt, InteriorField(field_index)) => {
base_cmt.resolve_field(field_index.0).map(|(adt_def, field_def)| {
ImmutabilityBlame::AdtFieldDeref(adt_def, field_def)
_ => None
}
}
- Categorization::Local(node_id) => {
- Some(ImmutabilityBlame::ImmLocal(node_id))
+ Categorization::Local(hir_id) => {
+ Some(ImmutabilityBlame::ImmLocal(hir_id))
}
Categorization::Rvalue(..) |
Categorization::Upvar(..) |
Ok(cmt_ {
hir_id,
span,
- cat: Categorization::Local(vid),
+ cat: Categorization::Local(self.tcx.hir().node_to_hir_id(vid)),
mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
ty: expr_ty,
note: NoteNone
"non-place".into()
}
Categorization::Local(vid) => {
- if tcx.hir().is_argument(vid) {
+ if tcx.hir().is_argument(tcx.hir().hir_to_node_id(vid)) {
"argument"
} else {
"local variable"
use crate::ty::query::Providers;
use crate::middle::privacy;
use crate::session::config;
-use crate::util::nodemap::{NodeSet, FxHashSet};
+use crate::util::nodemap::{HirIdSet, FxHashSet};
use rustc_target::spec::abi::Abi;
-use syntax::ast;
use crate::hir;
use crate::hir::def_id::LOCAL_CRATE;
use crate::hir::intravisit::{Visitor, NestedVisitorMap};
match item.node {
hir::ItemKind::Impl(..) |
hir::ItemKind::Fn(..) => {
- let generics = tcx.generics_of(tcx.hir().local_def_id(item.id));
+ let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(item.hir_id));
generics.requires_monomorphization(tcx)
}
_ => false,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
// The set of items which must be exported in the linkage sense.
- reachable_symbols: NodeSet,
+ reachable_symbols: HirIdSet,
// A worklist of item IDs. Each item ID in this worklist will be inlined
// and will be scanned for further references.
- worklist: Vec<ast::NodeId>,
+ worklist: Vec<hir::HirId>,
// Whether any output of this compilation is a library
any_library: bool,
}
match def {
Some(Def::Local(node_id)) | Some(Def::Upvar(node_id, ..)) => {
- self.reachable_symbols.insert(node_id);
+ let hir_id = self.tcx.hir().node_to_hir_id(node_id);
+ self.reachable_symbols.insert(hir_id);
}
Some(def) => {
- if let Some((node_id, def_id)) = def.opt_def_id().and_then(|def_id| {
- self.tcx.hir().as_local_node_id(def_id).map(|node_id| (node_id, def_id))
+ if let Some((hir_id, def_id)) = def.opt_def_id().and_then(|def_id| {
+ self.tcx.hir().as_local_hir_id(def_id).map(|hir_id| (hir_id, def_id))
}) {
if self.def_id_represents_local_inlined_item(def_id) {
- self.worklist.push(node_id);
+ self.worklist.push(hir_id);
} else {
match def {
// If this path leads to a constant, then we need to
// recurse into the constant to continue finding
// items that are reachable.
Def::Const(..) | Def::AssociatedConst(..) => {
- self.worklist.push(node_id);
+ self.worklist.push(hir_id);
}
// If this wasn't a static, then the destination is
// surely reachable.
_ => {
- self.reachable_symbols.insert(node_id);
+ self.reachable_symbols.insert(hir_id);
}
}
}
continue
}
- if let Some(ref item) = self.tcx.hir().find(search_item) {
+ if let Some(ref item) = self.tcx.hir().find_by_hir_id(search_item) {
self.propagate_node(item, search_item);
}
}
}
fn propagate_node(&mut self, node: &Node<'tcx>,
- search_item: ast::NodeId) {
+ search_item: hir::HirId) {
if !self.any_library {
// If we are building an executable, only explicitly extern
// types need to be exported.
} else {
false
};
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
let is_extern = codegen_attrs.contains_extern_indicator();
let std_internal = codegen_attrs.flags.contains(
Node::Item(item) => {
match item.node {
hir::ItemKind::Fn(.., body) => {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
if item_might_be_inlined(self.tcx,
&item,
self.tcx.codegen_fn_attrs(def_id)) {
self.visit_nested_body(body);
}
hir::ImplItemKind::Method(_, body) => {
- let did = self.tcx.hir().get_parent_did(search_item);
+ let did = self.tcx.hir().get_parent_did_by_hir_id(search_item);
if method_might_be_inlined(self.tcx, impl_item, did) {
self.visit_nested_body(body)
}
_ => {
bug!(
"found unexpected node kind in worklist: {} ({:?})",
- self.tcx.hir().node_to_string(search_item),
+ self.tcx.hir().hir_to_string(search_item),
node,
);
}
struct CollectPrivateImplItemsVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
access_levels: &'a privacy::AccessLevels,
- worklist: &'a mut Vec<ast::NodeId>,
+ worklist: &'a mut Vec<hir::HirId>,
}
impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> {
// Anything which has custom linkage gets thrown on the worklist no
// matter where it is in the crate, along with "special std symbols"
// which are currently akin to allocator symbols.
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
if codegen_attrs.contains_extern_indicator() ||
codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
- self.worklist.push(item.id);
+ self.worklist.push(item.hir_id);
}
// We need only trait impls here, not inherent impls, and only non-exported ones
if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node {
- if !self.access_levels.is_reachable(item.id) {
- self.worklist.extend(impl_item_refs.iter().map(|r| r.id.node_id));
+ let node_id = self.tcx.hir().hir_to_node_id(item.hir_id);
+ if !self.access_levels.is_reachable(node_id) {
+ self.worklist.extend(impl_item_refs.iter().map(|ii_ref| ii_ref.id.hir_id));
let trait_def_id = match trait_ref.path.def {
Def::Trait(def_id) => def_id,
let provided_trait_methods = self.tcx.provided_trait_methods(trait_def_id);
self.worklist.reserve(provided_trait_methods.len());
for default_method in provided_trait_methods {
- let node_id = self.tcx
- .hir()
- .as_local_node_id(default_method.def_id)
- .unwrap();
- self.worklist.push(node_id);
+ let hir_id = self.tcx
+ .hir()
+ .as_local_hir_id(default_method.def_id)
+ .unwrap();
+ self.worklist.push(hir_id);
}
}
}
// We introduce a new-type here, so we can have a specialized HashStable
// implementation for it.
#[derive(Clone)]
-pub struct ReachableSet(pub Lrc<NodeSet>);
+pub struct ReachableSet(pub Lrc<HirIdSet>);
fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> ReachableSet {
debug_assert!(crate_num == LOCAL_CRATE);
// If other crates link to us, they're going to expect to be able to
// use the lang items, so we need to be sure to mark them as
// exported.
- reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id));
+ reachable_context.worklist.extend(
+ access_levels.map.iter().map(|(id, _)| tcx.hir().node_to_hir_id(*id)));
for item in tcx.lang_items().items().iter() {
if let Some(did) = *item {
- if let Some(node_id) = tcx.hir().as_local_node_id(did) {
- reachable_context.worklist.push(node_id);
+ if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
+ reachable_context.worklist.push(hir_id);
}
}
}
use crate::rustc::lint;
use crate::session::Session;
-use crate::util::nodemap::{DefIdMap, FxHashMap, FxHashSet, HirIdMap, HirIdSet, NodeMap};
+use crate::util::nodemap::{DefIdMap, FxHashMap, FxHashSet, HirIdMap, HirIdSet};
use errors::{Applicability, DiagnosticBuilder};
use rustc_data_structures::sync::Lrc;
use std::borrow::Cow;
// For each type and trait definition, maps type parameters
// to the trait object lifetime defaults computed from them.
- pub object_lifetime_defaults: NodeMap<Vec<ObjectLifetimeDefault>>,
+ pub object_lifetime_defaults: HirIdMap<Vec<ObjectLifetimeDefault>>,
}
/// See [`NamedRegionMap`].
.or_default();
Lrc::get_mut(map).unwrap().insert(hir_id.local_id);
}
- for (k, v) in named_region_map.object_lifetime_defaults {
- let hir_id = tcx.hir().node_to_hir_id(k);
+ for (hir_id, v) in named_region_map.object_lifetime_defaults {
let map = rl.object_lifetime_defaults
.entry(hir_id.owner_local_def_id())
.or_default();
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
if let Some(Region::LateBound(_, def_id, _)) = def {
- if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
+ if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
// Ensure that the parent of the def is an item, not HRTB
- let parent_id = self.tcx.hir().get_parent_node(node_id);
- let parent_impl_id = hir::ImplItemId { node_id: parent_id };
- let parent_trait_id = hir::TraitItemId { node_id: parent_id };
+ let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
+ let parent_impl_id = hir::ImplItemId { hir_id: parent_id };
+ let parent_trait_id = hir::TraitItemId { hir_id: parent_id };
let krate = self.tcx.hir().forest.krate();
- if !(krate.items.contains_key(&parent_id)
+ let parent_node_id = self.tcx.hir().hir_to_node_id(parent_id);
+ if !(krate.items.contains_key(&parent_node_id)
|| krate.impl_items.contains_key(&parent_impl_id)
|| krate.trait_items.contains_key(&parent_trait_id))
{
fn compute_object_lifetime_defaults(
tcx: TyCtxt<'_, '_, '_>,
-) -> NodeMap<Vec<ObjectLifetimeDefault>> {
- let mut map = NodeMap::default();
+) -> HirIdMap<Vec<ObjectLifetimeDefault>> {
+ let mut map = HirIdMap::default();
for item in tcx.hir().krate().items.values() {
match item.node {
hir::ItemKind::Struct(_, ref generics)
tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
}
- map.insert(item.id, result);
+ map.insert(item.hir_id, result);
}
_ => {}
}
};
let map = &self.map;
- let unsubst = if let Some(id) = self.tcx.hir().as_local_node_id(def_id) {
+ let unsubst = if let Some(id) = self.tcx.hir().as_local_hir_id(def_id) {
&map.object_lifetime_defaults[&id]
} else {
let tcx = self.tcx;
object_lifetime_default,
..
} => Some(object_lifetime_default),
- GenericParamDefKind::Lifetime => None,
+ GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
})
.collect()
})
.expect_item_by_hir_id(self.tcx.hir().get_parent_item(parent))
.node
{
- let parent_node_id = self.tcx.hir().hir_to_node_id(parent);
assoc_item_kind = trait_items
.iter()
- .find(|ti| ti.id.node_id == parent_node_id)
+ .find(|ti| ti.id.hir_id == parent)
.map(|ti| ti.kind);
}
match *m {
.node
{
impl_self = Some(self_ty);
- let parent_node_id = self.tcx.hir().hir_to_node_id(parent);
assoc_item_kind = impl_items
.iter()
- .find(|ii| ii.id.node_id == parent_node_id)
+ .find(|ii| ii.id.hir_id == parent)
.map(|ii| ii.kind);
}
Some(body)
let help_name = if let Some(body) = parent {
let arg = &self.tcx.hir().body(body).arguments[index];
- format!("`{}`", self.tcx.hir().node_to_pretty_string(arg.pat.id))
+ format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.pat.hir_id))
} else {
format!("argument {}", index + 1)
};
impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> {
fn check_missing_stability(&self, hir_id: HirId, span: Span, name: &str) {
let stab = self.tcx.stability().local_stability(hir_id);
- let node_id = self.tcx.hir().hir_to_node_id(hir_id);
let is_error = !self.tcx.sess.opts.test &&
stab.is_none() &&
- self.access_levels.is_reachable(node_id);
+ self.access_levels.is_reachable(self.tcx.hir().hir_to_node_id(hir_id));
if is_error {
self.tcx.sess.span_err(
span,
// compiler-generated `extern crate` items have a dummy span.
if item.span.is_dummy() { return }
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let cnum = match self.tcx.extern_mod_stmt_cnum(def_id) {
Some(cnum) => cnum,
None => return,
// There's no good place to insert stability check for non-Copy unions,
// so semi-randomly perform it here in stability.rs
hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let adt_def = self.tcx.adt_def(def_id);
let ty = self.tcx.type_of(def_id);
use std::fmt;
-use crate::ty::{Ty, layout::{HasDataLayout, Size}};
+use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}};
use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
/// match the `LocalState` optimizations for easy conversions between `Value` and `ConstValue`.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
pub enum ConstValue<'tcx> {
+ /// A const generic parameter.
+ Param(ParamConst),
+
+ /// Infer the value of the const.
+ Infer(InferConst<'tcx>),
+
/// Used only for types with `layout::abi::Scalar` ABI and ZSTs.
///
/// Not using the enum `Value` to encode that this must not be `Undef`.
#[inline]
pub fn try_to_scalar(&self) -> Option<Scalar> {
match *self {
+ ConstValue::Param(_) |
+ ConstValue::Infer(_) |
ConstValue::ByRef(..) |
ConstValue::Slice(..) => None,
ConstValue::Scalar(val) => Some(val),
/// Converts safe fn() to unsafe fn()
UnsafeFnPointer,
+ /// Coerces *mut T to *const T, preserving T.
+ MutToConstPointer,
+
/// "Unsize" -- convert a thin-or-fat pointer to a fat pointer.
/// codegen must figure out the details once full monomorphization
/// is known. For example, this could be used to cast from a
Use with RUST_REGION_GRAPH=help for more info"),
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link"),
+ dual_proc_macros: bool = (false, parse_bool, [TRACKED],
+ "load proc macros for both target and host, but only link to the target"),
no_codegen: bool = (false, parse_bool, [TRACKED],
"run all passes except codegen; no output"),
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
"inject the given attribute in the crate"),
self_profile: bool = (false, parse_bool, [UNTRACKED],
- "run the self profiler"),
- profile_json: bool = (false, parse_bool, [UNTRACKED],
- "output a json file with profiler results"),
+ "run the self profiler and output the raw event data"),
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
"emits a section containing stack size metadata"),
plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
// A module for searching for libraries
+#[derive(Clone)]
pub struct FileSearch<'a> {
sysroot: &'a Path,
triple: &'a str,
use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
use rustc_data_structures::flock;
-use jobserver::Client;
+use rustc_data_structures::jobserver;
+use ::jobserver::Client;
use std;
use std::cell::{self, Cell, RefCell};
use std::io::Write;
use std::path::PathBuf;
use std::time::Duration;
-use std::sync::mpsc;
+use std::sync::{Arc, mpsc};
+
+use parking_lot::Mutex as PlMutex;
mod code_stats;
pub mod config;
/// Used by `-Z profile-queries` in `util::common`.
pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
- /// Used by `-Z self-profile`.
- pub self_profiling_active: bool,
-
- /// Used by `-Z self-profile`.
- pub self_profiling: Lock<SelfProfiler>,
+ /// Used by -Z self-profile
+ pub self_profiling: Option<Arc<PlMutex<SelfProfiler>>>,
/// Some measurements that are being gathered during compilation.
pub perf_stats: PerfStats,
#[inline(never)]
#[cold]
fn profiler_active<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
- let mut profiler = self.self_profiling.borrow_mut();
- f(&mut profiler);
+ match &self.self_profiling {
+ None => bug!("profiler_active() called but there was no profiler active"),
+ Some(profiler) => {
+ let mut p = profiler.lock();
+
+ f(&mut p);
+ }
+ }
}
#[inline(always)]
pub fn profiler<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
- if unlikely!(self.self_profiling_active) {
+ if unlikely!(self.self_profiling.is_some()) {
self.profiler_active(f)
}
}
- pub fn print_profiler_results(&self) {
- let mut profiler = self.self_profiling.borrow_mut();
- profiler.print_results(&self.opts);
- }
-
- pub fn save_json_results(&self) {
- let profiler = self.self_profiling.borrow();
- profiler.save_results(&self.opts);
- }
-
pub fn print_perf_stats(&self) {
println!(
"Total time spent computing symbol hashes: {}",
source_map: Lrc<source_map::SourceMap>,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
) -> Session {
+ let self_profiler =
+ if sopts.debugging_opts.self_profile { Some(Arc::new(PlMutex::new(SelfProfiler::new()))) }
+ else { None };
+
let host_triple = TargetTriple::from_triple(config::host_triple());
let host = Target::search(&host_triple).unwrap_or_else(|e|
span_diagnostic
CguReuseTracker::new_disabled()
};
- let self_profiling_active = sopts.debugging_opts.self_profile ||
- sopts.debugging_opts.profile_json;
-
let sess = Session {
target: target_cfg,
host,
imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
cgu_reuse_tracker,
- self_profiling_active,
- self_profiling: Lock::new(SelfProfiler::new()),
+ self_profiling: self_profiler,
profile_channel: Lock::new(None),
perf_stats: PerfStats {
symbol_hash_time: Lock::new(Duration::from_secs(0)),
optimization_fuel,
print_fuel_crate,
print_fuel,
- // Note that this is unsafe because it may misinterpret file descriptors
- // on Unix as jobserver file descriptors. We hopefully execute this near
- // the beginning of the process though to ensure we don't get false
- // positives, or in other words we try to execute this before we open
- // any file descriptors ourselves.
- //
- // Pick a "reasonable maximum" if we don't otherwise have
- // a jobserver in our environment, capping out at 32 so we
- // don't take everything down by hogging the process run queue.
- // The fixed number is used to have deterministic compilation
- // across machines.
- //
- // Also note that we stick this in a global because there could be
- // multiple `Session` instances in this process, and the jobserver is
- // per-process.
- jobserver: unsafe {
- static mut GLOBAL_JOBSERVER: *mut Client = 0 as *mut _;
- static INIT: std::sync::Once = std::sync::ONCE_INIT;
- INIT.call_once(|| {
- let client = Client::from_env().unwrap_or_else(|| {
- Client::new(32).expect("failed to create jobserver")
- });
- GLOBAL_JOBSERVER = Box::into_raw(Box::new(client));
- });
- (*GLOBAL_JOBSERVER).clone()
- },
+ jobserver: jobserver::client(),
has_global_allocator: Once::new(),
has_panic_handler: Once::new(),
driver_lint_caps,
for param in generics.params.iter() {
let value = match param.kind {
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } |
+ GenericParamDefKind::Const => {
trait_ref.substs[param.index as usize].to_string()
},
GenericParamDefKind::Lifetime => continue,
}
}
- pub fn report_selection_error(&self,
- obligation: &PredicateObligation<'tcx>,
- error: &SelectionError<'tcx>,
- fallback_has_occurred: bool)
- {
+ pub fn report_selection_error(
+ &self,
+ obligation: &PredicateObligation<'tcx>,
+ error: &SelectionError<'tcx>,
+ fallback_has_occurred: bool,
+ ) {
let span = obligation.cause.span;
let mut err = match *error {
self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
+ self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
// Try to report a help message
if !trait_ref.has_infer_types() &&
/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
/// suggestion to borrow the initializer in order to use have a slice instead.
- fn suggest_borrow_on_unsized_slice(&self,
- code: &ObligationCauseCode<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>) {
+ fn suggest_borrow_on_unsized_slice(
+ &self,
+ code: &ObligationCauseCode<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx>,
+ ) {
if let &ObligationCauseCode::VariableType(node_id) = code {
let parent_node = self.tcx.hir().get_parent_node(node_id);
if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
/// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
/// suggest removing these references until we reach a type that implements the trait.
- fn suggest_remove_reference(&self,
- obligation: &PredicateObligation<'tcx>,
- err: &mut DiagnosticBuilder<'tcx>,
- trait_ref: &ty::Binder<ty::TraitRef<'tcx>>) {
+ fn suggest_remove_reference(
+ &self,
+ obligation: &PredicateObligation<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx>,
+ trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+ ) {
let trait_ref = trait_ref.skip_binder();
let span = obligation.cause.span;
}
}
+ fn suggest_semicolon_removal(
+ &self,
+ obligation: &PredicateObligation<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx>,
+ span: Span,
+ trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+ ) {
+ let hir = self.tcx.hir();
+ let parent_node = hir.get_parent_node(
+ hir.hir_to_node_id(obligation.cause.body_id),
+ );
+ let node = hir.find(parent_node);
+ if let Some(hir::Node::Item(hir::Item {
+ node: hir::ItemKind::Fn(decl, _, _, body_id),
+ ..
+ })) = node {
+ let body = hir.body(*body_id);
+ if let hir::ExprKind::Block(blk, _) = &body.value.node {
+ if decl.output.span().overlaps(span) && blk.expr.is_none() &&
+ "()" == &trait_ref.self_ty().to_string()
+ {
+ // FIXME(estebank): When encountering a method with a trait
+ // bound not satisfied in the return type with a body that has
+ // no return, suggest removal of semicolon on last statement.
+ // Once that is added, close #54771.
+ if let Some(ref stmt) = blk.stmts.last() {
+ let sp = self.tcx.sess.source_map().end_point(stmt.span);
+ err.span_label(sp, "consider removing this semicolon");
+ }
+ }
+ }
+ }
+ }
+
/// Given some node representing a fn-like thing in the HIR map,
/// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to
InternalSubsts::for_item(tcx, def_id, |param, _|
match param.kind {
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } |
+ GenericParamDefKind::Const => {
trait_ref.substs[param.index as usize]
}
}
}
// We can't monomorphize things like `fn foo<A>(...)`.
- if self.generics_of(method.def_id).own_counts().types != 0 {
+ let own_counts = self.generics_of(method.def_id).own_counts();
+ if own_counts.types + own_counts.consts != 0 {
return Some(MethodViolationCode::Generic);
}
let generics = tcx.generics_of(trait_ref.def_id);
let generic_map = generics.params.iter().filter_map(|param| {
let value = match param.kind {
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } |
+ GenericParamDefKind::Const => {
trait_ref.substs[param.index as usize].to_string()
},
GenericParamDefKind::Lifetime => return None
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::{self, Mir, interpret, ProjectionKind};
-use crate::mir::interpret::Allocation;
-use crate::ty::subst::{Kind, InternalSubsts, Subst, SubstsRef};
+use crate::mir::interpret::{ConstValue, Allocation};
+use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
use crate::traits;
use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
use crate::ty::RegionKind;
-use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
+use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
use crate::ty::TyKind::*;
+use crate::ty::{InferConst, ParamConst};
use crate::ty::GenericParamDefKind;
use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
use crate::ty::query;
use std::fmt;
use std::mem;
use std::ops::{Deref, Bound};
-use std::ptr;
use std::iter;
use std::sync::mpsc;
use std::sync::Arc;
// Make sure we don't end up with inference
// types/regions in the global interner
- if ptr::eq(local, global) {
+ if ptr_eq(local, global) {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
&ty_struct);
}
_ => false,
},
+
+ UnpackedKind::Const(ct) => match ct {
+ ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Infer(InferConst::Canonical(debruijn, b)),
+ ..
+ }) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(*debruijn, ty::INNERMOST);
+ cvar == *b
+ }
+ _ => false,
+ },
}
})
},
/// Returns `true` if self is the same as self.global_tcx().
fn is_global(self) -> bool {
- ptr::eq(self.interners, &self.global_interners)
+ ptr_eq(self.interners, &self.global_interners)
}
/// Creates a type context and call the closure with a `TyCtxt` reference
}
pub mod tls {
- use super::{GlobalCtxt, TyCtxt};
+ use super::{GlobalCtxt, TyCtxt, ptr_eq};
use std::fmt;
use std::mem;
use std::marker::PhantomData;
- use std::ptr;
use syntax_pos;
use crate::ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
{
with_context(|context| {
unsafe {
- assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
+ assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
{
with_context(|context| {
unsafe {
- assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
- assert!(ptr::eq(context.tcx.interners, tcx.interners));
+ assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
+ assert!(ptr_eq(context.tcx.interners, tcx.interners));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
#[derive(Copy, Clone)]
struct DebugStat {
total: usize,
- region_infer: usize,
+ lt_infer: usize,
ty_infer: usize,
- both_infer: usize,
+ ct_infer: usize,
+ all_infer: usize,
}
pub fn go(tcx: TyCtxt<'_, '_, '_>) {
let mut total = DebugStat {
total: 0,
- region_infer: 0, ty_infer: 0, both_infer: 0,
+ lt_infer: 0,
+ ty_infer: 0,
+ ct_infer: 0,
+ all_infer: 0,
};
$(let mut $variant = total;)*
ty::Error => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)*
};
- let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
+ let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
+ let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
variant.total += 1;
total.total += 1;
- if region { total.region_infer += 1; variant.region_infer += 1 }
+ if lt { total.lt_infer += 1; variant.lt_infer += 1 }
if ty { total.ty_infer += 1; variant.ty_infer += 1 }
- if region && ty { total.both_infer += 1; variant.both_infer += 1 }
+ if ct { total.ct_infer += 1; variant.ct_infer += 1 }
+ if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
}
- println!("Ty interner total ty region both");
+ println!("Ty interner total ty lt ct all");
$(println!(" {:18}: {uses:6} {usespc:4.1}%, \
- {ty:4.1}% {region:5.1}% {both:4.1}%",
- stringify!($variant),
- uses = $variant.total,
- usespc = $variant.total as f64 * 100.0 / total.total as f64,
- ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
- region = $variant.region_infer as f64 * 100.0 / total.total as f64,
- both = $variant.both_infer as f64 * 100.0 / total.total as f64);
- )*
+ {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
+ stringify!($variant),
+ uses = $variant.total,
+ usespc = $variant.total as f64 * 100.0 / total.total as f64,
+ ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
+ lt = $variant.lt_infer as f64 * 100.0 / total.total as f64,
+ ct = $variant.ct_infer as f64 * 100.0 / total.total as f64,
+ all = $variant.all_infer as f64 * 100.0 / total.total as f64);
+ )*
println!(" total {uses:6} \
- {ty:4.1}% {region:5.1}% {both:4.1}%",
- uses = total.total,
- ty = total.ty_infer as f64 * 100.0 / total.total as f64,
- region = total.region_infer as f64 * 100.0 / total.total as f64,
- both = total.both_infer as f64 * 100.0 / total.total as f64)
+ {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
+ uses = total.total,
+ ty = total.ty_infer as f64 * 100.0 / total.total as f64,
+ lt = total.lt_infer as f64 * 100.0 / total.total as f64,
+ ct = total.ct_infer as f64 * 100.0 / total.total as f64,
+ all = total.all_infer as f64 * 100.0 / total.total as f64)
}
}
let adt_def = self.adt_def(def_id);
let substs = InternalSubsts::for_item(self, def_id, |param, substs| {
match param.kind {
- GenericParamDefKind::Lifetime => bug!(),
+ GenericParamDefKind::Lifetime |
+ GenericParamDefKind::Const => {
+ bug!()
+ }
GenericParamDefKind::Type { has_default, .. } => {
if param.index == 0 {
ty.into()
}
#[inline]
- pub fn mk_var(self, v: TyVid) -> Ty<'tcx> {
+ pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
self.mk_infer(TyVar(v))
}
+ #[inline]
+ pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
+ self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Infer(InferConst::Var(v)),
+ ty,
+ }))
+ }
+
#[inline]
pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
self.mk_infer(IntVar(v))
self.mk_ty(Param(ParamTy { idx: index, name: name }))
}
+ #[inline]
+ pub fn mk_const_param(
+ self,
+ index: u32,
+ name: InternedString,
+ ty: Ty<'tcx>
+ ) -> &'tcx LazyConst<'tcx> {
+ self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(ParamConst { index, name }),
+ ty,
+ }))
+ }
+
#[inline]
pub fn mk_self_type(self) -> Ty<'tcx> {
self.mk_ty_param(0, keywords::SelfUpper.name().as_interned_str())
GenericParamDefKind::Lifetime => {
self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
}
- GenericParamDefKind::Type {..} => self.mk_ty_param(param.index, param.name).into(),
+ GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
+ GenericParamDefKind::Const => {
+ self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into()
+ }
}
}
}
}
+// We are comparing types with different invariant lifetimes, so `ptr::eq`
+// won't work for us.
+fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
+ t as *const () == u as *const ()
+}
+
pub fn provide(providers: &mut ty::query::Providers<'_>) {
providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();
-use crate::ty::subst::SubstsRef;
-use crate::ty::{self, Ty, TypeFlags, TypeFoldable};
+use crate::ty::subst::{SubstsRef, UnpackedKind};
+use crate::ty::{self, Ty, TypeFlags, TypeFoldable, InferConst};
+use crate::mir::interpret::ConstValue;
#[derive(Debug)]
pub struct FlagComputation {
}
}
+ fn add_const(&mut self, c: &ty::LazyConst<'_>) {
+ match c {
+ ty::LazyConst::Unevaluated(_, substs) => self.add_substs(substs),
+ // Only done to add the binder for the type. The type flags are
+ // included in `Const::type_flags`.
+ ty::LazyConst::Evaluated(ty::Const { ty, val }) => {
+ self.add_ty(ty);
+ if let ConstValue::Infer(InferConst::Canonical(debruijn, _)) = val {
+ self.add_binder(*debruijn)
+ }
+ }
+ }
+ self.add_flags(c.type_flags());
+ }
+
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
self.add_substs(projection.substs);
self.add_ty(projection.ty);
}
fn add_substs(&mut self, substs: SubstsRef<'_>) {
- for ty in substs.types() {
- self.add_ty(ty);
- }
-
- for r in substs.regions() {
- self.add_region(r);
+ for kind in substs {
+ match kind.unpack() {
+ UnpackedKind::Type(ty) => self.add_ty(ty),
+ UnpackedKind::Lifetime(lt) => self.add_region(lt),
+ UnpackedKind::Const(ct) => self.add_const(ct),
+ }
}
}
}
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
fn needs_infer(&self) -> bool {
- self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
+ self.has_type_flags(
+ TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER
+ )
}
fn has_placeholders(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER | TypeFlags::HAS_TY_PLACEHOLDER)
}
/// Indicates whether this value references only 'global'
- /// types/lifetimes that are the same regardless of what fn we are
+ /// generic parameters that are the same regardless of what fn we are
/// in. This is used for caching.
fn is_global(&self) -> bool {
!self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
}
fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
- if let ty::LazyConst::Unevaluated(..) = c {
- let projection_flags = TypeFlags::HAS_NORMALIZABLE_PROJECTION |
- TypeFlags::HAS_PROJECTION;
- if projection_flags.intersects(self.flags) {
- return true;
- }
+ let flags = c.type_flags();
+ debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
+ if flags.intersects(self.flags) {
+ true
+ } else {
+ c.super_visit_with(self)
}
- c.super_visit_with(self)
}
}
/// This is invoked by the `layout_raw` query to record the final
/// layout of each type.
- #[inline]
+ #[inline(always)]
fn record_layout_for_printing(&self, layout: TyLayout<'tcx>) {
- // If we are running with `-Zprint-type-sizes`, record layouts for
- // dumping later. Ignore layouts that are done with non-empty
- // environments or non-monomorphic layouts, as the user only wants
- // to see the stuff resulting from the final codegen session.
+ // If we are running with `-Zprint-type-sizes`, maybe record layouts
+ // for dumping later.
+ if self.tcx.sess.opts.debugging_opts.print_type_sizes {
+ self.record_layout_for_printing_outlined(layout)
+ }
+ }
+
+ fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
+ // Ignore layouts that are done with non-empty environments or
+ // non-monomorphic layouts, as the user only wants to see the stuff
+ // resulting from the final codegen session.
if
- !self.tcx.sess.opts.debugging_opts.print_type_sizes ||
layout.ty.has_param_types() ||
layout.ty.has_self_ty() ||
!self.param_env.caller_bounds.is_empty()
return;
}
- self.record_layout_for_printing_outlined(layout)
- }
-
- fn record_layout_for_printing_outlined(&self, layout: TyLayout<'tcx>) {
// (delay format until we actually need it)
let record = |kind, packed, opt_discr_size, variants| {
let type_desc = format!("{:?}", layout.ty);
pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST};
pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig};
-pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
+pub use self::sty::{InferTy, ParamTy, ParamConst, InferConst, ProjectionTy, ExistentialPredicate};
pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::RegionKind;
-pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid};
+pub use self::sty::{TyVid, IntVid, FloatVid, ConstVid, RegionVid};
pub use self::sty::BoundRegion::*;
pub use self::sty::InferTy::*;
pub use self::sty::RegionKind::*;
}
impl Visibility {
- pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt<'_, '_, '_>) -> Self {
+ pub fn from_hir(visibility: &hir::Visibility, id: hir::HirId, tcx: TyCtxt<'_, '_, '_>) -> Self {
match visibility.node {
hir::VisibilityKind::Public => Visibility::Public,
hir::VisibilityKind::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
def => Visibility::Restricted(def.def_id()),
},
hir::VisibilityKind::Inherited => {
- Visibility::Restricted(tcx.hir().get_module_parent(id))
+ Visibility::Restricted(tcx.hir().get_module_parent_by_hir_id(id))
}
}
}
const HAS_TY_PLACEHOLDER = 1 << 14;
+ const HAS_CT_INFER = 1 << 15;
+
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits;
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_TY_INFER.bits |
TypeFlags::HAS_RE_INFER.bits |
+ TypeFlags::HAS_CT_INFER.bits |
TypeFlags::HAS_RE_PLACEHOLDER.bits |
TypeFlags::HAS_RE_EARLY_BOUND.bits |
TypeFlags::HAS_FREE_REGIONS.bits |
has_default: bool,
object_lifetime_default: ObjectLifetimeDefault,
synthetic: Option<hir::SyntheticTyParamKind>,
- }
+ },
+ Const,
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct GenericParamCount {
pub lifetimes: usize,
pub types: usize,
+ pub consts: usize,
}
/// Information about the formal type/lifetime parameters associated
match param.kind {
GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
GenericParamDefKind::Type { .. } => own_counts.types += 1,
+ GenericParamDefKind::Const => own_counts.consts += 1,
};
}
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
for param in &self.params {
match param.kind {
- GenericParamDefKind::Type { .. } => return true,
+ GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
GenericParamDefKind::Lifetime => {}
}
}
if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
let param = &self.params[index as usize];
match param.kind {
- ty::GenericParamDefKind::Lifetime => param,
+ GenericParamDefKind::Lifetime => param,
_ => bug!("expected lifetime parameter, but found another generic parameter")
}
} else {
if let Some(index) = param.idx.checked_sub(self.parent_count as u32) {
let param = &self.params[index as usize];
match param.kind {
- ty::GenericParamDefKind::Type {..} => param,
+ GenericParamDefKind::Type { .. } => param,
_ => bug!("expected type parameter, but found another generic parameter")
}
} else {
.type_param(param, tcx)
}
}
+
+ /// Returns the `ConstParameterDef` associated with this `ParamConst`.
+ pub fn const_param(&'tcx self,
+ param: &ParamConst,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ -> &GenericParamDef {
+ if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
+ let param = &self.params[index as usize];
+ match param.kind {
+ GenericParamDefKind::Const => param,
+ _ => bug!("expected const parameter, but found another generic parameter")
+ }
+ } else {
+ tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
+ .const_param(param, tcx)
+ }
+ }
}
/// Bounds on generics.
parent_vis: &hir::Visibility,
trait_item_ref: &hir::TraitItemRef)
-> AssociatedItem {
- let def_id = self.hir().local_def_id(trait_item_ref.id.node_id);
+ let def_id = self.hir().local_def_id_from_hir_id(trait_item_ref.id.hir_id);
let (kind, has_self) = match trait_item_ref.kind {
hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
hir::AssociatedItemKind::Method { has_self } => {
ident: trait_item_ref.ident,
kind,
// Visibility of trait items is inherited from their traits.
- vis: Visibility::from_hir(parent_vis, trait_item_ref.id.node_id, self),
+ vis: Visibility::from_hir(parent_vis, trait_item_ref.id.hir_id, self),
defaultness: trait_item_ref.defaultness,
def_id,
container: TraitContainer(parent_def_id),
parent_def_id: DefId,
impl_item_ref: &hir::ImplItemRef)
-> AssociatedItem {
- let def_id = self.hir().local_def_id(impl_item_ref.id.node_id);
+ let def_id = self.hir().local_def_id_from_hir_id(impl_item_ref.id.hir_id);
let (kind, has_self) = match impl_item_ref.kind {
hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
hir::AssociatedItemKind::Method { has_self } => {
ident: impl_item_ref.ident,
kind,
// Visibility of trait impl items doesn't matter.
- vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.node_id, self),
+ vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.hir_id, self),
defaultness: impl_item_ref.defaultness,
def_id,
container: ImplContainer(parent_def_id),
}
fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> AssociatedItem {
- let id = tcx.hir().as_local_node_id(def_id).unwrap();
- let parent_id = tcx.hir().get_parent(id);
- let parent_def_id = tcx.hir().local_def_id(parent_id);
- let parent_item = tcx.hir().expect_item(parent_id);
+ let id = tcx.hir().as_local_hir_id(def_id).unwrap();
+ let parent_id = tcx.hir().get_parent_item(id);
+ let parent_def_id = tcx.hir().local_def_id_from_hir_id(parent_id);
+ let parent_item = tcx.hir().expect_item_by_hir_id(parent_id);
match parent_item.node {
hir::ItemKind::Impl(.., ref impl_item_refs) => {
- if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.node_id == id) {
+ if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
let assoc_item = tcx.associated_item_from_impl_item_ref(parent_def_id,
impl_item_ref);
debug_assert_eq!(assoc_item.def_id, def_id);
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
- if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.node_id == id) {
+ if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.hir_id == id) {
let assoc_item = tcx.associated_item_from_trait_item_ref(parent_def_id,
&parent_item.vis,
trait_item_ref);
hir::ItemKind::Trait(.., ref trait_item_refs) => {
trait_item_refs.iter()
.map(|trait_item_ref| trait_item_ref.id)
- .map(|id| tcx.hir().local_def_id(id.node_id))
+ .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
.collect()
}
hir::ItemKind::Impl(.., ref impl_item_refs) => {
impl_item_refs.iter()
.map(|impl_item_ref| impl_item_ref.id)
- .map(|id| tcx.hir().local_def_id(id.node_id))
+ .map(|id| tcx.hir().local_def_id_from_hir_id(id.hir_id))
.collect()
}
hir::ItemKind::TraitAlias(..) => vec![],
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
use rustc_data_structures::OnDrop;
+use rustc_data_structures::jobserver;
use syntax_pos::Span;
use crate::ty::tls;
// we have to be in the `wait` call. This is ensured by the deadlock handler
// getting the self.info lock.
rayon_core::mark_blocked();
+ jobserver::release_thread();
waiter.condvar.wait(&mut info);
+ // Release the lock before we potentially block in `acquire_thread`
+ mem::drop(info);
+ jobserver::acquire_thread();
}
}
(UnpackedKind::Type(unpacked), x) => {
bug!("impossible case reached: can't relate: {:?} with {:?}", unpacked, x)
}
+ (UnpackedKind::Const(_), _) => {
+ unimplemented!() // FIXME(const_generics)
+ }
}
}
}
use crate::mir::ProjectionKind;
use crate::mir::interpret::ConstValue;
-use crate::ty::{self, Lift, Ty, TyCtxt};
+use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use smallvec::SmallVec;
use crate::mir::interpret;
+use std::marker::PhantomData;
use std::rc::Rc;
///////////////////////////////////////////////////////////////////////////
crate::ty::BoundRegion,
crate::ty::ClosureKind,
crate::ty::IntVarValue,
+ crate::ty::ParamConst,
crate::ty::ParamTy,
crate::ty::UniverseIndex,
crate::ty::Variance,
type Lifted = ConstValue<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
match *self {
+ ConstValue::Param(param) => Some(ConstValue::Param(param)),
+ ConstValue::Infer(infer) => {
+ Some(ConstValue::Infer(match infer {
+ InferConst::Var(vid) => InferConst::Var(vid.lift_to_tcx(tcx)?),
+ InferConst::Fresh(i) => InferConst::Fresh(i),
+ InferConst::Canonical(debrujin, var) => InferConst::Canonical(debrujin, var),
+ }))
+ }
ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
ConstValue::ByRef(ptr, alloc) => Some(ConstValue::ByRef(
}
}
+impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
+ type Lifted = ConstVid<'tcx>;
+ fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ Some(ConstVid {
+ index: self.index,
+ phantom: PhantomData,
+ })
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// TypeFoldable implementations.
//
use smallvec::SmallVec;
use std::iter;
use std::cmp::Ordering;
+use std::marker::PhantomData;
use rustc_target::spec::abi;
use syntax::ast::{self, Ident};
use syntax::symbol::{keywords, InternedString};
}
}
+#[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
+pub struct ParamConst {
+ pub index: u32,
+ pub name: InternedString,
+}
+
+impl<'a, 'gcx, 'tcx> ParamConst {
+ pub fn new(index: u32, name: InternedString) -> ParamConst {
+ ParamConst { index, name }
+ }
+
+ pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
+ ParamConst::new(def.index, def.name)
+ }
+
+ pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
+ tcx.mk_const_param(self.index, self.name, ty)
+ }
+}
+
/// A [De Bruijn index][dbi] is a standard means of representing
/// regions (and perhaps later types) in a higher-ranked setting. In
/// particular, imagine a type like this:
pub index: u32,
}
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub struct ConstVid<'tcx> {
+ pub index: u32,
+ pub phantom: PhantomData<&'tcx ()>,
+}
+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct IntVid {
pub index: u32,
pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
self.assert_usize(tcx).expect("expected `LazyConst` to contain a usize")
}
+
+ pub fn type_flags(&self) -> TypeFlags {
+ // FIXME(const_generics): incorporate substs flags.
+ let flags = match self {
+ LazyConst::Unevaluated(..) => {
+ TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION
+ }
+ LazyConst::Evaluated(c) => {
+ c.type_flags()
+ }
+ };
+
+ debug!("type_flags({:?}) = {:?}", self, flags);
+
+ flags
+ }
}
/// Typed constant value.
self.assert_usize(tcx).unwrap_or_else(||
bug!("expected constant usize, got {:#?}", self))
}
+
+ pub fn type_flags(&self) -> TypeFlags {
+ let mut flags = self.ty.flags;
+
+ match self.val {
+ ConstValue::Param(_) => {
+ flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
+ flags |= TypeFlags::HAS_PARAMS;
+ }
+ ConstValue::Infer(infer) => {
+ flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
+ flags |= TypeFlags::HAS_CT_INFER;
+ match infer {
+ InferConst::Fresh(_) |
+ InferConst::Canonical(_, _) => {}
+ InferConst::Var(_) => {
+ flags |= TypeFlags::KEEP_IN_LOCAL_TCX;
+ }
+ }
+ }
+ _ => {}
+ }
+
+ debug!("type_flags({:?}) = {:?}", self, flags);
+
+ flags
+ }
}
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {}
+
+/// An inference variable for a const, for use in const generics.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+pub enum InferConst<'tcx> {
+ /// Infer the value of the const.
+ Var(ConstVid<'tcx>),
+ /// A fresh const variable. See `infer::freshen` for more details.
+ Fresh(u32),
+ /// Canonicalized const variable, used only when preparing a trait query.
+ Canonical(DebruijnIndex, BoundVar),
+}
use crate::hir::def_id::DefId;
use crate::infer::canonical::Canonical;
-use crate::ty::{self, Lift, List, Ty, TyCtxt};
+use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use crate::mir::interpret::ConstValue;
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
use syntax_pos::{Span, DUMMY_SP};
use std::num::NonZeroUsize;
/// An entity in the Rust type system, which can be one of
-/// several kinds (only types and lifetimes for now).
+/// several kinds (types, lifetimes, and consts).
/// To reduce memory usage, a `Kind` is a interned pointer,
/// with the lowest 2 bits being reserved for a tag to
-/// indicate the type (`Ty` or `Region`) it points to.
+/// indicate the type (`Ty`, `Region`, or `Const`) it points to.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Kind<'tcx> {
ptr: NonZeroUsize,
- marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>)>
+ marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::LazyConst<'tcx>)>
}
const TAG_MASK: usize = 0b11;
const TYPE_TAG: usize = 0b00;
const REGION_TAG: usize = 0b01;
+const CONST_TAG: usize = 0b10;
#[derive(Debug, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord)]
pub enum UnpackedKind<'tcx> {
Lifetime(ty::Region<'tcx>),
Type(Ty<'tcx>),
+ Const(&'tcx ty::LazyConst<'tcx>),
}
impl<'tcx> UnpackedKind<'tcx> {
assert_eq!(mem::align_of_val(ty) & TAG_MASK, 0);
(TYPE_TAG, ty as *const _ as usize)
}
+ UnpackedKind::Const(ct) => {
+ // Ensure we can use the tag bits.
+ assert_eq!(mem::align_of_val(ct) & TAG_MASK, 0);
+ (CONST_TAG, ct as *const _ as usize)
+ }
};
Kind {
}
}
+impl<'tcx> From<&'tcx ty::LazyConst<'tcx>> for Kind<'tcx> {
+ fn from(c: &'tcx ty::LazyConst<'tcx>) -> Kind<'tcx> {
+ UnpackedKind::Const(c).pack()
+ }
+}
+
impl<'tcx> Kind<'tcx> {
#[inline]
pub fn unpack(self) -> UnpackedKind<'tcx> {
match ptr & TAG_MASK {
REGION_TAG => UnpackedKind::Lifetime(&*((ptr & !TAG_MASK) as *const _)),
TYPE_TAG => UnpackedKind::Type(&*((ptr & !TAG_MASK) as *const _)),
+ CONST_TAG => UnpackedKind::Const(&*((ptr & !TAG_MASK) as *const _)),
_ => intrinsics::unreachable()
}
}
match self.unpack() {
UnpackedKind::Lifetime(lt) => write!(f, "{:?}", lt),
UnpackedKind::Type(ty) => write!(f, "{:?}", ty),
+ UnpackedKind::Const(ct) => write!(f, "{:?}", ct),
}
}
}
match self.unpack() {
UnpackedKind::Lifetime(lt) => write!(f, "{}", lt),
UnpackedKind::Type(ty) => write!(f, "{}", ty),
+ UnpackedKind::Const(ct) => write!(f, "{}", ct),
}
}
}
fn lift_to_tcx<'cx, 'gcx>(&self, tcx: TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Self::Lifted> {
match self.unpack() {
- UnpackedKind::Lifetime(a) => a.lift_to_tcx(tcx).map(|a| a.into()),
- UnpackedKind::Type(a) => a.lift_to_tcx(tcx).map(|a| a.into()),
+ UnpackedKind::Lifetime(lt) => lt.lift_to_tcx(tcx).map(|lt| lt.into()),
+ UnpackedKind::Type(ty) => ty.lift_to_tcx(tcx).map(|ty| ty.into()),
+ UnpackedKind::Const(ct) => ct.lift_to_tcx(tcx).map(|ct| ct.into()),
}
}
}
match self.unpack() {
UnpackedKind::Lifetime(lt) => lt.fold_with(folder).into(),
UnpackedKind::Type(ty) => ty.fold_with(folder).into(),
+ UnpackedKind::Const(ct) => ct.fold_with(folder).into(),
}
}
match self.unpack() {
UnpackedKind::Lifetime(lt) => lt.visit_with(visitor),
UnpackedKind::Type(ty) => ty.visit_with(visitor),
+ UnpackedKind::Const(ct) => ct.visit_with(visitor),
}
}
}
ty::BoundRegion::BrNamed(param.def_id, param.name)
)).into()
}
+
+ ty::GenericParamDefKind::Const => {
+ tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Infer(
+ InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index))
+ ),
+ ty: tcx.type_of(def_id),
+ })).into()
+ }
}
})
}
})
}
+ #[inline]
+ pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::LazyConst<'tcx>> + 'a {
+ self.iter().filter_map(|k| {
+ if let UnpackedKind::Const(ct) = k.unpack() {
+ Some(ct)
+ } else {
+ None
+ }
+ })
+ }
+
+ #[inline]
+ pub fn non_erasable_generics(
+ &'a self
+ ) -> impl DoubleEndedIterator<Item = UnpackedKind<'tcx>> + 'a {
+ self.iter().filter_map(|k| {
+ match k.unpack() {
+ UnpackedKind::Lifetime(_) => None,
+ generic => Some(generic),
+ }
+ })
+ }
+
#[inline]
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
if let UnpackedKind::Type(ty) = self[i].unpack() {
}
}
+ #[inline]
+ pub fn const_at(&self, i: usize) -> &'tcx ty::LazyConst<'tcx> {
+ if let UnpackedKind::Const(ct) = self[i].unpack() {
+ ct
+ } else {
+ bug!("expected const for param #{} in {:?}", i, self);
+ }
+ }
+
#[inline]
pub fn type_for_def(&self, def: &ty::GenericParamDef) -> Kind<'tcx> {
self.type_at(def.index as usize).into()
return t1;
}
+
+ fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+ if !c.needs_subst() {
+ return c;
+ }
+
+ if let ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(p),
+ ..
+ }) = c {
+ self.const_for_param(*p, c)
+ } else {
+ c.super_fold_with(self)
+ }
+ }
}
impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
self.shift_vars_through_binders(ty)
}
+ fn const_for_param(
+ &self,
+ p: ParamConst,
+ source_cn: &'tcx ty::LazyConst<'tcx>
+ ) -> &'tcx ty::LazyConst<'tcx> {
+ // Look up the const in the substitutions. It really should be in there.
+ let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
+ let cn = match opt_cn {
+ Some(UnpackedKind::Const(cn)) => cn,
+ _ => {
+ let span = self.span.unwrap_or(DUMMY_SP);
+ span_bug!(
+ span,
+ "Const parameter `{:?}` ({:?}/{}) out of range \
+ when substituting (root type={:?}) substs={:?}",
+ p,
+ source_cn,
+ p.index,
+ self.root_ty,
+ self.substs,
+ );
+ }
+ };
+
+ // FIXME(const_generics): shift const through binders
+ cn
+ }
+
/// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs
/// when we are substituting a type with escaping bound vars into a context where we have
/// passed through binders. That's quite a mouthful. Let's see an example:
use crate::ty::query::TyCtxtAt;
use crate::ty::TyKind::*;
use crate::ty::layout::{Integer, IntegerExt};
+use crate::mir::interpret::ConstValue;
use crate::util::common::ErrorReported;
use crate::middle::lang_items;
}) => {
!impl_generics.type_param(pt, self).pure_wrt_drop
}
- UnpackedKind::Lifetime(_) | UnpackedKind::Type(_) => {
- // not a type or region param - this should be reported
+ UnpackedKind::Const(&ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(ref pc),
+ ..
+ })) => {
+ !impl_generics.const_param(pc, self).pure_wrt_drop
+ }
+ UnpackedKind::Lifetime(_) |
+ UnpackedKind::Type(_) |
+ UnpackedKind::Const(_) => {
+ // Not a type, const or region param: this should be reported
// as an error.
false
}
Some(ty::Binder::bind(env_ty))
}
- /// Given the `DefId` of some item that has no type parameters, make
+ /// Given the `DefId` of some item that has no type or const parameters, make
/// a suitable "empty substs" for it.
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> SubstsRef<'tcx> {
InternalSubsts::for_item(self, item_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => self.types.re_erased.into(),
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } => {
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
}
+ GenericParamDefKind::Const { .. } => {
+ bug!("empty_substs_for_def_id: {:?} has const parameters", item_def_id)
+ }
}
})
}
use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst};
+use crate::mir::interpret::ConstValue;
use crate::util::nodemap::FxHashSet;
use std::cell::Cell;
GenericParamDefKind::Type { has_default, .. } => {
Some((param.def_id, has_default))
}
+ GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
}).peekable();
let has_default = {
let has_default = type_params.peek().map(|(_, has_default)| has_default);
)?;
}
+ // FIXME(const_generics::defaults)
+ let consts = substs.consts();
+
+ for ct in consts {
+ start_or_continue(f, "<", ", ")?;
+ ct.print_display(f, self)?;
+ }
+
start_or_continue(f, "", ">")?;
// For values, also print their name and type parameters.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let type_name = match self.kind {
ty::GenericParamDefKind::Lifetime => "Lifetime",
- ty::GenericParamDefKind::Type {..} => "Type",
+ ty::GenericParamDefKind::Type { .. } => "Type",
+ ty::GenericParamDefKind::Const => "Const",
};
write!(f, "{}({}, {:?}, {})",
type_name,
}
}
+impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "_#{}f", self.index)
+ }
+}
+
impl fmt::Debug for ty::IntVid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "_#{}i", self.index)
write!(f, "_")?;
}
ty::LazyConst::Evaluated(c) => ty::tls::with(|tcx| {
- write!(f, "{}", c.unwrap_usize(tcx))
+ match c.val {
+ ConstValue::Infer(..) => write!(f, "_"),
+ ConstValue::Param(ParamConst { name, .. }) =>
+ write!(f, "{}", name),
+ _ => write!(f, "{}", c.unwrap_usize(tcx)),
+ }
})?,
}
write!(f, "]")
}
}
+define_print! {
+ ('tcx) ConstValue<'tcx>, (self, f, cx) {
+ display {
+ match self {
+ ConstValue::Infer(..) => write!(f, "_"),
+ ConstValue::Param(ParamConst { name, .. }) => write!(f, "{}", name),
+ _ => write!(f, "{:?}", self),
+ }
+ }
+ }
+}
+
+define_print! {
+ ('tcx) ty::Const<'tcx>, (self, f, cx) {
+ display {
+ write!(f, "{} : {}", self.val, self.ty)
+ }
+ }
+}
+
+define_print! {
+ ('tcx) ty::LazyConst<'tcx>, (self, f, cx) {
+ display {
+ match self {
+ ty::LazyConst::Unevaluated(..) => write!(f, "_ : _"),
+ ty::LazyConst::Evaluated(c) => write!(f, "{}", c),
+ }
+ }
+ }
+}
+
define_print! {
() ty::ParamTy, (self, f, cx) {
display {
}
}
+define_print! {
+ () ty::ParamConst, (self, f, cx) {
+ display {
+ write!(f, "{}", self.name)
+ }
+ debug {
+ write!(f, "{}/#{}", self.name, self.index)
+ }
+ }
+}
+
define_print! {
('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate<T, U>,
(self, f, cx) {
-use std::collections::{BTreeMap, HashMap};
use std::fs;
-use std::io::{self, Write};
+use std::io::{BufWriter, Write};
+use std::mem;
+use std::process;
use std::thread::ThreadId;
-use std::time::Instant;
+use std::time::{Duration, Instant, SystemTime};
-use crate::session::config::{Options, OptLevel};
+use crate::session::config::Options;
+
+use rustc_data_structures::fx::FxHashMap;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum ProfileCategory {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ProfilerEvent {
- QueryStart { query_name: &'static str, category: ProfileCategory, time: Instant },
- QueryEnd { query_name: &'static str, category: ProfileCategory, time: Instant },
- GenericActivityStart { category: ProfileCategory, time: Instant },
- GenericActivityEnd { category: ProfileCategory, time: Instant },
- QueryCacheHit { query_name: &'static str, category: ProfileCategory },
- QueryCount { query_name: &'static str, category: ProfileCategory, count: usize },
- IncrementalLoadResultStart { query_name: &'static str, time: Instant },
- IncrementalLoadResultEnd { query_name: &'static str, time: Instant },
- QueryBlockedStart { query_name: &'static str, category: ProfileCategory, time: Instant },
- QueryBlockedEnd { query_name: &'static str, category: ProfileCategory, time: Instant },
+ QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 },
+ QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
+ GenericActivityStart { category: ProfileCategory, time: u64 },
+ GenericActivityEnd { category: ProfileCategory, time: u64 },
+ IncrementalLoadResultStart { query_name: &'static str, time: u64 },
+ IncrementalLoadResultEnd { query_name: &'static str, time: u64 },
+ QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 },
+ QueryCount { query_name: &'static str, category: ProfileCategory, count: usize, time: u64 },
+ QueryBlockedStart { query_name: &'static str, category: ProfileCategory, time: u64 },
+ QueryBlockedEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
}
impl ProfilerEvent {
- fn is_start_event(&self) -> bool {
+ fn timestamp(&self) -> u64 {
use self::ProfilerEvent::*;
match self {
- QueryStart { .. } |
- GenericActivityStart { .. } |
- IncrementalLoadResultStart { .. } |
- QueryBlockedStart { .. } => true,
-
- QueryEnd { .. } |
- GenericActivityEnd { .. } |
- QueryCacheHit { .. } |
- QueryCount { .. } |
- IncrementalLoadResultEnd { .. } |
- QueryBlockedEnd { .. } => false,
- }
- }
-}
-
-pub struct SelfProfiler {
- events: HashMap<ThreadId, Vec<ProfilerEvent>>,
-}
-
-struct CategoryResultData {
- query_times: BTreeMap<&'static str, u64>,
- query_cache_stats: BTreeMap<&'static str, (u64, u64)>, //(hits, total)
-}
-
-impl CategoryResultData {
- fn new() -> CategoryResultData {
- CategoryResultData {
- query_times: BTreeMap::new(),
- query_cache_stats: BTreeMap::new(),
- }
- }
-
- fn total_time(&self) -> u64 {
- self.query_times.iter().map(|(_, time)| time).sum()
- }
-
- fn total_cache_data(&self) -> (u64, u64) {
- let (mut hits, mut total) = (0, 0);
-
- for (_, (h, t)) in &self.query_cache_stats {
- hits += h;
- total += t;
+ QueryStart { time, .. } |
+ QueryEnd { time, .. } |
+ GenericActivityStart { time, .. } |
+ GenericActivityEnd { time, .. } |
+ QueryCacheHit { time, .. } |
+ QueryCount { time, .. } |
+ IncrementalLoadResultStart { time, .. } |
+ IncrementalLoadResultEnd { time, .. } |
+ QueryBlockedStart { time, .. } |
+ QueryBlockedEnd { time, .. } => *time
}
-
- (hits, total)
}
}
-impl Default for CategoryResultData {
- fn default() -> CategoryResultData {
- CategoryResultData::new()
- }
-}
-
-struct CalculatedResults {
- categories: BTreeMap<ProfileCategory, CategoryResultData>,
- crate_name: Option<String>,
- optimization_level: OptLevel,
- incremental: bool,
- verbose: bool,
+fn thread_id_to_u64(tid: ThreadId) -> u64 {
+ unsafe { mem::transmute::<ThreadId, u64>(tid) }
}
-impl CalculatedResults {
- fn new() -> CalculatedResults {
- CalculatedResults {
- categories: BTreeMap::new(),
- crate_name: None,
- optimization_level: OptLevel::No,
- incremental: false,
- verbose: false,
- }
- }
-
- fn consolidate(mut cr1: CalculatedResults, cr2: CalculatedResults) -> CalculatedResults {
- for (category, data) in cr2.categories {
- let cr1_data = cr1.categories.entry(category).or_default();
-
- for (query, time) in data.query_times {
- *cr1_data.query_times.entry(query).or_default() += time;
- }
-
- for (query, (hits, total)) in data.query_cache_stats {
- let (h, t) = cr1_data.query_cache_stats.entry(query).or_insert((0, 0));
- *h += hits;
- *t += total;
- }
- }
-
- cr1
- }
-
- fn total_time(&self) -> u64 {
- self.categories.iter().map(|(_, data)| data.total_time()).sum()
- }
-
- fn with_options(mut self, opts: &Options) -> CalculatedResults {
- self.crate_name = opts.crate_name.clone();
- self.optimization_level = opts.optimize;
- self.incremental = opts.incremental.is_some();
- self.verbose = opts.debugging_opts.verbose;
-
- self
- }
-}
-
-fn time_between_ns(start: Instant, end: Instant) -> u64 {
- if start < end {
- let time = end - start;
- (time.as_secs() * 1_000_000_000) + (time.subsec_nanos() as u64)
- } else {
- debug!("time_between_ns: ignorning instance of end < start");
- 0
- }
-}
-
-fn calculate_percent(numerator: u64, denominator: u64) -> f32 {
- if denominator > 0 {
- ((numerator as f32) / (denominator as f32)) * 100.0
- } else {
- 0.0
- }
+pub struct SelfProfiler {
+ events: FxHashMap<ThreadId, Vec<ProfilerEvent>>,
+ start_time: SystemTime,
+ start_instant: Instant,
}
impl SelfProfiler {
pub fn new() -> SelfProfiler {
- let mut profiler = SelfProfiler {
- events: HashMap::new(),
+ let profiler = SelfProfiler {
+ events: Default::default(),
+ start_time: SystemTime::now(),
+ start_instant: Instant::now(),
};
- profiler.start_activity(ProfileCategory::Other);
-
profiler
}
pub fn start_activity(&mut self, category: ProfileCategory) {
self.record(ProfilerEvent::GenericActivityStart {
category,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
pub fn end_activity(&mut self, category: ProfileCategory) {
self.record(ProfilerEvent::GenericActivityEnd {
category,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
query_name,
category,
count,
+ time: self.get_time_from_start(),
})
}
self.record(ProfilerEvent::QueryCacheHit {
query_name,
category,
+ time: self.get_time_from_start(),
})
}
self.record(ProfilerEvent::QueryStart {
query_name,
category,
- time: Instant::now(),
+ time: self.get_time_from_start(),
});
}
self.record(ProfilerEvent::QueryEnd {
query_name,
category,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
pub fn incremental_load_result_start(&mut self, query_name: &'static str) {
self.record(ProfilerEvent::IncrementalLoadResultStart {
query_name,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
pub fn incremental_load_result_end(&mut self, query_name: &'static str) {
self.record(ProfilerEvent::IncrementalLoadResultEnd {
query_name,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
self.record(ProfilerEvent::QueryBlockedStart {
query_name,
category,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
self.record(ProfilerEvent::QueryBlockedEnd {
query_name,
category,
- time: Instant::now(),
+ time: self.get_time_from_start(),
})
}
events.push(event);
}
- fn calculate_thread_results(events: &Vec<ProfilerEvent>) -> CalculatedResults {
- use self::ProfilerEvent::*;
-
- assert!(
- events.last().map(|e| !e.is_start_event()).unwrap_or(true),
- "there was an event running when calculate_reslts() was called"
- );
-
- let mut results = CalculatedResults::new();
-
- //(event, child time to subtract)
- let mut query_stack = Vec::new();
-
- for event in events {
- match event {
- QueryStart { .. } | GenericActivityStart { .. } => {
- query_stack.push((event, 0));
- },
- QueryEnd { query_name, category, time: end_time } => {
- let previous_query = query_stack.pop();
- if let Some((QueryStart {
- query_name: p_query_name,
- time: start_time,
- category: _ }, child_time_to_subtract)) = previous_query {
- assert_eq!(
- p_query_name,
- query_name,
- "Saw a query end but the previous query wasn't the corresponding start"
- );
-
- let time_ns = time_between_ns(*start_time, *end_time);
- let self_time_ns = time_ns - child_time_to_subtract;
- let result_data = results.categories.entry(*category).or_default();
+ #[inline]
+ fn get_time_from_start(&self) -> u64 {
+ let duration = Instant::now() - self.start_instant;
+ duration.as_nanos() as u64
+ }
- *result_data.query_times.entry(query_name).or_default() += self_time_ns;
+ pub fn dump_raw_events(&self, opts: &Options) {
+ use self::ProfilerEvent::*;
- if let Some((_, child_time_to_subtract)) = query_stack.last_mut() {
- *child_time_to_subtract += time_ns;
- }
- } else {
- bug!("Saw a query end but the previous event wasn't a query start");
- }
+ let pid = process::id();
+
+ let filename =
+ format!("{}.profile_events.json", opts.crate_name.clone().unwrap_or_default());
+
+ let mut file = BufWriter::new(fs::File::create(filename).unwrap());
+
+ let threads: Vec<_> =
+ self.events
+ .keys()
+ .into_iter()
+ .map(|tid| format!("{}", thread_id_to_u64(*tid)))
+ .collect();
+
+ write!(file,
+ "{{\
+ \"processes\": {{\
+ \"{}\": {{\
+ \"threads\": [{}],\
+ \"crate_name\": \"{}\",\
+ \"opt_level\": \"{:?}\",\
+ \"incremental\": {}\
+ }}\
+ }},\
+ \"events\": [\
+ ",
+ pid,
+ threads.join(","),
+ opts.crate_name.clone().unwrap_or_default(),
+ opts.optimize,
+ if opts.incremental.is_some() { "true" } else { "false" },
+ ).unwrap();
+
+ let mut is_first = true;
+ for (thread_id, events) in &self.events {
+ let thread_id = thread_id_to_u64(*thread_id);
+
+ for event in events {
+ if is_first {
+ is_first = false;
+ } else {
+ writeln!(file, ",").unwrap();
}
- GenericActivityEnd { category, time: end_time } => {
- let previous_event = query_stack.pop();
- if let Some((GenericActivityStart {
- category: previous_category,
- time: start_time }, child_time_to_subtract)) = previous_event {
- assert_eq!(
- previous_category,
- category,
- "Saw an end but the previous event wasn't the corresponding start"
- );
-
- let time_ns = time_between_ns(*start_time, *end_time);
- let self_time_ns = time_ns - child_time_to_subtract;
- let result_data = results.categories.entry(*category).or_default();
-
- *result_data.query_times
- .entry("{time spent not running queries}")
- .or_default() += self_time_ns;
-
- if let Some((_, child_time_to_subtract)) = query_stack.last_mut() {
- *child_time_to_subtract += time_ns;
- }
- } else {
- bug!("Saw an activity end but the previous event wasn't an activity start");
- }
- },
- QueryCacheHit { category, query_name } => {
- let result_data = results.categories.entry(*category).or_default();
-
- let (hits, total) =
- result_data.query_cache_stats.entry(query_name).or_insert((0, 0));
- *hits += 1;
- *total += 1;
- },
- QueryCount { category, query_name, count } => {
- let result_data = results.categories.entry(*category).or_default();
-
- let (_, totals) =
- result_data.query_cache_stats.entry(query_name).or_insert((0, 0));
- *totals += *count as u64;
- },
- //we don't summarize incremental load result events in the simple output mode
- IncrementalLoadResultStart { .. } | IncrementalLoadResultEnd { .. } => { },
- //we don't summarize parallel query blocking in the simple output mode
- QueryBlockedStart { .. } | QueryBlockedEnd { .. } => { },
- }
- }
- //normalize the times to ms
- for (_, data) in &mut results.categories {
- for (_, time) in &mut data.query_times {
- *time = *time / 1_000_000;
- }
- }
-
- results
- }
-
- fn get_results(&self, opts: &Options) -> CalculatedResults {
- self.events
- .iter()
- .map(|(_, r)| SelfProfiler::calculate_thread_results(r))
- .fold(CalculatedResults::new(), CalculatedResults::consolidate)
- .with_options(opts)
- }
-
- pub fn print_results(&mut self, opts: &Options) {
- self.end_activity(ProfileCategory::Other);
-
- let results = self.get_results(opts);
-
- let total_time = results.total_time() as f32;
-
- let out = io::stderr();
- let mut lock = out.lock();
-
- let crate_name = results.crate_name.map(|n| format!(" for {}", n)).unwrap_or_default();
-
- writeln!(lock, "Self profiling results{}:", crate_name).unwrap();
- writeln!(lock).unwrap();
-
- writeln!(lock, "| Phase | Time (ms) \
- | Time (%) | Queries | Hits (%)")
- .unwrap();
- writeln!(lock, "| ----------------------------------------- | -------------- \
- | -------- | -------------- | --------")
- .unwrap();
-
- let mut categories: Vec<_> = results.categories.iter().collect();
- categories.sort_by_cached_key(|(_, d)| d.total_time());
-
- for (category, data) in categories.iter().rev() {
- let (category_hits, category_total) = data.total_cache_data();
- let category_hit_percent = calculate_percent(category_hits, category_total);
-
- writeln!(
- lock,
- "| {0: <41} | {1: >14} | {2: >8.2} | {3: >14} | {4: >8}",
- format!("{:?}", category),
- data.total_time(),
- ((data.total_time() as f32) / total_time) * 100.0,
- category_total,
- format!("{:.2}", category_hit_percent),
- ).unwrap();
-
- //in verbose mode, show individual query data
- if results.verbose {
- //don't show queries that took less than 1ms
- let mut times: Vec<_> = data.query_times.iter().filter(|(_, t)| **t > 0).collect();
- times.sort_by(|(_, time1), (_, time2)| time2.cmp(time1));
-
- for (query, time) in times {
- let (hits, total) = data.query_cache_stats.get(query).unwrap_or(&(0, 0));
- let hit_percent = calculate_percent(*hits, *total);
-
- writeln!(
- lock,
- "| - {0: <39} | {1: >14} | {2: >8.2} | {3: >14} | {4: >8}",
- query,
- time,
- ((*time as f32) / total_time) * 100.0,
- total,
- format!("{:.2}", hit_percent),
- ).unwrap();
+ let (secs, nanos) = {
+ let time = self.start_time + Duration::from_nanos(event.timestamp());
+ let time_since_unix =
+ time.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_default();
+ (time_since_unix.as_secs(), time_since_unix.subsec_nanos())
+ };
+
+ match event {
+ QueryStart { query_name, category, time: _ } =>
+ write!(file,
+ "{{ \
+ \"QueryStart\": {{ \
+ \"query_name\": \"{}\",\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ QueryEnd { query_name, category, time: _ } =>
+ write!(file,
+ "{{\
+ \"QueryEnd\": {{\
+ \"query_name\": \"{}\",\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ GenericActivityStart { category, time: _ } =>
+ write!(file,
+ "{{
+ \"GenericActivityStart\": {{\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ GenericActivityEnd { category, time: _ } =>
+ write!(file,
+ "{{\
+ \"GenericActivityEnd\": {{\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ QueryCacheHit { query_name, category, time: _ } =>
+ write!(file,
+ "{{\
+ \"QueryCacheHit\": {{\
+ \"query_name\": \"{}\",\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ QueryCount { query_name, category, count, time: _ } =>
+ write!(file,
+ "{{\
+ \"QueryCount\": {{\
+ \"query_name\": \"{}\",\
+ \"category\": \"{:?}\",\
+ \"count\": {},\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ category,
+ count,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ IncrementalLoadResultStart { query_name, time: _ } =>
+ write!(file,
+ "{{\
+ \"IncrementalLoadResultStart\": {{\
+ \"query_name\": \"{}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ IncrementalLoadResultEnd { query_name, time: _ } =>
+ write!(file,
+ "{{\
+ \"IncrementalLoadResultEnd\": {{\
+ \"query_name\": \"{}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ QueryBlockedStart { query_name, category, time: _ } =>
+ write!(file,
+ "{{\
+ \"QueryBlockedStart\": {{\
+ \"query_name\": \"{}\",\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap(),
+ QueryBlockedEnd { query_name, category, time: _ } =>
+ write!(file,
+ "{{\
+ \"QueryBlockedEnd\": {{\
+ \"query_name\": \"{}\",\
+ \"category\": \"{:?}\",\
+ \"time\": {{\
+ \"secs\": {},\
+ \"nanos\": {}\
+ }},\
+ \"thread_id\": {}\
+ }}\
+ }}",
+ query_name,
+ category,
+ secs,
+ nanos,
+ thread_id,
+ ).unwrap()
}
}
}
- writeln!(lock).unwrap();
- writeln!(lock, "Optimization level: {:?}", opts.optimize).unwrap();
- writeln!(lock, "Incremental: {}", if results.incremental { "on" } else { "off" }).unwrap();
- }
-
- pub fn save_results(&self, opts: &Options) {
- let results = self.get_results(opts);
-
- let compilation_options =
- format!("{{ \"optimization_level\": \"{:?}\", \"incremental\": {} }}",
- results.optimization_level,
- if results.incremental { "true" } else { "false" });
-
- let mut category_data = String::new();
-
- for (category, data) in &results.categories {
- let (hits, total) = data.total_cache_data();
- let hit_percent = calculate_percent(hits, total);
-
- category_data.push_str(&format!("{{ \"category\": \"{:?}\", \"time_ms\": {}, \
- \"query_count\": {}, \"query_hits\": {} }}",
- category,
- data.total_time(),
- total,
- format!("{:.2}", hit_percent)));
- }
-
- let json = format!("{{ \"category_data\": {}, \"compilation_options\": {} }}",
- category_data,
- compilation_options);
-
- fs::write("self_profiler_results.json", json).unwrap();
+ write!(file, "] }}").unwrap();
}
}
use rustc::middle::mem_categorization::Categorization;
use rustc::middle::region;
use rustc::ty::{self, TyCtxt, RegionKind};
-use syntax::ast;
use syntax_pos::Span;
use rustc::hir;
use rustc::hir::Node;
self.check_assignment(assignment_id.local_id, assignment_span, assignee_cmt);
}
- fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) { }
+ fn decl_without_init(&mut self, _id: hir::HirId, _span: Span) { }
}
pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
// Check for reassignments to (immutable) local variables. This
// needs to be done here instead of in check_loans because we
// depend on move data.
- if let Categorization::Local(local_id) = assignee_cmt.cat {
+ if let Categorization::Local(hir_id) = assignee_cmt.cat {
let lp = opt_loan_path(assignee_cmt).unwrap();
self.move_data.each_assignment_of(assignment_id, &lp, |assign| {
if assignee_cmt.mutbl.is_mutable() {
- let hir_id = self.bccx.tcx.hir().node_to_hir_id(local_id);
self.bccx.used_mut_nodes.borrow_mut().insert(hir_id);
} else {
self.bccx.report_reassigned_immutable_variable(
use rustc::ty::{self, Ty};
use std::rc::Rc;
-use syntax::ast;
use syntax_pos::Span;
use rustc::hir::*;
use rustc::hir::Node;
/// with a reference to the let
fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> PatternSource<'tcx> {
- let parent = tcx.hir().get_parent_node(pat.id);
+ let parent = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
- match tcx.hir().get(parent) {
+ match tcx.hir().get_by_hir_id(parent) {
Node::Expr(ref e) => {
// the enclosing expression must be a `match` or something else
assert!(match e.node {
pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_data: &MoveData<'tcx>,
- var_id: ast::NodeId,
+ var_id: hir::HirId,
var_ty: Ty<'tcx>) {
let loan_path = Rc::new(LoanPath::new(LpVar(var_id), var_ty));
- let hir_id = bccx.tcx.hir().node_to_hir_id(var_id);
- move_data.add_move(bccx.tcx, loan_path, hir_id.local_id, Declared);
+ move_data.add_move(bccx.tcx, loan_path, var_id.local_id, Declared);
}
pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
Categorization::Upvar(..) => {
self.bccx.tcx.mk_region(ty::ReScope(self.item_scope))
}
- Categorization::Local(local_id) => {
- let hir_id = self.bccx.tcx.hir().node_to_hir_id(local_id);
+ Categorization::Local(hir_id) => {
self.bccx.tcx.mk_region(ty::ReScope(
self.bccx.region_scope_tree.var_scope(hir_id.local_id)))
}
assignee_cmt);
}
- fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) {
+ fn decl_without_init(&mut self, id: hir::HirId, _span: Span) {
let ty = self.bccx
.tables
- .node_type(self.bccx.tcx.hir().node_to_hir_id(id));
+ .node_type(id);
gather_moves::gather_decl(self.bccx, &self.move_data, id, ty);
}
}
while let Some(current_path) = wrapped_path {
wrapped_path = match current_path.kind {
- LpVar(local_id) => {
+ LpVar(hir_id) => {
if !through_borrow {
- let hir_id = self.bccx.tcx.hir().node_to_hir_id(local_id);
self.bccx.used_mut_nodes.borrow_mut().insert(hir_id);
}
None
#[derive(PartialEq, Eq, Hash, Debug)]
pub enum LoanPathKind<'tcx> {
- LpVar(ast::NodeId), // `x` in README.md
+ LpVar(hir::HirId), // `x` in README.md
LpUpvar(ty::UpvarId), // `x` captured by-value into closure
LpDowncast(Rc<LoanPath<'tcx>>, DefId), // `x` downcast to particular enum variant
LpExtend(Rc<LoanPath<'tcx>>, mc::MutabilityCategory, LoanPathElem<'tcx>)
impl<'a, 'tcx> LoanPath<'tcx> {
pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::Scope {
match self.kind {
- LpVar(local_id) => {
- let hir_id = bccx.tcx.hir().node_to_hir_id(local_id);
+ LpVar(hir_id) => {
bccx.region_scope_tree.var_scope(hir_id.local_id)
}
LpUpvar(upvar_id) => {
self.note_immutability_blame(
&mut db,
err.cmt.immutability_blame(),
- self.tcx.hir().hir_to_node_id(err.cmt.hir_id)
+ err.cmt.hir_id
);
db.emit();
self.signal_error();
self.note_immutability_blame(
&mut err,
blame,
- self.tcx.hir().hir_to_node_id(cmt.hir_id)
+ cmt.hir_id
);
if is_closure {
}
}
- fn local_binding_mode(&self, node_id: ast::NodeId) -> ty::BindingMode {
- let pat = match self.tcx.hir().get(node_id) {
+ fn local_binding_mode(&self, hir_id: hir::HirId) -> ty::BindingMode {
+ let pat = match self.tcx.hir().get_by_hir_id(hir_id) {
Node::Binding(pat) => pat,
node => bug!("bad node for local: {:?}", node)
};
}
}
- fn local_ty(&self, node_id: ast::NodeId) -> (Option<&hir::Ty>, bool) {
- let parent = self.tcx.hir().get_parent_node(node_id);
- let parent_node = self.tcx.hir().get(parent);
+ fn local_ty(&self, hir_id: hir::HirId) -> (Option<&hir::Ty>, bool) {
+ let parent = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
+ let parent_node = self.tcx.hir().get_by_hir_id(parent);
// The parent node is like a fn
if let Some(fn_like) = FnLikeNode::from_node(parent_node) {
// `nid`'s parent's `Body`
let fn_body = self.tcx.hir().body(fn_like.body());
// Get the position of `node_id` in the arguments list
- let arg_pos = fn_body.arguments.iter().position(|arg| arg.pat.id == node_id);
+ let arg_pos = fn_body.arguments.iter().position(|arg| arg.pat.hir_id == hir_id);
if let Some(i) = arg_pos {
// The argument's `Ty`
(Some(&fn_like.decl().inputs[i]),
fn note_immutability_blame(&self,
db: &mut DiagnosticBuilder<'_>,
blame: Option<ImmutabilityBlame<'_>>,
- error_node_id: ast::NodeId) {
+ error_hir_id: hir::HirId) {
match blame {
None => {}
Some(ImmutabilityBlame::ClosureEnv(_)) => {}
- Some(ImmutabilityBlame::ImmLocal(node_id)) => {
- self.note_immutable_local(db, error_node_id, node_id)
+ Some(ImmutabilityBlame::ImmLocal(hir_id)) => {
+ self.note_immutable_local(db, error_hir_id, hir_id)
}
- Some(ImmutabilityBlame::LocalDeref(node_id)) => {
- match self.local_binding_mode(node_id) {
+ Some(ImmutabilityBlame::LocalDeref(hir_id)) => {
+ match self.local_binding_mode(hir_id) {
ty::BindByReference(..) => {
- let let_span = self.tcx.hir().span(node_id);
+ let let_span = self.tcx.hir().span_by_hir_id(hir_id);
let suggestion = suggest_ref_mut(self.tcx, let_span);
if let Some(replace_str) = suggestion {
db.span_suggestion(
}
}
ty::BindByValue(..) => {
- if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) {
+ if let (Some(local_ty), is_implicit_self) = self.local_ty(hir_id) {
if let Some(msg) =
self.suggest_mut_for_immutable(local_ty, is_implicit_self) {
db.span_label(local_ty.span, msg);
// not a mutable reference) or to avoid borrowing altogether
fn note_immutable_local(&self,
db: &mut DiagnosticBuilder<'_>,
- borrowed_node_id: ast::NodeId,
- binding_node_id: ast::NodeId) {
- let let_span = self.tcx.hir().span(binding_node_id);
- if let ty::BindByValue(..) = self.local_binding_mode(binding_node_id) {
+ borrowed_hir_id: hir::HirId,
+ binding_hir_id: hir::HirId) {
+ let let_span = self.tcx.hir().span_by_hir_id(binding_hir_id);
+ if let ty::BindByValue(..) = self.local_binding_mode(binding_hir_id) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(let_span) {
- let (ty, is_implicit_self) = self.local_ty(binding_node_id);
+ let (ty, is_implicit_self) = self.local_ty(binding_hir_id);
if is_implicit_self && snippet != "self" {
// avoid suggesting `mut &self`.
return
},
)) = ty.map(|t| &t.node)
{
- let borrow_expr_id = self.tcx.hir().get_parent_node(borrowed_node_id);
+ let borrow_expr_id = self.tcx.hir().get_parent_node_by_hir_id(borrowed_hir_id);
db.span_suggestion(
- self.tcx.hir().span(borrow_expr_id),
+ self.tcx.hir().span_by_hir_id(borrow_expr_id),
"consider removing the `&mut`, as it is an \
immutable binding to a mutable reference",
snippet,
if let Categorization::Deref(..) = err.cmt.cat {
db.span_label(*error_span, "cannot borrow as mutable");
} else if let Categorization::Local(local_id) = err.cmt.cat {
- let span = self.tcx.hir().span(local_id);
+ let span = self.tcx.hir().span_by_hir_id(local_id);
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") {
db.span_label(*error_span, "cannot reborrow mutably");
out.push_str(&self.tcx.hir().name_by_hir_id(id).as_str());
}
LpVar(id) => {
- out.push_str(&self.tcx.hir().name(id).as_str());
+ out.push_str(&self.tcx.hir().name_by_hir_id(id).as_str());
}
LpDowncast(ref lp_base, variant_def_id) => {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
LpVar(id) => {
- write!(f, "$({})", ty::tls::with(|tcx| tcx.hir().node_to_string(id)))
+ write!(f, "$({})", ty::tls::with(|tcx| tcx.hir().hir_to_string(id)))
}
LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath {hir_id: var_id}, closure_expr_id }) => {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.kind {
LpVar(id) => {
- write!(f, "$({})", ty::tls::with(|tcx| tcx.hir().node_to_user_string(id)))
+ write!(f, "$({})", ty::tls::with(|tcx| tcx.hir().hir_to_user_string(id)))
}
LpUpvar(ty::UpvarId{ var_path: ty::UpvarPath { hir_id }, closure_expr_id: _ }) => {
unsafe {
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
- let is_generic = instance.substs.types().next().is_some();
+ let is_generic = instance.substs.non_erasable_generics().next().is_some();
if is_generic {
// This is a monomorphization. Its expected visibility depends
) -> EncodedMetadata {
base::write_metadata(tcx, metadata)
}
- fn codegen_allocator(
+ fn codegen_allocator<'b, 'gcx>(
&self,
- tcx: TyCtxt<'_, '_, '_>,
+ tcx: TyCtxt<'b, 'gcx, 'gcx>,
mods: &mut ModuleLlvm,
kind: AllocatorKind
) {
log = "0.4.5"
libc = "0.2.44"
jobserver = "0.1.11"
+parking_lot = "0.7"
serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
let mut reachable_non_generics: DefIdMap<_> = tcx.reachable_set(LOCAL_CRATE).0
.iter()
- .filter_map(|&node_id| {
+ .filter_map(|&hir_id| {
// We want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// categories:
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
- match tcx.hir().get(node_id) {
+ match tcx.hir().get_by_hir_id(hir_id) {
Node::ForeignItem(..) => {
- let def_id = tcx.hir().local_def_id(node_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
if tcx.is_statically_included_foreign_item(def_id) {
Some(def_id)
} else {
node: hir::ImplItemKind::Method(..),
..
}) => {
- let def_id = tcx.hir().local_def_id(node_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
let generics = tcx.generics_of(def_id);
if !generics.requires_monomorphization(tcx) &&
// Functions marked with #[inline] are only ever codegened
def: InstanceDef::Item(def_id),
substs,
}) = mono_item {
- if substs.types().next().is_some() {
+ if substs.non_erasable_generics().next().is_some() {
symbols.push((ExportedSymbol::Generic(def_id, substs),
SymbolExportLevel::Rust));
}
}
fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
- if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
- !tcx.reachable_set(LOCAL_CRATE).0.contains(&node_id)
+ if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
+ !tcx.reachable_set(LOCAL_CRATE).0.contains(&hir_id)
} else {
bug!("is_unreachable_local_definition called with non-local DefId: {:?}",
def_id)
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc::ty::TyCtxt;
use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
+use rustc::util::profiling::SelfProfiler;
use rustc_fs_util::link_or_copy;
use rustc_data_structures::svh::Svh;
use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
use syntax_pos::MultiSpan;
use syntax_pos::symbol::Symbol;
use jobserver::{Client, Acquired};
+use parking_lot::Mutex as PlMutex;
use std::any::Any;
use std::fs;
// Resources needed when running LTO
pub backend: B,
pub time_passes: bool,
+ pub profiler: Option<Arc<PlMutex<SelfProfiler>>>,
pub lto: Lto,
pub no_landing_pads: bool,
pub save_temps: bool,
ModuleKind::Allocator => &self.allocator_module_config,
}
}
+
+ #[inline(never)]
+ #[cold]
+ fn profiler_active<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+ match &self.profiler {
+ None => bug!("profiler_active() called but there was no profiler active"),
+ Some(profiler) => {
+ let mut p = profiler.lock();
+
+ f(&mut p);
+ }
+ }
+ }
+
+ #[inline(always)]
+ pub fn profile<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+ if unlikely!(self.profiler.is_some()) {
+ self.profiler_active(f)
+ }
+ }
}
fn generate_lto_work<B: ExtraBackendMethods>(
save_temps: sess.opts.cg.save_temps,
opts: Arc::new(sess.opts.clone()),
time_passes: sess.time_passes(),
+ profiler: sess.self_profiling.clone(),
exported_symbols,
plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
remark: sess.opts.cg.remark.clone(),
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(libc)]
#![feature(rustc_diagnostic_macros)]
+#![feature(stmt_expr_attributes)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![allow(unused_attributes)]
#[macro_use] extern crate log;
#[macro_use] extern crate rustc;
+#[macro_use] extern crate rustc_data_structures;
#[macro_use] extern crate syntax;
use std::path::PathBuf;
};
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
- for (i, (decl, ty)) in mir.upvar_decls.iter().zip(upvar_tys).enumerate() {
- let byte_offset_of_var_in_env = closure_layout.fields.offset(i).bytes();
+ let extra_locals = {
+ let upvars = mir.upvar_decls
+ .iter()
+ .zip(upvar_tys)
+ .enumerate()
+ .map(|(i, (decl, ty))| (i, decl.debug_name, decl.by_ref, ty));
+
+ let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
+ let (def_id, gen_substs) = match closure_layout.ty.sty {
+ ty::Generator(def_id, substs, _) => (def_id, substs),
+ _ => bug!("generator layout without generator substs"),
+ };
+ let state_tys = gen_substs.state_tys(def_id, tcx);
+
+ let upvar_count = mir.upvar_decls.len();
+ generator_layout.fields
+ .iter()
+ .zip(state_tys)
+ .enumerate()
+ .filter_map(move |(i, (decl, ty))| {
+ let ty = fx.monomorphize(&ty);
+ decl.name.map(|name| (i + upvar_count + 1, name, false, ty))
+ })
+ }).into_iter().flatten();
+
+ upvars.chain(generator_fields)
+ };
+
+ for (field, name, by_ref, ty) in extra_locals {
+ let byte_offset_of_var_in_env = closure_layout.fields.offset(field).bytes();
let ops = bx.debuginfo_upvar_decls_ops_sequence(byte_offset_of_var_in_env);
// The environment and the capture can each be indirect.
let mut ops = if env_ref { &ops[..] } else { &ops[1..] };
- let ty = if let (true, &ty::Ref(_, ty, _)) = (decl.by_ref, &ty.sty) {
+ let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.sty) {
ty
} else {
ops = &ops[..ops.len() - 1];
};
bx.declare_local(
&fx.debug_context,
- decl.debug_name,
+ name,
ty,
scope,
variable_access,
}
let val = match val.val {
+ ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"),
+ ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"),
ConstValue::Scalar(x) => {
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,
}
}
}
- mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
+ mir::CastKind::MutToConstPointer
+ | mir::CastKind::Misc if bx.cx().is_backend_scalar_pair(operand.layout) => {
if let OperandValue::Pair(data_ptr, meta) = operand.val {
if bx.cx().is_backend_scalar_pair(cast) {
let data_cast = bx.pointercast(data_ptr,
bug!("Unexpected non-Pair operand")
}
}
- mir::CastKind::Misc => {
+ mir::CastKind::MutToConstPointer
+ | mir::CastKind::Misc => {
assert!(bx.cx().is_backend_immediate(cast));
let ll_t_out = bx.cx().immediate_backend_type(cast);
if operand.layout.abi.is_uninhabited() {
tcx: TyCtxt<'b, 'gcx, 'gcx>,
metadata: &mut Self::Module,
) -> EncodedMetadata;
- fn codegen_allocator(
+ fn codegen_allocator<'b, 'gcx>(
&self,
- tcx: TyCtxt<'_, '_, '_>,
+ tcx: TyCtxt<'b, 'gcx, 'gcx>,
mods: &mut Self::Module,
kind: AllocatorKind
);
assert!(!substs.needs_subst());
substs.hash_stable(&mut hcx, &mut hasher);
- let is_generic = substs.types().next().is_some();
+ let is_generic = substs.non_erasable_generics().next().is_some();
let avoid_cross_crate_conflicts =
// If this is an instance of a generic function, we also hash in
// the ID of the instantiating crate. This avoids symbol conflicts
[dependencies]
ena = "0.11"
log = "0.4"
+jobserver_crate = { version = "0.1", package = "jobserver" }
+lazy_static = "1"
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
serialize = { path = "../libserialize" }
graphviz = { path = "../libgraphviz" }
cfg-if = "0.1.2"
stable_deref_trait = "1.0.0"
-rayon = { version = "0.1.1", package = "rustc-rayon" }
-rayon-core = { version = "0.1.1", package = "rustc-rayon-core" }
+rayon = { version = "0.1.2", package = "rustc-rayon" }
+rayon-core = { version = "0.1.2", package = "rustc-rayon-core" }
rustc-hash = "1.0.1"
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
--- /dev/null
+use jobserver_crate::{Client, HelperThread, Acquired};
+use lazy_static::lazy_static;
+use std::sync::{Condvar, Arc, Mutex};
+use std::mem;
+
+#[derive(Default)]
+struct LockedProxyData {
+ /// The number of free thread tokens, this may include the implicit token given to the process
+ free: usize,
+
+ /// The number of threads waiting for a token
+ waiters: usize,
+
+ /// The number of tokens we requested from the server
+ requested: usize,
+
+ /// Stored tokens which will be dropped when we no longer need them
+ tokens: Vec<Acquired>,
+}
+
+impl LockedProxyData {
+ fn request_token(&mut self, thread: &Mutex<HelperThread>) {
+ self.requested += 1;
+ thread.lock().unwrap().request_token();
+ }
+
+ fn release_token(&mut self, cond_var: &Condvar) {
+ if self.waiters > 0 {
+ self.free += 1;
+ cond_var.notify_one();
+ } else {
+ if self.tokens.is_empty() {
+ // We are returning the implicit token
+ self.free += 1;
+ } else {
+ // Return a real token to the server
+ self.tokens.pop().unwrap();
+ }
+ }
+ }
+
+ fn take_token(&mut self, thread: &Mutex<HelperThread>) -> bool {
+ if self.free > 0 {
+ self.free -= 1;
+ self.waiters -= 1;
+
+ // We stole some token reqested by someone else
+ // Request another one
+ if self.requested + self.free < self.waiters {
+ self.request_token(thread);
+ }
+
+ true
+ } else {
+ false
+ }
+ }
+
+ fn new_requested_token(&mut self, token: Acquired, cond_var: &Condvar) {
+ self.requested -= 1;
+
+ // Does anything need this token?
+ if self.waiters > 0 {
+ self.free += 1;
+ self.tokens.push(token);
+ cond_var.notify_one();
+ } else {
+ // Otherwise we'll just drop it
+ mem::drop(token);
+ }
+ }
+}
+
+#[derive(Default)]
+struct ProxyData {
+ lock: Mutex<LockedProxyData>,
+ cond_var: Condvar,
+}
+
+/// A helper type which makes managing jobserver tokens easier.
+/// It also allows you to treat the implicit token given to the process
+/// in the same manner as requested tokens.
+struct Proxy {
+ thread: Mutex<HelperThread>,
+ data: Arc<ProxyData>,
+}
+
+lazy_static! {
+ // We can only call `from_env` once per process
+
+ // Note that this is unsafe because it may misinterpret file descriptors
+ // on Unix as jobserver file descriptors. We hopefully execute this near
+ // the beginning of the process though to ensure we don't get false
+ // positives, or in other words we try to execute this before we open
+ // any file descriptors ourselves.
+ //
+ // Pick a "reasonable maximum" if we don't otherwise have
+ // a jobserver in our environment, capping out at 32 so we
+ // don't take everything down by hogging the process run queue.
+ // The fixed number is used to have deterministic compilation
+ // across machines.
+ //
+ // Also note that we stick this in a global because there could be
+ // multiple rustc instances in this process, and the jobserver is
+ // per-process.
+ static ref GLOBAL_CLIENT: Client = unsafe {
+ Client::from_env().unwrap_or_else(|| {
+ Client::new(32).expect("failed to create jobserver")
+ })
+ };
+
+ static ref GLOBAL_PROXY: Proxy = {
+ let data = Arc::new(ProxyData::default());
+
+ Proxy {
+ data: data.clone(),
+ thread: Mutex::new(client().into_helper_thread(move |token| {
+ data.lock.lock().unwrap().new_requested_token(token.unwrap(), &data.cond_var);
+ }).unwrap()),
+ }
+ };
+}
+
+pub fn client() -> Client {
+ GLOBAL_CLIENT.clone()
+}
+
+pub fn acquire_thread() {
+ GLOBAL_PROXY.acquire_token();
+}
+
+pub fn release_thread() {
+ GLOBAL_PROXY.release_token();
+}
+
+impl Proxy {
+ fn release_token(&self) {
+ self.data.lock.lock().unwrap().release_token(&self.data.cond_var);
+ }
+
+ fn acquire_token(&self) {
+ let mut data = self.data.lock.lock().unwrap();
+ data.waiters += 1;
+ if data.take_token(&self.thread) {
+ return;
+ }
+ // Request a token for us
+ data.request_token(&self.thread);
+ loop {
+ data = self.data.cond_var.wait(data).unwrap();
+ if data.take_token(&self.thread) {
+ return;
+ }
+ }
+ }
+}
pub mod graph;
pub mod indexed_vec;
pub mod interner;
+pub mod jobserver;
pub mod obligation_forest;
pub mod owning_ref;
pub mod ptr_key;
/// A simple static assertion macro. The first argument should be a unique
/// ALL_CAPS identifier that describes the condition.
#[macro_export]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(type_ascription))]
+#[allow_internal_unstable(type_ascription)]
macro_rules! static_assert {
($name:ident: $test:expr) => {
// Use the bool to access an array such that if the bool is false, the access
graphviz = { path = "../libgraphviz" }
log = "0.4"
env_logger = { version = "0.5", default-features = false }
-rustc-rayon = "0.1.1"
+rustc-rayon = "0.1.2"
scoped-tls = "1.0"
rustc = { path = "../librustc" }
rustc_allocator = { path = "../librustc_allocator" }
use rustc_borrowck as borrowck;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::sync::{self, Lock};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::jobserver;
use rustc_incremental;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore};
let gcx_ptr = &Lock::new(0);
let config = ThreadPoolBuilder::new()
+ .acquire_thread_handler(jobserver::acquire_thread)
+ .release_thread_handler(jobserver::release_thread)
.num_threads(Session::threads_from_count(opts.debugging_opts.threads))
.deadlock_handler(|| unsafe { ty::query::handle_deadlock() })
.stack_size(::STACK_SIZE);
sess.print_perf_stats();
}
- if sess.opts.debugging_opts.self_profile {
- sess.print_profiler_results();
- }
-
- if sess.opts.debugging_opts.profile_json {
- sess.save_json_results();
- }
-
controller_entry_point!(
compilation_done,
sess,
&control)
};
+ if sess.opts.debugging_opts.self_profile {
+ sess.profiler(|p| p.dump_raw_events(&sess.opts));
+ }
+
(result, Some(sess))
}
pprust_hir::AnnNode::Name(_) => Ok(()),
pprust_hir::AnnNode::Item(item) => {
s.s.space()?;
- s.synth_comment(format!("node_id: {} hir local_id: {}",
- item.id, item.hir_id.local_id.as_u32()))
+ s.synth_comment(format!("hir_id: {} hir local_id: {}",
+ item.hir_id, item.hir_id.local_id.as_u32()))
}
pprust_hir::AnnNode::SubItem(id) => {
s.s.space()?;
}
pprust_hir::AnnNode::Pat(pat) => {
s.s.space()?;
- s.synth_comment(format!("pat node_id: {} hir local_id: {}",
- pat.id, pat.hir_id.local_id.as_u32()))
+ s.synth_comment(format!("pat hir_id: {} hir local_id: {}",
+ pat.hir_id, pat.hir_id.local_id.as_u32()))
}
}
}
}
#[allow(dead_code)] // this seems like it could be useful, even if we don't use it now
- pub fn lookup_item(&self, names: &[String]) -> ast::NodeId {
+ pub fn lookup_item(&self, names: &[String]) -> hir::HirId {
return match search_mod(self, &self.infcx.tcx.hir().krate().module, 0, names) {
Some(id) => id,
None => {
m: &hir::Mod,
idx: usize,
names: &[String],
- ) -> Option<ast::NodeId> {
+ ) -> Option<hir::HirId> {
assert!(idx < names.len());
for item in &m.item_ids {
let item = this.infcx.tcx.hir().expect_item(item.id);
return None;
}
- fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<ast::NodeId> {
+ fn search(this: &Env, it: &hir::Item, idx: usize, names: &[String]) -> Option<hir::HirId> {
if idx == names.len() {
- return Some(it.id);
+ return Some(it.hir_id);
}
return match it.node {
use rustc::hir;
use rustc::ty::TyCtxt;
use rustc::ty::query::Providers;
-use syntax::ast;
use syntax::attr;
pub fn find<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> Option<DefId> {
let mut finder = Finder { decls: None };
tcx.hir().krate().visit_all_item_likes(&mut finder);
- finder.decls.map(|id| tcx.hir().local_def_id(id))
+ finder.decls.map(|id| tcx.hir().local_def_id_from_hir_id(id))
}
struct Finder {
- decls: Option<ast::NodeId>,
+ decls: Option<hir::HirId>,
}
impl<'v> ItemLikeVisitor<'v> for Finder {
fn visit_item(&mut self, item: &hir::Item) {
if attr::contains_name(&item.attrs, "rustc_proc_macro_decls") {
- self.decls = Some(item.id);
+ self.decls = Some(item.hir_id);
}
}
use rustc::ty::{self, Ty};
use rustc::{lint, util};
use hir::Node;
-use util::nodemap::NodeSet;
+use util::nodemap::HirIdSet;
use lint::{LateContext, LintContext, LintArray};
use lint::{LintPass, LateLintPass, EarlyLintPass, EarlyContext};
hir::ItemKind::Enum(..) |
hir::ItemKind::Struct(..) |
hir::ItemKind::Union(..) => {
- let def_id = cx.tcx.hir().local_def_id(it.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
self.check_heap_type(cx, it.span, cx.tcx.type_of(def_id))
}
_ => ()
hir::ItemKind::Struct(ref struct_def, _) |
hir::ItemKind::Union(ref struct_def, _) => {
for struct_field in struct_def.fields() {
- let def_id = cx.tcx.hir().local_def_id(struct_field.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(struct_field.hir_id);
self.check_heap_type(cx, struct_field.span,
cx.tcx.type_of(def_id));
}
if let hir::VisibilityKind::Inherited = it.vis.node {
self.private_traits.insert(it.hir_id);
for trait_item_ref in trait_item_refs {
- let hir_id = cx.tcx.hir().node_to_hir_id(trait_item_ref.id.node_id);
- self.private_traits.insert(hir_id);
+ self.private_traits.insert(trait_item_ref.id.hir_id);
}
return;
}
Some(Node::Item(item)) => {
if let hir::VisibilityKind::Inherited = item.vis.node {
for impl_item_ref in impl_item_refs {
- let hir_id = cx.tcx.hir().node_to_hir_id(
- impl_item_ref.id.node_id);
- self.private_traits.insert(hir_id);
+ self.private_traits.insert(impl_item_ref.id.hir_id);
}
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
- if !cx.access_levels.is_reachable(item.id) {
+ let node_id = cx.tcx.hir().hir_to_node_id(item.hir_id);
+ if !cx.access_levels.is_reachable(node_id) {
return;
}
let (def, ty) = match item.node {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.id));
+ let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Union(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.id));
+ let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Enum(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id(item.id));
+ let def = cx.tcx.adt_def(cx.tcx.hir().local_def_id_from_hir_id(item.hir_id));
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
_ => return,
}
pub struct MissingDebugImplementations {
- impling_types: Option<NodeSet>,
+ impling_types: Option<HirIdSet>,
}
impl MissingDebugImplementations {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
- if !cx.access_levels.is_reachable(item.id) {
+ let node_id = cx.tcx.hir().hir_to_node_id(item.hir_id);
+ if !cx.access_levels.is_reachable(node_id) {
return;
}
};
if self.impling_types.is_none() {
- let mut impls = NodeSet::default();
+ let mut impls = HirIdSet::default();
cx.tcx.for_each_impl(debug, |d| {
if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
- if let Some(node_id) = cx.tcx.hir().as_local_node_id(ty_def.did) {
- impls.insert(node_id);
+ if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(ty_def.did) {
+ impls.insert(hir_id);
}
}
});
debug!("{:?}", self.impling_types);
}
- if !self.impling_types.as_ref().unwrap().contains(&item.id) {
+ if !self.impling_types.as_ref().unwrap().contains(&item.hir_id) {
cx.span_lint(MISSING_DEBUG_IMPLEMENTATIONS,
item.span,
"type does not implement `fmt::Debug`; consider adding #[derive(Debug)] \
_ => return,
};
- let def_id = cx.tcx.hir().local_def_id(it.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
let prfn = match cx.tcx.extern_mod_stmt_cnum(def_id) {
Some(cnum) => cx.tcx.plugin_registrar_fn(cnum),
None => {
fn check_item(&mut self, ctx: &LateContext<'_, '_>, item: &hir::Item) {
if let hir::ItemKind::Union(ref vdata, _) = item.node {
for field in vdata.fields() {
- let field_ty = ctx.tcx.type_of(ctx.tcx.hir().local_def_id(field.id));
+ let field_ty = ctx.tcx.type_of(
+ ctx.tcx.hir().local_def_id_from_hir_id(field.hir_id));
if field_ty.needs_drop(ctx.tcx, ctx.param_env) {
ctx.span_lint(UNIONS_WITH_DROP_FIELDS,
field.span,
if cx.tcx.features().trivial_bounds {
- let def_id = cx.tcx.hir().local_def_id(item.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let predicates = cx.tcx.predicates_of(def_id);
for &(predicate, span) in &predicates.predicates {
let predicate_kind_name = match predicate {
}
pub struct UnnameableTestItems {
- boundary: ast::NodeId, // NodeId of the item under which things are not nameable
+ boundary: hir::HirId, // HirId of the item under which things are not nameable
items_nameable: bool,
}
impl UnnameableTestItems {
pub fn new() -> Self {
Self {
- boundary: ast::DUMMY_NODE_ID,
+ boundary: hir::DUMMY_HIR_ID,
items_nameable: true
}
}
if let hir::ItemKind::Mod(..) = it.node {}
else {
self.items_nameable = false;
- self.boundary = it.id;
+ self.boundary = it.hir_id;
}
return;
}
}
fn check_item_post(&mut self, _cx: &LateContext<'_, '_>, it: &hir::Item) {
- if !self.items_nameable && self.boundary == it.id {
+ if !self.items_nameable && self.boundary == it.hir_id {
self.items_nameable = true;
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitOutlivesRequirements {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
let infer_static = cx.tcx.features().infer_static_outlives_requirements;
- let def_id = cx.tcx.hir().local_def_id(item.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
if let hir::ItemKind::Struct(_, ref generics) = item.node {
let mut bound_count = 0;
let mut lint_spans = Vec::new();
}
}
- fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
+ fn check_foreign_fn(&mut self, id: hir::HirId, decl: &hir::FnDecl) {
+ let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(id);
let sig = self.cx.tcx.fn_sig(def_id);
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
let inputs = if sig.c_variadic {
}
}
- fn check_foreign_static(&mut self, id: ast::NodeId, span: Span) {
- let def_id = self.cx.tcx.hir().local_def_id(id);
+ fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
+ let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(id);
let ty = self.cx.tcx.type_of(def_id);
self.check_type_for_ffi_and_report_errors(span, ty);
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
let mut vis = ImproperCTypesVisitor { cx };
- let abi = cx.tcx.hir().get_foreign_abi(it.id);
+ let abi = cx.tcx.hir().get_foreign_abi_by_hir_id(it.hir_id);
if abi != Abi::RustIntrinsic && abi != Abi::PlatformIntrinsic {
match it.node {
hir::ForeignItemKind::Fn(ref decl, _, _) => {
- vis.check_foreign_fn(it.id, decl);
+ vis.check_foreign_fn(it.hir_id, decl);
}
hir::ForeignItemKind::Static(ref ty, _) => {
- vis.check_foreign_static(it.id, ty.span);
+ vis.check_foreign_static(it.hir_id, ty.span);
}
hir::ForeignItemKind::Type => ()
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
if let hir::ItemKind::Enum(ref enum_definition, _) = it.node {
- let item_def_id = cx.tcx.hir().local_def_id(it.id);
+ let item_def_id = cx.tcx.hir().local_def_id_from_hir_id(it.hir_id);
let t = cx.tcx.type_of(item_def_id);
let ty = cx.tcx.erase_regions(&t);
match cx.layout_of(ty) {
--- /dev/null
+[package]
+name = "rustc_macros"
+version = "0.1.0"
+authors = ["The Rust Project Developers"]
+edition = "2018"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+synstructure = "0.10.1"
+syn = { version = "0.15.22", features = ["full"] }
+proc-macro2 = "0.4.24"
+quote = "0.6.10"
--- /dev/null
+use synstructure;
+use syn::{self, Meta, NestedMeta, parse_quote};
+use proc_macro2::{self, Ident};
+use quote::quote;
+
+struct Attributes {
+ ignore: bool,
+ project: Option<Ident>,
+}
+
+fn parse_attributes(field: &syn::Field) -> Attributes {
+ let mut attrs = Attributes {
+ ignore: false,
+ project: None,
+ };
+ for attr in &field.attrs {
+ if let Ok(meta) = attr.parse_meta() {
+ if &meta.name().to_string() != "stable_hasher" {
+ continue;
+ }
+ let mut any_attr = false;
+ if let Meta::List(list) = meta {
+ for nested in list.nested.iter() {
+ if let NestedMeta::Meta(meta) = nested {
+ if &meta.name().to_string() == "ignore" {
+ attrs.ignore = true;
+ any_attr = true;
+ }
+ if &meta.name().to_string() == "project" {
+ if let Meta::List(list) = meta {
+ if let Some(nested) = list.nested.iter().next() {
+ if let NestedMeta::Meta(meta) = nested {
+ attrs.project = Some(meta.name());
+ any_attr = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if !any_attr {
+ panic!("error parsing stable_hasher");
+ }
+ }
+ }
+ attrs
+}
+
+pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ let generic: syn::GenericParam = parse_quote!('__ctx);
+ s.add_bounds(synstructure::AddBounds::Generics);
+ s.add_impl_generic(generic);
+ let body = s.each(|bi| {
+ let attrs = parse_attributes(bi.ast());
+ if attrs.ignore {
+ quote!{}
+ } else if let Some(project) = attrs.project {
+ quote!{
+ &#bi.#project.hash_stable(__hcx, __hasher);
+ }
+ } else {
+ quote!{
+ #bi.hash_stable(__hcx, __hasher);
+ }
+ }
+ });
+
+ let discriminant = match s.ast().data {
+ syn::Data::Enum(_) => quote! {
+ ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
+ },
+ syn::Data::Struct(_) => quote! {},
+ syn::Data::Union(_) => panic!("cannot derive on union"),
+ };
+
+ s.bound_impl(quote!(::rustc_data_structures::stable_hasher::HashStable
+ <::rustc::ich::StableHashingContext<'__ctx>>), quote!{
+ fn hash_stable<__W: ::rustc_data_structures::stable_hasher::StableHasherResult>(
+ &self,
+ __hcx: &mut ::rustc::ich::StableHashingContext<'__ctx>,
+ __hasher: &mut ::rustc_data_structures::stable_hasher::StableHasher<__W>) {
+ #discriminant
+ match *self { #body }
+ }
+ })
+}
--- /dev/null
+#![feature(proc_macro_hygiene)]
+#![deny(rust_2018_idioms)]
+
+use synstructure::decl_derive;
+
+mod hash_stable;
+
+decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
});
}
- fn register_crate(&mut self,
- root: &Option<CratePaths>,
- ident: Symbol,
- span: Span,
- lib: Library,
- dep_kind: DepKind)
- -> (CrateNum, Lrc<cstore::CrateMetadata>) {
+ fn register_crate(
+ &mut self,
+ host_lib: Option<Library>,
+ root: &Option<CratePaths>,
+ ident: Symbol,
+ span: Span,
+ lib: Library,
+ dep_kind: DepKind
+ ) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
let crate_root = lib.metadata.get_root();
info!("register crate `extern crate {} as {}`", crate_root.name, ident);
self.verify_no_symbol_conflicts(span, &crate_root);
let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
let proc_macros = crate_root.proc_macro_decls_static.map(|_| {
- self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
+ if self.sess.opts.debugging_opts.dual_proc_macros {
+ let host_lib = host_lib.unwrap();
+ self.load_derive_macros(
+ &host_lib.metadata.get_root(),
+ host_lib.dylib.clone().map(|p| p.0),
+ span
+ )
+ } else {
+ self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
+ }
});
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
(cnum, cmeta)
}
+ fn load_proc_macro<'b> (
+ &mut self,
+ locate_ctxt: &mut locator::Context<'b>,
+ path_kind: PathKind,
+ ) -> Option<(LoadResult, Option<Library>)>
+ where
+ 'a: 'b
+ {
+ // Use a new locator Context so trying to load a proc macro doesn't affect the error
+ // message we emit
+ let mut proc_macro_locator = locate_ctxt.clone();
+
+ // Try to load a proc macro
+ proc_macro_locator.is_proc_macro = Some(true);
+
+ // Load the proc macro crate for the target
+ let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
+ proc_macro_locator.reset();
+ let result = match self.load(&mut proc_macro_locator)? {
+ LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
+ LoadResult::Loaded(library) => Some(LoadResult::Loaded(library))
+ };
+ // Don't look for a matching hash when looking for the host crate.
+ // It won't be the same as the target crate hash
+ locate_ctxt.hash = None;
+ // Use the locate_ctxt when looking for the host proc macro crate, as that is required
+ // so we want it to affect the error message
+ (locate_ctxt, result)
+ } else {
+ (&mut proc_macro_locator, None)
+ };
+
+ // Load the proc macro crate for the host
+
+ locator.reset();
+ locator.is_proc_macro = Some(true);
+ locator.target = &self.sess.host;
+ locator.triple = TargetTriple::from_triple(config::host_triple());
+ locator.filesearch = self.sess.host_filesearch(path_kind);
+
+ let host_result = self.load(locator)?;
+
+ Some(if self.sess.opts.debugging_opts.dual_proc_macros {
+ let host_result = match host_result {
+ LoadResult::Previous(..) => {
+ panic!("host and target proc macros must be loaded in lock-step")
+ }
+ LoadResult::Loaded(library) => library
+ };
+ (target_result.unwrap(), Some(host_result))
+ } else {
+ (host_result, None)
+ })
+ }
+
fn resolve_crate<'b>(
&'b mut self,
root: &'b Option<CratePaths>,
) -> Result<(CrateNum, Lrc<cstore::CrateMetadata>), LoadError<'b>> {
info!("resolving crate `extern crate {} as {}`", name, ident);
let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
- LoadResult::Previous(cnum)
+ (LoadResult::Previous(cnum), None)
} else {
info!("falling back to a load");
let mut locate_ctxt = locator::Context {
extra_filename: extra_filename,
filesearch: self.sess.target_filesearch(path_kind),
target: &self.sess.target.target,
- triple: &self.sess.opts.target_triple,
+ triple: self.sess.opts.target_triple.clone(),
root,
rejected_via_hash: vec![],
rejected_via_triple: vec![],
metadata_loader: &*self.cstore.metadata_loader,
};
- self.load(&mut locate_ctxt).or_else(|| {
+ self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| {
dep_kind = DepKind::UnexportedMacrosOnly;
-
- let mut proc_macro_locator = locator::Context {
- target: &self.sess.host,
- triple: &TargetTriple::from_triple(config::host_triple()),
- filesearch: self.sess.host_filesearch(path_kind),
- rejected_via_hash: vec![],
- rejected_via_triple: vec![],
- rejected_via_kind: vec![],
- rejected_via_version: vec![],
- rejected_via_filename: vec![],
- is_proc_macro: Some(true),
- ..locate_ctxt
- };
-
- self.load(&mut proc_macro_locator)
+ self.load_proc_macro(&mut locate_ctxt, path_kind)
}).ok_or_else(move || LoadError::LocatorError(locate_ctxt))?
};
match result {
- LoadResult::Previous(cnum) => {
+ (LoadResult::Previous(cnum), None) => {
let data = self.cstore.get_crate_data(cnum);
if data.root.proc_macro_decls_static.is_some() {
dep_kind = DepKind::UnexportedMacrosOnly;
});
Ok((cnum, data))
}
- LoadResult::Loaded(library) => {
- Ok(self.register_crate(root, ident, span, library, dep_kind))
+ (LoadResult::Loaded(library), host_library) => {
+ Ok(self.register_crate(host_library, root, ident, span, library, dep_kind))
}
+ _ => panic!()
}
}
// don't want to match a host crate against an equivalent target one
// already loaded.
let root = library.metadata.get_root();
- if locate_ctxt.triple == &self.sess.opts.target_triple {
+ if locate_ctxt.triple == self.sess.opts.target_triple {
let mut result = LoadResult::Loaded(library);
self.cstore.iter_crate_data(|cnum, data| {
if data.root.name == root.name && root.hash == data.root.hash {
fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol)
-> ExtensionCrate {
info!("read extension crate `extern crate {} as {}`", orig_name, rename);
- let target_triple = &self.sess.opts.target_triple;
+ let target_triple = self.sess.opts.target_triple.clone();
let host_triple = TargetTriple::from_triple(config::host_triple());
- let is_cross = target_triple != &host_triple;
+ let is_cross = target_triple != host_triple;
let mut target_only = false;
let mut locate_ctxt = locator::Context {
sess: self.sess,
extra_filename: None,
filesearch: self.sess.host_filesearch(PathKind::Crate),
target: &self.sess.host,
- triple: &host_triple,
+ triple: host_triple,
root: &None,
rejected_via_hash: vec![],
rejected_via_triple: vec![],
pub fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
match self.is_proc_macro(id) {
- true => None,
+ true => self.root.proc_macro_stability.clone(),
false => self.entry(id).stability.map(|stab| stab.decode(self)),
}
}
use std::path::Path;
use rustc_data_structures::sync::Lrc;
use std::u32;
-use syntax::ast::{self, CRATE_NODE_ID};
+use syntax::ast;
use syntax::attr;
use syntax::source_map::Spanned;
use syntax::symbol::keywords;
let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
index.record(DefId::local(CRATE_DEF_INDEX),
IsolatedEncoder::encode_info_for_mod,
- FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &vis)));
+ FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis)));
let mut visitor = EncodeVisitor { index };
krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
for macro_def in &krate.exported_macros {
} else {
None
},
-
+ proc_macro_stability: if is_proc_macro {
+ tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone())
+ } else {
+ None
+ },
compiler_builtins: attr::contains_name(&attrs, "compiler_builtins"),
needs_allocator: attr::contains_name(&attrs, "needs_allocator"),
needs_panic_runtime: attr::contains_name(&attrs, "needs_panic_runtime"),
}
};
- let enum_id = tcx.hir().as_local_node_id(enum_did).unwrap();
- let enum_vis = &tcx.hir().expect_item(enum_id).vis;
+ let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap();
+ let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis;
Entry {
kind: EntryKind::Variant(self.lazy(&data)),
&hir::Visibility)>)
-> Entry<'tcx> {
let tcx = self.tcx;
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id);
let data = ModData {
}
};
- let struct_id = tcx.hir().as_local_node_id(adt_def_id).unwrap();
- let struct_vis = &tcx.hir().expect_item(struct_id).vis;
+ let struct_id = tcx.hir().as_local_hir_id(adt_def_id).unwrap();
+ let struct_vis = &tcx.hir().expect_item_by_hir_id(struct_id).vis;
let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
for field in &variant.fields {
if ctor_vis.is_at_least(field.vis, tcx) {
EntryKind::Fn(self.lazy(&data))
}
hir::ItemKind::Mod(ref m) => {
- return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
+ return self.encode_info_for_mod(FromId(item.hir_id, (m, &item.attrs, &item.vis)));
}
hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
// for methods, write all the stuff get_trait_method
// needs to know
let struct_ctor = if !struct_def.is_struct() {
- Some(tcx.hir().local_def_id(struct_def.id()).index)
+ Some(tcx.hir().local_def_id_from_hir_id(struct_def.hir_id()).index)
} else {
None
};
Entry {
kind,
- visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)),
+ visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)),
span: self.lazy(&item.span),
attributes: self.encode_attributes(&item.attrs),
children: match item.node {
hir::ItemKind::ForeignMod(ref fm) => {
self.lazy_seq(fm.items
.iter()
- .map(|foreign_item| tcx.hir().local_def_id(foreign_item.id).index))
+ .map(|foreign_item| tcx.hir().local_def_id_from_hir_id(
+ foreign_item.hir_id).index))
}
hir::ItemKind::Enum(..) => {
let def = self.tcx.adt_def(def_id);
Entry {
kind,
- visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
+ visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)),
span: self.lazy(&nitem.span),
attributes: self.encode_attributes(&nitem.attrs),
children: LazySeq::empty(),
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
intravisit::walk_item(self, item);
- let def_id = self.index.tcx.hir().local_def_id(item.id);
+ let def_id = self.index.tcx.hir().local_def_id_from_hir_id(item.hir_id);
match item.node {
hir::ItemKind::ExternCrate(_) |
hir::ItemKind::Use(..) => (), // ignore these
}
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
intravisit::walk_foreign_item(self, ni);
- let def_id = self.index.tcx.hir().local_def_id(ni.id);
+ let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
self.index.record(def_id,
IsolatedEncoder::encode_info_for_foreign_item,
(def_id, ni));
/// so it's easier to do that here then to wait until we would encounter
/// normally in the visitor walk.
fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
match item.node {
hir::ItemKind::Static(..) |
hir::ItemKind::Const(..) |
// If the struct has a constructor, encode it.
if !struct_def.is_struct() {
- let ctor_def_id = self.tcx.hir().local_def_id(struct_def.id());
+ let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(struct_def.hir_id());
self.record(ctor_def_id,
IsolatedEncoder::encode_struct_ctor,
(def_id, ctor_def_id));
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if let hir::ItemKind::Impl(..) = item.node {
- let impl_id = self.tcx.hir().local_def_id(item.id);
+ let impl_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
self.impls
.entry(trait_ref.def_id)
};
let foreign_items = fm.items.iter()
- .map(|it| self.tcx.hir().local_def_id(it.id))
+ .map(|it| self.tcx.hir().local_def_id_from_hir_id(it.hir_id))
.collect();
self.modules.push(ForeignModule {
foreign_items,
- def_id: self.tcx.hir().local_def_id(it.id),
+ def_id: self.tcx.hir().local_def_id_from_hir_id(it.hir_id),
});
}
/// HIR node that doesn't carry its own ID. This will allow an
/// arbitrary `T` to be passed in, but register a read on the given
/// `NodeId`.
-pub struct FromId<T>(pub ast::NodeId, pub T);
+pub struct FromId<T>(pub hir::HirId, pub T);
impl<T> DepGraphRead for FromId<T> {
fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
- tcx.hir().read(self.0);
+ tcx.hir().read_by_hir_id(self.0);
}
}
use log::{debug, info, warn};
+#[derive(Clone)]
pub struct CrateMismatch {
path: PathBuf,
got: String,
}
+#[derive(Clone)]
pub struct Context<'a> {
pub sess: &'a Session,
pub span: Span,
pub extra_filename: Option<&'a str>,
// points to either self.sess.target.target or self.sess.host, must match triple
pub target: &'a Target,
- pub triple: &'a TargetTriple,
+ pub triple: TargetTriple,
pub filesearch: FileSearch<'a>,
pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
}
impl<'a> Context<'a> {
+ pub fn reset(&mut self) {
+ self.rejected_via_hash.clear();
+ self.rejected_via_triple.clear();
+ self.rejected_via_kind.clear();
+ self.rejected_via_version.clear();
+ self.rejected_via_filename.clear();
+ }
+
pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
let mut seen_paths = FxHashSet::default();
match self.extra_filename {
add);
if (self.ident == "std" || self.ident == "core")
- && self.triple != &TargetTriple::from_triple(config::host_triple()) {
+ && self.triple != TargetTriple::from_triple(config::host_triple()) {
err.note(&format!("the `{}` target may not be installed", self.triple));
}
err.span_label(self.span, "can't find crate");
}
}
- if &root.triple != self.triple {
+ if root.triple != self.triple {
info!("Rejecting via crate triple: expected {} got {}",
self.triple,
root.triple);
name: None,
kind: cstore::NativeUnknown,
cfg: None,
- foreign_module: Some(self.tcx.hir().local_def_id(it.id)),
+ foreign_module: Some(self.tcx.hir().local_def_id_from_hir_id(it.hir_id)),
wasm_import_module: None,
};
let mut kind_specified = false;
pub has_default_lib_allocator: bool,
pub plugin_registrar_fn: Option<DefIndex>,
pub proc_macro_decls_static: Option<DefIndex>,
+ pub proc_macro_stability: Option<attr::Stability>,
pub crate_deps: LazySeq<CrateDep>,
pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>,
use crate::borrow_check::location::{LocationIndex, LocationTable};
use crate::borrow_check::nll::facts::AllFactsExt;
use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints};
-use crate::borrow_check::nll::type_check::liveness::liveness_map::NllLivenessMap;
use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::dataflow::indexes::BorrowIndex;
use crate::dataflow::move_paths::MoveData;
search_stack.push((ty, hir_ty));
}
- (UnpackedKind::Lifetime(_), _) | (UnpackedKind::Type(_), _) => {
+ (UnpackedKind::Const(_ct), hir::GenericArg::Const(_hir_ct)) => {
+ // Lifetimes cannot be found in consts, so we don't need
+ // to search anything here.
+ }
+
+ (UnpackedKind::Lifetime(_), _)
+ | (UnpackedKind::Type(_), _)
+ | (UnpackedKind::Const(_), _) => {
// I *think* that HIR lowering should ensure this
// doesn't happen, even in erroneous
// programs. Else we should use delay-span-bug.
fn apply_requirements(
&self,
tcx: TyCtxt<'_, 'gcx, 'tcx>,
- location: Location,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryRegionConstraint<'tcx>>;
fn apply_requirements(
&self,
tcx: TyCtxt<'_, 'gcx, 'tcx>,
- location: Location,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryRegionConstraint<'tcx>> {
debug!(
- "apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
- location, closure_def_id, closure_substs
+ "apply_requirements(closure_def_id={:?}, closure_substs={:?})",
+ closure_def_id, closure_substs
);
// Extract the values of the free regions in `closure_substs`
/// Creates a new set of "region values" that tracks causal information.
/// Each of the regions in num_region_variables will be initialized with an
/// empty set of points and no causal information.
- crate fn new(elements: &Rc<RegionValueElements>) -> Self {
+ crate fn new(elements: Rc<RegionValueElements>) -> Self {
Self {
- elements: elements.clone(),
points: SparseBitMatrix::new(elements.num_points),
+ elements: elements,
}
}
}
impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
+ fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
+ for promoted in mir.promoted.iter_mut() {
+ self.visit_mir(promoted);
+ }
+
+ self.super_mir(mir);
+ }
+
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);
param_env,
).type_must_outlive(origin, t1, r2);
}
+
+ UnpackedKind::Const(_) => {
+ // Consts cannot outlive one another, so we
+ // don't need to handle any relations here.
+ }
}
}
+++ /dev/null
-//! For the NLL computation, we need to compute liveness, but only for those
-//! local variables whose types contain regions. The others are not of interest
-//! to us. This file defines a new index type (LiveVar) that indexes into
-//! a list of "variables whose type contain regions". It also defines a map from
-//! Local to LiveVar and vice versa -- this map can be given to the
-//! liveness code so that it only operates over variables with regions in their
-//! types, instead of all variables.
-
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
-use crate::util::liveness::LiveVariableMap;
-use rustc::mir::{Local, Mir};
-use rustc::ty::{RegionVid, TyCtxt};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-
-/// Map between Local and LiveVar indices: the purpose of this
-/// map is to define the subset of local variables for which we need
-/// to do a liveness computation. We only need to compute whether a
-/// variable `X` is live if that variable contains some region `R` in
-/// its type where `R` is not known to outlive a free region (i.e.,
-/// where `R` may be valid for just a subset of the fn body).
-crate struct NllLivenessMap {
- /// For each local variable, contains `Some(i)` if liveness is
- /// needed for this variable.
- pub from_local: IndexVec<Local, Option<LiveVar>>,
-
- /// For each `LiveVar`, maps back to the original `Local` index.
- pub to_local: IndexVec<LiveVar, Local>,
-}
-
-impl LiveVariableMap for NllLivenessMap {
- fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
- self.from_local[local]
- }
-
- type LiveVar = LiveVar;
-
- fn from_live_var(&self, local: Self::LiveVar) -> Local {
- self.to_local[local]
- }
-
- fn num_variables(&self) -> usize {
- self.to_local.len()
- }
-}
-
-impl NllLivenessMap {
- crate fn compute(
- tcx: TyCtxt<'_, '_, 'tcx>,
- free_regions: &FxHashSet<RegionVid>,
- mir: &Mir<'tcx>,
- ) -> Self {
- let mut to_local = IndexVec::default();
- let facts_enabled = AllFacts::enabled(tcx);
- let from_local: IndexVec<Local, Option<_>> = mir.local_decls
- .iter_enumerated()
- .map(|(local, local_decl)| {
- if tcx.all_free_regions_meet(&local_decl.ty, |r| {
- free_regions.contains(&r.to_region_vid())
- }) && !facts_enabled {
- // If all the regions in the type are free regions
- // (or there are no regions), then we don't need
- // to track liveness for this variable.
- None
- } else {
- Some(to_local.push(local))
- }
- })
- .collect();
-
- debug!("{} total variables", mir.local_decls.len());
- debug!("{} variables need liveness", to_local.len());
- debug!("{} regions outlive free regions", free_regions.len());
-
- Self {
- from_local,
- to_local,
- }
- }
-
- /// Returns `true` if there are no local variables that need liveness computation.
- crate fn is_empty(&self) -> bool {
- self.to_local.is_empty()
- }
-}
-
-/// Index given to each local variable for which we need to
-/// compute liveness information. For many locals, we are able to
-/// skip liveness information: for example, those variables whose
-/// types contain no regions.
-newtype_index! {
- pub struct LiveVar { .. }
-}
use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
-use crate::borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
-use crate::util::liveness::{categorize, DefUse, LiveVariableMap};
+use crate::util::liveness::{categorize, DefUse};
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::{Local, Location, Mir};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
/// A map that cross references each local with the locations where it
/// is defined (assigned), used, or dropped. Used during liveness
/// computation.
-crate struct LocalUseMap<'me> {
- liveness_map: &'me NllLivenessMap,
-
+///
+/// We keep track only of `Local`s we'll do the liveness analysis later,
+/// this means that our internal `IndexVec`s will only be sparsely populated.
+/// In the time-memory trade-off between keeping compact vectors with new
+/// indexes (and needing to continuously map the `Local` index to its compact
+/// counterpart) and having `IndexVec`s that we only use a fraction of, time
+/// (and code simplicity) was favored. The rationale is that we only keep
+/// a small number of `IndexVec`s throughout the entire analysis while, in
+/// contrast, we're accessing each `Local` *many* times.
+crate struct LocalUseMap {
/// Head of a linked list of **definitions** of each variable --
/// definition in this context means assignment, e.g., `x` is
/// defined in `x = y` but not `y`; that first def is the head of
/// a linked list that lets you enumerate all places the variable
/// is assigned.
- first_def_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
+ first_def_at: IndexVec<Local, Option<AppearanceIndex>>,
/// Head of a linked list of **uses** of each variable -- use in
/// this context means that the existing value of the variable is
/// read or modified. e.g., `y` is used in `x = y` but not `x`.
/// Note that `DROP(x)` terminators are excluded from this list.
- first_use_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
+ first_use_at: IndexVec<Local, Option<AppearanceIndex>>,
/// Head of a linked list of **drops** of each variable -- these
/// are a special category of uses corresponding to the drop that
/// we add for each local variable.
- first_drop_at: IndexVec<LiveVar, Option<AppearanceIndex>>,
+ first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
appearances: IndexVec<AppearanceIndex, Appearance>,
}
}
}
-impl LocalUseMap<'me> {
+impl LocalUseMap {
crate fn build(
- liveness_map: &'me NllLivenessMap,
+ live_locals: &Vec<Local>,
elements: &RegionValueElements,
mir: &Mir<'_>,
) -> Self {
- let nones = IndexVec::from_elem_n(None, liveness_map.num_variables());
+ let nones = IndexVec::from_elem_n(None, mir.local_decls.len());
let mut local_use_map = LocalUseMap {
- liveness_map,
first_def_at: nones.clone(),
first_use_at: nones.clone(),
first_drop_at: nones,
appearances: IndexVec::new(),
};
+ let mut locals_with_use_data: IndexVec<Local, bool> =
+ IndexVec::from_elem_n(false, mir.local_decls.len());
+ live_locals
+ .iter()
+ .for_each(|&local| locals_with_use_data[local] = true);
+
LocalUseMapBuild {
local_use_map: &mut local_use_map,
elements,
- }.visit_mir(mir);
+ locals_with_use_data,
+ }
+ .visit_mir(mir);
local_use_map
}
- crate fn defs(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
+ crate fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
vll::iter(self.first_def_at[local], &self.appearances)
.map(move |aa| self.appearances[aa].point_index)
}
- crate fn uses(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
+ crate fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
vll::iter(self.first_use_at[local], &self.appearances)
.map(move |aa| self.appearances[aa].point_index)
}
- crate fn drops(&self, local: LiveVar) -> impl Iterator<Item = PointIndex> + '_ {
+ crate fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
vll::iter(self.first_drop_at[local], &self.appearances)
.map(move |aa| self.appearances[aa].point_index)
}
}
-struct LocalUseMapBuild<'me, 'map: 'me> {
- local_use_map: &'me mut LocalUseMap<'map>,
+struct LocalUseMapBuild<'me> {
+ local_use_map: &'me mut LocalUseMap,
elements: &'me RegionValueElements,
+
+ // Vector used in `visit_local` to signal which `Local`s do we need
+ // def/use/drop information on, constructed from `live_locals` (that
+ // contains the variables we'll do the liveness analysis for).
+ // This vector serves optimization purposes only: we could have
+ // obtained the same information from `live_locals` but we want to
+ // avoid repeatedly calling `Vec::contains()` (see `LocalUseMap` for
+ // the rationale on the time-memory trade-off we're favoring here).
+ locals_with_use_data: IndexVec<Local, bool>,
}
-impl LocalUseMapBuild<'_, '_> {
- fn insert_def(&mut self, local: LiveVar, location: Location) {
+impl LocalUseMapBuild<'_> {
+ fn insert_def(&mut self, local: Local, location: Location) {
Self::insert(
self.elements,
&mut self.local_use_map.first_def_at[local],
);
}
- fn insert_use(&mut self, local: LiveVar, location: Location) {
+ fn insert_use(&mut self, local: Local, location: Location) {
Self::insert(
self.elements,
&mut self.local_use_map.first_use_at[local],
);
}
- fn insert_drop(&mut self, local: LiveVar, location: Location) {
+ fn insert_drop(&mut self, local: Local, location: Location) {
Self::insert(
self.elements,
&mut self.local_use_map.first_drop_at[local],
}
}
-impl Visitor<'tcx> for LocalUseMapBuild<'_, '_> {
+impl Visitor<'tcx> for LocalUseMapBuild<'_> {
fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, location: Location) {
- if let Some(local_with_region) = self.local_use_map.liveness_map.from_local(local) {
+ if self.locals_with_use_data[local] {
match categorize(context) {
- Some(DefUse::Def) => self.insert_def(local_with_region, location),
- Some(DefUse::Use) => self.insert_use(local_with_region, location),
- Some(DefUse::Drop) => self.insert_drop(local_with_region, location),
+ Some(DefUse::Def) => self.insert_def(local, location),
+ Some(DefUse::Use) => self.insert_use(local, location),
+ Some(DefUse::Drop) => self.insert_drop(local, location),
_ => (),
}
}
use crate::borrow_check::location::LocationTable;
-use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::borrow_check::nll::constraints::ConstraintSet;
-use crate::borrow_check::nll::NllLivenessMap;
+use crate::borrow_check::nll::facts::{AllFacts, AllFactsExt};
+use crate::borrow_check::nll::region_infer::values::RegionValueElements;
use crate::borrow_check::nll::universal_regions::UniversalRegions;
+use crate::borrow_check::nll::ToRegionVid;
use crate::dataflow::move_paths::MoveData;
-use crate::dataflow::MaybeInitializedPlaces;
use crate::dataflow::FlowAtLocation;
-use rustc::mir::Mir;
-use rustc::ty::RegionVid;
+use crate::dataflow::MaybeInitializedPlaces;
+use rustc::mir::{Local, Mir};
+use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use std::rc::Rc;
use super::TypeChecker;
-crate mod liveness_map;
mod local_use_map;
mod trace;
location_table: &LocationTable,
) {
debug!("liveness::generate");
- let free_regions = {
- let borrowck_context = typeck.borrowck_context.as_ref().unwrap();
- regions_that_outlive_free_regions(
- typeck.infcx.num_region_vars(),
- &borrowck_context.universal_regions,
- &borrowck_context.constraints.outlives_constraints,
- )
+
+ let live_locals: Vec<Local> = if AllFacts::enabled(typeck.tcx()) {
+ // If "dump facts from NLL analysis" was requested perform
+ // the liveness analysis for all `Local`s. This case opens
+ // the possibility of the variables being analyzed in `trace`
+ // to be *any* `Local`, not just the "live" ones, so we can't
+ // make any assumptions past this point as to the characteristics
+ // of the `live_locals`.
+ // FIXME: Review "live" terminology past this point, we should
+ // not be naming the `Local`s as live.
+ mir.local_decls.indices().collect()
+ } else {
+ let free_regions = {
+ let borrowck_context = typeck.borrowck_context.as_ref().unwrap();
+ regions_that_outlive_free_regions(
+ typeck.infcx.num_region_vars(),
+ &borrowck_context.universal_regions,
+ &borrowck_context.constraints.outlives_constraints,
+ )
+ };
+ compute_live_locals(typeck.tcx(), &free_regions, mir)
};
- let liveness_map = NllLivenessMap::compute(typeck.tcx(), &free_regions, mir);
- trace::trace(typeck, mir, elements, flow_inits, move_data, &liveness_map, location_table);
+
+ if !live_locals.is_empty() {
+ trace::trace(
+ typeck,
+ mir,
+ elements,
+ flow_inits,
+ move_data,
+ live_locals,
+ location_table,
+ );
+ }
+}
+
+// The purpose of `compute_live_locals` is to define the subset of `Local`
+// variables for which we need to do a liveness computation. We only need
+// to compute whether a variable `X` is live if that variable contains
+// some region `R` in its type where `R` is not known to outlive a free
+// region (i.e., where `R` may be valid for just a subset of the fn body).
+fn compute_live_locals(
+ tcx: TyCtxt<'_, '_, 'tcx>,
+ free_regions: &FxHashSet<RegionVid>,
+ mir: &Mir<'tcx>,
+) -> Vec<Local> {
+ let live_locals: Vec<Local> = mir
+ .local_decls
+ .iter_enumerated()
+ .filter_map(|(local, local_decl)| {
+ if tcx.all_free_regions_meet(&local_decl.ty, |r| {
+ free_regions.contains(&r.to_region_vid())
+ }) {
+ None
+ } else {
+ Some(local)
+ }
+ })
+ .collect();
+
+ debug!("{} total variables", mir.local_decls.len());
+ debug!("{} variables need liveness", live_locals.len());
+ debug!("{} regions outlive free regions", free_regions.len());
+
+ live_locals
}
/// Computes all regions that are (currently) known to outlive free
use crate::borrow_check::location::LocationTable;
use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
-use crate::borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
use crate::borrow_check::nll::type_check::NormalizeLocation;
use crate::borrow_check::nll::type_check::TypeChecker;
use crate::dataflow::move_paths::indexes::MovePathIndex;
use crate::dataflow::move_paths::MoveData;
use crate::dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
-use crate::util::liveness::LiveVariableMap;
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Mir};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
elements: &Rc<RegionValueElements>,
flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
move_data: &MoveData<'tcx>,
- liveness_map: &NllLivenessMap,
+ live_locals: Vec<Local>,
location_table: &LocationTable,
) {
debug!("trace()");
- if liveness_map.is_empty() {
- return;
- }
-
- let local_use_map = &LocalUseMap::build(liveness_map, elements, mir);
+ let local_use_map = &LocalUseMap::build(&live_locals, elements, mir);
let cx = LivenessContext {
typeck,
elements,
local_use_map,
move_data,
- liveness_map,
drop_data: FxHashMap::default(),
location_table,
};
- LivenessResults::new(cx).compute_for_all_locals();
+ LivenessResults::new(cx).compute_for_all_locals(live_locals);
}
/// Contextual state for the type-liveness generator.
/// Index indicating where each variable is assigned, used, or
/// dropped.
- local_use_map: &'me LocalUseMap<'me>,
-
- /// Map tracking which variables need liveness computation.
- liveness_map: &'me NllLivenessMap,
+ local_use_map: &'me LocalUseMap,
/// Maps between a MIR Location and a LocationIndex
location_table: &'me LocationTable,
}
}
- fn compute_for_all_locals(&mut self) {
- for live_local in self.cx.liveness_map.to_local.indices() {
- let local = self.cx.liveness_map.from_live_var(live_local);
- debug!("local={:?} live_local={:?}", local, live_local);
-
+ fn compute_for_all_locals(&mut self, live_locals: Vec<Local>) {
+ for local in live_locals {
self.reset_local_state();
- self.add_defs_for(live_local);
- self.compute_use_live_points_for(live_local);
- self.compute_drop_live_points_for(live_local);
+ self.add_defs_for(local);
+ self.compute_use_live_points_for(local);
+ self.compute_drop_live_points_for(local);
let local_ty = self.cx.mir.local_decls[local].ty;
}
/// Adds the definitions of `local` into `self.defs`.
- fn add_defs_for(&mut self, live_local: LiveVar) {
- for def in self.cx.local_use_map.defs(live_local) {
+ fn add_defs_for(&mut self, local: Local) {
+ for def in self.cx.local_use_map.defs(local) {
debug!("- defined at {:?}", def);
self.defs.insert(def);
}
/// Computes all points where local is "use live" -- meaning its
/// current value may be used later (except by a drop). This is
- /// done by walking backwards from each use of `live_local` until we
+ /// done by walking backwards from each use of `local` until we
/// find a `def` of local.
///
- /// Requires `add_defs_for(live_local)` to have been executed.
- fn compute_use_live_points_for(&mut self, live_local: LiveVar) {
- debug!("compute_use_live_points_for(live_local={:?})", live_local);
+ /// Requires `add_defs_for(local)` to have been executed.
+ fn compute_use_live_points_for(&mut self, local: Local) {
+ debug!("compute_use_live_points_for(local={:?})", local);
- self.stack.extend(self.cx.local_use_map.uses(live_local));
+ self.stack.extend(self.cx.local_use_map.uses(local));
while let Some(p) = self.stack.pop() {
if self.defs.contains(p) {
continue;
///
/// Requires `compute_use_live_points_for` and `add_defs_for` to
/// have been executed.
- fn compute_drop_live_points_for(&mut self, live_local: LiveVar) {
- debug!("compute_drop_live_points_for(live_local={:?})", live_local);
+ fn compute_drop_live_points_for(&mut self, local: Local) {
+ debug!("compute_drop_live_points_for(local={:?})", local);
- let local = self.cx.liveness_map.from_live_var(live_local);
let mpi = self.cx.move_data.rev_lookup.find_local(local);
debug!("compute_drop_live_points_for: mpi = {:?}", mpi);
// Find the drops where `local` is initialized.
- for drop_point in self.cx.local_use_map.drops(live_local) {
+ for drop_point in self.cx.local_use_map.drops(local) {
let location = self.cx.elements.to_location(drop_point);
debug_assert_eq!(self.cx.mir.terminator_loc(location.block), location,);
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
+use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
use rustc::mir::tcx::PlaceTy;
use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind, UserSubsts};
use rustc::ty::{
self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
- CanonicalUserTypeAnnotation, UserTypeAnnotationIndex,
+ CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+ UserTypeAnnotationIndex,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc::ty::layout::VariantIdx;
use std::rc::Rc;
-use std::{fmt, iter};
+use std::{fmt, iter, mem};
use syntax_pos::{Span, DUMMY_SP};
macro_rules! span_mirbug {
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
- liveness_constraints: LivenessValues::new(elements),
+ liveness_constraints: LivenessValues::new(elements.clone()),
outlives_constraints: ConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
/// is a problem.
struct TypeVerifier<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
- mir: &'a Mir<'tcx>,
+ mir: &'b Mir<'tcx>,
last_span: Span,
mir_def_id: DefId,
errors_reported: bool,
location.to_locations(),
ConstraintCategory::Boring,
) {
- let annotation = &self.mir.user_type_annotations[annotation_index];
+ let annotation = &self.cx.user_type_annotations[annotation_index];
span_mirbug!(
self,
constant,
}
impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
- fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+ fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'b Mir<'tcx>) -> Self {
TypeVerifier {
mir,
mir_def_id: cx.mir_def_id,
Place::Base(PlaceBase::Local(index)) => PlaceTy::Ty {
ty: self.mir.local_decls[index].ty,
},
- Place::Base(PlaceBase::Promoted(box (_index, sty))) => {
+ Place::Base(PlaceBase::Promoted(box (index, sty))) => {
let sty = self.sanitize_type(place, sty);
- // FIXME -- promoted MIR return types reference
- // various "free regions" (e.g., scopes and things)
- // that they ought not to do. We have to figure out
- // how best to handle that -- probably we want treat
- // promoted MIR much like closures, renumbering all
- // their free regions and propagating constraints
- // upwards. We have the same acyclic guarantees, so
- // that should be possible. But for now, ignore them.
- //
- // let promoted_mir = &self.mir.promoted[index];
- // promoted_mir.return_ty()
+
+ if !self.errors_reported {
+ let promoted_mir = &self.mir.promoted[index];
+ self.sanitize_promoted(promoted_mir, location);
+
+ let promoted_ty = promoted_mir.return_ty();
+
+ if let Err(terr) = self.cx.eq_types(
+ sty,
+ promoted_ty,
+ location.to_locations(),
+ ConstraintCategory::Boring,
+ ) {
+ span_mirbug!(
+ self,
+ place,
+ "bad promoted type ({:?}: {:?}): {:?}",
+ promoted_ty,
+ sty,
+ terr
+ );
+ };
+ }
PlaceTy::Ty { ty: sty }
}
Place::Base(PlaceBase::Static(box Static { def_id, ty: sty })) => {
place_ty
}
+ fn sanitize_promoted(&mut self, promoted_mir: &'b Mir<'tcx>, location: Location) {
+ // Determine the constraints from the promoted MIR by running the type
+ // checker on the promoted MIR, then transfer the constraints back to
+ // the main MIR, changing the locations to the provided location.
+
+ let parent_mir = mem::replace(&mut self.mir, promoted_mir);
+
+ let all_facts = &mut None;
+ let mut constraints = Default::default();
+ let mut closure_bounds = Default::default();
+ if let Some(ref mut bcx) = self.cx.borrowck_context {
+ // Don't try to add borrow_region facts for the promoted MIR
+ mem::swap(bcx.all_facts, all_facts);
+
+ // Use a new sets of constraints and closure bounds so that we can
+ // modify their locations.
+ mem::swap(&mut bcx.constraints.outlives_constraints, &mut constraints);
+ mem::swap(&mut bcx.constraints.closure_bounds_mapping, &mut closure_bounds);
+ };
+
+ self.visit_mir(promoted_mir);
+
+ if !self.errors_reported {
+ // if verifier failed, don't do further checks to avoid ICEs
+ self.cx.typeck_mir(promoted_mir);
+ }
+
+ self.mir = parent_mir;
+ // Merge the outlives constraints back in, at the given location.
+ if let Some(ref mut base_bcx) = self.cx.borrowck_context {
+ mem::swap(base_bcx.all_facts, all_facts);
+ mem::swap(&mut base_bcx.constraints.outlives_constraints, &mut constraints);
+ mem::swap(&mut base_bcx.constraints.closure_bounds_mapping, &mut closure_bounds);
+
+ let locations = location.to_locations();
+ for constraint in constraints.iter() {
+ let mut constraint = *constraint;
+ constraint.locations = locations;
+ if let ConstraintCategory::Return
+ | ConstraintCategory::UseAsConst
+ | ConstraintCategory::UseAsStatic = constraint.category
+ {
+ // "Returning" from a promoted is an assigment to a
+ // temporary from the user's point of view.
+ constraint.category = ConstraintCategory::Boring;
+ }
+ base_bcx.constraints.outlives_constraints.push(constraint)
+ }
+
+ if !closure_bounds.is_empty() {
+ let combined_bounds_mapping = closure_bounds
+ .into_iter()
+ .flat_map(|(_, value)| value)
+ .collect();
+ let existing = base_bcx
+ .constraints
+ .closure_bounds_mapping
+ .insert(location, combined_bounds_mapping);
+ assert!(
+ existing.is_none(),
+ "Multiple promoteds/closures at the same location."
+ );
+ }
+ }
+ }
+
fn sanitize_projection(
&mut self,
base: PlaceTy<'tcx>,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'gcx>,
last_span: Span,
- mir: &'a Mir<'tcx>,
+ /// User type annotations are shared between the main MIR and the MIR of
+ /// all of the promoted items.
+ user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
mir_def_id: DefId,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
let mut checker = Self {
infcx,
last_span: DUMMY_SP,
- mir,
mir_def_id,
+ user_type_annotations: &mir.user_type_annotations,
param_env,
region_bound_pairs,
implicit_region_bound,
fn check_user_type_annotations(&mut self) {
debug!(
"check_user_type_annotations: user_type_annotations={:?}",
- self.mir.user_type_annotations
+ self.user_type_annotations
);
- for user_annotation in &self.mir.user_type_annotations {
+ for user_annotation in self.user_type_annotations {
let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
span, user_ty
a, v, user_ty, locations,
);
- let annotated_type = self.mir.user_type_annotations[user_ty.base].inferred_ty;
+ let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
let tcx = self.infcx.tcx;
location.to_locations(),
ConstraintCategory::Boring,
) {
- let annotation = &mir.user_type_annotations[annotation_index];
+ let annotation = &self.user_type_annotations[annotation_index];
span_mirbug!(
self,
stmt,
Locations::All(stmt.source_info.span),
ConstraintCategory::TypeAnnotation,
) {
- let annotation = &mir.user_type_annotations[projection.base];
+ let annotation = &self.user_type_annotations[projection.base];
span_mirbug!(
self,
stmt,
);
}
- CastKind::Misc => {}
+ CastKind::MutToConstPointer => {
+ let ty_from = match op.ty(mir, tcx).sty {
+ ty::RawPtr(ty::TypeAndMut {
+ ty: ty_from,
+ mutbl: hir::MutMutable,
+ }) => ty_from,
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "unexpected base type for cast {:?}",
+ ty,
+ );
+ return;
+ }
+ };
+ let ty_to = match ty.sty {
+ ty::RawPtr(ty::TypeAndMut {
+ ty: ty_to,
+ mutbl: hir::MutImmutable,
+ }) => ty_to,
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "unexpected target type for cast {:?}",
+ ty,
+ );
+ return;
+ }
+ };
+ if let Err(terr) = self.sub_types(
+ ty_from,
+ ty_to,
+ location.to_locations(),
+ ConstraintCategory::Cast,
+ ) {
+ span_mirbug!(
+ self,
+ rvalue,
+ "relating {:?} with {:?} yields {:?}",
+ ty_from,
+ ty_to,
+ terr
+ )
+ }
+ }
+
+ CastKind::Misc => {
+ if let ty::Ref(_, mut ty_from, _) = op.ty(mir, tcx).sty {
+ let (mut ty_to, mutability) = if let ty::RawPtr(ty::TypeAndMut {
+ ty: ty_to,
+ mutbl,
+ }) = ty.sty {
+ (ty_to, mutbl)
+ } else {
+ span_mirbug!(
+ self,
+ rvalue,
+ "invalid cast types {:?} -> {:?}",
+ op.ty(mir, tcx),
+ ty,
+ );
+ return;
+ };
+
+ // Handle the direct cast from `&[T; N]` to `*const T` by unwrapping
+ // any array we find.
+ while let ty::Array(ty_elem_from, _) = ty_from.sty {
+ ty_from = ty_elem_from;
+ if let ty::Array(ty_elem_to, _) = ty_to.sty {
+ ty_to = ty_elem_to;
+ } else {
+ break;
+ }
+ }
+
+ if let hir::MutMutable = mutability {
+ if let Err(terr) = self.eq_types(
+ ty_from,
+ ty_to,
+ location.to_locations(),
+ ConstraintCategory::Cast,
+ ) {
+ span_mirbug!(
+ self,
+ rvalue,
+ "equating {:?} with {:?} yields {:?}",
+ ty_from,
+ ty_to,
+ terr
+ )
+ }
+ } else {
+ if let Err(terr) = self.sub_types(
+ ty_from,
+ ty_to,
+ location.to_locations(),
+ ConstraintCategory::Cast,
+ ) {
+ span_mirbug!(
+ self,
+ rvalue,
+ "relating {:?} with {:?} yields {:?}",
+ ty_from,
+ ty_to,
+ terr
+ )
+ }
+ }
+ }
+ }
}
}
Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
- self.add_reborrow_constraint(location, region, borrowed_place);
+ self.add_reborrow_constraint(mir, location, region, borrowed_place);
+ }
+
+ Rvalue::BinaryOp(BinOp::Eq, left, right)
+ | Rvalue::BinaryOp(BinOp::Ne, left, right)
+ | Rvalue::BinaryOp(BinOp::Lt, left, right)
+ | Rvalue::BinaryOp(BinOp::Le, left, right)
+ | Rvalue::BinaryOp(BinOp::Gt, left, right)
+ | Rvalue::BinaryOp(BinOp::Ge, left, right) => {
+ let ty_left = left.ty(mir, tcx);
+ if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.sty {
+ let ty_right = right.ty(mir, tcx);
+ let common_ty = self.infcx.next_ty_var(
+ TypeVariableOrigin::MiscVariable(mir.source_info(location).span),
+ );
+ self.sub_types(
+ common_ty,
+ ty_left,
+ location.to_locations(),
+ ConstraintCategory::Boring
+ ).unwrap_or_else(|err| {
+ bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
+ });
+ if let Err(terr) = self.sub_types(
+ common_ty,
+ ty_right,
+ location.to_locations(),
+ ConstraintCategory::Boring
+ ) {
+ span_mirbug!(
+ self,
+ rvalue,
+ "unexpected comparison types {:?} and {:?} yields {:?}",
+ ty_left,
+ ty_right,
+ terr
+ )
+ }
+ }
}
- // FIXME: These other cases have to be implemented in future PRs
Rvalue::Use(..)
| Rvalue::Len(..)
| Rvalue::BinaryOp(..)
/// - `borrowed_place`: the place `P` being borrowed
fn add_reborrow_constraint(
&mut self,
+ mir: &Mir<'tcx>,
location: Location,
borrow_region: ty::Region<'tcx>,
borrowed_place: &Place<'tcx>,
match *elem {
ProjectionElem::Deref => {
let tcx = self.infcx.tcx;
- let base_ty = base.ty(self.mir, tcx).to_ty(tcx);
+ let base_ty = base.ty(mir, tcx).to_ty(tcx);
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.sty {
) -> ty::InstantiatedPredicates<'tcx> {
if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
let closure_constraints =
- closure_region_requirements.apply_requirements(tcx, location, def_id, substs);
+ closure_region_requirements.apply_requirements(tcx, def_id, substs);
if let Some(ref mut borrowck_context) = self.borrowck_context {
let bounds_mapping = closure_constraints
),
))
}
- UnpackedKind::Type(_) => None,
+ UnpackedKind::Type(_) | UnpackedKind::Const(_) => None,
}
})
.collect();
| ExprKind::ReifyFnPointer { .. }
| ExprKind::ClosureFnPointer { .. }
| ExprKind::UnsafeFnPointer { .. }
+ | ExprKind::MutToConstPointer { .. }
| ExprKind::Unsize { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
block.and(Rvalue::Use(Operand::Move(Place::Base(PlaceBase::Local(result)))))
}
ExprKind::Cast { source } => {
- let source = this.hir.mirror(source);
-
let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
}
let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::ClosureFnPointer, source, expr.ty))
}
+ ExprKind::MutToConstPointer { source } => {
+ let source = unpack!(block = this.as_operand(block, scope, source));
+ block.and(Rvalue::Cast(CastKind::MutToConstPointer, source, expr.ty))
+ }
ExprKind::Unsize { source } => {
let source = unpack!(block = this.as_operand(block, scope, source));
block.and(Rvalue::Cast(CastKind::Unsize, source, expr.ty))
| ExprKind::ReifyFnPointer { .. }
| ExprKind::ClosureFnPointer { .. }
| ExprKind::UnsafeFnPointer { .. }
+ | ExprKind::MutToConstPointer { .. }
| ExprKind::Unsize { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
| ExprKind::ReifyFnPointer { .. }
| ExprKind::ClosureFnPointer { .. }
| ExprKind::UnsafeFnPointer { .. }
+ | ExprKind::MutToConstPointer { .. }
| ExprKind::Unsize { .. }
| ExprKind::Repeat { .. }
| ExprKind::Borrow { .. }
-> Mir<'tcx>
{
let span = tcx.hir().span(ctor_id);
- if let hir::VariantData::Tuple(ref fields, ctor_id, _) = *v {
+ if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
tcx.infer_ctxt().enter(|infcx| {
let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span);
};
mir_util::dump_mir(tcx, None, "mir_map", &0,
- MirSource::item(tcx.hir().local_def_id(ctor_id)),
+ MirSource::item(tcx.hir().local_def_id_from_hir_id(ctor_id)),
&mir, |_, _| Ok(()) );
mir
use crate::hair::util::UserAnnotatedTyHelpers;
use rustc_data_structures::indexed_vec::Idx;
use rustc::hir::def::{Def, CtorKind};
-use rustc::mir::interpret::{GlobalId, ErrorHandled};
+use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
use rustc::ty::cast::CastKind as TyCastKind;
ExprKind::NeverToAny { source: expr.to_ref() }
}
Adjust::MutToConstPointer => {
- ExprKind::Cast { source: expr.to_ref() }
+ ExprKind::MutToConstPointer { source: expr.to_ref() }
}
Adjust::Deref(None) => {
// Adjust the span from the block, to the last expression of the
};
let source = if let Some((did, offset, var_ty)) = var {
- let mk_const = |literal| Expr {
+ let mk_lazy_const = |literal| Expr {
temp_lifetime,
ty: var_ty,
span: expr.span,
user_ty: None
},
}.to_ref();
- let offset = mk_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
+ let offset = mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
cx.tcx,
offset as u128,
cx.param_env.and(var_ty),
// in case we are offsetting from a computed discriminant
// and not the beginning of discriminants (which is always `0`)
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
- let lhs = mk_const(ty::LazyConst::Unevaluated(did, substs));
+ let lhs = mk_lazy_const(ty::LazyConst::Unevaluated(did, substs));
let bin = ExprKind::Binary {
op: BinOp::Add,
lhs,
))),
user_ty,
}
- },
+ }
+
+ Def::ConstParam(def_id) => {
+ let node_id = cx.tcx.hir().as_local_node_id(def_id).unwrap();
+ let item_id = cx.tcx.hir().get_parent_node(node_id);
+ let item_def_id = cx.tcx.hir().local_def_id(item_id);
+ let generics = cx.tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&cx.tcx.hir().local_def_id(node_id)];
+ let name = cx.tcx.hir().name(node_id).as_interned_str();
+ let val = ConstValue::Param(ty::ParamConst::new(index, name));
+ ExprKind::Literal {
+ literal: cx.tcx.mk_lazy_const(
+ ty::LazyConst::Evaluated(ty::Const {
+ val,
+ ty: cx.tables().node_type(expr.hir_id),
+ })
+ ),
+ user_ty: None,
+ }
+ }
Def::Const(def_id) |
Def::AssociatedConst(def_id) => {
pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> {
let tcx = self.tcx.global_tcx();
- let p = match tcx.hir().get(p.id) {
+ let p = match tcx.hir().get_by_hir_id(p.hir_id) {
Node::Pat(p) | Node::Binding(p) => p,
node => bug!("pattern became {:?}", node)
};
UnsafeFnPointer {
source: ExprRef<'tcx>,
},
+ MutToConstPointer {
+ source: ExprRef<'tcx>,
+ },
Unsize {
source: ExprRef<'tcx>,
},
self.apply_constructor(cx, ctor, ty)
}
-
/// Constructs a partial witness for a pattern given a list of
/// patterns expanded by the specialization step.
///
use rustc::middle::mem_categorization::cmt_;
use rustc::middle::region;
use rustc::session::Session;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, TyKind};
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::lint;
use rustc_errors::{Applicability, DiagnosticBuilder};
use smallvec::smallvec;
use std::slice;
-use syntax::ast;
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
// is uninhabited.
let pat_ty = self.tables.node_type(scrut.hir_id);
let module = self.tcx.hir().get_module_parent_by_hir_id(scrut.hir_id);
+ let mut def_span = None;
+ let mut missing_variants = vec![];
if inlined_arms.is_empty() {
let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns {
self.tcx.is_ty_uninhabited_from(module, pat_ty)
} else {
match pat_ty.sty {
ty::Never => true,
- ty::Adt(def, _) => def.variants.is_empty(),
+ ty::Adt(def, _) => {
+ def_span = self.tcx.hir().span_if_local(def.did);
+ if def.variants.len() < 4 && !def.variants.is_empty() {
+ // keep around to point at the definition of non-covered variants
+ missing_variants = def.variants.iter()
+ .map(|variant| variant.ident)
+ .collect();
+ }
+ def.variants.is_empty()
+ },
_ => false
}
};
if !scrutinee_is_uninhabited {
// We know the type is inhabited, so this must be wrong
- let mut err = create_e0004(self.tcx.sess, scrut.span,
- format!("non-exhaustive patterns: type `{}` \
- is non-empty",
- pat_ty));
- span_help!(&mut err, scrut.span,
- "ensure that all possible cases are being handled, \
- possibly by adding wildcards or more match arms");
+ let mut err = create_e0004(
+ self.tcx.sess,
+ scrut.span,
+ format!("non-exhaustive patterns: {}", match missing_variants.len() {
+ 0 => format!("type `{}` is non-empty", pat_ty),
+ 1 => format!(
+ "pattern `{}` of type `{}` is not handled",
+ missing_variants[0].name,
+ pat_ty,
+ ),
+ _ => format!("multiple patterns of type `{}` are not handled", pat_ty),
+ }),
+ );
+ err.help("ensure that all possible cases are being handled, \
+ possibly by adding wildcards or more match arms");
+ if let Some(sp) = def_span {
+ err.span_label(sp, format!("`{}` defined here", pat_ty));
+ }
+ // point at the definition of non-covered enum variants
+ for variant in &missing_variants {
+ err.span_label(variant.span, "variant not covered");
+ }
err.emit();
}
// If the type *is* uninhabited, it's vacuously exhaustive
}
fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
- let module = self.tcx.hir().get_module_parent(pat.id);
+ let module = self.tcx.hir().get_module_parent_by_hir_id(pat.hir_id);
MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
let mut patcx = PatternContext::new(self.tcx,
self.param_env.and(self.identity_substs),
};
let pattern_string = witness[0].single_pattern().to_string();
- let mut diag = struct_span_err!(
+ let mut err = struct_span_err!(
self.tcx.sess, pat.span, E0005,
"refutable pattern in {}: `{}` not covered",
origin, pattern_string
}
_ => format!("pattern `{}` not covered", pattern_string),
};
- diag.span_label(pat.span, label_msg);
- diag.emit();
+ err.span_label(pat.span, label_msg);
+ if let ty::Adt(def, _) = pattern_ty.sty {
+ if let Some(sp) = self.tcx.hir().span_if_local(def.did){
+ err.span_label(sp, format!("`{}` defined here", pattern_ty));
+ }
+ }
+ err.emit();
});
}
}
}
// Check for unreachable patterns
-fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
- arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
- source: hir::MatchSource)
-{
+fn check_arms<'a, 'tcx>(
+ cx: &mut MatchCheckCtxt<'a, 'tcx>,
+ arms: &[(Vec<(&'a Pattern<'tcx>, &hir::Pat)>, Option<&hir::Expr>)],
+ source: hir::MatchSource,
+) {
let mut seen = Matrix::empty();
let mut catchall = None;
for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
}
}
-fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
- scrut_ty: Ty<'tcx>,
- sp: Span,
- matrix: &Matrix<'p, 'tcx>) {
+fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(
+ cx: &mut MatchCheckCtxt<'a, 'tcx>,
+ scrut_ty: Ty<'tcx>,
+ sp: Span,
+ matrix: &Matrix<'p, 'tcx>,
+) {
let wild_pattern = Pattern {
ty: scrut_ty,
span: DUMMY_SP,
1 => format!("pattern {} not covered", joined_patterns),
_ => format!("patterns {} not covered", joined_patterns),
};
- create_e0004(cx.tcx.sess, sp,
- format!("non-exhaustive patterns: {} not covered",
- joined_patterns))
- .span_label(sp, label_text)
- .emit();
+ let mut err = create_e0004(cx.tcx.sess, sp, format!(
+ "non-exhaustive patterns: {} not covered",
+ joined_patterns,
+ ));
+ err.span_label(sp, label_text);
+ // point at the definition of non-covered enum variants
+ if let ty::Adt(def, _) = scrut_ty.sty {
+ if let Some(sp) = cx.tcx.hir().span_if_local(def.did){
+ err.span_label(sp, format!("`{}` defined here", scrut_ty));
+ }
+ }
+ let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern<'_>>>();
+ if patterns.len() < 4 {
+ for sp in maybe_point_at_variant(cx, &scrut_ty.sty, patterns.as_slice()) {
+ err.span_label(sp, "not covered");
+ }
+ }
+ err.help("ensure that all possible cases are being handled, \
+ possibly by adding wildcards or more match arms");
+ err.emit();
}
NotUseful => {
// This is good, wildcard pattern isn't reachable
}
}
+fn maybe_point_at_variant(
+ cx: &mut MatchCheckCtxt<'a, 'tcx>,
+ sty: &TyKind<'tcx>,
+ patterns: &[Pattern<'_>],
+) -> Vec<Span> {
+ let mut covered = vec![];
+ if let ty::Adt(def, _) = sty {
+ // Don't point at variants that have already been covered due to other patterns to avoid
+ // visual clutter
+ for pattern in patterns {
+ let pk: &PatternKind<'_> = &pattern.kind;
+ if let PatternKind::Variant { adt_def, variant_index, subpatterns, .. } = pk {
+ if adt_def.did == def.did {
+ let sp = def.variants[*variant_index].ident.span;
+ if covered.contains(&sp) {
+ continue;
+ }
+ covered.push(sp);
+ let subpatterns = subpatterns.iter()
+ .map(|field_pattern| field_pattern.pattern.clone())
+ .collect::<Vec<_>>();
+ covered.extend(
+ maybe_point_at_variant(cx, sty, subpatterns.as_slice()),
+ );
+ }
+ }
+ if let PatternKind::Leaf { subpatterns } = pk {
+ let subpatterns = subpatterns.iter()
+ .map(|field_pattern| field_pattern.pattern.clone())
+ .collect::<Vec<_>>();
+ covered.extend(maybe_point_at_variant(cx, sty, subpatterns.as_slice()));
+ }
+ }
+ }
+ covered
+}
+
// Legality of move bindings checking
-fn check_legality_of_move_bindings(cx: &MatchVisitor<'_, '_>,
- has_guard: bool,
- pats: &[P<Pat>]) {
+fn check_legality_of_move_bindings(
+ cx: &MatchVisitor<'_, '_>,
+ has_guard: bool,
+ pats: &[P<Pat>],
+) {
let mut by_ref_span = None;
for pat in pats {
pat.each_binding(|_, hir_id, span, _path| {
ty::ImmBorrow | ty::UniqueImmBorrow => {}
}
}
- fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {}
+ fn decl_without_init(&mut self, _: hir::HirId, _: Span) {}
fn mutate(&mut self, _: hir::HirId, span: Span, _: &cmt_<'_>, mode: MutateMode) {
match mode {
MutateMode::JustWrite | MutateMode::WriteAndRead => {
self.unsize_into(src, dest)?;
}
- Misc => {
+ Misc | MutToConstPointer => {
let src = self.read_immediate(src)?;
if self.type_is_fat_ptr(src.layout.ty) {
val: ty::Const<'tcx>,
layout: Option<TyLayout<'tcx>>,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
+ let val = self.monomorphize(val)?;
let layout = from_known_layout(layout, || {
- let ty = self.monomorphize(val.ty)?;
- self.layout_of(ty)
+ self.layout_of(val.ty)
})?;
let op = match val.val {
+ ConstValue::Param(_) | ConstValue::Infer(_) => bug!(),
ConstValue::ByRef(ptr, alloc) => {
// We rely on mutability being set correctly in that allocation to prevent writes
// where none should happen -- and for `static mut`, we copy on demand anyway.
instance: Instance<'tcx>)
{
let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
- debug!(" => type length={}", type_length);
+ let const_length = instance.substs.consts()
+ .flat_map(|ct| {
+ let ty = match ct {
+ ty::LazyConst::Evaluated(ct) => ct.ty,
+ ty::LazyConst::Unevaluated(def_id, _) => tcx.type_of(*def_id),
+ };
+ ty.walk()
+ })
+ .count();
+ debug!(" => type length={}, const length={}", type_length, const_length);
// Rust code can easily create exponentially-long types using only a
// polynomial recursion depth. Even with the default recursion
//
// Bail out in these cases to avoid that bad user experience.
let type_length_limit = *tcx.sess.type_length_limit.get();
- if type_length > type_length_limit {
+ // We include the const length in the type length, as it's better
+ // to be overly conservative.
+ if type_length + const_length > type_length_limit {
// The instance name is already known to be too long for rustc. Use
// `{:.64}` to avoid blasting the user's terminal with thousands of
// lines of type-name.
diag.note(&format!(
"consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
- type_length_limit*2));
+ type_length_limit * 2));
diag.emit();
tcx.sess.abort_if_errors();
}
return false
}
- // If this instance has no type parameters, it cannot be a shared
+ // If this instance has non-erasable parameters, it cannot be a shared
// monomorphization. Non-generic instances are already handled above
// by `is_reachable_non_generic()`
- if substs.types().next().is_none() {
+ if substs.non_erasable_generics().next().is_none() {
return false
}
hir::ItemKind::Union(_, ref generics) => {
if generics.params.is_empty() {
if self.mode == MonoItemCollectionMode::Eager {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
debug!("RootCollector: ADT drop-glue for {}",
def_id_to_string(self.tcx, def_id));
hir::ItemKind::GlobalAsm(..) => {
debug!("RootCollector: ItemKind::GlobalAsm({})",
def_id_to_string(self.tcx,
- self.tcx.hir().local_def_id(item.id)));
- self.output.push(MonoItem::GlobalAsm(item.id));
+ self.tcx.hir().local_def_id_from_hir_id(item.hir_id)));
+ let node_id = self.tcx.hir().hir_to_node_id(item.hir_id);
+ self.output.push(MonoItem::GlobalAsm(node_id));
}
hir::ItemKind::Static(..) => {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
debug!("RootCollector: ItemKind::Static({})",
def_id_to_string(self.tcx, def_id));
self.output.push(MonoItem::Static(def_id));
// actually used somewhere. Just declaring them is insufficient.
// but even just declaring them must collect the items they refer to
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let instance = Instance::mono(self.tcx, def_id);
let cid = GlobalId {
}
}
hir::ItemKind::Fn(..) => {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
self.push_if_root(def_id);
}
}
}
}
- let impl_def_id = tcx.hir().local_def_id(item.id);
+ let impl_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
debug!("create_mono_items_for_default_impls(item={})",
def_id_to_string(tcx, impl_def_id));
continue;
}
- if tcx.generics_of(method.def_id).own_counts().types != 0 {
+ let counts = tcx.generics_of(method.def_id).own_counts();
+ if counts.types + counts.consts != 0 {
continue;
}
let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } |
+ GenericParamDefKind::Const => {
trait_ref.substs[param.index as usize]
}
}
use crate::monomorphize::Instance;
use rustc::hir;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::mir::interpret::ConstValue;
use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
+use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
use rustc::ty::subst::{SubstsRef, InternalSubsts};
use syntax::ast;
use syntax::attr::InlineAttr;
fn is_generic_fn(&self) -> bool {
match *self.as_mono_item() {
MonoItem::Fn(ref instance) => {
- instance.substs.types().next().is_some()
+ instance.substs.non_erasable_generics().next().is_some()
}
MonoItem::Static(..) |
MonoItem::GlobalAsm(..) => false,
ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
ty::Adt(adt_def, substs) => {
self.push_def_path(adt_def.did, output);
- self.push_type_params(substs, iter::empty(), output, debug);
+ self.push_generic_params(substs, iter::empty(), output, debug);
},
ty::Tuple(component_types) => {
output.push('(');
ty::Dynamic(ref trait_data, ..) => {
if let Some(principal) = trait_data.principal() {
self.push_def_path(principal.def_id(), output);
- self.push_type_params(
+ self.push_generic_params(
principal.skip_binder().substs,
trait_data.projection_bounds(),
output,
self.push_def_path(def_id, output);
let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
let substs = substs.truncate_to(self.tcx, generics);
- self.push_type_params(substs, iter::empty(), output, debug);
+ self.push_generic_params(substs, iter::empty(), output, debug);
}
ty::Error |
ty::Bound(..) |
}
}
+ // FIXME(const_generics): handle debug printing.
+ pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
+ match c {
+ LazyConst::Unevaluated(..) => output.push_str("_: _"),
+ LazyConst::Evaluated(Const { ty, val }) => {
+ match val {
+ ConstValue::Infer(..) => output.push_str("_"),
+ ConstValue::Param(ParamConst { name, .. }) => {
+ write!(output, "{}", name).unwrap();
+ }
+ _ => write!(output, "{:?}", c).unwrap(),
+ }
+ output.push_str(": ");
+ self.push_type_name(ty, output, debug);
+ }
+ }
+ }
+
pub fn push_def_path(&self,
def_id: DefId,
output: &mut String) {
output.pop();
}
- fn push_type_params<I>(&self,
- substs: SubstsRef<'tcx>,
- projections: I,
- output: &mut String,
- debug: bool)
- where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>>
- {
+ fn push_generic_params<I>(
+ &self,
+ substs: SubstsRef<'tcx>,
+ projections: I,
+ output: &mut String,
+ debug: bool,
+ ) where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>> {
let mut projections = projections.peekable();
- if substs.types().next().is_none() && projections.peek().is_none() {
+ if substs.non_erasable_generics().next().is_none() && projections.peek().is_none() {
return;
}
output.push_str(", ");
}
+ for const_parameter in substs.consts() {
+ self.push_const_name(const_parameter, output, debug);
+ output.push_str(", ");
+ }
+
output.pop();
output.pop();
output: &mut String,
debug: bool) {
self.push_def_path(instance.def_id(), output);
- self.push_type_params(instance.substs, iter::empty(), output, debug);
+ self.push_generic_params(instance.substs, iter::empty(), output, debug);
}
}
return Visibility::Hidden
}
- let is_generic = instance.substs.types().next().is_some();
+ let is_generic = instance.substs.non_erasable_generics().next().is_some();
// Upstream `DefId` instances get different handling than local ones
if !def_id.is_local() {
use rustc::hir::def_id::DefId;
use rustc::infer;
use rustc::mir::*;
-use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
+use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::ty::query::Providers;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_target::spec::abi::Abi;
-use syntax::ast;
use syntax_pos::Span;
use std::fmt;
) {
let tcx = self.tcx;
- let substs = InternalSubsts::for_item(tcx, self.def_id, |param, _| {
- match param.kind {
- GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
- GenericParamDefKind::Type {..} => ty.into(),
- }
- });
+ let substs = tcx.mk_substs_trait(ty, &[]);
// `func == Clone::clone(&ty) -> ty`
let func_ty = tcx.mk_fn_def(self.def_id, substs);
}
pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
- ctor_id: ast::NodeId,
+ ctor_id: hir::HirId,
fields: &[hir::StructField],
span: Span)
-> Mir<'tcx>
{
let tcx = infcx.tcx;
let gcx = tcx.global_tcx();
- let def_id = tcx.hir().local_def_id(ctor_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(ctor_id);
let param_env = gcx.param_env(def_id);
// Normalize the sig.
// FIXME: when we make this a hard error, this should have its
// own error code.
- let message = if tcx.generics_of(def_id).own_counts().types != 0 {
+ let counts = tcx.generics_of(def_id).own_counts();
+ let message = if counts.types + counts.consts != 0 {
"#[derive] can't be used on a #[repr(packed)] struct with \
- type parameters (error E0133)".to_string()
+ type or const parameters (error E0133)".to_string()
} else {
"#[derive] can't be used on a #[repr(packed)] struct that \
does not derive Copy (error E0133)".to_string()
use crate::dataflow::{do_dataflow, DebugFormatted, state_for_location};
use crate::dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
use crate::util::dump_mir;
-use crate::util::liveness::{self, IdentityMap};
+use crate::util::liveness;
pub struct StateTransform;
state: u32,
resume: BasicBlock,
drop: Option<BasicBlock>,
- storage_liveness: liveness::LiveVarSet<Local>,
+ storage_liveness: liveness::LiveVarSet,
}
struct TransformVisitor<'a, 'tcx: 'a> {
// A map from a suspension point in a block to the locals which have live storage at that point
// FIXME(eddyb) This should use `IndexVec<BasicBlock, Option<_>>`.
- storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
+ storage_liveness: FxHashMap<BasicBlock, liveness::LiveVarSet>,
// A list of suspension points, generated during the transform
suspension_points: Vec<SuspensionPoint>,
new_ret_local
}
-struct StorageIgnored(liveness::LiveVarSet<Local>);
+struct StorageIgnored(liveness::LiveVarSet);
impl<'tcx> Visitor<'tcx> for StorageIgnored {
fn visit_statement(&mut self,
source: MirSource<'tcx>,
movable: bool,
) -> (
- liveness::LiveVarSet<Local>,
- FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>,
+ liveness::LiveVarSet,
+ FxHashMap<BasicBlock, liveness::LiveVarSet>,
) {
let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
let node_id = tcx.hir().as_local_node_id(source.def_id()).unwrap();
let mut set = liveness::LiveVarSet::new_empty(mir.local_decls.len());
let mut liveness = liveness::liveness_of_locals(
mir,
- &IdentityMap::new(mir),
);
liveness::dump_mir(
tcx,
"generator_liveness",
source,
mir,
- &IdentityMap::new(mir),
&liveness,
);
mir: &mut Mir<'tcx>)
-> (FxHashMap<Local, (Ty<'tcx>, usize)>,
GeneratorLayout<'tcx>,
- FxHashMap<BasicBlock, liveness::LiveVarSet<Local>>)
+ FxHashMap<BasicBlock, liveness::LiveVarSet>)
{
// Use a liveness analysis to compute locals which are live across a suspension point
let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx,
// inlining. This is to ensure that the final crate doesn't have MIR that
// reference unexported symbols
if callsite.callee.is_local() {
- if callsite.substs.types().count() == 0 && !hinted {
+ if callsite.substs.non_erasable_generics().count() == 0 && !hinted {
debug!(" callee is an exported function - not inlining");
return false;
}
_: &'tcx hir::Generics,
_: hir::HirId,
_: Span) {
- if let hir::VariantData::Tuple(_, node_id, _) = *v {
- self.set.insert(self.tcx.hir().local_def_id(node_id));
+ if let hir::VariantData::Tuple(_, hir_id) = *v {
+ self.set.insert(self.tcx.hir().local_def_id_from_hir_id(hir_id));
}
intravisit::walk_struct_def(self, v)
}
Rvalue::Cast(CastKind::UnsafeFnPointer, ..) |
Rvalue::Cast(CastKind::ClosureFnPointer, ..) |
Rvalue::Cast(CastKind::Unsize, ..) |
+ Rvalue::Cast(CastKind::MutToConstPointer, ..) |
Rvalue::Discriminant(..) |
Rvalue::Len(_) |
Rvalue::Ref(..) |
_ => check_operand(tcx, mir, operand, span),
}
}
+ Rvalue::Cast(CastKind::MutToConstPointer, operand, _) => {
+ check_operand(tcx, mir, operand, span)
+ }
Rvalue::Cast(CastKind::UnsafeFnPointer, _, _) |
Rvalue::Cast(CastKind::ClosureFnPointer, _, _) |
Rvalue::Cast(CastKind::ReifyFnPointer, _, _) => Err((
use crate::transform::MirSource;
use crate::util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
-pub type LiveVarSet<V> = BitSet<V>;
+pub type LiveVarSet = BitSet<Local>;
/// This gives the result of the liveness analysis at the boundary of
/// basic blocks.
/// liveness for. This is often `Local`, in which case we computed
/// liveness for all variables -- but it can also be some other type,
/// which indicates a subset of the variables within the graph.
-pub struct LivenessResult<V: Idx> {
+pub struct LivenessResult {
/// Live variables on exit to each basic block. This is equal to
/// the union of the `ins` for each successor.
- pub outs: IndexVec<BasicBlock, LiveVarSet<V>>,
-}
-
-/// Defines the mapping to/from the MIR local variables (`Local`) to
-/// the "live variable indices" we are using in a particular
-/// computation.
-pub trait LiveVariableMap {
- type LiveVar;
-
- fn from_local(&self, local: Local) -> Option<Self::LiveVar>;
- fn from_live_var(&self, local: Self::LiveVar) -> Local;
- fn num_variables(&self) -> usize;
-}
-
-#[derive(Debug)]
-pub struct IdentityMap<'a, 'tcx: 'a> {
- mir: &'a Mir<'tcx>,
-}
-
-impl<'a, 'tcx> IdentityMap<'a, 'tcx> {
- pub fn new(mir: &'a Mir<'tcx>) -> Self {
- Self { mir }
- }
-}
-
-impl<'a, 'tcx> LiveVariableMap for IdentityMap<'a, 'tcx> {
- type LiveVar = Local;
-
- fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
- Some(local)
- }
-
- fn from_live_var(&self, local: Self::LiveVar) -> Local {
- local
- }
-
- fn num_variables(&self) -> usize {
- self.mir.local_decls.len()
- }
+ pub outs: IndexVec<BasicBlock, LiveVarSet>,
}
/// Computes which local variables are live within the given function
/// `mir`. The liveness mode `mode` determines what sorts of uses are
/// considered to make a variable live (e.g., do drops count?).
-pub fn liveness_of_locals<'tcx, V: Idx>(
+pub fn liveness_of_locals<'tcx>(
mir: &Mir<'tcx>,
- map: &impl LiveVariableMap<LiveVar = V>,
-) -> LivenessResult<V> {
- let num_live_vars = map.num_variables();
+) -> LivenessResult {
+ let num_live_vars = mir.local_decls.len();
- let def_use: IndexVec<_, DefsUses<V>> = mir
+ let def_use: IndexVec<_, DefsUses> = mir
.basic_blocks()
.iter()
- .map(|b| block(map, b, num_live_vars))
+ .map(|b| block(b, num_live_vars))
.collect();
- let mut outs: IndexVec<_, LiveVarSet<V>> = mir
+ let mut outs: IndexVec<_, LiveVarSet> = mir
.basic_blocks()
.indices()
.map(|_| LiveVarSet::new_empty(num_live_vars))
}
}
-struct DefsUsesVisitor<'lv, V, M>
-where
- V: Idx,
- M: LiveVariableMap<LiveVar = V> + 'lv,
+struct DefsUsesVisitor
{
- map: &'lv M,
- defs_uses: DefsUses<V>,
+ defs_uses: DefsUses,
}
#[derive(Eq, PartialEq, Clone)]
-struct DefsUses<V: Idx> {
- defs: LiveVarSet<V>,
- uses: LiveVarSet<V>,
+struct DefsUses {
+ defs: LiveVarSet,
+ uses: LiveVarSet,
}
-impl<V: Idx> DefsUses<V> {
- fn apply(&self, bits: &mut LiveVarSet<V>) -> bool {
+impl DefsUses {
+ fn apply(&self, bits: &mut LiveVarSet) -> bool {
bits.subtract(&self.defs) | bits.union(&self.uses)
}
- fn add_def(&mut self, index: V) {
+ fn add_def(&mut self, index: Local) {
// If it was used already in the block, remove that use
// now that we found a definition.
//
self.defs.insert(index);
}
- fn add_use(&mut self, index: V) {
+ fn add_use(&mut self, index: Local) {
// Inverse of above.
//
// Example:
}
}
-impl<'tcx, 'lv, V, M> Visitor<'tcx> for DefsUsesVisitor<'lv, V, M>
-where
- V: Idx,
- M: LiveVariableMap<LiveVar = V>,
+impl<'tcx> Visitor<'tcx> for DefsUsesVisitor
{
fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) {
- if let Some(v_index) = self.map.from_local(local) {
- match categorize(context) {
- Some(DefUse::Def) => self.defs_uses.add_def(v_index),
- Some(DefUse::Use) | Some(DefUse::Drop) => self.defs_uses.add_use(v_index),
- _ => (),
- }
+ match categorize(context) {
+ Some(DefUse::Def) => self.defs_uses.add_def(local),
+ Some(DefUse::Use) | Some(DefUse::Drop) => self.defs_uses.add_use(local),
+ _ => (),
}
}
}
-fn block<'tcx, V: Idx>(
- map: &impl LiveVariableMap<LiveVar = V>,
+fn block<'tcx>(
b: &BasicBlockData<'tcx>,
locals: usize,
-) -> DefsUses<V> {
+) -> DefsUses {
let mut visitor = DefsUsesVisitor {
- map,
defs_uses: DefsUses {
defs: LiveVarSet::new_empty(locals),
uses: LiveVarSet::new_empty(locals),
visitor.defs_uses
}
-pub fn dump_mir<'a, 'tcx, V: Idx>(
+pub fn dump_mir<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_name: &str,
source: MirSource<'tcx>,
mir: &Mir<'tcx>,
- map: &impl LiveVariableMap<LiveVar = V>,
- result: &LivenessResult<V>,
+ result: &LivenessResult,
) {
if !dump_enabled(tcx, pass_name, source) {
return;
// see notes on #41697 below
tcx.item_path_str(source.def_id())
});
- dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, map, result);
+ dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result);
}
-fn dump_matched_mir_node<'a, 'tcx, V: Idx>(
+fn dump_matched_mir_node<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_name: &str,
node_path: &str,
source: MirSource<'tcx>,
mir: &Mir<'tcx>,
- map: &dyn LiveVariableMap<LiveVar = V>,
- result: &LivenessResult<V>,
+ result: &LivenessResult,
) {
let mut file_path = PathBuf::new();
file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir));
writeln!(file, "// source = {:?}", source)?;
writeln!(file, "// pass_name = {}", pass_name)?;
writeln!(file, "")?;
- write_mir_fn(tcx, source, mir, map, &mut file, result)?;
+ write_mir_fn(tcx, source, mir, &mut file, result)?;
Ok(())
});
}
-pub fn write_mir_fn<'a, 'tcx, V: Idx>(
+pub fn write_mir_fn<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource<'tcx>,
mir: &Mir<'tcx>,
- map: &dyn LiveVariableMap<LiveVar = V>,
w: &mut dyn Write,
- result: &LivenessResult<V>,
+ result: &LivenessResult,
) -> io::Result<()> {
write_mir_intro(tcx, src, mir, w)?;
for block in mir.basic_blocks().indices() {
- let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LiveVarSet<V>>| {
+ let print = |w: &mut dyn Write, prefix, result: &IndexVec<BasicBlock, LiveVarSet>| {
let live: Vec<String> = result[block]
.iter()
- .map(|v| map.from_live_var(v))
.map(|local| format!("{:?}", local))
.collect();
writeln!(w, "{} {{{}}}", prefix, live.join(", "))
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let item_def_id = self.tcx.hir().local_def_id(item.id);
+ let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
if let ItemKind::Ty(..) = item.node {
for attr in self.tcx.get_attrs(item_def_id).iter() {
use rustc::util::nodemap::{ItemLocalSet, HirIdSet};
use rustc::hir;
use rustc_data_structures::sync::Lrc;
-use syntax::ast;
use syntax_pos::{Span, DUMMY_SP};
use log::debug;
use Promotability::*;
}
}
- fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) {}
+ fn decl_without_init(&mut self, _id: hir::HirId, _span: Span) {}
fn mutate(&mut self,
_assignment_id: hir::HirId,
_assignment_span: Span,
//! Used by `rustc` when compiling a plugin crate.
-use syntax::ast;
use syntax::attr;
use syntax_pos::Span;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ty::query::Providers;
struct RegistrarFinder {
- registrars: Vec<(ast::NodeId, Span)> ,
+ registrars: Vec<(hir::HirId, Span)> ,
}
impl<'v> ItemLikeVisitor<'v> for RegistrarFinder {
if let hir::ItemKind::Fn(..) = item.node {
if attr::contains_name(&item.attrs,
"plugin_registrar") {
- self.registrars.push((item.id, item.span));
+ self.registrars.push((item.hir_id, item.span));
}
}
}
match finder.registrars.len() {
0 => None,
1 => {
- let (node_id, _) = finder.registrars.pop().unwrap();
- Some(tcx.hir().local_def_id(node_id))
+ let (hir_id, _) = finder.registrars.pop().unwrap();
+ Some(tcx.hir().local_def_id_from_hir_id(hir_id))
},
_ => {
let diagnostic = tcx.sess.diagnostic();
use rustc::util::nodemap::HirIdSet;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
-use syntax::ast::{self, DUMMY_NODE_ID, Ident};
+use syntax::ast::Ident;
use syntax::attr;
use syntax::symbol::keywords;
use syntax_pos::Span;
fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-> (ty::Visibility, Span, &'static str) {
- match tcx.hir().as_local_node_id(def_id) {
- Some(node_id) => {
- let vis = match tcx.hir().get(node_id) {
+ match tcx.hir().as_local_hir_id(def_id) {
+ Some(hir_id) => {
+ let vis = match tcx.hir().get_by_hir_id(hir_id) {
Node::Item(item) => &item.vis,
Node::ForeignItem(foreign_item) => &foreign_item.vis,
Node::TraitItem(..) | Node::Variant(..) => {
- return def_id_visibility(tcx, tcx.hir().get_parent_did(node_id));
+ return def_id_visibility(tcx, tcx.hir().get_parent_did_by_hir_id(hir_id));
}
Node::ImplItem(impl_item) => {
- match tcx.hir().get(tcx.hir().get_parent(node_id)) {
+ match tcx.hir().get_by_hir_id(tcx.hir().get_parent_item(hir_id)) {
Node::Item(item) => match &item.node {
hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis,
hir::ItemKind::Impl(.., Some(trait_ref), _, _)
}
}
Node::StructCtor(vdata) => {
- let struct_node_id = tcx.hir().get_parent(node_id);
- let item = match tcx.hir().get(struct_node_id) {
+ let struct_hir_id = tcx.hir().get_parent_item(hir_id);
+ let item = match tcx.hir().get_by_hir_id(struct_hir_id) {
Node::Item(item) => item,
node => bug!("unexpected node kind: {:?}", node),
};
let (mut ctor_vis, mut span, mut descr) =
- (ty::Visibility::from_hir(&item.vis, struct_node_id, tcx),
+ (ty::Visibility::from_hir(&item.vis, struct_hir_id, tcx),
item.vis.span, item.vis.node.descr());
for field in vdata.fields() {
- let field_vis = ty::Visibility::from_hir(&field.vis, node_id, tcx);
+ let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
if ctor_vis.is_at_least(field_vis, tcx) {
ctor_vis = field_vis;
span = field.vis.span;
// If the structure is marked as non_exhaustive then lower the
// visibility to within the crate.
if ctor_vis == ty::Visibility::Public {
- let adt_def = tcx.adt_def(tcx.hir().get_parent_did(node_id));
+ let adt_def = tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span;
}
node => bug!("unexpected node kind: {:?}", node)
};
- (ty::Visibility::from_hir(vis, node_id, tcx), vis.span, vis.node.descr())
+ (ty::Visibility::from_hir(vis, hir_id, tcx), vis.span, vis.node.descr())
}
None => {
let vis = tcx.visibility(def_id);
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
// associated types for which we can't determine visibility precisely.
- fn of_impl<'a, 'tcx>(node_id: ast::NodeId, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ fn of_impl<'a, 'tcx>(hir_id: hir::HirId, tcx: TyCtxt<'a, 'tcx, 'tcx>,
access_levels: &'a AccessLevels) -> Self {
let mut find = FindMin { tcx, access_levels, min: Self::MAX };
- let def_id = tcx.hir().local_def_id(node_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
find.visit(tcx.type_of(def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref);
}
impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
- fn get(&self, id: ast::NodeId) -> Option<AccessLevel> {
- self.access_levels.map.get(&id).cloned()
+ fn get(&self, id: hir::HirId) -> Option<AccessLevel> {
+ let node_id = self.tcx.hir().hir_to_node_id(id);
+ self.access_levels.map.get(&node_id).cloned()
}
// Updates node level and returns the updated level.
- fn update(&mut self, id: ast::NodeId, level: Option<AccessLevel>) -> Option<AccessLevel> {
+ fn update(&mut self, id: hir::HirId, level: Option<AccessLevel>) -> Option<AccessLevel> {
let old_level = self.get(id);
// Accessibility levels can only grow.
if level > old_level {
- self.access_levels.map.insert(id, level.unwrap());
+ let node_id = self.tcx.hir().hir_to_node_id(id);
+ self.access_levels.map.insert(node_id, level.unwrap());
self.changed = true;
level
} else {
}
}
- fn reach(&mut self, item_id: ast::NodeId, access_level: Option<AccessLevel>)
+ fn reach(&mut self, item_id: hir::HirId, access_level: Option<AccessLevel>)
-> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
- item_def_id: self.tcx.hir().local_def_id(item_id),
+ item_def_id: self.tcx.hir().local_def_id_from_hir_id(item_id),
ev: self,
}
}
let def_id = self.tcx.hir().local_def_id(item_id.id);
if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) { continue; }
if let hir::ItemKind::Use(..) = item.node {
- self.update(item.id, Some(AccessLevel::Exported));
+ self.update(item.hir_id, Some(AccessLevel::Exported));
}
}
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
let inherited_item_level = match item.node {
hir::ItemKind::Impl(..) =>
- Option::<AccessLevel>::of_impl(item.id, self.tcx, &self.access_levels),
+ Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels),
// Foreign modules inherit level from parents.
hir::ItemKind::ForeignMod(..) => self.prev_level,
// Other `pub` items inherit levels from parents.
};
// Update level of the item itself.
- let item_level = self.update(item.id, inherited_item_level);
+ let item_level = self.update(item.hir_id, inherited_item_level);
// Update levels of nested things.
match item.node {
hir::ItemKind::Enum(ref def, _) => {
for variant in &def.variants {
- let variant_level = self.update(variant.node.data.id(), item_level);
+ let variant_level = self.update(variant.node.data.hir_id(), item_level);
for field in variant.node.data.fields() {
- self.update(field.id, variant_level);
+ self.update(field.hir_id, variant_level);
}
}
}
hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
for impl_item_ref in impl_item_refs {
if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() {
- self.update(impl_item_ref.id.node_id, item_level);
+ self.update(impl_item_ref.id.hir_id, item_level);
}
}
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
for trait_item_ref in trait_item_refs {
- self.update(trait_item_ref.id.node_id, item_level);
+ self.update(trait_item_ref.id.hir_id, item_level);
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
if !def.is_struct() {
- self.update(def.id(), item_level);
+ self.update(def.hir_id(), item_level);
}
for field in def.fields() {
if field.vis.node.is_pub() {
- self.update(field.id, item_level);
+ self.update(field.hir_id, item_level);
}
}
}
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
if foreign_item.vis.node.is_pub() {
- self.update(foreign_item.id, item_level);
+ self.update(foreign_item.hir_id, item_level);
}
}
}
// in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
// reachable if they are returned via `impl Trait`, even from private functions.
let exist_level = cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
- self.reach(item.id, exist_level).generics().predicates().ty();
+ self.reach(item.hir_id, exist_level).generics().predicates().ty();
}
// Visit everything.
hir::ItemKind::Const(..) | hir::ItemKind::Static(..) |
hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => {
if item_level.is_some() {
- self.reach(item.id, item_level).generics().predicates().ty();
+ self.reach(item.hir_id, item_level).generics().predicates().ty();
}
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
if item_level.is_some() {
- self.reach(item.id, item_level).generics().predicates();
+ self.reach(item.hir_id, item_level).generics().predicates();
for trait_item_ref in trait_item_refs {
- let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
+ let mut reach = self.reach(trait_item_ref.id.hir_id, item_level);
reach.generics().predicates();
if trait_item_ref.kind == AssociatedItemKind::Type &&
}
hir::ItemKind::TraitAlias(..) => {
if item_level.is_some() {
- self.reach(item.id, item_level).generics().predicates();
+ self.reach(item.hir_id, item_level).generics().predicates();
}
}
// Visit everything except for private impl items.
hir::ItemKind::Impl(.., ref impl_item_refs) => {
if item_level.is_some() {
- self.reach(item.id, item_level).generics().predicates().ty().trait_ref();
+ self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
for impl_item_ref in impl_item_refs {
- let impl_item_level = self.get(impl_item_ref.id.node_id);
+ let impl_item_level = self.get(impl_item_ref.id.hir_id);
if impl_item_level.is_some() {
- self.reach(impl_item_ref.id.node_id, impl_item_level)
+ self.reach(impl_item_ref.id.hir_id, impl_item_level)
.generics().predicates().ty();
}
}
// Visit everything, but enum variants have their own levels.
hir::ItemKind::Enum(ref def, _) => {
if item_level.is_some() {
- self.reach(item.id, item_level).generics().predicates();
+ self.reach(item.hir_id, item_level).generics().predicates();
}
for variant in &def.variants {
- let variant_level = self.get(variant.node.data.id());
+ let variant_level = self.get(variant.node.data.hir_id());
if variant_level.is_some() {
for field in variant.node.data.fields() {
- self.reach(field.id, variant_level).ty();
+ self.reach(field.hir_id, variant_level).ty();
}
// Corner case: if the variant is reachable, but its
// enum is not, make the enum reachable as well.
- self.update(item.id, variant_level);
+ self.update(item.hir_id, variant_level);
}
}
}
// Visit everything, but foreign items have their own levels.
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
- let foreign_item_level = self.get(foreign_item.id);
+ let foreign_item_level = self.get(foreign_item.hir_id);
if foreign_item_level.is_some() {
- self.reach(foreign_item.id, foreign_item_level)
+ self.reach(foreign_item.hir_id, foreign_item_level)
.generics().predicates().ty();
}
}
hir::ItemKind::Struct(ref struct_def, _) |
hir::ItemKind::Union(ref struct_def, _) => {
if item_level.is_some() {
- self.reach(item.id, item_level).generics().predicates();
+ self.reach(item.hir_id, item_level).generics().predicates();
for field in struct_def.fields() {
- let field_level = self.get(field.id);
+ let field_level = self.get(field.hir_id);
if field_level.is_some() {
- self.reach(field.id, field_level).ty();
+ self.reach(field.hir_id, field_level).ty();
}
}
}
for export in exports.iter() {
if export.vis == ty::Visibility::Public {
if let Some(def_id) = export.def.opt_def_id() {
- if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) {
- self.update(node_id, Some(AccessLevel::Exported));
+ if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
+ self.update(hir_id, Some(AccessLevel::Exported));
}
}
}
}
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
- let node_id = self.tcx.hir().hir_to_node_id(md.hir_id);
-
if md.legacy {
- self.update(node_id, Some(AccessLevel::Public));
+ self.update(md.hir_id, Some(AccessLevel::Public));
return
}
self.tcx,
self.tcx.hir().local_def_id_from_hir_id(md.hir_id)
).unwrap();
- let mut module_id = self.tcx.hir().as_local_node_id(module_did).unwrap();
+ let mut module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap();
let level = if md.vis.node.is_pub() { self.get(module_id) } else { None };
- let level = self.update(node_id, level);
+ let level = self.update(md.hir_id, level);
if level.is_none() {
return
}
loop {
- let module = if module_id == ast::CRATE_NODE_ID {
+ let module = if module_id == hir::CRATE_HIR_ID {
&self.tcx.hir().krate().module
} else if let hir::ItemKind::Mod(ref module) =
- self.tcx.hir().expect_item(module_id).node {
+ self.tcx.hir().expect_item_by_hir_id(module_id).node {
module
} else {
unreachable!()
};
for id in &module.item_ids {
- self.update(id.id, level);
+ let hir_id = self.tcx.hir().node_to_hir_id(id.id);
+ self.update(hir_id, level);
}
- let def_id = self.tcx.hir().local_def_id(module_id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(module_id);
if let Some(exports) = self.tcx.module_exports(def_id) {
for export in exports.iter() {
- if let Some(node_id) = self.tcx.hir().as_local_node_id(export.def.def_id()) {
- self.update(node_id, level);
+ if let Some(hir_id) = self.tcx.hir().as_local_hir_id(export.def.def_id()) {
+ self.update(hir_id, level);
}
}
}
- if module_id == ast::CRATE_NODE_ID {
+ if module_id == hir::CRATE_HIR_ID {
break
}
- module_id = self.tcx.hir().get_parent_node(module_id);
+ module_id = self.tcx.hir().get_parent_node_by_hir_id(module_id);
}
}
}
fn generics(&mut self) -> &mut Self {
for param in &self.ev.tcx.generics_of(self.item_def_id).params {
match param.kind {
+ GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { has_default, .. } => {
if has_default {
self.visit(self.ev.tcx.type_of(param.def_id));
}
}
- GenericParamDefKind::Lifetime => {}
+ GenericParamDefKind::Const => {
+ self.visit(self.ev.tcx.type_of(param.def_id));
+ }
}
}
self
impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.ev.tcx }
fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
- if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) {
- self.ev.update(node_id, self.access_level);
+ if let Some(hir_id) = self.ev.tcx.hir().as_local_hir_id(def_id) {
+ self.ev.update(hir_id, self.access_level);
}
false
}
struct NamePrivacyVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
- current_item: ast::NodeId,
+ current_item: hir::HirId,
empty_tables: &'a ty::TypeckTables<'tcx>,
}
def: &'tcx ty::AdtDef, // definition of the struct or enum
field: &'tcx ty::FieldDef) { // definition of the field
let ident = Ident::new(keywords::Invalid.name(), use_ctxt);
- let current_hir = self.tcx.hir().node_to_hir_id(self.current_item);
+ let current_hir = self.current_item;
let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1;
if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let orig_current_item = mem::replace(&mut self.current_item, item.id);
+ let orig_current_item = mem::replace(&mut self.current_item, item.hir_id);
let orig_tables =
mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
intravisit::walk_item(self, item);
// Check types in item interfaces.
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let orig_current_item =
- mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id));
+ let orig_current_item = mem::replace(&mut self.current_item,
+ self.tcx.hir().local_def_id_from_hir_id(item.hir_id));
let orig_in_body = mem::replace(&mut self.in_body, false);
let orig_tables =
mem::replace(&mut self.tables, item_tables(self.tcx, item.hir_id, self.empty_tables));
}
}
- fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
+ fn trait_is_public(&self, trait_id: hir::HirId) -> bool {
// FIXME: this would preferably be using `exported_items`, but all
// traits are exported currently (see `EmbargoVisitor.exported_trait`).
- self.access_levels.is_public(trait_id)
+ let node_id = self.tcx.hir().hir_to_node_id(trait_id);
+ self.access_levels.is_public(node_id)
}
fn check_generic_bound(&mut self, bound: &hir::GenericBound) {
}
}
- fn item_is_public(&self, id: &ast::NodeId, vis: &hir::Visibility) -> bool {
- self.access_levels.is_reachable(*id) || vis.node.is_pub()
+ fn item_is_public(&self, id: &hir::HirId, vis: &hir::Visibility) -> bool {
+ let node_id = self.tcx.hir().hir_to_node_id(*id);
+ self.access_levels.is_reachable(node_id) || vis.node.is_pub()
}
}
hir::ItemKind::ForeignMod(_) => {}
hir::ItemKind::Trait(.., ref bounds, _) => {
- if !self.trait_is_public(item.id) {
+ if !self.trait_is_public(item.hir_id) {
return
}
|tr| {
let did = tr.path.def.def_id();
- if let Some(node_id) = self.tcx.hir().as_local_node_id(did) {
- self.trait_is_public(node_id)
+ if let Some(hir_id) = self.tcx.hir().as_local_hir_id(did) {
+ self.trait_is_public(hir_id)
} else {
true // external traits must be public
}
match impl_item.node {
hir::ImplItemKind::Const(..) |
hir::ImplItemKind::Method(..) => {
- let node_id = self.tcx.hir().hir_to_node_id(
- impl_item.hir_id);
- self.access_levels.is_reachable(node_id)
+ self.access_levels.is_reachable(
+ self.tcx.hir().hir_to_node_id(
+ impl_item_ref.id.hir_id))
}
hir::ImplItemKind::Existential(..) |
hir::ImplItemKind::Type(_) => false,
// don't erroneously report errors for private
// types in private items.
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
- let node_id = self.tcx.hir().hir_to_node_id(impl_item.hir_id);
match impl_item.node {
hir::ImplItemKind::Const(..) |
hir::ImplItemKind::Method(..)
- if self.item_is_public(&node_id, &impl_item.vis) =>
+ if self.item_is_public(&impl_item.hir_id, &impl_item.vis) =>
{
intravisit::walk_impl_item(self, impl_item)
}
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
for impl_item_ref in impl_item_refs {
- if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
+ if self.item_is_public(&impl_item_ref.id.hir_id, &impl_item_ref.vis) {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item_ref.kind {
AssociatedItemKind::Const => {
hir::ItemKind::Ty(..) => return,
// Not at all public, so we don't care.
- _ if !self.item_is_public(&item.id, &item.vis) => {
+ _ if !self.item_is_public(&item.hir_id, &item.vis) => {
return;
}
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
- if self.access_levels.is_reachable(item.id) {
+ let node_id = self.tcx.hir().hir_to_node_id(item.hir_id);
+ if self.access_levels.is_reachable(node_id) {
intravisit::walk_foreign_item(self, item)
}
}
v: &'tcx hir::Variant,
g: &'tcx hir::Generics,
item_id: hir::HirId) {
- if self.access_levels.is_reachable(v.node.data.id()) {
+ let node_id = self.tcx.hir().hir_to_node_id(v.node.data.hir_id());
+ if self.access_levels.is_reachable(node_id) {
self.in_variant = true;
intravisit::walk_variant(self, v, g, item_id);
self.in_variant = false;
fn generics(&mut self) -> &mut Self {
for param in &self.tcx.generics_of(self.item_def_id).params {
match param.kind {
+ GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { has_default, .. } => {
if has_default {
self.visit(self.tcx.type_of(param.def_id));
}
}
- GenericParamDefKind::Lifetime => {}
+ GenericParamDefKind::Const => {
+ self.visit(self.tcx.type_of(param.def_id));
+ }
}
}
self
fn visit_item(&mut self, item: &'tcx hir::Item) {
let tcx = self.tcx;
- let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx);
+ let item_visibility = ty::Visibility::from_hir(&item.vis, item.hir_id, tcx);
match item.node {
// Crates are always public.
self.check(item.hir_id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs {
- let hir_id = tcx.hir().node_to_hir_id(trait_item_ref.id.node_id);
- self.check_trait_or_impl_item(hir_id, trait_item_ref.kind,
+ self.check_trait_or_impl_item(trait_item_ref.id.hir_id, trait_item_ref.kind,
trait_item_ref.defaultness, item_visibility);
}
}
// Subitems of foreign modules have their own publicity.
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
- let vis = ty::Visibility::from_hir(&foreign_item.vis, item.id, tcx);
+ let vis = ty::Visibility::from_hir(&foreign_item.vis, item.hir_id, tcx);
self.check(foreign_item.hir_id, vis).generics().predicates().ty();
}
}
self.check(item.hir_id, item_visibility).generics().predicates();
for field in struct_def.fields() {
- let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx);
+ let field_visibility = ty::Visibility::from_hir(&field.vis, item.hir_id, tcx);
self.check(field.hir_id, min(item_visibility, field_visibility, tcx)).ty();
}
}
// A trait impl is public when both its type and its trait are public
// Subitems of trait impls have inherited publicity.
hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => {
- let impl_vis = ty::Visibility::of_impl(item.id, tcx, &Default::default());
+ let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default());
self.check(item.hir_id, impl_vis).generics().predicates();
for impl_item_ref in impl_item_refs {
let impl_item = tcx.hir().impl_item(impl_item_ref.id);
let impl_item_vis = if trait_ref.is_none() {
- min(ty::Visibility::from_hir(&impl_item.vis, item.id, tcx), impl_vis, tcx)
+ min(ty::Visibility::from_hir(&impl_item.vis, item.hir_id, tcx),
+ impl_vis,
+ tcx)
} else {
impl_vis
};
- let hir_id = tcx.hir().node_to_hir_id(impl_item_ref.id.node_id);
- self.check_trait_or_impl_item(hir_id, impl_item_ref.kind,
+ self.check_trait_or_impl_item(impl_item_ref.id.hir_id, impl_item_ref.kind,
impl_item_ref.defaultness, impl_item_vis);
}
}
let mut visitor = NamePrivacyVisitor {
tcx,
tables: &empty_tables,
- current_item: DUMMY_NODE_ID,
+ current_item: hir::DUMMY_HIR_ID,
empty_tables: &empty_tables,
};
let (module, span, node_id) = tcx.hir().get_module(module_def_id);
break
}
}
- visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public));
+ visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
{
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
--- /dev/null
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+ let base = super::freebsd_base::opts();
+ Ok(Target {
+ llvm_target: "armv6-unknown-freebsd-gnueabihf".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "32".to_string(),
+ target_c_int_width: "32".to_string(),
+ data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+ arch: "arm".to_string(),
+ target_os: "freebsd".to_string(),
+ target_env: "gnueabihf".to_string(),
+ target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
+
+ options: TargetOptions {
+ features: "+v6,+vfp2".to_string(),
+ max_atomic_width: Some(64),
+ abi_blacklist: super::arm_base::abi_blacklist(),
+ .. base
+ }
+ })
+}
--- /dev/null
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+ let base = super::freebsd_base::opts();
+ Ok(Target {
+ llvm_target: "armv7-unknown-freebsd-gnueabihf".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "32".to_string(),
+ target_c_int_width: "32".to_string(),
+ data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+ arch: "arm".to_string(),
+ target_os: "freebsd".to_string(),
+ target_env: "gnueabihf".to_string(),
+ target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
+
+ options: TargetOptions {
+ features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
+ max_atomic_width: Some(64),
+ abi_blacklist: super::arm_base::abi_blacklist(),
+ .. base
+ }
+ })
+}
("aarch64-linux-android", aarch64_linux_android),
("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
+ ("armv6-unknown-freebsd", armv6_unknown_freebsd),
+ ("armv7-unknown-freebsd", armv7_unknown_freebsd),
("i686-unknown-freebsd", i686_unknown_freebsd),
("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd),
("x86_64-unknown-freebsd", x86_64_unknown_freebsd),
InEnvironment,
ChalkCanonicalGoal,
};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, TyCtxt, InferConst};
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc::ty::query::Providers;
use rustc::ty::subst::{Kind, UnpackedKind};
use rustc_data_structures::sync::Lrc;
+use rustc::mir::interpret::ConstValue;
use syntax_pos::DUMMY_SP;
use std::fmt::{self, Debug};
}
_ => false,
},
+ UnpackedKind::Const(ct) => match ct {
+ ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)),
+ ..
+ }) => {
+ debug_assert_eq!(*debruijn, ty::INNERMOST);
+ cvar == *bound_ct
+ }
+ _ => false,
+ }
})
}
//! instance of `AstConv`.
use errors::{Applicability, DiagnosticId};
-use crate::hir::{self, GenericArg, GenericArgs};
+use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
use crate::hir::def::Def;
use crate::hir::def_id::DefId;
use crate::hir::HirVec;
use rustc::ty::{GenericParamDef, GenericParamDefKind};
use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
use rustc::ty::wf::object_region_bounds;
+use rustc::mir::interpret::ConstValue;
use rustc_data_structures::sync::Lrc;
use rustc_target::spec::abi;
use crate::require_c_abi_if_c_variadic;
let param_counts = def.own_counts();
let arg_counts = args.own_counts();
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+ let infer_consts = position != GenericArgPosition::Type && arg_counts.consts == 0;
let mut defaults: ty::GenericParamCount = Default::default();
for param in &def.params {
GenericParamDefKind::Type { has_default, .. } => {
defaults.types += has_default as usize
}
+ GenericParamDefKind::Const => {
+ // FIXME(const_generics:defaults)
+ }
};
}
}
}
- let check_kind_count = |kind,
- required,
- permitted,
- provided,
- offset| {
+ let check_kind_count = |kind, required, permitted, provided, offset| {
+ debug!(
+ "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
+ kind,
+ required,
+ permitted,
+ provided,
+ offset
+ );
// We enforce the following: `required` <= `provided` <= `permitted`.
// For kinds without defaults (i.e., lifetimes), `required == permitted`.
// For other kinds (i.e., types), `permitted` may be greater than `required`.
0,
);
}
+ // FIXME(const_generics:defaults)
+ if !infer_consts || arg_counts.consts > param_counts.consts {
+ check_kind_count(
+ "const",
+ param_counts.consts,
+ param_counts.consts,
+ arg_counts.consts,
+ arg_counts.lifetimes + arg_counts.types,
+ );
+ }
+ // Note that type errors are currently be emitted *after* const errors.
if !infer_types
|| arg_counts.types > param_counts.types - defaults.types - has_self as usize {
check_kind_count(
(Some(&arg), Some(¶m)) => {
match (arg, ¶m.kind) {
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
- | (GenericArg::Type(_), GenericParamDefKind::Type { .. }) => {
+ | (GenericArg::Type(_), GenericParamDefKind::Type { .. })
+ | (GenericArg::Const(_), GenericParamDefKind::Const) => {
substs.push(provided_kind(param, arg));
args.next();
params.next();
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.ast_ty_to_ty(&ty).into()
}
+ (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+ self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into()
+ }
_ => unreachable!(),
}
},
tcx.types.err.into()
}
}
+ GenericParamDefKind::Const => {
+ // FIXME(const_generics:defaults)
+ // We've already errored above about the mismatch.
+ tcx.types.err.into()
+ }
}
},
);
// Case 3. Reference to a top-level value.
Def::Fn(def_id) |
Def::Const(def_id) |
+ Def::ConstParam(def_id) |
Def::Static(def_id, _) => {
path_segs.push(PathSeg(def_id, last));
}
self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, def, segment, false).0
}
hir::TyKind::Array(ref ty, ref length) => {
- let length_def_id = tcx.hir().local_def_id_from_hir_id(length.hir_id);
- let substs = InternalSubsts::identity_for_item(tcx, length_def_id);
- let length = ty::LazyConst::Unevaluated(length_def_id, substs);
- let length = tcx.mk_lazy_const(length);
+ let length = self.ast_const_to_const(length, tcx.types.usize);
let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(&ty), length));
self.normalize_ty(ast_ty.span, array_ty)
}
result_ty
}
+ pub fn ast_const_to_const(
+ &self,
+ ast_const: &hir::AnonConst,
+ ty: Ty<'tcx>
+ ) -> &'tcx ty::LazyConst<'tcx> {
+ debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);
+
+ let tcx = self.tcx();
+ let def_id = tcx.hir().local_def_id_from_hir_id(ast_const.hir_id);
+
+ let mut lazy_const = ty::LazyConst::Unevaluated(
+ def_id,
+ InternalSubsts::identity_for_item(tcx, def_id),
+ );
+
+ let expr = &tcx.hir().body(ast_const.body).value;
+ if let ExprKind::Path(ref qpath) = expr.node {
+ if let hir::QPath::Resolved(_, ref path) = qpath {
+ if let Def::ConstParam(def_id) = path.def {
+ let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+ let item_id = tcx.hir().get_parent_node(node_id);
+ let item_def_id = tcx.hir().local_def_id(item_id);
+ let generics = tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
+ let name = tcx.hir().name(node_id).as_interned_str();
+ lazy_const = ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(ty::ParamConst::new(index, name)),
+ ty,
+ })
+ }
+ }
+ };
+
+ tcx.mk_lazy_const(lazy_const)
+ }
+
pub fn impl_trait_ty_to_ty(
&self,
def_id: DefId,
let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
- span_bug!(expr.span, "closure has region param")
+ span_bug!(expr.span, "closure has lifetime param")
}
- GenericParamDefKind::Type {..} => {
- self.infcx
- .next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)).into()
+ GenericParamDefKind::Type { .. } => {
+ self.infcx.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)).into()
+ }
+ GenericParamDefKind::Const => {
+ span_bug!(expr.span, "closure has const param")
}
}
});
use rustc::ty::error::{ExpectedFound, TypeError};
use rustc::ty::subst::{Subst, InternalSubsts, SubstsRef};
use rustc::util::common::ErrorReported;
-use errors::Applicability;
+use errors::{Applicability, DiagnosticId};
use syntax_pos::Span;
Ok(())
}
-fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- impl_m: &ty::AssociatedItem,
- impl_m_span: Span,
- trait_m: &ty::AssociatedItem,
- trait_item_span: Option<Span>)
- -> Result<(), ErrorReported> {
- let impl_m_generics = tcx.generics_of(impl_m.def_id);
- let trait_m_generics = tcx.generics_of(trait_m.def_id);
- let num_impl_m_type_params = impl_m_generics.own_counts().types;
- let num_trait_m_type_params = trait_m_generics.own_counts().types;
-
- if num_impl_m_type_params != num_trait_m_type_params {
- let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap();
- let impl_m_item = tcx.hir().expect_impl_item(impl_m_node_id);
- let span = if impl_m_item.generics.params.is_empty()
- || impl_m_item.generics.span.is_dummy() // impl Trait in argument position (#55374)
- {
- impl_m_span
- } else {
- impl_m_item.generics.span
- };
+fn compare_number_of_generics<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ impl_: &ty::AssociatedItem,
+ impl_span: Span,
+ trait_: &ty::AssociatedItem,
+ trait_span: Option<Span>,
+) -> Result<(), ErrorReported> {
+ let trait_own_counts = tcx.generics_of(trait_.def_id).own_counts();
+ let impl_own_counts = tcx.generics_of(impl_.def_id).own_counts();
+
+ let matchings = [
+ ("type", trait_own_counts.types, impl_own_counts.types),
+ ("const", trait_own_counts.consts, impl_own_counts.consts),
+ ];
+
+ let mut err_occurred = false;
+ for &(kind, trait_count, impl_count) in &matchings {
+ if impl_count != trait_count {
+ err_occurred = true;
+
+ let impl_node_id = tcx.hir().as_local_node_id(impl_.def_id).unwrap();
+ let impl_item = tcx.hir().expect_impl_item(impl_node_id);
+ let span = if impl_item.generics.params.is_empty()
+ || impl_item.generics.span.is_dummy() { // argument position impl Trait (#55374)
+ impl_span
+ } else {
+ impl_item.generics.span
+ };
- let mut err = struct_span_err!(tcx.sess, span, E0049,
- "method `{}` has {} but its trait declaration has {}",
- trait_m.ident,
- potentially_plural_count(num_impl_m_type_params, "type parameter"),
- potentially_plural_count(num_trait_m_type_params, "type parameter")
- );
+ let mut err = tcx.sess.struct_span_err_with_code(
+ span,
+ &format!(
+ "method `{}` has {} {kind} parameter{} but its trait \
+ declaration has {} {kind} parameter{}",
+ trait_.ident,
+ impl_count,
+ if impl_count != 1 { "s" } else { "" },
+ trait_count,
+ if trait_count != 1 { "s" } else { "" },
+ kind = kind,
+ ),
+ DiagnosticId::Error("E0049".into()),
+ );
- let mut suffix = None;
+ let mut suffix = None;
- if let Some(span) = trait_item_span {
- err.span_label(span, format!("expected {}",
- potentially_plural_count(num_trait_m_type_params, "type parameter")));
- } else {
- suffix = Some(format!(", expected {}", num_trait_m_type_params));
- }
-
- err.span_label(span,
- format!("found {}{}",
- potentially_plural_count(num_impl_m_type_params, "type parameter"),
- suffix.as_ref().map(|s| &s[..]).unwrap_or("")));
+ if let Some(span) = trait_span {
+ err.span_label(
+ span,
+ format!("expected {} {} parameter{}", trait_count, kind,
+ if trait_count != 1 { "s" } else { "" })
+ );
+ } else {
+ suffix = Some(format!(", expected {}", trait_count));
+ }
- err.emit();
+ err.span_label(
+ span,
+ format!("found {} {} parameter{}{}", impl_count, kind,
+ if impl_count != 1 { "s" } else { "" },
+ suffix.unwrap_or_else(|| String::new())),
+ );
- return Err(ErrorReported);
+ err.emit();
+ }
}
- Ok(())
+ if err_occurred {
+ Err(ErrorReported)
+ } else {
+ Ok(())
+ }
}
fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let trait_m_generics = tcx.generics_of(trait_m.def_id);
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind {
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
- GenericParamDefKind::Lifetime => None,
+ GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
});
let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| {
match param.kind {
GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)),
- GenericParamDefKind::Lifetime => None,
+ GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None,
}
});
for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic))
.source_map()
.span_to_snippet(trait_span)
.ok()?;
- let trait_m = tcx.hir().as_local_node_id(trait_m.def_id)?;
- let trait_m = tcx.hir().trait_item(hir::TraitItemId { node_id: trait_m });
+ let trait_m = tcx.hir().as_local_hir_id(trait_m.def_id)?;
+ let trait_m = tcx.hir().trait_item(hir::TraitItemId { hir_id: trait_m });
- let impl_m = tcx.hir().as_local_node_id(impl_m.def_id)?;
- let impl_m = tcx.hir().impl_item(hir::ImplItemId { node_id: impl_m });
+ let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id)?;
+ let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
// in case there are no generics, take the spot between the function name
// and the opening paren of the argument list
(None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
(|| {
- let impl_m = tcx.hir().as_local_node_id(impl_m.def_id)?;
- let impl_m = tcx.hir().impl_item(hir::ImplItemId { node_id: impl_m });
+ let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id)?;
+ let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
let input_tys = match impl_m.node {
hir::ImplItemKind::Method(ref sig, _) => &sig.decl.inputs,
_ => unreachable!(),
// Maybe remove `&`?
hir::ExprKind::AddrOf(_, ref expr) => {
if !cm.span_to_filename(expr.span).is_real() {
+ if let Ok(code) = cm.span_to_snippet(sp) {
+ if code.chars().next() == Some('&') {
+ return Some((
+ sp,
+ "consider removing the borrow",
+ code[1..].to_string()),
+ );
+ }
+ }
return None;
}
if let Ok(code) = cm.span_to_snippet(expr.span) {
match kind.unpack() {
UnpackedKind::Lifetime(r) => rcx.sub_regions(origin(), parent_scope, r),
UnpackedKind::Type(ty) => rcx.type_must_outlive(origin(), ty, parent_scope),
+ UnpackedKind::Const(_) => {
+ // Generic consts don't add constraints.
+ }
}
}
Ok(())
inputs: Vec<Ty<'tcx>>,
output: Ty<'tcx>,
) {
- let def_id = tcx.hir().local_def_id(it.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
match it.node {
hir::ForeignItemKind::Fn(..) => {}
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.to_ty(ty).into()
}
+ (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+ self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into()
+ }
_ => unreachable!(),
}
},
// Construct a trait-reference `self_ty : Trait<input_tys>`
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
match param.kind {
- GenericParamDefKind::Lifetime => {}
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Lifetime | GenericParamDefKind::Const => {}
+ GenericParamDefKind::Type { .. } => {
if param.index == 0 {
return self_ty.into();
} else if let Some(ref input_types) = opt_input_types {
// `impl_self_ty()` for an explanation.
self.tcx.types.re_erased.into()
}
- GenericParamDefKind::Type {..} => self.var_for_def(self.span, param),
+ GenericParamDefKind::Type { .. }
+ | GenericParamDefKind::Const => {
+ self.var_for_def(self.span, param)
+ }
}
}
});
InternalSubsts::for_item(self.tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => self.tcx.types.re_erased.into(),
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } => {
self.next_ty_var(TypeVariableOrigin::SubstitutionPlaceholder(
self.tcx.def_span(def_id))).into()
}
+ GenericParamDefKind::Const { .. } => {
+ unimplemented!() // FIXME(const_generics)
+ }
}
})
}
impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'v hir::Item) {
if let hir::ItemKind::Trait(..) = i.node {
- let def_id = self.map.local_def_id(i.id);
+ let def_id = self.map.local_def_id_from_hir_id(i.hir_id);
self.traits.push(def_id);
}
}
if let PatKind::Binding(_, _, _, ident, _) = p.node {
let var_ty = self.assign(p.span, p.hir_id, None);
+ let node_id = self.fcx.tcx.hir().hir_to_node_id(p.hir_id);
if !self.fcx.tcx.features().unsized_locals {
self.fcx.require_type_is_sized(var_ty, p.span,
- traits::VariableType(p.id));
+ traits::VariableType(node_id));
}
debug!("Pattern binding {} is assigned to {} with type {:?}",
}
fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- id: ast::NodeId,
+ id: hir::HirId,
span: Span) {
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
}
fn check_union<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- id: ast::NodeId,
+ id: hir::HirId,
span: Span) {
- let def_id = tcx.hir().local_def_id(id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
check_representable(tcx, span, def_id);
pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item) {
debug!(
- "check_item_type(it.id={}, it.name={})",
- it.id,
- tcx.item_path_str(tcx.hir().local_def_id(it.id))
+ "check_item_type(it.hir_id={}, it.name={})",
+ it.hir_id,
+ tcx.item_path_str(tcx.hir().local_def_id_from_hir_id(it.hir_id))
);
let _indenter = indenter();
match it.node {
// Consts can play a role in type-checking, so they are included here.
hir::ItemKind::Static(..) => {
- let def_id = tcx.hir().local_def_id(it.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
tcx.typeck_tables_of(def_id);
maybe_check_static_with_link_section(tcx, def_id, it.span);
}
hir::ItemKind::Const(..) => {
- tcx.typeck_tables_of(tcx.hir().local_def_id(it.id));
+ tcx.typeck_tables_of(tcx.hir().local_def_id_from_hir_id(it.hir_id));
}
hir::ItemKind::Enum(ref enum_definition, _) => {
- check_enum(tcx, it.span, &enum_definition.variants, it.id);
+ check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
}
hir::ItemKind::Fn(..) => {} // entirely within check_item_body
hir::ItemKind::Impl(.., ref impl_item_refs) => {
- debug!("ItemKind::Impl {} with id {}", it.ident, it.id);
- let impl_def_id = tcx.hir().local_def_id(it.id);
+ debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
+ let impl_def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
check_impl_items_against_trait(
tcx,
}
}
hir::ItemKind::Trait(..) => {
- let def_id = tcx.hir().local_def_id(it.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
check_on_unimplemented(tcx, def_id, it);
}
hir::ItemKind::Struct(..) => {
- check_struct(tcx, it.id, it.span);
+ check_struct(tcx, it.hir_id, it.span);
}
hir::ItemKind::Union(..) => {
- check_union(tcx, it.id, it.span);
+ check_union(tcx, it.hir_id, it.span);
}
hir::ItemKind::Existential(..) => {
- let def_id = tcx.hir().local_def_id(it.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
let substs = InternalSubsts::identity_for_item(tcx, def_id);
check_opaque(tcx, def_id, substs, it.span);
}
hir::ItemKind::Ty(..) => {
- let def_id = tcx.hir().local_def_id(it.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(it.hir_id);
let pty_ty = tcx.type_of(def_id);
let generics = tcx.generics_of(def_id);
check_bounds_are_used(tcx, &generics, pty_ty);
}
} else {
for item in &m.items {
- let generics = tcx.generics_of(tcx.hir().local_def_id(item.id));
+ let generics = tcx.generics_of(tcx.hir().local_def_id_from_hir_id(item.hir_id));
if generics.params.len() - generics.own_counts().lifetimes != 0 {
let mut err = struct_span_err!(
tcx.sess,
fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trait_def_id: DefId,
item: &hir::Item) {
- let item_def_id = tcx.hir().local_def_id(item.id);
+ let item_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
// an error would be reported if this fails.
let _ = traits::OnUnimplementedDirective::of_item(tcx, trait_def_id, item_def_id);
}
pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
sp: Span,
vs: &'tcx [hir::Variant],
- id: ast::NodeId) {
- let def_id = tcx.hir().local_def_id(id);
+ id: hir::HirId) {
+ let def_id = tcx.hir().local_def_id_from_hir_id(id);
let def = tcx.adt_def(def_id);
def.destructor(tcx); // force the destructor to be evaluated
ty
}
+ pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+ AstConv::ast_const_to_const(self, ast_c, ty)
+ }
+
// If the type given by the user has free regions, save it for later, since
// NLL would like to enforce those. Also pass in types that involve
// projections, since those can resolve to `'static` bounds (modulo #54940,
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.to_ty(ty).into()
}
+ (GenericParamDefKind::Const, GenericArg::Const(ct)) => {
+ self.to_const(&ct.value, self.tcx.type_of(param.def_id)).into()
+ }
_ => unreachable!(),
}
},
self.var_for_def(span, param)
}
}
+ GenericParamDefKind::Const => {
+ // FIXME(const_generics:defaults)
+ // No const parameters were provided, we have to infer them.
+ self.var_for_def(span, param)
+ }
}
},
);
generics: &ty::Generics,
ty: Ty<'tcx>) {
let own_counts = generics.own_counts();
- debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
+ debug!(
+ "check_bounds_are_used(n_tys={}, n_cts={}, ty={:?})",
+ own_counts.types,
+ own_counts.consts,
+ ty
+ );
+
+ // FIXME(const_generics): we probably want to check the bounds for const parameters too.
if own_counts.types == 0 {
return;
}
+
// Make a vector of booleans initially false, set to true when used.
let mut types_used = vec![false; own_counts.types];
use rustc::infer::outlives::env::OutlivesEnvironment;
use rustc::infer::{self, RegionObligation, SuppressRegionErrors};
use rustc::ty::adjustment;
-use rustc::ty::subst::SubstsRef;
+use rustc::ty::subst::{SubstsRef, UnpackedKind};
use rustc::ty::{self, Ty};
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
let origin = infer::ParameterInScope(origin, expr_span);
- for region in substs.regions() {
- self.sub_regions(origin.clone(), expr_region, region);
- }
-
- for ty in substs.types() {
- let ty = self.resolve_type(ty);
- self.type_must_outlive(origin.clone(), ty, expr_region);
+ for kind in substs {
+ match kind.unpack() {
+ UnpackedKind::Lifetime(lt) => {
+ self.sub_regions(origin.clone(), expr_region, lt);
+ }
+ UnpackedKind::Type(ty) => {
+ let ty = self.resolve_type(ty);
+ self.type_must_outlive(origin.clone(), ty, expr_region);
+ }
+ UnpackedKind::Const(_) => {
+ // Const parameters don't impose constraints.
+ }
+ }
}
}
}
}
}
- fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) {}
+ fn decl_without_init(&mut self, _id: hir::HirId, _span: Span) {}
fn mutate(
&mut self,
use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::mir::interpret::ConstValue;
use rustc::middle::lang_items;
use rustc::infer::opaque_types::may_define_existential_type;
{
for_item(tcx, item).with_fcx(|fcx, fcx_tcx| {
let variants = lookup_fields(fcx);
- let def_id = fcx.tcx.hir().local_def_id(item.id);
+ let def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let packed = fcx.tcx.adt_def(def_id).repr.packed();
for variant in &variants {
}
fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
- debug!("check_trait: {:?}", item.id);
+ debug!("check_trait: {:?}", item.hir_id);
- let trait_def_id = tcx.hir().local_def_id(item.id);
+ let trait_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
let trait_def = tcx.trait_def(trait_def_id);
if trait_def.is_marker {
fn check_item_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
for_item(tcx, item).with_fcx(|fcx, tcx| {
- let def_id = fcx.tcx.hir().local_def_id(item.id);
+ let def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let sig = fcx.tcx.fn_sig(def_id);
let sig = fcx.normalize_associated_types_in(item.span, &sig);
let mut implied_bounds = vec![];
debug!("check_impl: {:?}", item);
for_item(tcx, item).with_fcx(|fcx, tcx| {
- let item_def_id = fcx.tcx.hir().local_def_id(item.id);
+ let item_def_id = fcx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
// struct Foo<T = Vec<[u32]>> { .. }
// Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
for param in &generics.params {
- if let GenericParamDefKind::Type {..} = param.kind {
+ if let GenericParamDefKind::Type { .. } = param.kind {
if is_our_default(¶m) {
let ty = fcx.tcx.type_of(param.def_id);
// ignore dependent defaults -- that is, where the default of one type
// All regions are identity.
fcx.tcx.mk_param_from_def(param)
}
- GenericParamDefKind::Type {..} => {
+ GenericParamDefKind::Type { .. } => {
// If the param has a default,
if is_our_default(param) {
let default_ty = fcx.tcx.type_of(param.def_id);
// Mark unwanted params as err.
fcx.tcx.types.err.into()
}
+ GenericParamDefKind::Const => {
+ // FIXME(const_generics:defaults)
+ fcx.tcx.types.err.into()
+ }
}
});
// Now we build the substituted predicates.
fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {
true
}
+
+ fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
+ if let ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(param),
+ ..
+ }) = c {
+ self.params.insert(param.index);
+ }
+ c.super_visit_with(self)
+ }
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count);
for (subst, param) in substs.iter().zip(&generics.params) {
match subst.unpack() {
ty::subst::UnpackedKind::Type(ty) => match ty.sty {
- ty::Param(..) => {},
+ ty::Param(..) => {}
// prevent `fn foo() -> Foo<u32>` from being defining
_ => {
- tcx
- .sess
+ tcx.sess
.struct_span_err(
span,
"non-defining existential type use \
),
)
.emit();
- },
- }, // match ty
+ }
+ }
+
ty::subst::UnpackedKind::Lifetime(region) => {
let param_span = tcx.def_span(param.def_id);
if let ty::ReStatic = region {
} else {
seen.entry(region).or_default().push(param_span);
}
- },
+ }
+
+ ty::subst::UnpackedKind::Const(ct) => match ct {
+ ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(_),
+ ..
+ }) => {}
+ _ => {
+ tcx.sess
+ .struct_span_err(
+ span,
+ "non-defining existential type use \
+ in defining scope",
+ )
+ .span_note(
+ tcx.def_span(param.def_id),
+ &format!(
+ "used non-generic const {} for \
+ generic parameter",
+ ty,
+ ),
+ )
+ .emit();
+ }
+ }
} // match subst
} // for (subst, param)
for (_, spans) in seen {
item: &hir::Item,
hir_generics: &hir::Generics)
{
- let item_def_id = tcx.hir().local_def_id(item.id);
+ let item_def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
let ty = tcx.type_of(item_def_id);
if tcx.has_error_field(ty) {
return;
let parent = tcx.generics_of(generics.parent.unwrap());
let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind {
GenericParamDefKind::Lifetime => None,
- GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
+ GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+ Some((param.name, param.def_id))
+ }
}).collect();
for method_param in &generics.params {
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'tcx hir::Item) {
debug!("visit_item: {:?}", i);
- let def_id = self.tcx.hir().local_def_id(i.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(i.hir_id);
self.tcx.ensure().check_item_well_formed(def_id);
}
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn non_enum_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
let fields = struct_def.fields().iter().map(|field| {
- let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id(field.id));
+ let field_ty = self.tcx.type_of(self.tcx.hir().local_def_id_from_hir_id(field.hir_id));
let field_ty = self.normalize_associated_types_in(field.span,
&field_ty);
AdtField { ty: field_ty, span: field.span }
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
if let hir::ItemKind::ExternCrate(orig_name) = item.node {
- let extern_crate_def_id = self.tcx.hir().local_def_id(item.id);
+ let extern_crate_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
self.crates_to_lint.push(
ExternCrateToLint {
def_id: extern_crate_def_id,
_ => return
};
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let self_ty = self.tcx.type_of(def_id);
let lang_items = self.tcx.lang_items();
match self_ty.sty {
// Add the implementation to the mapping from implementation to base
// type def ID, if there is a base type for this implementation and
// the implementation does not have any associated traits.
- let impl_def_id = self.tcx.hir().local_def_id(item.id);
+ let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
let mut rc_vec = self.impls_map.inherent_impls
.entry(def_id)
.or_default();
hir::ItemKind::Struct(..) |
hir::ItemKind::Trait(..) |
hir::ItemKind::Union(..) => {
- let type_def_id = self.tcx.hir().local_def_id(item.id);
+ let type_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
self.check_for_overlapping_inherent_impls(type_def_id);
}
_ => {}
/// to prevent inundating the user with a bunch of similar error
/// reports.
fn visit_item(&mut self, item: &hir::Item) {
- let def_id = self.tcx.hir().local_def_id(item.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
// "Trait" impl
if let hir::ItemKind::Impl(.., Some(_), _, _) = item.node {
debug!("coherence2::orphan check: trait impl {}",
- self.tcx.hir().node_to_string(item.id));
+ self.tcx.hir().hir_to_string(item.hir_id));
let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
let trait_def_id = trait_ref.def_id;
let cm = self.tcx.sess.source_map();
unsafety: hir::Unsafety,
polarity: hir::ImplPolarity)
{
- if let Some(trait_ref) = self.tcx.impl_trait_ref(self.tcx.hir().local_def_id(item.id)) {
+ let local_did = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+ if let Some(trait_ref) = self.tcx.impl_trait_ref(local_did) {
let trait_def = self.tcx.trait_def(trait_ref.def_id);
let unsafe_attr = impl_generics.and_then(|generics| {
generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle")
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
- convert_item(self.tcx, item.id);
+ convert_item(self.tcx, item.hir_id);
intravisit::walk_item(self, item);
}
}
}
-fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
- let it = tcx.hir().expect_item(item_id);
- debug!("convert: item {} with id {}", it.ident, it.id);
- let def_id = tcx.hir().local_def_id(item_id);
+fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: hir::HirId) {
+ let it = tcx.hir().expect_item_by_hir_id(item_id);
+ debug!("convert: item {} with id {}", it.ident, it.hir_id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(item_id);
match it.node {
// These don't define types.
hir::ItemKind::ExternCrate(_)
| hir::ItemKind::GlobalAsm(_) => {}
hir::ItemKind::ForeignMod(ref foreign_mod) => {
for item in &foreign_mod.items {
- let def_id = tcx.hir().local_def_id(item.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(item.hir_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
tcx.predicates_of(def_id);
for f in struct_def.fields() {
- let def_id = tcx.hir().local_def_id(f.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(f.hir_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
}
if !struct_def.is_struct() {
- convert_variant_ctor(tcx, struct_def.id());
+ convert_variant_ctor(tcx, struct_def.hir_id());
}
}
}
}
-fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor_id: ast::NodeId) {
- let def_id = tcx.hir().local_def_id(ctor_id);
+fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctor_id: hir::HirId) {
+ let def_id = tcx.hir().local_def_id_from_hir_id(ctor_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
);
for f in variant.node.data.fields() {
- let def_id = tcx.hir().local_def_id(f.id);
+ let def_id = tcx.hir().local_def_id_from_hir_id(f.hir_id);
tcx.generics_of(def_id);
tcx.type_of(def_id);
tcx.predicates_of(def_id);
// Convert the ctor, if any. This also registers the variant as
// an item.
- convert_variant_ctor(tcx, variant.node.data.id());
+ convert_variant_ctor(tcx, variant.node.data.hir_id());
}
}
attribute_def_id: DefId
) -> ty::VariantDef {
let mut seen_fields: FxHashMap<ast::Ident, Span> = Default::default();
- let node_id = tcx.hir().as_local_node_id(did).unwrap();
+ let hir_id = tcx.hir().as_local_hir_id(did).unwrap();
let fields = def
.fields()
.iter()
.map(|f| {
- let fid = tcx.hir().local_def_id(f.id);
+ let fid = tcx.hir().local_def_id_from_hir_id(f.hir_id);
let dup_span = seen_fields.get(&f.ident.modern()).cloned();
if let Some(prev_span) = dup_span {
struct_span_err!(
ty::FieldDef {
did: fid,
ident: f.ident,
- vis: ty::Visibility::from_hir(&f.vis, node_id, tcx),
+ vis: ty::Visibility::from_hir(&f.vis, hir_id, tcx),
}
})
.collect();
def.variants
.iter()
.map(|v| {
- let did = tcx.hir().local_def_id(v.node.data.id());
+ let did = tcx.hir().local_def_id_from_hir_id(v.node.data.hir_id());
let discr = if let Some(ref e) = v.node.disr_expr {
distance_from_explicit = 0;
ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id))
ItemKind::Struct(ref def, _) => {
// Use separate constructor id for unit/tuple structs and reuse did for braced structs.
let ctor_id = if !def.is_struct() {
- Some(tcx.hir().local_def_id(def.id()))
+ Some(tcx.hir().local_def_id_from_hir_id(def.hir_id()))
} else {
None
};
//
// Something of a hack: use the node id for the trait, also as
// the node id for the Self type parameter.
- let param_id = item.id;
+ let param_id = item.hir_id;
opt_self = Some(ty::GenericParamDef {
index: 0,
name: keywords::SelfUpper.name().as_interned_str(),
- def_id: tcx.hir().local_def_id(param_id),
+ def_id: tcx.hir().local_def_id_from_hir_id(param_id),
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
ast_generics
.params
.iter()
- .filter_map(|param| match param.kind {
- GenericParamKind::Type {
- ref default,
- synthetic,
- ..
- } => {
- if param.name.ident().name == keywords::SelfUpper.name() {
- span_bug!(
- param.span,
- "`Self` should not be the name of a regular parameter"
- );
- }
-
- if !allow_defaults && default.is_some() {
- if !tcx.features().default_type_parameter_fallback {
- tcx.lint_hir(
- lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
- param.hir_id,
+ .filter_map(|param| {
+ let kind = match param.kind {
+ GenericParamKind::Type {
+ ref default,
+ synthetic,
+ ..
+ } => {
+ if param.name.ident().name == keywords::SelfUpper.name() {
+ span_bug!(
param.span,
- &format!(
- "defaults for type parameters are only allowed in \
- `struct`, `enum`, `type`, or `trait` definitions."
- ),
+ "`Self` should not be the name of a regular parameter"
);
}
- }
- let ty_param = ty::GenericParamDef {
- index: type_start + i as u32,
- name: param.name.ident().as_interned_str(),
- def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
- pure_wrt_drop: param.pure_wrt_drop,
- kind: ty::GenericParamDefKind::Type {
+ if !allow_defaults && default.is_some() {
+ if !tcx.features().default_type_parameter_fallback {
+ tcx.lint_hir(
+ lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+ param.hir_id,
+ param.span,
+ &format!(
+ "defaults for type parameters are only allowed in \
+ `struct`, `enum`, `type`, or `trait` definitions."
+ ),
+ );
+ }
+ }
+
+ ty::GenericParamDefKind::Type {
has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults
.as_ref()
.map_or(rl::Set1::Empty, |o| o[i]),
synthetic,
- },
- };
- i += 1;
- Some(ty_param)
- }
- GenericParamKind::Const { .. } => {
- if param.name.ident().name == keywords::SelfUpper.name() {
- span_bug!(
- param.span,
- "`Self` should not be the name of a regular parameter",
- );
+ }
}
+ GenericParamKind::Const { .. } => {
+ if param.name.ident().name == keywords::SelfUpper.name() {
+ span_bug!(
+ param.span,
+ "`Self` should not be the name of a regular parameter",
+ );
+ }
- // Emit an error, but skip the parameter rather than aborting to
- // continue to get other errors.
- tcx.sess.struct_span_err(
- param.span,
- "const generics in any position are currently unsupported",
- ).emit();
- None
- }
- _ => None,
- }),
+ ty::GenericParamDefKind::Const
+ }
+ _ => return None,
+ };
+
+ let param_def = ty::GenericParamDef {
+ index: type_start + i as u32,
+ name: param.name.ident().as_interned_str(),
+ def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
+ pure_wrt_drop: param.pure_wrt_drop,
+ kind,
+ };
+ i += 1;
+ Some(param_def)
+ })
);
// provide junk type parameter defs - the only place that
tcx.mk_closure(def_id, substs)
}
- Node::AnonConst(_) => match tcx.hir().get_by_hir_id(
- tcx.hir().get_parent_node_by_hir_id(hir_id))
- {
- Node::Ty(&hir::Ty {
- node: hir::TyKind::Array(_, ref constant),
- ..
- })
- | Node::Ty(&hir::Ty {
- node: hir::TyKind::Typeof(ref constant),
- ..
- })
- | Node::Expr(&hir::Expr {
- node: ExprKind::Repeat(_, ref constant),
- ..
- }) if constant.hir_id == hir_id =>
- {
- tcx.types.usize
- }
+ Node::AnonConst(_) => {
+ let parent_node = tcx.hir().get_by_hir_id(tcx.hir().get_parent_node_by_hir_id(hir_id));
+ match parent_node {
+ Node::Ty(&hir::Ty {
+ node: hir::TyKind::Array(_, ref constant),
+ ..
+ })
+ | Node::Ty(&hir::Ty {
+ node: hir::TyKind::Typeof(ref constant),
+ ..
+ })
+ | Node::Expr(&hir::Expr {
+ node: ExprKind::Repeat(_, ref constant),
+ ..
+ }) if constant.hir_id == hir_id =>
+ {
+ tcx.types.usize
+ }
- Node::Variant(&Spanned {
- node:
- VariantKind {
- disr_expr: Some(ref e),
- ..
- },
- ..
- }) if e.hir_id == hir_id =>
- {
- tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id))
- .repr
- .discr_type()
- .to_ty(tcx)
- }
+ Node::Variant(&Spanned {
+ node:
+ VariantKind {
+ disr_expr: Some(ref e),
+ ..
+ },
+ ..
+ }) if e.hir_id == hir_id =>
+ {
+ tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id))
+ .repr
+ .discr_type()
+ .to_ty(tcx)
+ }
- x => {
- bug!("unexpected const parent in type_of_def_id(): {:?}", x);
+ Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) |
+ Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) |
+ Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) => {
+ let path = match parent_node {
+ Node::Ty(&hir::Ty { node: hir::TyKind::Path(ref path), .. }) |
+ Node::Expr(&hir::Expr { node: ExprKind::Path(ref path), .. }) => {
+ path
+ }
+ Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => {
+ &*path
+ }
+ _ => unreachable!(),
+ };
+
+ match path {
+ QPath::Resolved(_, ref path) => {
+ let mut arg_index = 0;
+ let mut found_const = false;
+ for seg in &path.segments {
+ if let Some(generic_args) = &seg.args {
+ let args = &generic_args.args;
+ for arg in args {
+ if let GenericArg::Const(ct) = arg {
+ if ct.value.hir_id == hir_id {
+ found_const = true;
+ break;
+ }
+ arg_index += 1;
+ }
+ }
+ }
+ }
+ // Sanity check to make sure everything is as expected.
+ if !found_const {
+ bug!("no arg matching AnonConst in path")
+ }
+ match path.def {
+ // We've encountered an `AnonConst` in some path, so we need to
+ // figure out which generic parameter it corresponds to and return
+ // the relevant type.
+ Def::Struct(def_id)
+ | Def::Union(def_id)
+ | Def::Enum(def_id)
+ | Def::Fn(def_id) => {
+ let generics = tcx.generics_of(def_id);
+ let mut param_index = 0;
+ for param in &generics.params {
+ if let ty::GenericParamDefKind::Const = param.kind {
+ if param_index == arg_index {
+ return tcx.type_of(param.def_id);
+ }
+ param_index += 1;
+ }
+ }
+ // This is no generic parameter associated with the arg. This is
+ // probably from an extra arg where one is not needed.
+ return tcx.types.err;
+ }
+ Def::Err => tcx.types.err,
+ x => bug!("unexpected const parent path def {:?}", x),
+ }
+ }
+ x => bug!("unexpected const parent path {:?}", x),
+ }
+ }
+
+ x => {
+ bug!("unexpected const parent in type_of_def_id(): {:?}", x);
+ }
}
- },
+ }
Node::GenericParam(param) => match ¶m.kind {
hir::GenericParamKind::Type { default: Some(ref ty), .. } |
intravisit::NestedVisitorMap::All(&self.tcx.hir())
}
fn visit_item(&mut self, it: &'tcx Item) {
- let def_id = self.tcx.hir().local_def_id(it.id);
+ let def_id = self.tcx.hir().local_def_id_from_hir_id(it.hir_id);
// the existential type itself or its children are not within its reveal scope
if def_id != self.def_id {
self.check(def_id);
let ty = tcx.type_of(tcx.hir().get_parent_did(node_id));
let inputs = fields
.iter()
- .map(|f| tcx.type_of(tcx.hir().local_def_id(f.id)));
+ .map(|f| tcx.type_of(tcx.hir().local_def_id_from_hir_id(f.hir_id)));
ty::Binder::bind(tcx.mk_fn_sig(
inputs,
ty,
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::fold::{TypeFoldable, TypeVisitor};
use rustc::util::nodemap::FxHashSet;
+use rustc::mir::interpret::ConstValue;
use syntax::source_map::Span;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
fn from(param: ty::EarlyBoundRegion) -> Self { Parameter(param.index) }
}
+impl From<ty::ParamConst> for Parameter {
+ fn from(param: ty::ParamConst) -> Self { Parameter(param.index) }
+}
+
/// Returns the set of parameters constrained by the impl header.
pub fn parameters_for_impl<'tcx>(impl_self_ty: Ty<'tcx>,
impl_trait_ref: Option<ty::TraitRef<'tcx>>)
}
false
}
+
+ fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
+ if let ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(data),
+ ..
+ }) = c {
+ self.parameters.push(Parameter::from(*data));
+ }
+ false
+ }
}
pub fn identify_constrained_type_params<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>,
E0049: r##"
This error indicates that an attempted implementation of a trait method
-has the wrong number of type parameters.
+has the wrong number of type or const parameters.
For example, the trait below has a method `foo` with a type parameter `T`,
but the implementation of `foo` for the type `Bar` is missing this parameter:
```
"##,
+// FIXME(const_generics:docs): example of inferring const parameter.
E0087: r##"
#### Note: this error code is no longer emitted by the compiler.
"##,
E0091: r##"
-You gave an unnecessary type parameter in a type alias. Erroneous code
-example:
+You gave an unnecessary type or const parameter in a type alias. Erroneous
+code example:
```compile_fail,E0091
type Foo<T> = u32; // error: type parameter `T` is unused
type Foo<A,B> = Box<A>; // error: type parameter `B` is unused
```
-Please check you didn't write too many type parameters. Example:
+Please check you didn't write too many parameters. Example:
```
type Foo = u32; // ok!
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.node {
- let impl_def_id = self.tcx.hir().local_def_id(item.id);
+ let impl_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
enforce_impl_params_are_constrained(self.tcx,
impl_def_id,
impl_item_refs);
// Disallow unconstrained lifetimes, but only if they appear in assoc types.
let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter()
- .map(|item_ref| tcx.hir().local_def_id(item_ref.id.node_id))
+ .map(|item_ref| tcx.hir().local_def_id_from_hir_id(item_ref.id.hir_id))
.filter(|&def_id| {
let item = tcx.associated_item(def_id);
item.kind == ty::AssociatedKind::Type && item.defaultness.has_value()
for param in &impl_generics.params {
match param.kind {
// Disallow ANY unconstrained type parameters.
- ty::GenericParamDefKind::Type {..} => {
+ ty::GenericParamDefKind::Type { .. } => {
let param_ty = ty::ParamTy::for_def(param);
if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
report_unused_parameter(tcx,
¶m.name.to_string());
}
}
+ ty::GenericParamDefKind::Const => {
+ let param_ct = ty::ParamConst::for_def(param);
+ if !input_parameters.contains(&ctp::Parameter::from(param_ct)) {
+ report_unused_parameter(tcx,
+ tcx.def_span(param.def_id),
+ "const",
+ ¶m_ct.to_string());
+ }
+ }
}
}
impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
- let item_did = self.tcx.hir().local_def_id(item.id);
+ let item_did = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
debug!("InferVisitor::visit_item(item={:?})", item_did);
- let node_id = self
+ let hir_id = self
.tcx
.hir()
- .as_local_node_id(item_did)
+ .as_local_hir_id(item_did)
.expect("expected local def-id");
- let item = match self.tcx.hir().get(node_id) {
+ let item = match self.tcx.hir().get_by_hir_id(hir_id) {
Node::Item(item) => item,
_ => bug!(),
};
.map(|(&def_id, set)| {
let vec: Vec<ty::Predicate<'tcx>> = set
.iter()
- .map(
+ .filter_map(
|ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
- UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder::bind(
- ty::OutlivesPredicate(ty1, region2),
- )),
- UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives(
- ty::Binder::bind(ty::OutlivesPredicate(region1, region2)),
- ),
+ UnpackedKind::Type(ty1) => {
+ Some(ty::Predicate::TypeOutlives(ty::Binder::bind(
+ ty::OutlivesPredicate(ty1, region2)
+ )))
+ }
+ UnpackedKind::Lifetime(region1) => {
+ Some(ty::Predicate::RegionOutlives(
+ ty::Binder::bind(ty::OutlivesPredicate(region1, region2))
+ ))
+ }
+ UnpackedKind::Const(_) => {
+ // Generic consts don't impose any constraints.
+ None
+ }
},
).collect();
(def_id, Lrc::new(vec))
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let item_def_id = self.tcx.hir().local_def_id(item.id);
+ let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
// For unit testing: check for a special "rustc_outlives"
// attribute and report an error with various results if found.
}
required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
}
+
+ UnpackedKind::Const(_) => {
+ // Generic consts don't impose any constraints.
+ }
}
}
//! We walk the set of items and, for each member, generate new constraints.
use hir::def_id::DefId;
-use rustc::ty::subst::{UnpackedKind, SubstsRef};
+use rustc::mir::interpret::ConstValue;
+use rustc::ty::subst::{SubstsRef, UnpackedKind};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
// Trait are always invariant so we can take advantage of that.
let variance_i = self.invariant(variance);
- for ty in substs.types() {
- self.add_constraints_from_ty(current, ty, variance_i);
- }
- for region in substs.regions() {
- self.add_constraints_from_region(current, region, variance_i);
+ for k in substs {
+ match k.unpack() {
+ UnpackedKind::Lifetime(lt) => {
+ self.add_constraints_from_region(current, lt, variance_i)
+ }
+ UnpackedKind::Type(ty) => {
+ self.add_constraints_from_ty(current, ty, variance_i)
+ }
+ UnpackedKind::Const(ct) => {
+ self.add_constraints_from_const(current, ct, variance_i)
+ }
+ }
}
}
self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
}
- ty::Array(typ, _) |
+ ty::Array(typ, len) => {
+ self.add_constraints_from_ty(current, typ, variance);
+ self.add_constraints_from_const(current, len, variance);
+ }
+
ty::Slice(typ) => {
self.add_constraints_from_ty(current, typ, variance);
}
UnpackedKind::Type(ty) => {
self.add_constraints_from_ty(current, ty, variance_i)
}
+ UnpackedKind::Const(ct) => {
+ self.add_constraints_from_const(current, ct, variance_i)
+ }
}
}
}
}
}
+ fn add_constraints_from_const(
+ &mut self,
+ current: &CurrentItem,
+ ct: &ty::LazyConst<'tcx>,
+ variance: VarianceTermPtr<'a>
+ ) {
+ debug!(
+ "add_constraints_from_const(ct={:?}, variance={:?})",
+ ct,
+ variance
+ );
+
+ if let ty::LazyConst::Evaluated(ct) = ct {
+ self.add_constraints_from_ty(current, ct.ty, variance);
+ if let ConstValue::Param(ref data) = ct.val {
+ self.add_constraint(current, data.index, variance);
+ }
+ }
+ }
+
/// Adds constraints appropriate for a mutability-type pair
/// appearing in a context with ambient variance `variance`
fn add_constraints_from_mt(&mut self,
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
debug!("add_inferreds for item {}",
- self.tcx.hir().node_to_string(item.id));
+ self.tcx.hir().hir_to_string(item.hir_id));
match item.node {
hir::ItemKind::Struct(ref struct_def, _) |
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let item_def_id = self.tcx.hir().local_def_id(item.id);
+ let item_def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
// For unit testing: check for a special "rustc_variance"
// attribute and report an error with various results if found.
synthetic: None,
})
}
+ ty::GenericParamDefKind::Const { .. } => {
+ unimplemented!() // FIXME(const_generics)
+ }
};
GenericParamDef {
}
Some(param.clean(cx))
}
+ ty::GenericParamDefKind::Const { .. } => {
+ unimplemented!() // FIXME(const_generics)
+ }
}).collect::<Vec<GenericParamDef>>();
let mut where_predicates = preds.predicates.iter()
.flat_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
ty::GenericParamDefKind::Type { .. } => None,
+ ty::GenericParamDefKind::Const { .. } => {
+ unimplemented!() // FIXME(const_generics)
+ }
}).chain(simplify::ty_params(stripped_typarams).into_iter())
.collect(),
where_predicates: simplify::where_clauses(cx, where_predicates),
(self.generics.clean(cx), (&self.decl, self.body).clean(cx))
});
- let did = cx.tcx.hir().local_def_id(self.id);
+ let did = cx.tcx.hir().local_def_id_from_hir_id(self.id);
let constness = if cx.tcx.is_min_const_fn(did) {
hir::Constness::Const
} else {
name: Some(self.name.clean(cx)),
attrs: attrs,
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs,
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
impl Clean<Item> for hir::StructField {
fn clean(&self, cx: &DocContext<'_, '_, '_>) -> Item {
+ let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
+
Item {
name: Some(self.ident.name).clean(cx),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
visibility: self.vis.clean(cx),
- stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ stability: get_stability(cx, local_did),
+ deprecation: get_deprecation(cx, local_did),
+ def_id: local_did,
inner: StructFieldItem(self.ty.clean(cx)),
}
}
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
visibility: None,
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.def.id()),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.def.hir_id()),
inner: VariantItem(Variant {
kind: self.def.clean(cx),
}),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id.clone()),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id.clone()),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
}
};
+ let local_did = cx.tcx.hir().local_def_id_from_hir_id(self.hir_id);
+
Item {
name: Some(self.ident.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: local_did,
visibility: self.vis.clean(cx),
- stability: get_stability(cx, cx.tcx.hir().local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.tcx.hir().local_def_id(self.id)),
+ stability: get_stability(cx, local_did),
+ deprecation: get_deprecation(cx, local_did),
inner,
}
}
visibility: Some(Public),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.tcx.hir().local_def_id(self.id),
+ def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id),
inner: ProcMacroItem(ProcMacro {
kind: self.kind,
helpers: self.helpers.clean(cx),
ty::GenericParamDefKind::Type { .. } => {
args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
}
+ ty::GenericParamDefKind::Const { .. } => {
+ unimplemented!() // FIXME(const_generics)
+ }
}
}
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
- pub id: NodeId,
+ pub id: hir::HirId,
pub struct_type: StructType,
pub name: Name,
pub generics: hir::Generics,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
- pub id: NodeId,
+ pub id: hir::HirId,
pub struct_type: StructType,
pub name: Name,
pub generics: hir::Generics,
pub variants: hir::HirVec<Variant>,
pub generics: hir::Generics,
pub attrs: hir::HirVec<ast::Attribute>,
- pub id: NodeId,
+ pub id: hir::HirId,
pub whence: Span,
pub name: Name,
}
pub struct Function {
pub decl: hir::FnDecl,
pub attrs: hir::HirVec<ast::Attribute>,
- pub id: NodeId,
+ pub id: hir::HirId,
pub name: Name,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub ty: P<hir::Ty>,
pub gen: hir::Generics,
pub name: Name,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
pub attrs: hir::HirVec<ast::Attribute>,
pub whence: Span,
pub vis: hir::Visibility,
pub struct Existential {
pub exist_ty: hir::ExistTy,
pub name: Name,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
pub attrs: hir::HirVec<ast::Attribute>,
pub whence: Span,
pub vis: hir::Visibility,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
pub whence: Span,
}
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
pub whence: Span,
}
pub generics: hir::Generics,
pub bounds: hir::HirVec<hir::GenericBound>,
pub attrs: hir::HirVec<ast::Attribute>,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
pub whence: Span,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub generics: hir::Generics,
pub bounds: hir::HirVec<hir::GenericBound>,
pub attrs: hir::HirVec<ast::Attribute>,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
pub whence: Span,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub vis: hir::Visibility,
pub stab: Option<attr::Stability>,
pub depr: Option<attr::Deprecation>,
- pub id: ast::NodeId,
+ pub id: hir::HirId,
}
// For Macro we store the DefId instead of the NodeId, since we also create
pub struct Import {
pub name: Name,
- pub id: NodeId,
+ pub id: hir::HirId,
pub vis: hir::Visibility,
pub attrs: hir::HirVec<ast::Attribute>,
pub path: hir::Path,
pub struct ProcMacro {
pub name: Name,
- pub id: NodeId,
+ pub id: hir::HirId,
pub kind: MacroKind,
pub helpers: Vec<Name>,
pub attrs: hir::HirVec<ast::Attribute>,
debug!("Visiting struct");
let struct_type = struct_type_from_def(&*sd);
Struct {
- id: item.id,
+ id: item.hir_id,
struct_type,
name,
vis: item.vis.clone(),
debug!("Visiting union");
let struct_type = struct_type_from_def(&*sd);
Union {
- id: item.id,
+ id: item.hir_id,
struct_type,
name,
vis: item.vis.clone(),
depr: self.deprecation(it.hir_id),
generics: params.clone(),
attrs: it.attrs.clone(),
- id: it.id,
+ id: it.hir_id,
whence: it.span,
}
}
om.proc_macros.push(ProcMacro {
name,
- id: item.id,
+ id: item.hir_id,
kind,
helpers,
attrs: item.attrs.clone(),
}
None => {
om.fns.push(Function {
- id: item.id,
+ id: item.hir_id,
vis: item.vis.clone(),
stab: self.stability(item.hir_id),
depr: self.deprecation(item.hir_id),
///
/// Returns `true` if the target has been inlined.
fn maybe_inline_local(&mut self,
- id: ast::NodeId,
+ id: hir::HirId,
def: Def,
renamed: Option<ast::Ident>,
glob: bool,
return false;
};
- let use_attrs = tcx.hir().attrs(id);
+ let use_attrs = tcx.hir().attrs_by_hir_id(id);
// Don't inline `doc(hidden)` imports so they can be stripped at a later stage.
let is_no_inline = use_attrs.lists("doc").has_word("no_inline") ||
use_attrs.lists("doc").has_word("hidden");
Node::ForeignItem(it) if !glob => {
// Generate a fresh `extern {}` block if we want to inline a foreign item.
om.foreigns.push(hir::ForeignMod {
- abi: tcx.hir().get_foreign_abi(it.id),
+ abi: tcx.hir().get_foreign_abi_by_hir_id(it.hir_id),
items: vec![hir::ForeignItem {
ident: renamed.unwrap_or(it.ident),
.. it.clone()
let ident = renamed.unwrap_or(item.ident);
if item.vis.node.is_pub() {
- let def_id = self.cx.tcx.hir().local_def_id(item.id);
+ let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
self.store_path(def_id);
}
_ if self.inlining && !item.vis.node.is_pub() => {}
hir::ItemKind::GlobalAsm(..) => {}
hir::ItemKind::ExternCrate(orig_name) => {
- let def_id = self.cx.tcx.hir().local_def_id(item.id);
+ let def_id = self.cx.tcx.hir().local_def_id_from_hir_id(item.hir_id);
om.extern_crates.push(ExternCrate {
cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id)
.unwrap_or(LOCAL_CRATE),
}
});
let ident = if is_glob { None } else { Some(ident) };
- if self.maybe_inline_local(item.id,
+ if self.maybe_inline_local(item.hir_id,
path.def,
ident,
is_glob,
om.imports.push(Import {
name: ident.name,
- id: item.id,
+ id: item.hir_id,
vis: item.vis.clone(),
attrs: item.attrs.clone(),
path: (**path).clone(),
ty: ty.clone(),
gen: gen.clone(),
name: ident.name,
- id: item.id,
+ id: item.hir_id,
attrs: item.attrs.clone(),
whence: item.span,
vis: item.vis.clone(),
let t = Existential {
exist_ty: exist_ty.clone(),
name: ident.name,
- id: item.id,
+ id: item.hir_id,
attrs: item.attrs.clone(),
whence: item.span,
vis: item.vis.clone(),
type_: ty.clone(),
mutability: mut_.clone(),
expr: exp.clone(),
- id: item.id,
+ id: item.hir_id,
name: ident.name,
attrs: item.attrs.clone(),
whence: item.span,
let s = Constant {
type_: ty.clone(),
expr: exp.clone(),
- id: item.id,
+ id: item.hir_id,
name: ident.name,
attrs: item.attrs.clone(),
whence: item.span,
items,
generics: gen.clone(),
bounds: b.iter().cloned().collect(),
- id: item.id,
+ id: item.hir_id,
attrs: item.attrs.clone(),
whence: item.span,
vis: item.vis.clone(),
name: ident.name,
generics: gen.clone(),
bounds: b.iter().cloned().collect(),
- id: item.id,
+ id: item.hir_id,
attrs: item.attrs.clone(),
whence: item.span,
vis: item.vis.clone(),
for_: ty.clone(),
items,
attrs: item.attrs.clone(),
- id: item.id,
+ id: item.hir_id,
whence: item.span,
vis: item.vis.clone(),
stab: self.stability(item.hir_id),
elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
}
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, K: 'a + Send, V: 'a + Send> Send for OccupiedEntry<'a, K, V> {}
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, K: 'a + Sync, V: 'a + Sync> Sync for OccupiedEntry<'a, K, V> {}
+
#[stable(feature= "debug_hash_map", since = "1.12.0")]
impl<K: Debug, V: Debug> Debug for OccupiedEntry<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
}
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, K: 'a + Send, V: 'a + Send> Send for VacantEntry<'a, K, V> {}
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, K: 'a + Sync, V: 'a + Sync> Sync for VacantEntry<'a, K, V> {}
+
#[stable(feature= "debug_hash_map", since = "1.12.0")]
impl<K: Debug, V> Debug for VacantEntry<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
}
+}
+impl<R> BufReader<R> {
/// Gets a reference to the underlying reader.
///
/// It is inadvisable to directly read from the underlying reader.
}
}
+// Used by panicking::default_hook
+#[cfg(test)]
+/// This impl is only used by printing logic, so any error returned is always
+/// of kind `Other`, and should be ignored.
+impl Write for Box<dyn (::realstd::io::Write) + Send> {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ (**self).write(buf).map_err(|_| ErrorKind::Other.into())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ (**self).flush().map_err(|_| ErrorKind::Other.into())
+ }
+}
+
// =============================================================================
// In-memory buffer implementations
+#![cfg_attr(test, allow(unused))]
+
use crate::io::prelude::*;
use crate::cell::RefCell;
}
}
+/// Stderr used by eprint! and eprintln! macros, and panics
+thread_local! {
+ static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
+ RefCell::new(None)
+ }
+}
+
/// A handle to a raw instance of the standard input stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
issue = "0")]
#[doc(hidden)]
pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> {
- use crate::panicking::LOCAL_STDERR;
use crate::mem;
LOCAL_STDERR.with(move |slot| {
mem::replace(&mut *slot.borrow_mut(), sink)
reason = "implementation detail which may disappear or be replaced at any time",
issue = "0")]
#[doc(hidden)]
+#[cfg(not(test))]
pub fn _print(args: fmt::Arguments) {
print_to(args, &LOCAL_STDOUT, stdout, "stdout");
}
reason = "implementation detail which may disappear or be replaced at any time",
issue = "0")]
#[doc(hidden)]
+#[cfg(not(test))]
pub fn _eprint(args: fmt::Arguments) {
- use crate::panicking::LOCAL_STDERR;
print_to(args, &LOCAL_STDERR, stderr, "stderr");
}
+#[cfg(test)]
+pub use realstd::io::{_eprint, _print};
+
#[cfg(test)]
mod tests {
use crate::panic::{UnwindSafe, RefUnwindSafe};
// std may use features in a platform-specific way
#![allow(unused_features)]
-#![cfg_attr(test, feature(test, update_panic_count))]
+#![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))]
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
feature(global_asm, range_contains, slice_index_methods,
decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(__rust_unstable_column, libstd_sys_internals))]
+#[allow_internal_unstable(__rust_unstable_column, libstd_sys_internals)]
macro_rules! panic {
() => ({
panic!("explicit panic")
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(print_internals))]
+#[allow_internal_unstable(print_internals)]
macro_rules! print {
($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
}
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(print_internals, format_args_nl))]
+#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! println {
() => (print!("\n"));
($($arg:tt)*) => ({
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(print_internals))]
+#[allow_internal_unstable(print_internals)]
macro_rules! eprint {
($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
}
/// ```
#[macro_export]
#[stable(feature = "eprint", since = "1.19.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(print_internals, format_args_nl))]
+#[allow_internal_unstable(print_internals, format_args_nl)]
macro_rules! eprintln {
() => (eprint!("\n"));
($($arg:tt)*) => ({
/// A macro to await on an async call.
#[macro_export]
#[unstable(feature = "await_macro", issue = "50547")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(gen_future, generators))]
+#[allow_internal_unstable(gen_future, generators)]
#[allow_internal_unsafe]
macro_rules! r#await {
($e:expr) => { {
//! * Executing a panic up to doing the actual implementation
//! * Shims around "try"
-use core::panic::BoxMeUp;
-use core::panic::{PanicInfo, Location};
-
-use crate::io::prelude::*;
+use core::panic::{BoxMeUp, PanicInfo, Location};
use crate::any::Any;
-use crate::cell::RefCell;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
use crate::sys_common::util;
use crate::thread;
-thread_local! {
- pub static LOCAL_STDERR: RefCell<Option<Box<dyn Write + Send>>> = {
- RefCell::new(None)
- }
-}
+#[cfg(not(test))]
+use crate::io::set_panic;
+// make sure to use the stderr output configured
+// by libtest in the real copy of std
+#[cfg(test)]
+use realstd::io::set_panic;
// Binary interface to the panic runtime that the standard library depends on.
//
}
};
- if let Some(mut local) = LOCAL_STDERR.with(|s| s.borrow_mut().take()) {
- write(&mut *local);
- let mut s = Some(local);
- LOCAL_STDERR.with(|slot| {
- *slot.borrow_mut() = s.take();
- });
+ if let Some(mut local) = set_panic(None) {
+ // NB. In `cfg(test)` this uses the forwarding impl
+ // for `Box<dyn (::realstd::io::Write) + Send>`.
+ write(&mut local);
+ set_panic(Some(local));
} else if let Some(mut out) = panic_output() {
write(&mut out);
}
/// the specified value (or combines it with `custom_flags` and `attributes`
/// to set the `dwFlagsAndAttributes` for [`CreateFile`]).
///
- /// By default, `security_qos_flags` is set to `SECURITY_ANONYMOUS`. For
- /// information about possible values, see [Impersonation Levels] on the
- /// Windows Dev Center site.
- ///
+ /// By default `security_qos_flags` is not set. It should be specified when
+ /// opening a named pipe, to control to which degree a server process can
+ /// act on behalf of a client process (security impersonation level).
+ ///
+ /// When `security_qos_flags` is not set a malicious program can gain the
+ /// elevated privileges of a privileged Rust process when it allows opening
+ /// user-specified paths, by tricking it into opening a named pipe. So
+ /// arguably `security_qos_flags` should also be set when opening arbitrary
+ /// paths. However the bits can then conflict with other flags, specifically
+ /// `FILE_FLAG_OPEN_NO_RECALL`.
+ ///
+ /// For information about possible values, see [Impersonation Levels] on the
+ /// Windows Dev Center site. The `SECURITY_SQOS_PRESENT` flag is set
+ /// automatically when using this method.
+
/// # Examples
///
/// ```no_run
+ /// # #[cfg(for_demonstration_only)]
+ /// extern crate winapi;
+ /// # mod winapi { pub const SECURITY_IDENTIFICATION: u32 = 0; }
/// use std::fs::OpenOptions;
/// use std::os::windows::prelude::*;
///
/// .create(true)
///
/// // Sets the flag value to `SecurityIdentification`.
- /// .security_qos_flags(1)
+ /// .security_qos_flags(winapi::SECURITY_IDENTIFICATION)
///
- /// .open("foo.txt");
+ /// .open(r"\\.\pipe\MyPipe");
/// ```
///
/// [`CreateFile`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx
pub fn access_mode(&mut self, access_mode: u32) { self.access_mode = Some(access_mode); }
pub fn share_mode(&mut self, share_mode: u32) { self.share_mode = share_mode; }
pub fn attributes(&mut self, attrs: u32) { self.attributes = attrs; }
- pub fn security_qos_flags(&mut self, flags: u32) { self.security_qos_flags = flags; }
+ pub fn security_qos_flags(&mut self, flags: u32) {
+ // We have to set `SECURITY_SQOS_PRESENT` here, because one of the valid flags we can
+ // receive is `SECURITY_ANONYMOUS = 0x0`, which we can't check for later on.
+ self.security_qos_flags = flags | c::SECURITY_SQOS_PRESENT;
+ }
pub fn security_attributes(&mut self, attrs: c::LPSECURITY_ATTRIBUTES) {
self.security_attributes = attrs as usize;
}
self.custom_flags |
self.attributes |
self.security_qos_flags |
- if self.security_qos_flags != 0 { c::SECURITY_SQOS_PRESENT } else { 0 } |
if self.create_new { c::FILE_FLAG_OPEN_REPARSE_POINT } else { 0 }
}
}
/// });
///
/// // each thread starts out with the initial value of 1
-/// thread::spawn(move|| {
+/// let t = thread::spawn(move|| {
/// FOO.with(|f| {
/// assert_eq!(*f.borrow(), 1);
/// *f.borrow_mut() = 3;
/// });
/// });
///
+/// // wait for the thread to complete and bail out on panic
+/// t.join().unwrap();
+///
/// // we retain our original value of 2 despite the child thread
/// FOO.with(|f| {
/// assert_eq!(*f.borrow(), 2);
/// [`std::thread::LocalKey`]: ../std/thread/struct.LocalKey.html
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(thread_local_internals))]
+#[allow_internal_unstable(thread_local_internals)]
macro_rules! thread_local {
// empty (base case for the recursion)
() => {};
reason = "should not be necessary",
issue = "0")]
#[macro_export]
-#[cfg_attr(stage0, allow_internal_unstable)]
-#[cfg_attr(not(stage0), allow_internal_unstable(
- thread_local_internals, cfg_target_thread_local, thread_local,
-))]
+#[allow_internal_unstable(thread_local_internals, cfg_target_thread_local, thread_local)]
#[allow_internal_unsafe]
macro_rules! __thread_local_inner {
(@key $(#[$attr:meta])* $vis:vis $name:ident, $t:ty, $init:expr) => {
let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
if parse_plus {
self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
- bounds.append(&mut self.parse_generic_bounds(None)?);
+ bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?);
}
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
}
let mut bounds = Vec::new();
let mut negative_bounds = Vec::new();
let mut last_plus_span = None;
+ let mut was_negative = false;
loop {
// This needs to be synchronized with `Token::can_begin_bound`.
let is_bound_start = self.check_path() || self.check_lifetime() ||
}
let poly_span = lo.to(self.prev_span);
if is_negative {
- negative_bounds.push(
- last_plus_span.or(colon_span).unwrap()
- .to(poly_span));
+ was_negative = true;
+ if let Some(sp) = last_plus_span.or(colon_span) {
+ negative_bounds.push(sp.to(poly_span));
+ }
} else {
let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
let modifier = if question.is_some() {
}
}
- if !negative_bounds.is_empty() {
+ if !negative_bounds.is_empty() || was_negative {
let plural = negative_bounds.len() > 1;
let mut err = self.struct_span_err(negative_bounds,
"negative trait bounds are not supported");
- let bound_list = colon_span.unwrap().to(self.prev_span);
- let mut new_bound_list = String::new();
- if !bounds.is_empty() {
- let mut snippets = bounds.iter().map(|bound| bound.span())
- .map(|span| self.sess.source_map().span_to_snippet(span));
- while let Some(Ok(snippet)) = snippets.next() {
- new_bound_list.push_str(" + ");
- new_bound_list.push_str(&snippet);
- }
- new_bound_list = new_bound_list.replacen(" +", ":", 1);
- }
- err.span_suggestion_short(bound_list,
- &format!("remove the trait bound{}",
- if plural { "s" } else { "" }),
- new_bound_list,
- Applicability::MachineApplicable);
+ if let Some(bound_list) = colon_span {
+ let bound_list = bound_list.to(self.prev_span);
+ let mut new_bound_list = String::new();
+ if !bounds.is_empty() {
+ let mut snippets = bounds.iter().map(|bound| bound.span())
+ .map(|span| self.sess.source_map().span_to_snippet(span));
+ while let Some(Ok(snippet)) = snippets.next() {
+ new_bound_list.push_str(" + ");
+ new_bound_list.push_str(&snippet);
+ }
+ new_bound_list = new_bound_list.replacen(" +", ":", 1);
+ }
+ err.span_suggestion_short(bound_list,
+ &format!("remove the trait bound{}",
+ if plural { "s" } else { "" }),
+ new_bound_list,
+ Applicability::MachineApplicable);
+ }
err.emit();
}
// Parse optional colon and param bounds.
let bounds = if self.eat(&token::Colon) {
- self.parse_generic_bounds(None)?
+ self.parse_generic_bounds(Some(self.prev_span))?
} else {
Vec::new()
};
// or with mandatory equality sign and the second type.
let ty = self.parse_ty()?;
if self.eat(&token::Colon) {
- let bounds = self.parse_generic_bounds(None)?;
+ let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
where_clause.predicates.push(ast::WherePredicate::BoundPredicate(
ast::WhereBoundPredicate {
span: lo.to(self.prev_span),
tps.where_clause = self.parse_where_clause()?;
let alias = if existential {
self.expect(&token::Colon)?;
- let bounds = self.parse_generic_bounds(None)?;
+ let bounds = self.parse_generic_bounds(Some(self.prev_span))?;
AliasKind::Existential(bounds)
} else {
self.expect(&token::Eq)?;
-> io::Result<()> {
self.popen()?;
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
- if decl.c_variadic {
- self.s.word(", ...")?;
- }
self.pclose()?;
self.print_fn_output(decl)
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.
-date: 2019-02-17
+date: 2019-02-27
rustc: beta
cargo: beta
// gdb-command:run
// gdb-command:print a
// gdb-check:$1 = 5
+// gdb-command:print d
+// gdb-check:$2 = 6
// === LLDB TESTS ==================================================================================
// lldb-command:print a
// lldbg-check:(int) $0 = 5
// lldbr-check:(int) a = 5
+// lldb-command:print d
+// lldbg-check:(int) $1 = 6
+// lldbr-check:(int) d = 6
-#![feature(omit_gdb_pretty_printer_section, generators, generator_trait, pin)]
+#![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
#![omit_gdb_pretty_printer_section]
use std::ops::Generator;
fn main() {
let mut a = 5;
let mut b = || {
+ let d = 6;
yield;
_zzz(); // #break
- a = 6;
+ a = d;
};
Pin::new(&mut b).resume();
Pin::new(&mut b).resume();
--- /dev/null
+// Adapated from rust-lang/rust#58813
+
+// revisions: rpass1 cfail2
+
+#[cfg(rpass1)]
+pub trait T2 { }
+#[cfg(cfail2)]
+pub trait T2: T1 { }
+//[cfail2]~^ ERROR cycle detected when computing the supertraits of `T2`
+//[cfail2]~| ERROR cycle detected when computing the supertraits of `T2`
+
+pub trait T1: T2 { }
+
+fn main() { }
--- /dev/null
+// Check that `fn foo(x: i32, ...)` does not print as `fn foo(x: i32, ..., ...)`.
+// See issue #58853.
+
+// pp-exact
+#![feature(c_variadic)]
+
+extern "C" {
+ pub fn foo(x: i32, ...);
+}
+
+pub unsafe extern "C" fn bar(_: i32, mut ap: ...) -> usize {
+ ap.arg::<usize>()
+}
+
+fn main() { }
cpp-executable:
$(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs
- $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3
+ $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3
# Make sure we don't find a call instruction to the function we expect to
# always be inlined.
- llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined"
+ $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined"
# As a sanity check, make sure we do find a call instruction to a
# non-inlined function
- llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined"
+ $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined"
rust-executable:
- $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2
+ $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2
(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
$(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain
- llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined"
- llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined"
+ $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined"
+ $(LD_LIB_PATH_ENVVAR)=$(REAL_LD_LIBRARY_PATH) llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined"
--- /dev/null
+// This issue reproduces an ICE on compile (E.g. fails on 2018-12-19 nightly).
+// "cannot relate bound region: ReLateBound(DebruijnIndex(1), BrAnon(1)) <= '_#1r"
+// run-pass
+// edition:2018
+#![feature(generators,generator_trait)]
+use std::ops::Generator;
+
+fn with<F>(f: F) -> impl Generator<Yield=(), Return=()>
+where F: Fn() -> ()
+{
+ move || {
+ loop {
+ match f() {
+ _ => yield,
+ }
+ }
+ }
+}
+
+fn main() {
+ let data = &vec![1];
+ || {
+ let _to_pin = with(move || println!("{:p}", data));
+ loop {
+ yield
+ }
+ };
+}
--- /dev/null
+// run-pass
+// compile-flags: -g
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+struct Database;
+
+impl Database {
+ fn get_connection(&self) -> impl Iterator<Item = ()> {
+ Some(()).into_iter()
+ }
+
+ fn check_connection(&self) -> impl Generator<Yield = (), Return = ()> + '_ {
+ move || {
+ let iter = self.get_connection();
+ for i in iter {
+ yield i
+ }
+ }
+ }
+}
+
+fn main() {
+ Database.check_connection();
+}
--- /dev/null
+// The const-evaluator was at one point ICE'ing while trying to
+// evaluate the body of `fn id` during the `s.id()` call in main.
+
+struct S<T>(T);
+
+impl<T> S<T> {
+ const ID: fn(&S<T>) -> &S<T> = |s| s;
+ pub fn id(&self) -> &Self {
+ Self::ID(self) // This, plus call below ...
+ }
+}
+
+fn main() {
+ let s = S(10u32);
+ assert!(S::<u32>::ID(&s).0 == 10); // Works fine
+ assert!(s.id().0 == 10); // ... causes compiler to panic
+}
is_sync_send!(BTreeSet::<usize>::new(), union(&BTreeSet::<usize>::new()));
all_sync_send!(HashMap::<usize, usize>::new(), iter, iter_mut, drain, into_iter, keys, values);
+ is_sync_send!(HashMap::<usize, usize>::new(), entry(0));
all_sync_send!(HashSet::<usize>::new(), iter, drain, into_iter);
is_sync_send!(HashSet::<usize>::new(), difference(&HashSet::<usize>::new()));
is_sync_send!(HashSet::<usize>::new(), symmetric_difference(&HashSet::<usize>::new()));
use rustc_plugin::Registry;
use syntax::ast;
declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
-declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
+declare_tool_lint!(
+ /// Some docs
+ pub clippy::TEST_GROUP,
+ Warn, "Warn about other stuff"
+);
struct Pass;
--- /dev/null
+// ignore-stage1
+
+extern crate rustc_data_structures;
+//~^ use of unstable library feature 'rustc_private'
+extern crate rustc;
+//~^ use of unstable library feature 'rustc_private'
+extern crate rustc_macros;
+//~^ use of unstable library feature 'rustc_private'
+
+use rustc_macros::HashStable;
+//~^ use of unstable library feature 'rustc_private'
+
+#[derive(HashStable)]
+//~^ use of unstable library feature 'rustc_private'
+struct Test;
--- /dev/null
+error[E0601]: `main` function not found in crate `hash_stable_is_unstable`
+ |
+ = note: consider adding a `main` function to `$DIR/hash-stable-is-unstable.rs`
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+ --> $DIR/hash-stable-is-unstable.rs:3:1
+ |
+LL | extern crate rustc_data_structures;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(rustc_private)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+ --> $DIR/hash-stable-is-unstable.rs:5:1
+ |
+LL | extern crate rustc;
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(rustc_private)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+ --> $DIR/hash-stable-is-unstable.rs:7:1
+ |
+LL | extern crate rustc_macros;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(rustc_private)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+ --> $DIR/hash-stable-is-unstable.rs:10:5
+ |
+LL | use rustc_macros::HashStable;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(rustc_private)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? (see issue #27812)
+ --> $DIR/hash-stable-is-unstable.rs:13:10
+ |
+LL | #[derive(HashStable)]
+ | ^^^^^^^^^^
+ |
+ = help: add #![feature(rustc_private)] to the crate attributes to enable
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0601, E0658.
+For more information about an error, try `rustc --explain E0601`.
LL | match uninhab_ref() {
| ^^^^^^^^^^^^^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/always-inhabited-union-ref.rs:23:11
- |
-LL | match uninhab_ref() {
- | ^^^^^^^^^^^^^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
--> $DIR/always-inhabited-union-ref.rs:27:11
LL | match uninhab_union() {
| ^^^^^^^^^^^^^^^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/always-inhabited-union-ref.rs:27:11
- |
-LL | match uninhab_union() {
- | ^^^^^^^^^^^^^^^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
LL | fn main() {
| - expected `()` because of default return type
LL | &panic!()
- | ^^^^^^^^^ expected (), found reference
+ | ^^^^^^^^^
+ | |
+ | expected (), found reference
+ | help: consider removing the borrow: `panic!()`
|
= note: expected type `()`
found type `&_`
|
LL | match (A, ()) { //~ ERROR non-exhaustive
| ^^^^^^^ patterns `(B, _)`, `(C, _)`, `(D, _)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
--> $DIR/issue-35609.rs:14:11
|
LL | match (A, A) { //~ ERROR non-exhaustive
| ^^^^^^ patterns `(_, B)`, `(_, C)`, `(_, D)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
--> $DIR/issue-35609.rs:18:11
|
LL | match ((A, ()), ()) { //~ ERROR non-exhaustive
| ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
--> $DIR/issue-35609.rs:22:11
|
LL | match ((A, ()), A) { //~ ERROR non-exhaustive
| ^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
--> $DIR/issue-35609.rs:26:11
|
LL | match ((A, ()), ()) { //~ ERROR non-exhaustive
| ^^^^^^^^^^^^^ patterns `((B, _), _)`, `((C, _), _)`, `((D, _), _)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
--> $DIR/issue-35609.rs:31:11
|
+LL | struct S(Enum, ());
+ | ------------------- `S` defined here
+...
LL | match S(A, ()) { //~ ERROR non-exhaustive
| ^^^^^^^^ patterns `S(B, _)`, `S(C, _)`, `S(D, _)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
--> $DIR/issue-35609.rs:35:11
|
+LL | struct Sd { x: Enum, y: () }
+ | ---------------------------- `Sd` defined here
+...
LL | match (Sd { x: A, y: () }) { //~ ERROR non-exhaustive
| ^^^^^^^^^^^^^^^^^^^^ patterns `Sd { x: B, .. }`, `Sd { x: C, .. }`, `Sd { x: D, .. }` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
--> $DIR/issue-35609.rs:39:11
|
LL | match Some(A) { //~ ERROR non-exhaustive
| ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 8 previous errors
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
-fn u32_identity<const X: u32>() -> u32 {
- //~^ ERROR const generics in any position are currently unsupported
+fn i32_identity<const X: i32>() -> i32 {
5
}
fn foo_a() {
- u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
+ i32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
}
fn foo_b() {
- u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
+ i32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
}
fn foo_c() {
- u32_identity::< -1 >(); // ok
+ i32_identity::< -1 >(); // ok
}
fn main() {
- u32_identity::<5>(); // ok
+ i32_identity::<5>(); // ok
}
error: expected identifier, found `<-`
- --> $DIR/const-expression-parameter.rs:10:19
+ --> $DIR/const-expression-parameter.rs:9:19
|
-LL | u32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
+LL | i32_identity::<-1>(); //~ ERROR expected identifier, found `<-`
| ^^ expected identifier
error: expected one of `,` or `>`, found `+`
- --> $DIR/const-expression-parameter.rs:14:22
+ --> $DIR/const-expression-parameter.rs:13:22
|
-LL | u32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
+LL | i32_identity::<1 + 2>(); //~ ERROR expected one of `,` or `>`, found `+`
| ^ expected one of `,` or `>` here
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
-error: const generics in any position are currently unsupported
- --> $DIR/const-expression-parameter.rs:4:23
- |
-LL | fn u32_identity<const X: u32>() -> u32 {
- | ^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
const fn const_u32_identity<const X: u32>() -> u32 {
//~^ ERROR const parameters are not permitted in `const fn`
- //~^^ ERROR const generics in any position are currently unsupported
X
}
|
LL | / const fn const_u32_identity<const X: u32>() -> u32 {
LL | | //~^ ERROR const parameters are not permitted in `const fn`
-LL | | //~^^ ERROR const generics in any position are currently unsupported
LL | | X
LL | | }
| |_^
-error: const generics in any position are currently unsupported
- --> $DIR/const-fn-with-const-param.rs:4:35
- |
-LL | const fn const_u32_identity<const X: u32>() -> u32 {
- | ^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
-fn foo<const X: (), T>(_: T) {
+fn foo<const X: (), T>(_: &T) {
//~^ ERROR type parameters must be declared prior to const parameters
- //~^^ ERROR const generics in any position are currently unsupported
}
fn bar<const X: (), 'a>(_: &'a ()) {
//~^ ERROR lifetime parameters must be declared prior to const parameters
- //~^^ ERROR const generics in any position are currently unsupported
}
fn main() {}
error: type parameters must be declared prior to const parameters
--> $DIR/const-param-before-other-params.rs:4:21
|
-LL | fn foo<const X: (), T>(_: T) {
+LL | fn foo<const X: (), T>(_: &T) {
| --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
error: lifetime parameters must be declared prior to const parameters
- --> $DIR/const-param-before-other-params.rs:9:21
+ --> $DIR/const-param-before-other-params.rs:8:21
|
LL | fn bar<const X: (), 'a>(_: &'a ()) {
| --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
-error: const generics in any position are currently unsupported
- --> $DIR/const-param-before-other-params.rs:4:14
- |
-LL | fn foo<const X: (), T>(_: T) {
- | ^
-
-error: const generics in any position are currently unsupported
- --> $DIR/const-param-before-other-params.rs:9:14
- |
-LL | fn bar<const X: (), 'a>(_: &'a ()) {
- | ^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn foo<const X: u32>() {
- //~^ ERROR const generics in any position are currently unsupported
fn bar() -> u32 {
X //~ ERROR can't use generic parameters from outer function
}
| ^^^^^^^^^^^^^^
error[E0401]: can't use generic parameters from outer function
- --> $DIR/const-param-from-outer-fn.rs:7:9
+ --> $DIR/const-param-from-outer-fn.rs:6:9
|
LL | fn foo<const X: u32>() {
| - const variable from outer function
-LL | //~^ ERROR const generics in any position are currently unsupported
LL | fn bar() -> u32 {
| --- try adding a local generic parameter in this method instead
LL | X //~ ERROR can't use generic parameters from outer function
| ^ use of generic parameter from outer function
-error: const generics in any position are currently unsupported
- --> $DIR/const-param-from-outer-fn.rs:4:14
- |
-LL | fn foo<const X: u32>() {
- | ^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0401`.
#![deny(non_upper_case_globals)]
fn noop<const x: u32>() {
- //~^ ERROR const generics in any position are currently unsupported
+ //~^ ERROR const parameter `x` should have an upper case name
}
+
+fn main() {}
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
-error[E0601]: `main` function not found in crate `const_parameter_uppercase_lint`
- |
- = note: consider adding a `main` function to `$DIR/const-parameter-uppercase-lint.rs`
-
-error: const generics in any position are currently unsupported
+error: const parameter `x` should have an upper case name
--> $DIR/const-parameter-uppercase-lint.rs:6:15
|
LL | fn noop<const x: u32>() {
- | ^
+ | ^ help: convert the identifier to upper case: `X`
+ |
+note: lint level defined here
+ --> $DIR/const-parameter-uppercase-lint.rs:4:9
+ |
+LL | #![deny(non_upper_case_globals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0601`.
|
LL | match C { //~ ERROR non-exhaustive
| ^ pattern `&S` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
-error: #[derive] can't be used on a #[repr(packed)] struct with type parameters (error E0133)
+error: #[derive] can't be used on a #[repr(packed)] struct with type or const parameters (error E0133)
--> $DIR/deriving-with-repr-packed.rs:8:16
|
LL | #[derive(Copy, Clone, PartialEq, Eq)]
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
-error: #[derive] can't be used on a #[repr(packed)] struct with type parameters (error E0133)
+error: #[derive] can't be used on a #[repr(packed)] struct with type or const parameters (error E0133)
--> $DIR/deriving-with-repr-packed.rs:8:23
|
LL | #[derive(Copy, Clone, PartialEq, Eq)]
error[E0308]: mismatched types
--> $DIR/diverging-tuple-parts-39485.rs:8:5
|
-LL | fn g() {
- | - help: try adding a return type: `-> &_`
LL | &panic!() //~ ERROR mismatched types
| ^^^^^^^^^ expected (), found reference
|
= note: expected type `()`
found type `&_`
+help: try adding a return type
+ |
+LL | fn g() -> &_ {
+ | ^^^^^
+help: consider removing the borrow
+ |
+LL | panic!() //~ ERROR mismatched types
+ | ^^^^^^^^
error[E0308]: mismatched types
--> $DIR/diverging-tuple-parts-39485.rs:12:5
error[E0005]: refutable pattern in local binding: `T(_, _)` not covered
--> $DIR/empty-never-array.rs:10:9
|
-LL | let Helper::U(u) = Helper::T(t, []);
- | ^^^^^^^^^^^^ pattern `T(_, _)` not covered
+LL | / enum Helper<T, U> {
+LL | | T(T, [!; 0]),
+LL | | #[allow(dead_code)]
+LL | | U(U),
+LL | | }
+ | |_- `Helper<T, U>` defined here
+...
+LL | let Helper::U(u) = Helper::T(t, []);
+ | ^^^^^^^^^^^^ pattern `T(_, _)` not covered
error: aborting due to previous error
-error[E0004]: non-exhaustive patterns: type `std::option::Option<i32>` is non-empty
+error[E0004]: non-exhaustive patterns: multiple patterns of type `std::option::Option<i32>` are not handled
--> $DIR/E0004-2.rs:4:11
|
LL | match x { } //~ ERROR E0004
| ^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/E0004-2.rs:4:11
- |
-LL | match x { } //~ ERROR E0004
- | ^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `HastaLaVistaBaby` not covered
--> $DIR/E0004.rs:9:11
|
-LL | match x { //~ ERROR E0004
- | ^ pattern `HastaLaVistaBaby` not covered
+LL | / enum Terminator {
+LL | | HastaLaVistaBaby,
+ | | ---------------- not covered
+LL | | TalkToMyHand,
+LL | | }
+ | |_- `Terminator` defined here
+...
+LL | match x { //~ ERROR E0004
+ | ^ pattern `HastaLaVistaBaby` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | match x { //~ ERROR non-exhaustive patterns
| ^ pattern `128u8..=255u8` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
--> $DIR/exhaustive_integer_patterns.rs:33:11
|
LL | match x { //~ ERROR non-exhaustive patterns
| ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: unreachable pattern
--> $DIR/exhaustive_integer_patterns.rs:44:9
|
LL | match x { //~ ERROR non-exhaustive patterns
| ^ patterns `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `-128i8` not covered
--> $DIR/exhaustive_integer_patterns.rs:82:11
|
LL | match 0i8 { //~ ERROR non-exhaustive patterns
| ^^^ pattern `-128i8` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `0i16` not covered
--> $DIR/exhaustive_integer_patterns.rs:90:11
|
LL | match 0i16 { //~ ERROR non-exhaustive patterns
| ^^^^ pattern `0i16` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered
--> $DIR/exhaustive_integer_patterns.rs:108:11
|
LL | match 0u8 { //~ ERROR non-exhaustive patterns
| ^^^ pattern `128u8..=255u8` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
--> $DIR/exhaustive_integer_patterns.rs:120:11
|
LL | match (0u8, Some(())) { //~ ERROR non-exhaustive patterns
| ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered
--> $DIR/exhaustive_integer_patterns.rs:125:11
|
LL | match (0u8, true) { //~ ERROR non-exhaustive patterns
| ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211455u128` not covered
--> $DIR/exhaustive_integer_patterns.rs:145:11
|
LL | match 0u128 { //~ ERROR non-exhaustive patterns
| ^^^^^ pattern `340282366920938463463374607431768211455u128` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `5u128..=340282366920938463463374607431768211455u128` not covered
--> $DIR/exhaustive_integer_patterns.rs:149:11
|
LL | match 0u128 { //~ ERROR non-exhaustive patterns
| ^^^^^ pattern `5u128..=340282366920938463463374607431768211455u128` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered
--> $DIR/exhaustive_integer_patterns.rs:153:11
|
LL | match 0u128 { //~ ERROR non-exhaustive patterns
| ^^^^^ pattern `0u128..=3u128` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 13 previous errors
fn foo<const X: ()>() {} //~ ERROR const generics are unstable
-//~^ const generics in any position are currently unsupported
struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
-//~^ const generics in any position are currently unsupported
fn main() {}
= help: add #![feature(const_generics)] to the crate attributes to enable
error[E0658]: const generics are unstable (see issue #44580)
- --> $DIR/feature-gate-const_generics.rs:4:18
+ --> $DIR/feature-gate-const_generics.rs:3:18
|
LL | struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
| ^
|
= help: add #![feature(const_generics)] to the crate attributes to enable
-error: const generics in any position are currently unsupported
- --> $DIR/feature-gate-const_generics.rs:1:14
- |
-LL | fn foo<const X: ()>() {} //~ ERROR const generics are unstable
- | ^
-
-error: const generics in any position are currently unsupported
- --> $DIR/feature-gate-const_generics.rs:4:18
- |
-LL | struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
- | ^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.
|
LL | match 0usize { //~ERROR non-exhaustive patterns: `_` not covered
| ^^^^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/feature-gate-precise_pointer_size_matching.rs:10:11
|
LL | match 0isize { //~ERROR non-exhaustive patterns: `_` not covered
| ^^^^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
|
LL | match (T::T1(()), V::V2(true)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `(T1(()), V2(_))` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | match (a,b) {
| ^^^^^ pattern `(None, None)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | match "world" { //~ ERROR non-exhaustive patterns: `&_`
| ^^^^^^^ pattern `&_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/issue-30240.rs:6:11
|
LL | match "world" { //~ ERROR non-exhaustive patterns: `&_`
| ^^^^^^^ pattern `&_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
LL | match () { } //~ ERROR non-exhaustive
| ^^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/issue-3096-1.rs:2:11
- |
-LL | match () { } //~ ERROR non-exhaustive
- | ^^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
LL | match x { } //~ ERROR non-exhaustive patterns
| ^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/issue-3096-2.rs:5:11
- |
-LL | match x { } //~ ERROR non-exhaustive patterns
- | ^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
error[E0005]: refutable pattern in local binding: `Bar` not covered
--> $DIR/issue-31561.rs:8:9
|
-LL | let Thing::Foo(y) = Thing::Foo(1);
- | ^^^^^^^^^^^^^ pattern `Bar` not covered
+LL | / enum Thing {
+LL | | Foo(u8),
+LL | | Bar,
+LL | | Baz
+LL | | }
+ | |_- `Thing` defined here
+...
+LL | let Thing::Foo(y) = Thing::Foo(1);
+ | ^^^^^^^^^^^^^ pattern `Bar` not covered
error: aborting due to previous error
|
LL | box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
| ^^^^^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
--> $DIR/issue-39362.rs:10:11
|
-LL | match f {
- | ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+LL | / enum Foo {
+LL | | Bar { bar: Bar, id: usize }
+LL | | }
+ | |_- `Foo` defined here
+...
+LL | match f {
+ | ^ patterns `Bar { bar: C, .. }`, `Bar { bar: D, .. }`, `Bar { bar: E, .. }` and 1 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | println!("foo {:}", match tup { //~ ERROR non-exhaustive patterns: `(true, false)` not covered
| ^^^ pattern `(true, false)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
--- /dev/null
+fn main() {
+ Vec::<[(); 1 + for x in 0..1 {}]>::new();
+ //~^ ERROR cannot add
+}
--- /dev/null
+error[E0277]: cannot add `()` to `{integer}`
+ --> $DIR/issue-50582.rs:2:18
+ |
+LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
+ | ^ no implementation for `{integer} + ()`
+ |
+ = help: the trait `std::ops::Add<()>` is not implemented for `{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+struct Conj<A> {a : A}
+trait Valid {}
+
+impl<A: !Valid> Conj<A>{}
+//~^ ERROR negative trait bounds are not supported
+
+fn main() {}
--- /dev/null
+error: negative trait bounds are not supported
+ --> $DIR/issue-58857.rs:4:7
+ |
+LL | impl<A: !Valid> Conj<A>{}
+ | ^^^^^^^^ help: remove the trait bound
+
+error: aborting due to previous error
+
|
LL | match (true, false) {
| ^^^^^^^^^^^^^ pattern `(true, false)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
--> $DIR/match-argm-statics-2.rs:29:11
|
LL | match Some(Some(North)) {
| ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
--> $DIR/match-argm-statics-2.rs:48:11
|
-LL | match (Foo { bar: Some(North), baz: NewBool(true) }) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+LL | / struct Foo {
+LL | | bar: Option<Direction>,
+LL | | baz: NewBool
+LL | | }
+ | |_- `Foo` defined here
+...
+LL | match (Foo { bar: Some(North), baz: NewBool(true) }) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { bar: Some(North), baz: NewBool(true) }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 3 previous errors
|
LL | match buf { //~ ERROR non-exhaustive
| ^^^ pattern `&[_, _, _, _]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
--> $DIR/match-byte-array-patterns-2.rs:10:11
|
LL | match buf { //~ ERROR non-exhaustive
| ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
|
LL | match 0 { 1 => () } //~ ERROR non-exhaustive patterns
| ^ patterns `-2147483648i32..=0i32` and `2i32..=2147483647i32` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `_` not covered
--> $DIR/match-non-exhaustive.rs:3:11
|
LL | match 0 { 0 if false => () } //~ ERROR non-exhaustive patterns
| ^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
|
LL | match private::DATA {
| ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | match list {
| ^^^^ pattern `&[_, Some(_), None, _]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `C(QA)` not covered
--> $DIR/issue-40221.rs:11:11
|
-LL | match proto { //~ ERROR non-exhaustive patterns
- | ^^^^^ pattern `C(QA)` not covered
+LL | / enum P {
+LL | | C(PC),
+ | | - not covered
+LL | | }
+ | |_- `P` defined here
+...
+LL | match proto { //~ ERROR non-exhaustive patterns
+ | ^^^^^ pattern `C(QA)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
// Regression test for #48697
-// compile-pass
-
#![feature(nll)]
fn foo(x: &i32) -> &i32 {
let z = 4;
let f = &|y| y;
let k = f(&z);
- f(x)
+ f(x) //~ cannot return value referencing local variable
}
fn main() {}
--- /dev/null
+error[E0515]: cannot return value referencing local variable `z`
+ --> $DIR/issue-48697.rs:9:5
+ |
+LL | let k = f(&z);
+ | -- `z` is borrowed here
+LL | f(x) //~ cannot return value referencing local variable
+ | ^^^^ returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
--- /dev/null
+#![feature(nll)]
+
+fn shorten_lifetime<'a, 'b, 'min>(a: &'a i32, b: &'b i32) -> &'min i32
+where
+ 'a: 'min,
+ 'b: 'min,
+{
+ if *a < *b {
+ &a
+ } else {
+ &b
+ }
+}
+
+fn main() {
+ let promoted_fn_item_ref = &shorten_lifetime;
+
+ let a = &5;
+ let ptr = {
+ let l = 3;
+ let b = &l; //~ ERROR does not live long enough
+ let c = promoted_fn_item_ref(a, b);
+ c
+ };
+
+ println!("ptr = {:?}", ptr);
+}
--- /dev/null
+error[E0597]: `l` does not live long enough
+ --> $DIR/promoted-bounds.rs:21:17
+ |
+LL | let ptr = {
+ | --- borrow later stored here
+LL | let l = 3;
+LL | let b = &l; //~ ERROR does not live long enough
+ | ^^ borrowed value does not live long enough
+...
+LL | };
+ | - `l` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
--- /dev/null
+// Check that we handle multiple closures in the same promoted constant.
+
+#![feature(nll)]
+
+fn foo() -> &'static i32 {
+ let z = 0;
+ let p = &(|y| y, |y| y);
+ p.0(&z);
+ p.1(&z) //~ ERROR cannot return
+}
+
+fn main() {}
--- /dev/null
+error[E0515]: cannot return value referencing local variable `z`
+ --> $DIR/promoted-closure-pair.rs:9:5
+ |
+LL | p.1(&z) //~ ERROR cannot return
+ | ^^^^--^
+ | | |
+ | | `z` is borrowed here
+ | returns a value referencing data owned by the current function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
--- /dev/null
+#![feature(nll)]
+
+fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 {
+ x //~ ERROR
+}
+
+fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 {
+ x //~ ERROR
+}
+
+fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
+ // Two errors because *mut is invariant
+ x //~ ERROR
+ //~| ERROR
+}
+
+fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 {
+ x //~ ERROR
+}
+
+fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 {
+ let z = &[x; 3];
+ let y = z as *const &i32;
+ y //~ ERROR
+}
+
+fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] {
+ let z = &[x; 3];
+ let y = z as *const [&i32; 3];
+ y //~ ERROR
+}
+
+fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] {
+ let z = &[[x; 2]; 3];
+ let y = z as *const [&i32; 2];
+ y //~ ERROR
+}
+
+fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:4:5
+ |
+LL | fn shared_to_const<'a, 'b>(x: &&'a i32) -> *const &'b i32 {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:8:5
+ |
+LL | fn unique_to_const<'a, 'b>(x: &mut &'a i32) -> *const &'b i32 {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:13:5
+ |
+LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // Two errors because *mut is invariant
+LL | x //~ ERROR
+ | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:13:5
+ |
+LL | fn unique_to_mut<'a, 'b>(x: &mut &'a i32) -> *mut &'b i32 {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | // Two errors because *mut is invariant
+LL | x //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:18:5
+ |
+LL | fn mut_to_const<'a, 'b>(x: *mut &'a i32) -> *const &'b i32 {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:24:5
+ |
+LL | fn array_elem<'a, 'b>(x: &'a i32) -> *const &'b i32 {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | y //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:30:5
+ |
+LL | fn array_coerce<'a, 'b>(x: &'a i32) -> *const [&'b i32; 3] {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | y //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-coercions.rs:36:5
+ |
+LL | fn nested_array<'a, 'b>(x: &'a i32) -> *const [&'b i32; 2] {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+...
+LL | y //~ ERROR
+ | ^ returning this value requires that `'a` must outlive `'b`
+
+error: aborting due to 8 previous errors
+
--- /dev/null
+#![feature(nll)]
+
+// Check that we assert that pointers have a common subtype for comparisons
+
+fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
+ x == y;
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR lifetime may not live long enough
+}
+
+fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
+ x == y;
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR lifetime may not live long enough
+}
+
+fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
+ f == g;
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR lifetime may not live long enough
+}
+
+fn compare_hr_fn_ptr<'a>(f: fn(&'a i32), g: fn(&i32)) {
+ // Ideally this should compile with the operands swapped as well, but HIR
+ // type checking prevents it (and stops compilation) for now.
+ f == g; // OK
+}
+
+fn compare_const_fn_ptr<'a>(f: *const fn(&'a i32), g: *const fn(&i32)) {
+ f == g; // OK
+}
+
+fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-comparisons.rs:6:5
+ |
+LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x == y;
+ | ^ requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-comparisons.rs:6:10
+ |
+LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x == y;
+ | ^ requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-comparisons.rs:12:5
+ |
+LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x == y;
+ | ^ requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-comparisons.rs:12:10
+ |
+LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | x == y;
+ | ^ requires that `'b` must outlive `'a`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-comparisons.rs:18:5
+ |
+LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | f == g;
+ | ^ requires that `'a` must outlive `'b`
+
+error: lifetime may not live long enough
+ --> $DIR/type-check-pointer-comparisons.rs:18:10
+ |
+LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) {
+ | -- -- lifetime `'b` defined here
+ | |
+ | lifetime `'a` defined here
+LL | f == g;
+ | ^ requires that `'b` must outlive `'a`
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+// Test that type annotations are checked in promoted constants correctly.
+
+#![feature(nll)]
+
+fn foo<'a>() {
+ let x = 0;
+ let f = &drop::<&'a i32>;
+ f(&x);
+ //~^ ERROR `x` does not live long enough
+}
+
+fn main() {}
--- /dev/null
+error[E0597]: `x` does not live long enough
+ --> $DIR/promoted-annotation.rs:8:7
+ |
+LL | fn foo<'a>() {
+ | -- lifetime `'a` defined here
+LL | let x = 0;
+LL | let f = &drop::<&'a i32>;
+ | ---------------- assignment requires that `x` is borrowed for `'a`
+LL | f(&x);
+ | ^^ borrowed value does not live long enough
+LL | //~^ ERROR `x` does not live long enough
+LL | }
+ | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
|
LL | match 0.0 { //~ ERROR non-exhaustive patterns
| ^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
| ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `A(C)` not covered
--> $DIR/non-exhaustive-match-nested.rs:17:11
|
+LL | enum T { A(U), B }
+ | ------------------
+ | | |
+ | | not covered
+ | `T` defined here
+...
LL | match x { //~ ERROR non-exhaustive patterns: `A(C)` not covered
| ^ pattern `A(C)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
error[E0004]: non-exhaustive patterns: `A` not covered
--> $DIR/non-exhaustive-match.rs:8:11
|
+LL | enum T { A, B }
+ | ---------------
+ | | |
+ | | not covered
+ | `T` defined here
+...
LL | match x { T::B => { } } //~ ERROR non-exhaustive patterns: `A` not covered
| ^ pattern `A` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `false` not covered
--> $DIR/non-exhaustive-match.rs:9:11
|
LL | match true { //~ ERROR non-exhaustive patterns: `false` not covered
| ^^^^ pattern `false` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/non-exhaustive-match.rs:12:11
|
LL | match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
| ^^^^^^^^ pattern `Some(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered
--> $DIR/non-exhaustive-match.rs:15:11
|
LL | match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, -2147483648i32..=3i32)`
| ^^^^^^^^^ patterns `(_, _, -2147483648i32..=3i32)` and `(_, _, 5i32..=2147483647i32)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `(A, A)` not covered
--> $DIR/non-exhaustive-match.rs:19:11
|
LL | match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` not covered
| ^^^^^^^^^^^^ pattern `(A, A)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `B` not covered
--> $DIR/non-exhaustive-match.rs:23:11
|
+LL | enum T { A, B }
+ | ---------------
+ | | |
+ | | not covered
+ | `T` defined here
+...
LL | match T::A { //~ ERROR non-exhaustive patterns: `B` not covered
| ^^^^ pattern `B` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `[]` not covered
--> $DIR/non-exhaustive-match.rs:34:11
|
LL | match *vec { //~ ERROR non-exhaustive patterns: `[]` not covered
| ^^^^ pattern `[]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
--> $DIR/non-exhaustive-match.rs:47:11
|
LL | match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
| ^^^^ pattern `[_, _, _, _]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 8 previous errors
error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
--> $DIR/non-exhaustive-pattern-witness.rs:9:11
|
-LL | match (Foo { first: true, second: None }) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+LL | / struct Foo {
+LL | | first: bool,
+LL | | second: Option<[usize; 4]>
+LL | | }
+ | |_- `Foo` defined here
+...
+LL | match (Foo { first: true, second: None }) {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo { first: false, second: Some([_, _, _, _]) }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Red` not covered
--> $DIR/non-exhaustive-pattern-witness.rs:25:11
|
-LL | match Color::Red {
- | ^^^^^^^^^^ pattern `Red` not covered
+LL | / enum Color {
+LL | | Red,
+ | | --- not covered
+LL | | Green,
+LL | | CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+LL | | }
+ | |_- `Color` defined here
+...
+LL | match Color::Red {
+ | ^^^^^^^^^^ pattern `Red` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
--> $DIR/non-exhaustive-pattern-witness.rs:37:11
|
-LL | match Direction::North {
- | ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+LL | / enum Direction {
+LL | | North, East, South, West
+ | | ---- ----- ---- not covered
+ | | | |
+ | | | not covered
+ | | not covered
+LL | | }
+ | |_- `Direction` defined here
+...
+LL | match Direction::North {
+ | ^^^^^^^^^^^^^^^^ patterns `East`, `South` and `West` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
--> $DIR/non-exhaustive-pattern-witness.rs:48:11
|
-LL | match ExcessiveEnum::First {
- | ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+LL | / enum ExcessiveEnum {
+LL | | First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
+LL | | }
+ | |_- `ExcessiveEnum` defined here
+...
+LL | match ExcessiveEnum::First {
+ | ^^^^^^^^^^^^^^^^^^^^ patterns `Second`, `Third`, `Fourth` and 8 more not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
--> $DIR/non-exhaustive-pattern-witness.rs:56:11
|
-LL | match Color::Red {
- | ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+LL | / enum Color {
+LL | | Red,
+LL | | Green,
+LL | | CustomRGBA { a: bool, r: u8, g: u8, b: u8 }
+ | | ---------- not covered
+LL | | }
+ | |_- `Color` defined here
+...
+LL | match Color::Red {
+ | ^^^^^^^^^^ pattern `CustomRGBA { a: true, .. }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
--> $DIR/non-exhaustive-pattern-witness.rs:72:11
|
LL | match *x {
| ^^ pattern `[Second(true), Second(false)]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `((), false)` not covered
--> $DIR/non-exhaustive-pattern-witness.rs:85:11
|
LL | match ((), false) {
| ^^^^^^^^^^^ pattern `((), false)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 7 previous errors
|
LL | match 0isize { //~ ERROR non-exhaustive patterns
| ^^^^^^ patterns `$ISIZE_MIN..=-6isize` and `21isize..=$ISIZE_MAX` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=$USIZE_MAX` not covered
--> $DIR/precise_pointer_size_matching.rs:29:11
|
LL | match 0usize { //~ ERROR non-exhaustive patterns
| ^^^^^^ patterns `0usize` and `21usize..=$USIZE_MAX` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to 2 previous errors
|
LL | match sl { //~ ERROR non-exhaustive patterns
| ^^ pattern `&[]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
|
LL | match enum_unit {
| ^^^^^^^^^ pattern `_` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
error[E0004]: non-exhaustive patterns: `B { x: Some(_) }` not covered
--> $DIR/struct-like-enum-nonexhaustive.rs:8:11
|
-LL | match x { //~ ERROR non-exhaustive patterns
- | ^ pattern `B { x: Some(_) }` not covered
+LL | / enum A {
+LL | | B { x: Option<isize> },
+ | | - not covered
+LL | | C
+LL | | }
+ | |_- `A` defined here
+...
+LL | match x { //~ ERROR non-exhaustive patterns
+ | ^ pattern `B { x: Some(_) }` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
--- /dev/null
+fn main() {
+ let a: String = &String::from("a");
+ //~^ ERROR mismatched types
+ let b: String = &format!("b");
+ //~^ ERROR mismatched types
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/format-borrow.rs:2:21
+ |
+LL | let a: String = &String::from("a");
+ | ^^^^^^^^^^^^^^^^^^
+ | |
+ | expected struct `std::string::String`, found reference
+ | help: consider removing the borrow: `String::from("a")`
+ |
+ = note: expected type `std::string::String`
+ found type `&std::string::String`
+
+error[E0308]: mismatched types
+ --> $DIR/format-borrow.rs:4:21
+ |
+LL | let b: String = &format!("b");
+ | ^^^^^^^^^^^^^
+ | |
+ | expected struct `std::string::String`, found reference
+ | help: consider removing the borrow: `format!("b")`
+ |
+ = note: expected type `std::string::String`
+ found type `&std::string::String`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+trait Bar {}
+impl Bar for u8 {}
+fn foo() -> impl Bar {
+ 5; //~^ ERROR the trait bound `(): Bar` is not satisfied
+}
+
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `(): Bar` is not satisfied
+ --> $DIR/impl-trait-return-trailing-semicolon.rs:3:13
+ |
+LL | fn foo() -> impl Bar {
+ | ^^^^^^^^ the trait `Bar` is not implemented for `()`
+LL | 5; //~^ ERROR the trait bound `(): Bar` is not satisfied
+ | - consider removing this semicolon
+ |
+ = note: the return type of a function must have a statically known size
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+#![deny(unused_variables)]
+
+struct Point {
+ x: i32,
+ y: i32,
+}
+
+fn main() {
+ let points = vec!(Point { x: 1, y: 2 }, Point { x: 3, y: 4 });
+
+ let _: i32 = points.iter()
+ .map(|Point { x, y }| y)
+ //~^ ERROR unused variable
+ .sum();
+
+ let _: i32 = points.iter()
+ .map(|x| 4)
+ //~^ ERROR unused variable
+ .sum();
+}
--- /dev/null
+error: unused variable: `x`
+ --> $DIR/unused-closure-argument.rs:12:23
+ |
+LL | .map(|Point { x, y }| y)
+ | ^ help: try ignoring the field: `x: _`
+ |
+note: lint level defined here
+ --> $DIR/unused-closure-argument.rs:1:9
+ |
+LL | #![deny(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+
+error: unused variable: `x`
+ --> $DIR/unused-closure-argument.rs:17:15
+ |
+LL | .map(|x| 4)
+ | ^ help: consider prefixing with an underscore: `_x`
+
+error: aborting due to 2 previous errors
+
error[E0004]: non-exhaustive patterns: `Foo(_, _)` not covered
--> $DIR/tuple-struct-nonexhaustive.rs:5:11
|
+LL | struct Foo(isize, isize);
+ | ------------------------- `Foo` defined here
+...
LL | match x { //~ ERROR non-exhaustive
| ^ pattern `Foo(_, _)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error: aborting due to previous error
error[E0005]: refutable pattern in local binding: `A(_)` not covered
--> $DIR/uninhabited-irrefutable.rs:27:9
|
-LL | let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
- | ^^^^^^^^^^ pattern `A(_)` not covered
+LL | / enum Foo {
+LL | | A(foo::SecretlyEmpty),
+LL | | B(foo::NotSoSecretlyEmpty),
+LL | | C(NotSoSecretlyEmpty),
+LL | | D(u32),
+LL | | }
+ | |_- `Foo` defined here
+...
+LL | let Foo::D(_y) = x; //~ ERROR refutable pattern in local binding: `A(_)` not covered
+ | ^^^^^^^^^^ pattern `A(_)` not covered
error: aborting due to previous error
|
LL | let _ = match x { //~ ERROR non-exhaustive
| ^ pattern `Err(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
--> $DIR/uninhabited-matches-feature-gated.rs:10:19
LL | let _ = match x {}; //~ ERROR non-exhaustive
| ^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/uninhabited-matches-feature-gated.rs:10:19
- |
-LL | let _ = match x {}; //~ ERROR non-exhaustive
- | ^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
--> $DIR/uninhabited-matches-feature-gated.rs:13:19
LL | let _ = match x {}; //~ ERROR non-exhaustive
| ^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/uninhabited-matches-feature-gated.rs:13:19
- |
-LL | let _ = match x {}; //~ ERROR non-exhaustive
- | ^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
--> $DIR/uninhabited-matches-feature-gated.rs:16:19
LL | let _ = match x {}; //~ ERROR non-exhaustive
| ^
|
-help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- --> $DIR/uninhabited-matches-feature-gated.rs:16:19
- |
-LL | let _ = match x {}; //~ ERROR non-exhaustive
- | ^
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `&[_]` not covered
--> $DIR/uninhabited-matches-feature-gated.rs:19:19
|
LL | let _ = match x { //~ ERROR non-exhaustive
| ^ pattern `&[_]` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
--> $DIR/uninhabited-matches-feature-gated.rs:27:19
|
LL | let _ = match x { //~ ERROR non-exhaustive
| ^ pattern `Err(_)` not covered
+ |
+ = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
--> $DIR/uninhabited-matches-feature-gated.rs:32:9
-Subproject commit 7bc2e1d60d23a2f6a31d7a04d40171372d80b5b3
+Subproject commit caccf8bd4c3d490d6a4cf329a3411bbf68753642
-Subproject commit 724be298a1e12593dbc3786cafc307627e46e802
+Subproject commit e3527fdba7178120a6398e76aa4b3908b10ef85e
+#![deny(rust_2018_idioms)]
+
/// This is a small client program intended to pair with `remote-test-server` in
/// this repository. This client connects to the server over TCP and is used to
/// push artifacts and run tests on the server instead of locally.
use std::thread;
use std::time::Duration;
-const REMOTE_ADDR_ENV: &'static str = "TEST_DEVICE_ADDR";
+const REMOTE_ADDR_ENV: &str = "TEST_DEVICE_ADDR";
macro_rules! t {
($e:expr) => (match $e {
+#![deny(rust_2018_idioms)]
+
/// This is a small server which is intended to run inside of an emulator or
/// on a remote test device. This server pairs with the `remote-test-client`
/// program in this repository. The `remote-test-client` connects to this
inner: &'a Path,
}
-impl<'a> Drop for RemoveOnDrop<'a> {
+impl Drop for RemoveOnDrop<'_> {
fn drop(&mut self) {
t!(fs::remove_dir_all(self.inner));
}
-//
+#![deny(rust_2018_idioms)]
+
use clap::{crate_version};
use std::env;
}
// Build command implementation
-pub fn build_1(args: &ArgMatches) -> Result1<()> {
+pub fn build_1(args: &ArgMatches<'_>) -> Result1<()> {
let book_dir = get_book_dir(args);
let mut book = MDBook1::load(&book_dir)?;
}
// Build command implementation
-pub fn build_2(args: &ArgMatches) -> Result2<()> {
+pub fn build_2(args: &ArgMatches<'_>) -> Result2<()> {
let book_dir = get_book_dir(args);
let mut book = MDBook2::load(&book_dir)?;
Ok(())
}
-fn get_book_dir(args: &ArgMatches) -> PathBuf {
+fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
if let Some(dir) = args.value_of("dir") {
// Check if path is relative from current dir, or absolute...
let p = Path::new(dir);
];
/// Which crates to check against the whitelist?
-const WHITELIST_CRATES: &[CrateVersion] = &[
+const WHITELIST_CRATES: &[CrateVersion<'_>] = &[
CrateVersion("rustc", "0.0.0"),
CrateVersion("rustc_codegen_llvm", "0.0.0"),
];
/// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
-const WHITELIST: &[Crate] = &[
+const WHITELIST: &[Crate<'_>] = &[
Crate("adler32"),
Crate("aho-corasick"),
Crate("arrayvec"),
Crate("smallvec"),
Crate("stable_deref_trait"),
Crate("syn"),
+ Crate("synstructure"),
Crate("tempfile"),
Crate("termcolor"),
Crate("terminon"),
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
struct CrateVersion<'a>(&'a str, &'a str); // (name, version)
-impl<'a> Crate<'a> {
+impl Crate<'_> {
pub fn id_str(&self) -> String {
format!("{} ", self.0)
}
/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
/// the whitelist. Returns a list of illegal dependencies.
-fn check_crate_whitelist<'a, 'b>(
- whitelist: &'a HashSet<Crate>,
+fn check_crate_whitelist<'a>(
+ whitelist: &'a HashSet<Crate<'_>>,
resolve: &'a Resolve,
- visited: &'b mut BTreeSet<CrateVersion<'a>>,
+ visited: &mut BTreeSet<CrateVersion<'a>>,
krate: CrateVersion<'a>,
must_be_on_whitelist: bool,
) -> BTreeSet<Crate<'a>> {
// to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
// under control.
- // "cargo", // FIXME(#53005)
+ "cargo",
"rustc-ap-syntax",
];
let mut name_to_id: HashMap<_, Vec<_>> = HashMap::new();
}
impl fmt::Display for Status {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let as_str = match *self {
Status::Stable => "stable",
Status::Unstable => "unstable",
//! This library contains the tidy lints and exposes it
//! to be used by tools.
-extern crate serde;
+#![deny(rust_2018_idioms)]
+
extern crate serde_json;
#[macro_use]
extern crate serde_derive;