.settings/
.valgrindrc
.vscode/
+.favorites.json
/*-*-*-*/
/*-*-*/
/Makefile
The enforcement policies listed above apply to all official Rust venues; including official IRC channels (#rust, #rust-internals, #rust-tools, #rust-libs, #rustc, #rust-beginners, #rust-docs, #rust-community, #rust-lang, and #cargo); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion.
-*Adapted from the [Node.js Policy on Trolling](http://blog.izs.me/post/30036893703/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
+*Adapted from the [Node.js Policy on Trolling](https://blog.izs.me/2012/08/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).*
[mod_team]: https://www.rust-lang.org/team.html#Moderation-team
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0",
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "cc"
-version = "1.0.25"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
"clippy-mini-macro-test 0.2.0",
"clippy_dev 0.0.1",
"clippy_lints 0.0.212",
- "compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.18 (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)",
"rustc-workspace-hack 1.0.0",
- "rustc_tools_util 0.1.0",
+ "rustc_tools_util 0.1.1",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-std-workspace-core 1.0.0",
]
[[package]]
name = "compiletest_rs"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.82 (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)",
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"libnghttp2-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)",
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide 0.2.0 (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.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "compiletest_rs 0.3.18 (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 = "111.1.0+1.1.1a"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.9.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-src 111.1.0+1.1.1a (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
name = "profiler_builtins"
version = "0.0.0"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
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]]
"rls-vfs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-workspace-hack 1.0.0",
- "rustc_tools_util 0.1.0",
+ "rustc_tools_util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustfmt-nightly 1.0.1",
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
name = "rustc-workspace-hack"
version = "1.0.0"
dependencies = [
+ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
name = "rustc_codegen_llvm"
version = "0.0.0"
dependencies = [
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (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)",
"rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.0.0"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
[[package]]
name = "rustc_tools_util"
-version = "0.1.0"
+version = "0.1.1"
+
+[[package]]
+name = "rustc_tools_util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc_traits"
dependencies = [
"alloc 0.0.0",
"backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
"dlmalloc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum bytesize 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010"
"checksum cargo_metadata 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8dfe3adeb30f7938e6c1dd5327f29235d8ada3e898aeb08c343005ec2915a2"
-"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
+"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a"
"checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
"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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bd14d75a16b6c836c62350e2e8c85495ed8e13df30a7298c574cb1ee4cdac7bc"
-"checksum compiletest_rs 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "89747fe073b7838343bd2c2445e7a7c2e0d415598f8925f0fa9205b9cdfc48cb"
+"checksum compiletest_rs 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0d76d4322a40f6b0db7259d4f2c8a65ed8b0d84fce0bbc61b98cf47f8ec6eec3"
"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 crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
"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-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 rustfix 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "af7c21531a91512a4a51b490be6ba1c8eff34fdda0dc5bf87dc28d86748aac56"
"checksum rusty-fork 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9591f190d2852720b679c21f66ad929f9f1d7bb09d1193c26167586029d8489c"
[patch."https://github.com/rust-lang/rust-clippy"]
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
-rustc_tools_util = { path = "src/tools/clippy/rustc_tools_util" }
3. Build and install:
```sh
- $ git submodule update --init --recursive --progress
$ ./x.py build && sudo ./x.py install
```
+Version 1.32.0 (2019-01-17)
+==========================
+
+Language
+--------
+#### 2018 edition
+- [You can now use the `?` operator in macro definitions.][56245] The `?`
+ operator allows you to specify zero or one repetitions similar to the `*` and
+ `+` operators.
+- [Module paths with no leading keyword like `super`, `self`, or `crate`, will
+ now always resolve to the item (`enum`, `struct`, etc.) available in the
+ module if present, before resolving to a external crate or an item the prelude.][56759]
+ E.g.
+ ```rust
+ enum Color { Red, Green, Blue }
+
+ use Color::*;
+ ```
+
+#### All editions
+- [You can now match against `PhantomData<T>` types.][55837]
+- [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.
+ ```rust
+ struct Point(i32, i32);
+
+ impl Point {
+ pub fn new(x: i32, y: i32) -> Self {
+ Self(x, y)
+ }
+
+ pub fn is_origin(&self) -> bool {
+ match self {
+ Self(0, 0) => true,
+ _ => false,
+ }
+ }
+ }
+ ```
+- [Self can also now be used in type definitions.][56366] E.g.
+ ```rust
+ enum List<T>
+ where
+ Self: PartialOrd<Self> // can write `Self` instead of `List<T>`
+ {
+ Nil,
+ Cons(T, Box<Self>) // likewise here
+ }
+ ```
+- [You can now mark traits with `#[must_use]`.][55663] This provides a warning if
+ a `impl Trait` or `dyn Trait` is returned and unused in the program.
+
+Compiler
+--------
+- [The default allocator has changed from jemalloc to the default allocator on
+ your system.][55238] The compiler itself on Linux & macOS will still use
+ jemalloc, but programs compiled with it will use the system allocator.
+- [Added the `aarch64-pc-windows-msvc` target.][55702]
+
+Libraries
+---------
+- [`PathBuf` now implements `FromStr`.][55148]
+- [`Box<[T]>` now implements `FromIterator<T>`.][55843]
+- [The `dbg!` macro has been stabilized.][56395] This macro enables you to
+ easily debug expressions in your rust program. E.g.
+ ```rust
+ let a = 2;
+ let b = dbg!(a * 2) + 1;
+ // ^-- prints: [src/main.rs:4] a * 2 = 4
+ assert_eq!(b, 5);
+ ```
+
+The following APIs are now `const` functions and can be used in a
+`const` context.
+
+- [`Cell::as_ptr`]
+- [`UnsafeCell::get`]
+- [`char::is_ascii`]
+- [`iter::empty`]
+- [`ManuallyDrop::new`]
+- [`ManuallyDrop::into_inner`]
+- [`RangeInclusive::start`]
+- [`RangeInclusive::end`]
+- [`NonNull::as_ptr`]
+- [`slice::as_ptr`]
+- [`str::as_ptr`]
+- [`Duration::as_secs`]
+- [`Duration::subsec_millis`]
+- [`Duration::subsec_micros`]
+- [`Duration::subsec_nanos`]
+- [`CStr::as_ptr`]
+- [`Ipv4Addr::is_unspecified`]
+- [`Ipv6Addr::new`]
+- [`Ipv6Addr::octets`]
+
+Stabilized APIs
+---------------
+- [`i8::to_be_bytes`]
+- [`i8::to_le_bytes`]
+- [`i8::to_ne_bytes`]
+- [`i8::from_be_bytes`]
+- [`i8::from_le_bytes`]
+- [`i8::from_ne_bytes`]
+- [`i16::to_be_bytes`]
+- [`i16::to_le_bytes`]
+- [`i16::to_ne_bytes`]
+- [`i16::from_be_bytes`]
+- [`i16::from_le_bytes`]
+- [`i16::from_ne_bytes`]
+- [`i32::to_be_bytes`]
+- [`i32::to_le_bytes`]
+- [`i32::to_ne_bytes`]
+- [`i32::from_be_bytes`]
+- [`i32::from_le_bytes`]
+- [`i32::from_ne_bytes`]
+- [`i64::to_be_bytes`]
+- [`i64::to_le_bytes`]
+- [`i64::to_ne_bytes`]
+- [`i64::from_be_bytes`]
+- [`i64::from_le_bytes`]
+- [`i64::from_ne_bytes`]
+- [`i128::to_be_bytes`]
+- [`i128::to_le_bytes`]
+- [`i128::to_ne_bytes`]
+- [`i128::from_be_bytes`]
+- [`i128::from_le_bytes`]
+- [`i128::from_ne_bytes`]
+- [`isize::to_be_bytes`]
+- [`isize::to_le_bytes`]
+- [`isize::to_ne_bytes`]
+- [`isize::from_be_bytes`]
+- [`isize::from_le_bytes`]
+- [`isize::from_ne_bytes`]
+- [`u8::to_be_bytes`]
+- [`u8::to_le_bytes`]
+- [`u8::to_ne_bytes`]
+- [`u8::from_be_bytes`]
+- [`u8::from_le_bytes`]
+- [`u8::from_ne_bytes`]
+- [`u16::to_be_bytes`]
+- [`u16::to_le_bytes`]
+- [`u16::to_ne_bytes`]
+- [`u16::from_be_bytes`]
+- [`u16::from_le_bytes`]
+- [`u16::from_ne_bytes`]
+- [`u32::to_be_bytes`]
+- [`u32::to_le_bytes`]
+- [`u32::to_ne_bytes`]
+- [`u32::from_be_bytes`]
+- [`u32::from_le_bytes`]
+- [`u32::from_ne_bytes`]
+- [`u64::to_be_bytes`]
+- [`u64::to_le_bytes`]
+- [`u64::to_ne_bytes`]
+- [`u64::from_be_bytes`]
+- [`u64::from_le_bytes`]
+- [`u64::from_ne_bytes`]
+- [`u128::to_be_bytes`]
+- [`u128::to_le_bytes`]
+- [`u128::to_ne_bytes`]
+- [`u128::from_be_bytes`]
+- [`u128::from_le_bytes`]
+- [`u128::from_ne_bytes`]
+- [`usize::to_be_bytes`]
+- [`usize::to_le_bytes`]
+- [`usize::to_ne_bytes`]
+- [`usize::from_be_bytes`]
+- [`usize::from_le_bytes`]
+- [`usize::from_ne_bytes`]
+
+Cargo
+-----
+- [You can now run `cargo c` as an alias for `cargo check`.][cargo/6218]
+- [Usernames are now allowed in alt registry URLs.][cargo/6242]
+
+Misc
+----
+- [`libproc_macro` has been added to the `rust-src` distribution.][55280]
+
+Compatibility Notes
+-------------------
+- [The argument types for AVX's
+ `_mm256_stream_si256`, `_mm256_stream_pd`, `_mm256_stream_ps`][55610] have
+ been changed from `*const` to `*mut` as the previous implementation
+ was unsound.
+
+
+[55148]: https://github.com/rust-lang/rust/pull/55148/
+[55238]: https://github.com/rust-lang/rust/pull/55238/
+[55280]: https://github.com/rust-lang/rust/pull/55280/
+[55610]: https://github.com/rust-lang/rust/pull/55610/
+[55663]: https://github.com/rust-lang/rust/pull/55663/
+[55702]: https://github.com/rust-lang/rust/pull/55702/
+[55837]: https://github.com/rust-lang/rust/pull/55837/
+[55843]: https://github.com/rust-lang/rust/pull/55843/
+[56072]: https://github.com/rust-lang/rust/pull/56072/
+[56245]: https://github.com/rust-lang/rust/pull/56245/
+[56365]: https://github.com/rust-lang/rust/pull/56365/
+[56366]: https://github.com/rust-lang/rust/pull/56366/
+[56395]: https://github.com/rust-lang/rust/pull/56395/
+[56759]: https://github.com/rust-lang/rust/pull/56759/
+[cargo/6218]: https://github.com/rust-lang/cargo/pull/6218/
+[cargo/6242]: https://github.com/rust-lang/cargo/pull/6242/
+[`CStr::as_ptr`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.as_ptr
+[`Cell::as_ptr`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_ptr
+[`Duration::as_secs`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.as_secs
+[`Duration::subsec_micros`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_micros
+[`Duration::subsec_millis`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_millis
+[`Duration::subsec_nanos`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.subsec_nanos
+[`Ipv4Addr::is_unspecified`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html#method.is_unspecified
+[`Ipv6Addr::new`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html#method.new
+[`Ipv6Addr::octets`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html#method.octets
+[`ManuallyDrop::into_inner`]: https://doc.rust-lang.org/std/mem/struct.ManuallyDrop.html#method.into_inner
+[`ManuallyDrop::new`]: https://doc.rust-lang.org/std/mem/struct.ManuallyDrop.html#method.new
+[`NonNull::as_ptr`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ptr
+[`RangeInclusive::end`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html#method.end
+[`RangeInclusive::start`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html#method.start
+[`UnsafeCell::get`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html#method.get
+[`slice::as_ptr`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr
+[`char::is_ascii`]: https://doc.rust-lang.org/std/primitive.char.html#method.is_ascii
+[`i128::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.from_be_bytes
+[`i128::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.from_le_bytes
+[`i128::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.from_ne_bytes
+[`i128::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.to_be_bytes
+[`i128::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.to_le_bytes
+[`i128::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i128.html#method.to_ne_bytes
+[`i16::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.from_be_bytes
+[`i16::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.from_le_bytes
+[`i16::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.from_ne_bytes
+[`i16::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.to_be_bytes
+[`i16::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.to_le_bytes
+[`i16::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i16.html#method.to_ne_bytes
+[`i32::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.from_be_bytes
+[`i32::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.from_le_bytes
+[`i32::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.from_ne_bytes
+[`i32::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.to_be_bytes
+[`i32::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.to_le_bytes
+[`i32::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i32.html#method.to_ne_bytes
+[`i64::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.from_be_bytes
+[`i64::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.from_le_bytes
+[`i64::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.from_ne_bytes
+[`i64::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.to_be_bytes
+[`i64::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.to_le_bytes
+[`i64::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i64.html#method.to_ne_bytes
+[`i8::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.from_be_bytes
+[`i8::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.from_le_bytes
+[`i8::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.from_ne_bytes
+[`i8::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.to_be_bytes
+[`i8::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.to_le_bytes
+[`i8::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.i8.html#method.to_ne_bytes
+[`isize::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.from_be_bytes
+[`isize::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.from_le_bytes
+[`isize::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.from_ne_bytes
+[`isize::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.to_be_bytes
+[`isize::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.to_le_bytes
+[`isize::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.isize.html#method.to_ne_bytes
+[`iter::empty`]: https://doc.rust-lang.org/std/iter/fn.empty.html
+[`str::as_ptr`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_ptr
+[`u128::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.from_be_bytes
+[`u128::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.from_le_bytes
+[`u128::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.from_ne_bytes
+[`u128::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.to_be_bytes
+[`u128::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.to_le_bytes
+[`u128::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u128.html#method.to_ne_bytes
+[`u16::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.from_be_bytes
+[`u16::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.from_le_bytes
+[`u16::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.from_ne_bytes
+[`u16::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.to_be_bytes
+[`u16::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.to_le_bytes
+[`u16::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u16.html#method.to_ne_bytes
+[`u32::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.from_be_bytes
+[`u32::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.from_le_bytes
+[`u32::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.from_ne_bytes
+[`u32::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.to_be_bytes
+[`u32::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.to_le_bytes
+[`u32::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u32.html#method.to_ne_bytes
+[`u64::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.from_be_bytes
+[`u64::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.from_le_bytes
+[`u64::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.from_ne_bytes
+[`u64::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.to_be_bytes
+[`u64::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.to_le_bytes
+[`u64::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.to_ne_bytes
+[`u8::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_be_bytes
+[`u8::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_le_bytes
+[`u8::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.from_ne_bytes
+[`u8::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.to_be_bytes
+[`u8::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.to_le_bytes
+[`u8::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.u8.html#method.to_ne_bytes
+[`usize::from_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.from_be_bytes
+[`usize::from_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.from_le_bytes
+[`usize::from_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.from_ne_bytes
+[`usize::to_be_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.to_be_bytes
+[`usize::to_le_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.to_le_bytes
+[`usize::to_ne_bytes`]: https://doc.rust-lang.org/stable/std/primitive.usize.html#method.to_ne_bytes
+
+
Version 1.31.1 (2018-12-20)
===========================
# with clang-cl, so this is special in that it only compiles LLVM with clang-cl
#clang-cl = '/path/to/clang-cl.exe'
+# Use libc++ when building LLVM instead of libstdc++. This is the default on
+# platforms already use libc++ as the default C++ library, but this option
+# allows you to use libc++ even on platforms when it's not. You need to ensure
+# that your host compiler ships with libc++.
+#use-libcxx = true
+
# =============================================================================
# General build configuration options
# =============================================================================
#codegen-units-std = 1
# Whether or not debug assertions are enabled for the compiler and standard
-# library. Also enables compilation of debug! and trace! logging macros.
+# library.
#debug-assertions = false
# Whether or not debuginfo is emitted
dist::Rls,
dist::Rustfmt,
dist::Clippy,
+ dist::Miri,
dist::LlvmTools,
dist::Lldb,
dist::Extended,
install::Rls,
install::Rustfmt,
install::Clippy,
+ install::Miri,
install::Analysis,
install::Src,
install::Rustc
{
cargo.env("LLVM_LINK_SHARED", "1");
}
+ if builder.config.llvm_use_libcxx {
+ cargo.env("LLVM_USE_LIBCXX", "1");
+ }
}
_ => panic!("unknown backend: {}", backend),
}
pub lldb_enabled: bool,
pub llvm_tools_enabled: bool,
+ pub llvm_use_libcxx: bool,
+
// rust codegen options
pub rust_optimize: bool,
pub rust_codegen_units: Option<u32>,
link_shared: Option<bool>,
version_suffix: Option<String>,
clang_cl: Option<String>,
+ use_libcxx: Option<bool>,
}
#[derive(Deserialize, Default, Clone)]
config.llvm_link_jobs = llvm.link_jobs;
config.llvm_version_suffix = llvm.version_suffix.clone();
config.llvm_clang_cl = llvm.clang_cl.clone();
+ set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
}
if let Some(ref rust) = toml.rust {
o("lld", "rust.lld", "build lld")
o("lldb", "rust.lldb", "build lldb")
o("missing-tools", "dist.missing-tools", "allow failures when building tools")
+o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++")
# Optimization and debugging options. These may be overridden by the release
# channel, etc.
format!("{}-{}", component, builder.rls_package_vers())
} else if component == "clippy" {
format!("{}-{}", component, builder.clippy_package_vers())
+ } else if component == "miri" {
+ format!("{}-{}", component, builder.miri_package_vers())
} else if component == "rustfmt" {
format!("{}-{}", component, builder.rustfmt_package_vers())
} else if component == "llvm-tools" {
}
}
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Miri {
+ pub stage: u32,
+ pub target: Interned<String>,
+}
+
+impl Step for Miri {
+ type Output = Option<PathBuf>;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun) -> ShouldRun {
+ run.path("miri")
+ }
+
+ fn make_run(run: RunConfig) {
+ run.builder.ensure(Miri {
+ stage: run.builder.top_stage,
+ target: run.target,
+ });
+ }
+
+ fn run(self, builder: &Builder) -> Option<PathBuf> {
+ let stage = self.stage;
+ let target = self.target;
+ assert!(builder.config.extended);
+
+ builder.info(&format!("Dist miri stage{} ({})", stage, target));
+ let src = builder.src.join("src/tools/miri");
+ let release_num = builder.release_num("miri");
+ let name = pkgname(builder, "miri");
+ let version = builder.miri_info.version(builder, &release_num);
+
+ let tmp = tmpdir(builder);
+ let image = tmp.join("miri-image");
+ drop(fs::remove_dir_all(&image));
+ builder.create_dir(&image);
+
+ // Prepare the image directory
+ // We expect miri to build, because we've exited this step above if tool
+ // state for miri isn't testing.
+ let miri = builder.ensure(tool::Miri {
+ compiler: builder.compiler(stage, builder.config.build),
+ target, extra_features: Vec::new()
+ }).or_else(|| { missing_tool("miri", builder.build.config.missing_tools); None })?;
+ let cargomiri = builder.ensure(tool::CargoMiri {
+ compiler: builder.compiler(stage, builder.config.build),
+ target, extra_features: Vec::new()
+ }).or_else(|| { missing_tool("cargo miri", builder.build.config.missing_tools); None })?;
+
+ builder.install(&miri, &image.join("bin"), 0o755);
+ builder.install(&cargomiri, &image.join("bin"), 0o755);
+ let doc = image.join("share/doc/miri");
+ builder.install(&src.join("README.md"), &doc, 0o644);
+ builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+ builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+
+ // Prepare the overlay
+ let overlay = tmp.join("miri-overlay");
+ drop(fs::remove_dir_all(&overlay));
+ t!(fs::create_dir_all(&overlay));
+ builder.install(&src.join("README.md"), &overlay, 0o644);
+ builder.install(&src.join("LICENSE-APACHE"), &doc, 0o644);
+ builder.install(&src.join("LICENSE-MIT"), &doc, 0o644);
+ builder.create(&overlay.join("version"), &version);
+
+ // Generate the installer tarball
+ let mut cmd = rust_installer(builder);
+ cmd.arg("generate")
+ .arg("--product-name=Rust")
+ .arg("--rel-manifest-dir=rustlib")
+ .arg("--success-message=miri-ready-to-serve.")
+ .arg("--image-dir").arg(&image)
+ .arg("--work-dir").arg(&tmpdir(builder))
+ .arg("--output-dir").arg(&distdir(builder))
+ .arg("--non-installed-overlay").arg(&overlay)
+ .arg(format!("--package-name={}-{}", name, target))
+ .arg("--legacy-manifest-dirs=rustlib,cargo")
+ .arg("--component-name=miri-preview");
+
+ builder.run(&mut cmd);
+ Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
+ }
+}
+
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustfmt {
pub stage: u32,
let rls_installer = builder.ensure(Rls { stage, target });
let llvm_tools_installer = builder.ensure(LlvmTools { stage, target });
let clippy_installer = builder.ensure(Clippy { stage, target });
+ let miri_installer = builder.ensure(Miri { stage, target });
let lldb_installer = builder.ensure(Lldb { target });
let mingw_installer = builder.ensure(Mingw { host: target });
let analysis_installer = builder.ensure(Analysis {
tarballs.push(cargo_installer);
tarballs.extend(rls_installer.clone());
tarballs.extend(clippy_installer.clone());
+ tarballs.extend(miri_installer.clone());
tarballs.extend(rustfmt_installer.clone());
tarballs.extend(llvm_tools_installer);
tarballs.extend(lldb_installer);
if clippy_installer.is_none() {
contents = filter(&contents, "clippy");
}
+ if miri_installer.is_none() {
+ contents = filter(&contents, "miri");
+ }
if rustfmt_installer.is_none() {
contents = filter(&contents, "rustfmt");
}
if clippy_installer.is_some() {
prepare("clippy");
}
+ if miri_installer.is_some() {
+ prepare("miri");
+ }
// create an 'uninstall' package
builder.install(&etc.join("pkg/postinstall"), &pkg.join("uninstall"), 0o755);
"rls-preview".to_string()
} else if name == "clippy" {
"clippy-preview".to_string()
+ } else if name == "miri" {
+ "miri-preview".to_string()
} else {
name.to_string()
};
if clippy_installer.is_some() {
prepare("clippy");
}
+ if miri_installer.is_some() {
+ prepare("miri");
+ }
if target.contains("windows-gnu") {
prepare("rust-mingw");
}
.arg("-out").arg(exe.join("ClippyGroup.wxs"))
.arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
}
+ if miri_installer.is_some() {
+ builder.run(Command::new(&heat)
+ .current_dir(&exe)
+ .arg("dir")
+ .arg("miri")
+ .args(&heat_flags)
+ .arg("-cg").arg("MiriGroup")
+ .arg("-dr").arg("Miri")
+ .arg("-var").arg("var.MiriDir")
+ .arg("-out").arg(exe.join("MiriGroup.wxs"))
+ .arg("-t").arg(etc.join("msi/remove-duplicates.xsl")));
+ }
builder.run(Command::new(&heat)
.current_dir(&exe)
.arg("dir")
if clippy_installer.is_some() {
cmd.arg("-dClippyDir=clippy");
}
+ if miri_installer.is_some() {
+ cmd.arg("-dMiriDir=miri");
+ }
if target.contains("windows-gnu") {
cmd.arg("-dGccDir=rust-mingw");
}
if clippy_installer.is_some() {
candle("ClippyGroup.wxs".as_ref());
}
+ if miri_installer.is_some() {
+ candle("MiriGroup.wxs".as_ref());
+ }
candle("AnalysisGroup.wxs".as_ref());
if target.contains("windows-gnu") {
if clippy_installer.is_some() {
cmd.arg("ClippyGroup.wixobj");
}
+ if miri_installer.is_some() {
+ cmd.arg("MiriGroup.wixobj");
+ }
if target.contains("windows-gnu") {
cmd.arg("GccGroup.wixobj");
cmd.arg(distdir(builder));
cmd.arg(today.trim());
cmd.arg(builder.rust_package_vers());
+ cmd.arg(addr);
cmd.arg(builder.package_vers(&builder.release_num("cargo")));
cmd.arg(builder.package_vers(&builder.release_num("rls")));
cmd.arg(builder.package_vers(&builder.release_num("clippy")));
+ cmd.arg(builder.package_vers(&builder.release_num("miri")));
cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
cmd.arg(builder.llvm_tools_package_vers());
cmd.arg(builder.lldb_package_vers());
- cmd.arg(addr);
builder.create_dir(&distdir(builder));
pub fn install_clippy(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "clippy", "clippy", stage, Some(host));
}
+pub fn install_miri(builder: &Builder, stage: u32, host: Interned<String>) {
+ install_sh(builder, "miri", "miri", stage, Some(host));
+}
pub fn install_rustfmt(builder: &Builder, stage: u32, host: Interned<String>) {
install_sh(builder, "rustfmt", "rustfmt", stage, Some(host));
builder.info(&format!("skipping Install clippy stage{} ({})", self.stage, self.target));
}
};
+ Miri, "miri", Self::should_build(_config), only_hosts: true, {
+ if builder.ensure(dist::Miri { stage: self.stage, target: self.target }).is_some() ||
+ Self::should_install(builder) {
+ install_miri(builder, self.stage, self.target);
+ } else {
+ builder.info(&format!("skipping Install miri stage{} ({})", self.stage, self.target));
+ }
+ };
Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() ||
Self::should_install(builder) {
cargo_info: channel::GitInfo,
rls_info: channel::GitInfo,
clippy_info: channel::GitInfo,
+ miri_info: channel::GitInfo,
rustfmt_info: channel::GitInfo,
local_rebuild: bool,
fail_fast: bool,
let cargo_info = channel::GitInfo::new(&config, &src.join("src/tools/cargo"));
let rls_info = channel::GitInfo::new(&config, &src.join("src/tools/rls"));
let clippy_info = channel::GitInfo::new(&config, &src.join("src/tools/clippy"));
+ let miri_info = channel::GitInfo::new(&config, &src.join("src/tools/miri"));
let rustfmt_info = channel::GitInfo::new(&config, &src.join("src/tools/rustfmt"));
let mut build = Build {
cargo_info,
rls_info,
clippy_info,
+ miri_info,
rustfmt_info,
cc: HashMap::new(),
cxx: HashMap::new(),
self.package_vers(&self.release_num("clippy"))
}
+ /// Returns the value of `package_vers` above for miri
+ fn miri_package_vers(&self) -> String {
+ self.package_vers(&self.release_num("miri"))
+ }
+
/// Returns the value of `package_vers` above for rustfmt
fn rustfmt_package_vers(&self) -> String {
self.package_vers(&self.release_num("rustfmt"))
cfg.define("PYTHON_EXECUTABLE", python);
}
- configure_cmake(builder, target, &mut cfg, false);
+ configure_cmake(builder, target, &mut cfg);
// FIXME: we don't actually need to build all LLVM tools and all LLVM
// libraries here, e.g., we just want a few components and a few
fn configure_cmake(builder: &Builder,
target: Interned<String>,
- cfg: &mut cmake::Config,
- building_dist_binaries: bool) {
+ cfg: &mut cmake::Config) {
if builder.config.ninja {
cfg.generator("Ninja");
}
if builder.config.llvm_clang_cl.is_some() && target.contains("i686") {
cfg.env("SCCACHE_EXTRA_ARGS", "-m32");
}
-
- // If ccache is configured we inform the build a little differently how
- // to invoke ccache while also invoking our compilers.
- } else if let Some(ref ccache) = builder.config.ccache {
- cfg.define("CMAKE_C_COMPILER", ccache)
- .define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
- .define("CMAKE_CXX_COMPILER", ccache)
- .define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx));
} else {
+ // If ccache is configured we inform the build a little differently how
+ // to invoke ccache while also invoking our compilers.
+ if let Some(ref ccache) = builder.config.ccache {
+ cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
+ .define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
+ }
cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
.define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
}
cfg.build_arg("-j").build_arg(builder.jobs().to_string());
cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" "));
let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
- if building_dist_binaries {
- if builder.config.llvm_static_stdcpp && !target.contains("windows") {
- cxxflags.push_str(" -static-libstdc++");
- }
+ if builder.config.llvm_static_stdcpp &&
+ !target.contains("windows") &&
+ !target.contains("netbsd")
+ {
+ cxxflags.push_str(" -static-libstdc++");
}
cfg.define("CMAKE_CXX_FLAGS", cxxflags);
if let Some(ar) = builder.ar(target) {
t!(fs::create_dir_all(&out_dir));
let mut cfg = cmake::Config::new(builder.src.join("src/tools/lld"));
- configure_cmake(builder, target, &mut cfg, true);
+ configure_cmake(builder, target, &mut cfg);
// This is an awful, awful hack. Discovered when we migrated to using
// clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
| "rls"
| "cargo"
| "clippy-driver"
+ | "miri"
=> {}
_ => return,
if path.ends_with("cargo") ||
path.ends_with("rls") ||
path.ends_with("clippy") ||
+ path.ends_with("miri") ||
path.ends_with("rustfmt")
{
cargo.env("LIBZ_SYS_STATIC", "1");
});
};
Miri, miri, "src/tools/miri", "miri", {};
+ CargoMiri, miri, "src/tools/miri", "cargo-miri", {
+ // Miri depends on procedural macros (serde), which requires a full host
+ // compiler to be available, so we need to depend on that.
+ builder.ensure(compile::Rustc {
+ compiler: self.compiler,
+ target: builder.config.build,
+ });
+ };
Rls, rls, "src/tools/rls", "rls", {
let clippy = builder.ensure(Clippy {
compiler: self.compiler,
patch \
libssl-dev \
pkg-config \
- gcc-arm-none-eabi \
libnewlib-arm-none-eabi \
- qemu-system-arm
+ qemu-system-arm \
+# software-properties-common for the add-apt-repository command
+ software-properties-common
WORKDIR /build
+# Use the team-gcc-arm-embedded PPA for a newer version of Arm GCC
+RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa && \
+ apt-get update && \
+ apt-get install -y --no-install-recommends gcc-arm-embedded
+
COPY dist-various-1/build-rumprun.sh /build
RUN ./build-rumprun.sh
ENV TARGETS=$TARGETS,thumbv7m-none-eabi
ENV TARGETS=$TARGETS,thumbv7em-none-eabi
ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
+ENV TARGETS=$TARGETS,thumbv8m.main-none-eabi
ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
ENV TARGETS=$TARGETS,armebv7r-none-eabi
+++ /dev/null
-# `cfg_attr_multi`
-
-The tracking issue for this feature is: [#54881]
-The RFC for this feature is: [#2539]
-
-[#54881]: https://github.com/rust-lang/rust/issues/54881
-[#2539]: https://github.com/rust-lang/rfcs/pull/2539
-
-------------------------
-
-This feature flag lets you put multiple attributes into a `cfg_attr` attribute.
-
-Example:
-
-```rust,ignore
-#[cfg_attr(all(), must_use, optimize)]
-```
-
-Because `cfg_attr` resolves before procedural macros, this does not affect
-macro resolution at all.
\ No newline at end of file
# `const_fn`
-The tracking issue for this feature is: [#24111]
+The tracking issue for this feature is: [#57563]
-[#24111]: https://github.com/rust-lang/rust/issues/24111
+[#57563]: https://github.com/rust-lang/rust/issues/57563
------------------------
+++ /dev/null
-# `irrefutable_let_patterns`
-
-The tracking issue for this feature is: [#44495]
-
-[#44495]: https://github.com/rust-lang/rust/issues/44495
-
-------------------------
-
-This feature changes the way that "irrefutable patterns" are handled
-in the `if let` and `while let` forms. An *irrefutable pattern* is one
-that cannot fail to match -- for example, the `_` pattern matches any
-value, and hence it is "irrefutable". Without this feature, using an
-irrefutable pattern in an `if let` gives a hard error (since often
-this indicates programmer error). But when the feature is enabled, the
-error becomes a lint (since in some cases irrefutable patterns are
-expected). This means you can use `#[allow]` to silence the lint:
-
-```rust
-#![feature(irrefutable_let_patterns)]
-
-#[allow(irrefutable_let_patterns)]
-fn main() {
- // These two examples used to be errors, but now they
- // trigger a lint (that is allowed):
- if let _ = 5 {}
- while let _ = 5 { break; }
-}
-```
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
r"""
htmldocck.py is a custom checker script for Rustdoc HTML outputs.
"""
-from __future__ import print_function
+from __future__ import absolute_import, print_function, unicode_literals
+
+import codecs
+import io
import sys
import os.path
import re
from HTMLParser import HTMLParser
from xml.etree import cElementTree as ET
-# ⇤/⇥ are not in HTML 4 but are in HTML 5
try:
- from html.entities import entitydefs
+ from html.entities import name2codepoint
except ImportError:
- from htmlentitydefs import entitydefs
-entitydefs['larrb'] = u'\u21e4'
-entitydefs['rarrb'] = u'\u21e5'
-entitydefs['nbsp'] = ' '
+ from htmlentitydefs import name2codepoint
# "void elements" (no closing tag) from the HTML Standard section 12.1.2
VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
self.__builder.data(data)
def handle_entityref(self, name):
- self.__builder.data(entitydefs[name])
+ self.__builder.data(unichr(name2codepoint[name]))
def handle_charref(self, name):
code = int(name[1:], 16) if name.startswith(('x', 'X')) else int(name, 10)
- self.__builder.data(unichr(code).encode('utf-8'))
+ self.__builder.data(unichr(code))
def close(self):
HTMLParser.close(self)
(?<=(?<!\S)@)(?P<negated>!?)
(?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
(?P<args>.*)$
-''', re.X)
+''', re.X | re.UNICODE)
def get_commands(template):
- with open(template, 'rU') as f:
+ with io.open(template, encoding='utf-8') as f:
for lineno, line in concat_multi_lines(f):
m = LINE_PATTERN.search(line)
if not m:
if args and not args[:1].isspace():
print_err(lineno, line, 'Invalid template syntax')
continue
- args = shlex.split(args)
+ try:
+ args = shlex.split(args)
+ except UnicodeEncodeError:
+ args = [arg.decode('utf-8') for arg in shlex.split(args.encode('utf-8'))]
yield Command(negated=negated, cmd=cmd, args=args, lineno=lineno+1, context=line)
if not(os.path.exists(abspath) and os.path.isfile(abspath)):
raise FailedCheck('File does not exist {!r}'.format(path))
- with open(abspath) as f:
+ with io.open(abspath, encoding='utf-8') as f:
data = f.read()
self.files[path] = data
return data
if not(os.path.exists(abspath) and os.path.isfile(abspath)):
raise FailedCheck('File does not exist {!r}'.format(path))
- with open(abspath) as f:
+ with io.open(abspath, encoding='utf-8') as f:
try:
- tree = ET.parse(f, CustomHTMLParser())
+ tree = ET.fromstringlist(f.readlines(), CustomHTMLParser())
except Exception as e:
raise RuntimeError('Cannot parse an HTML file {!r}: {}'.format(path, e))
self.trees[path] = tree
if not pat:
return True # special case a presence testing
elif regexp:
- return re.search(pat, data) is not None
+ return re.search(pat, data, flags=re.UNICODE) is not None
else:
data = ' '.join(data.split())
pat = ' '.join(pat.split())
break
except Exception as e:
print('Failed to get path "{}"'.format(path))
- raise e
+ raise
return ret
return len(tree.findall(path))
def stderr(*args):
- print(*args, file=sys.stderr)
+ if sys.version_info.major < 3:
+ file = codecs.getwriter('utf-8')(sys.stderr)
+ else:
+ file = sys.stderr
+
+ print(*args, file=file)
def print_err(lineno, context, err, message=None):
global ERR_COUNT
import os
import sys
import threading
-import thread
import re
import time
+try:
+ import thread
+except ModuleNotFoundError:
+ # The `thread` module was renamed to `_thread` in Python 3.
+ import _thread as thread
+
# Set this to True for additional output
DEBUG_OUTPUT = False
self
}
- /// Sets the length of a vector.
+ /// Forces the length of the vector to `new_len`.
///
- /// This will explicitly set the size of the vector, without actually
- /// modifying its buffers, so it is up to the caller to ensure that the
- /// vector is actually the specified size.
+ /// This is a low-level operation that maintains none of the normal
+ /// invariants of the type. Normally changing the length of a vector
+ /// is done using one of the safe operations instead, such as
+ /// [`truncate`], [`resize`], [`extend`], or [`clear`].
///
- /// # Examples
+ /// [`truncate`]: #method.truncate
+ /// [`resize`]: #method.resize
+ /// [`extend`]: #method.extend-1
+ /// [`clear`]: #method.clear
///
- /// ```
- /// use std::ptr;
+ /// # Safety
///
- /// let mut vec = vec!['r', 'u', 's', 't'];
+ /// - `new_len` must be less than or equal to [`capacity()`].
+ /// - The elements at `old_len..new_len` must be initialized.
///
- /// unsafe {
- /// ptr::drop_in_place(&mut vec[3]);
- /// vec.set_len(3);
+ /// [`capacity()`]: #method.capacity
+ ///
+ /// # Examples
+ ///
+ /// This method can be useful for situations in which the vector
+ /// is serving as a buffer for other code, particularly over FFI:
+ ///
+ /// ```no_run
+ /// # #![allow(dead_code)]
+ /// # // This is just a minimal skeleton for the doc example;
+ /// # // don't use this as a starting point for a real library.
+ /// # pub struct StreamWrapper { strm: *mut std::ffi::c_void }
+ /// # const Z_OK: i32 = 0;
+ /// # extern "C" {
+ /// # fn deflateGetDictionary(
+ /// # strm: *mut std::ffi::c_void,
+ /// # dictionary: *mut u8,
+ /// # dictLength: *mut usize,
+ /// # ) -> i32;
+ /// # }
+ /// # impl StreamWrapper {
+ /// pub fn get_dictionary(&self) -> Option<Vec<u8>> {
+ /// // Per the FFI method's docs, "32768 bytes is always enough".
+ /// let mut dict = Vec::with_capacity(32_768);
+ /// let mut dict_length = 0;
+ /// // SAFETY: When `deflateGetDictionary` returns `Z_OK`, it holds that:
+ /// // 1. `dict_length` elements were initialized.
+ /// // 2. `dict_length` <= the capacity (32_768)
+ /// // which makes `set_len` safe to call.
+ /// unsafe {
+ /// // Make the FFI call...
+ /// let r = deflateGetDictionary(self.strm, dict.as_mut_ptr(), &mut dict_length);
+ /// if r == Z_OK {
+ /// // ...and update the length to what was initialized.
+ /// dict.set_len(dict_length);
+ /// Some(dict)
+ /// } else {
+ /// None
+ /// }
+ /// }
/// }
- /// assert_eq!(vec, ['r', 'u', 's']);
+ /// # }
/// ```
///
- /// In this example, there is a memory leak since the memory locations
- /// owned by the inner vectors were not freed prior to the `set_len` call:
+ /// While the following example is sound, there is a memory leak since
+ /// the inner vectors were not freed prior to the `set_len` call:
///
/// ```
/// let mut vec = vec![vec![1, 0, 0],
/// vec![0, 1, 0],
/// vec![0, 0, 1]];
+ /// // SAFETY:
+ /// // 1. `old_len..0` is empty so no elements need to be initialized.
+ /// // 2. `0 <= capacity` always holds whatever `capacity` is.
/// unsafe {
/// vec.set_len(0);
/// }
/// ```
///
- /// In this example, the vector gets expanded from zero to four items
- /// without any memory allocations occurring, resulting in vector
- /// values of unallocated memory:
- ///
- /// ```
- /// let mut vec: Vec<char> = Vec::new();
- ///
- /// unsafe {
- /// vec.set_len(4);
- /// }
- /// ```
+ /// Normally, here, one would use [`clear`] instead to correctly drop
+ /// the contents and thus not leak memory.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub unsafe fn set_len(&mut self, len: usize) {
- self.len = len;
+ pub unsafe fn set_len(&mut self, new_len: usize) {
+ self.len = new_len;
}
/// Removes an element from the vector and returns it.
//! Functionality for ordering and comparison.
//!
-//! This module defines both [`PartialOrd`] and [`PartialEq`] traits which are used
-//! by the compiler to implement comparison operators. Rust programs may
-//! implement [`PartialOrd`] to overload the `<`, `<=`, `>`, and `>=` operators,
-//! and may implement [`PartialEq`] to overload the `==` and `!=` operators.
+//! This module contains various tools for ordering and comparing values. In
+//! summary:
//!
-//! [`PartialOrd`]: trait.PartialOrd.html
-//! [`PartialEq`]: trait.PartialEq.html
+//! * [`Eq`] and [`PartialEq`] are traits that allow you to define total and
+//! partial equality between values, respectively. Implementing them overloads
+//! the `==` and `!=` operators.
+//! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and
+//! partial orderings between values, respectively. Implementing them overloads
+//! the `<`, `<=`, `>`, and `>=` operators.
+//! * [`Ordering`][cmp::Ordering] is an enum returned by the
+//! main functions of [`Ord`] and [`PartialOrd`], and describes an ordering.
+//! * [`Reverse`][cmp::Reverse] is a struct that allows you to easily reverse
+//! an ordering.
+//! * [`max`][cmp::max] and [`min`][cmp::min] are functions that build off of
+//! [`Ord`] and allow you to find the maximum or minimum of two values.
//!
-//! # Examples
-//!
-//! ```
-//! let x: u32 = 0;
-//! let y: u32 = 1;
-//!
-//! // these two lines are equivalent
-//! assert_eq!(x < y, true);
-//! assert_eq!(x.lt(&y), true);
-//!
-//! // these two lines are also equivalent
-//! assert_eq!(x == y, false);
-//! assert_eq!(x.eq(&y), false);
-//! ```
+//! For more details, see the respective documentation of each item in the list.
#![stable(feature = "rust1", since = "1.0.0")]
/// assert_eq!(&buf, "world");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- fn write_fmt(&mut self, args: Arguments) -> Result {
- // This Adapter is needed to allow `self` (of type `&mut
- // Self`) to be cast to a Write (below) without
- // requiring a `Sized` bound.
- struct Adapter<'a,T: ?Sized +'a>(&'a mut T);
-
- impl<T: ?Sized> Write for Adapter<'_, T>
- where T: Write
- {
- fn write_str(&mut self, s: &str) -> Result {
- self.0.write_str(s)
- }
-
- fn write_char(&mut self, c: char) -> Result {
- self.0.write_char(c)
- }
-
- fn write_fmt(&mut self, args: Arguments) -> Result {
- self.0.write_fmt(args)
- }
- }
-
- write(&mut Adapter(self), args)
+ fn write_fmt(mut self: &mut Self, args: Arguments) -> Result {
+ write(&mut self, args)
}
}
/// family of functions. It contains a function to format the given value. At
/// compile time it is ensured that the function and the value have the correct
/// types, and then this struct is used to canonicalize arguments to one type.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "fmt_internals", reason = "internal to format_args!",
issue = "0")]
formatter: fn(&Void, &mut Formatter) -> Result,
}
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
-impl Clone for ArgumentV1<'_> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
impl<'a> ArgumentV1<'a> {
#[inline(never)]
fn show_usize(x: &usize, f: &mut Formatter) -> Result {
self.args[i].as_usize()
}
rt::v1::Count::NextParam => {
- self.curarg.next().and_then(|arg| arg.as_usize())
+ self.curarg.next()?.as_usize()
}
}
}
sign = Some('+'); width += 1;
}
- let mut prefixed = false;
- if self.alternate() {
- prefixed = true; width += prefix.chars().count();
+ let prefixed = self.alternate();
+ if prefixed {
+ width += prefix.chars().count();
}
// Writes the sign if it exists, and then the prefix if it was requested
let write_prefix = |f: &mut Formatter| {
if let Some(c) = sign {
- f.buf.write_str(c.encode_utf8(&mut [0; 4]))?;
+ f.buf.write_char(c)?;
}
if prefixed { f.buf.write_str(prefix) }
else { Ok(()) }
// remove the sign from the formatted parts
formatted.sign = b"";
- width = if width < sign.len() { 0 } else { width - sign.len() };
+ width = width.saturating_sub(sign.len());
align = rt::v1::Alignment::Right;
self.fill = '0';
self.align = rt::v1::Alignment::Right;
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
-#[must_use]
+#[must_use = "futures do nothing unless polled"]
pub trait Future {
/// The result of the `Future`.
type Output;
/// use std::intrinsics::ctlz;
///
/// let x = 0b0001_1100_u8;
- /// let num_leading = unsafe { ctlz(x) };
+ /// let num_leading = ctlz(x);
/// assert_eq!(num_leading, 3);
/// ```
///
/// use std::intrinsics::ctlz;
///
/// let x = 0u16;
- /// let num_leading = unsafe { ctlz(x) };
+ /// let num_leading = ctlz(x);
/// assert_eq!(num_leading, 16);
/// ```
pub fn ctlz<T>(x: T) -> T;
/// use std::intrinsics::cttz;
///
/// let x = 0b0011_1000_u8;
- /// let num_trailing = unsafe { cttz(x) };
+ /// let num_trailing = cttz(x);
/// assert_eq!(num_trailing, 3);
/// ```
///
/// use std::intrinsics::cttz;
///
/// let x = 0u16;
- /// let num_trailing = unsafe { cttz(x) };
+ /// let num_trailing = cttz(x);
/// assert_eq!(num_trailing, 16);
/// ```
pub fn cttz<T>(x: T) -> T;
message="`{Self}` is not an iterator"
)]
#[doc(spotlight)]
-#[must_use]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
pub trait Iterator {
/// The type of the elements being iterated over.
#[stable(feature = "rust1", since = "1.0.0")]
//! using it. The compiler will warn us about this kind of behavior:
//!
//! ```text
-//! warning: unused result that must be used: iterator adaptors are lazy and
+//! warning: unused result that must be used: iterators are lazy and
//! do nothing unless consumed
//! ```
//!
/// [`rev`]: trait.Iterator.html#method.rev
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Rev<T> {
iter: T
/// [`copied`]: trait.Iterator.html#method.copied
/// [`Iterator`]: trait.Iterator.html
#[unstable(feature = "iter_copied", issue = "57127")]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct Copied<I> {
it: I,
/// [`cloned`]: trait.Iterator.html#method.cloned
/// [`Iterator`]: trait.Iterator.html
#[stable(feature = "iter_cloned", since = "1.1.0")]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct Cloned<I> {
it: I,
/// [`cycle`]: trait.Iterator.html#method.cycle
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Cycle<I> {
orig: I,
///
/// [`step_by`]: trait.Iterator.html#method.step_by
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_step_by", since = "1.28.0")]
#[derive(Clone, Debug)]
pub struct StepBy<I> {
/// [`chain`]: trait.Iterator.html#method.chain
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chain<A, B> {
a: A,
/// [`zip`]: trait.Iterator.html#method.zip
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Zip<A, B> {
a: A,
/// println!("{:?}", pair);
/// }
/// ```
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Map<I, F> {
///
/// [`filter`]: trait.Iterator.html#method.filter
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Filter<I, P> {
///
/// [`filter_map`]: trait.Iterator.html#method.filter_map
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct FilterMap<I, F> {
/// [`enumerate`]: trait.Iterator.html#method.enumerate
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Enumerate<I> {
iter: I,
/// [`peekable`]: trait.Iterator.html#method.peekable
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Peekable<I: Iterator> {
iter: I,
///
/// [`skip_while`]: trait.Iterator.html#method.skip_while
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct SkipWhile<I, P> {
///
/// [`take_while`]: trait.Iterator.html#method.take_while
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct TakeWhile<I, P> {
/// [`skip`]: trait.Iterator.html#method.skip
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Skip<I> {
iter: I,
/// [`take`]: trait.Iterator.html#method.take
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Take<I> {
iter: I,
///
/// [`scan`]: trait.Iterator.html#method.scan
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Scan<I, St, F> {
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator>
where I::Item: IntoIterator {
/// [`fuse`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Fuse<I> {
iter: I,
///
/// [`inspect`]: trait.Iterator.html#method.inspect
/// [`Iterator`]: trait.Iterator.html
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Inspect<I, F> {
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
#![feature(const_fn)]
-#![feature(const_int_ops)]
+#![cfg_attr(stage0, feature(const_int_ops))]
#![feature(const_fn_union)]
#![feature(custom_attribute)]
#![feature(doc_cfg)]
#![feature(const_slice_len)]
#![feature(const_str_as_bytes)]
#![feature(const_str_len)]
-#![feature(const_int_rotate)]
-#![feature(const_int_wrapping)]
-#![feature(const_int_sign)]
+#![cfg_attr(stage0, feature(const_let))]
+#![cfg_attr(stage0, feature(const_int_rotate))]
#![feature(const_int_conversion)]
#![feature(const_transmute)]
#![feature(reverse_bits)]
#![feature(non_exhaustive)]
#![feature(structural_match)]
+#![feature(abi_unadjusted)]
+#![cfg_attr(not(stage0), feature(adx_target_feature))]
#[prelude_import]
#[allow(unused)]
($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
$(
impl FullOps for $ty {
+ #[cfg(stage0)]
fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
- // this cannot overflow, the output is between 0 and 2*2^nbits - 1
- // FIXME will LLVM optimize this into ADC or similar???
+ // This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`.
+ // FIXME: will LLVM optimize this into ADC or similar?
let (v, carry1) = unsafe { intrinsics::add_with_overflow(self, other) };
let (v, carry2) = unsafe {
intrinsics::add_with_overflow(v, if carry {1} else {0})
};
(carry1 || carry2, v)
}
+ #[cfg(not(stage0))]
+ fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
+ // This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`.
+ // FIXME: will LLVM optimize this into ADC or similar?
+ let (v, carry1) = intrinsics::add_with_overflow(self, other);
+ let (v, carry2) = intrinsics::add_with_overflow(v, if carry {1} else {0});
+ (carry1 || carry2, v)
+ }
fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
- // this cannot overflow, the output is between 0 and 2^nbits * (2^nbits - 1)
+ // This cannot overflow;
+ // the output is between `0` and `2^nbits * (2^nbits - 1)`.
+ // FIXME: will LLVM optimize this into ADC or similar?
let nbits = mem::size_of::<$ty>() * 8;
let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
((v >> nbits) as $ty, v as $ty)
}
fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
- // this cannot overflow, the output is between 0 and 2^(2*nbits) - 1
+ // This cannot overflow;
+ // the output is between `0` and `2^nbits * (2^nbits - 1)`.
let nbits = mem::size_of::<$ty>() * 8;
let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
(carry as $bigty);
fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
debug_assert!(borrow < other);
- // this cannot overflow, the dividend is between 0 and other * 2^nbits - 1
+ // This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`.
let nbits = mem::size_of::<$ty>() * 8;
let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
let rhs = other as $bigty;
u8: add(intrinsics::u8_add_with_overflow), mul/div(u16);
u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
-// u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); // see RFC #521 for enabling this.
+ // See RFC #521 for enabling this.
+ // u64: add(intrinsics::u64_add_with_overflow), mul/div(u128);
}
/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
self != self
}
+ // FIXME(#50145): `abs` is publicly unavailable in libcore due to
+ // concerns about portability, so this implementation is for
+ // private use internally.
+ #[inline]
+ fn abs_private(self) -> f32 {
+ f32::from_bits(self.to_bits() & 0x7fff_ffff)
+ }
+
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
///
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool {
- self == INFINITY || self == NEG_INFINITY
+ self.abs_private() == INFINITY
}
/// Returns `true` if this number is neither infinite nor `NaN`.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool {
- !(self.is_nan() || self.is_infinite())
+ // There's no need to handle NaN separately: if self is NaN,
+ // the comparison is not true, exactly as desired.
+ self.abs_private() < INFINITY
}
/// Returns `true` if the number is neither zero, infinite,
self != self
}
+ // FIXME(#50145): `abs` is publicly unavailable in libcore due to
+ // concerns about portability, so this implementation is for
+ // private use internally.
+ #[inline]
+ fn abs_private(self) -> f64 {
+ f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff)
+ }
+
/// Returns `true` if this value is positive infinity or negative infinity and
/// false otherwise.
///
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_infinite(self) -> bool {
- self == INFINITY || self == NEG_INFINITY
+ self.abs_private() == INFINITY
}
/// Returns `true` if this number is neither infinite nor `NaN`.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_finite(self) -> bool {
- !(self.is_nan() || self.is_infinite())
+ // There's no need to handle NaN separately: if self is NaN,
+ // the comparison is not true, exactly as desired.
+ self.abs_private() < INFINITY
}
/// Returns `true` if the number is neither zero, infinite,
```
"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
}
", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 1);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn count_zeros(self) -> u32 {
(!self).count_ones()
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn leading_zeros(self) -> u32 {
(self as $UnsignedT).leading_zeros()
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn trailing_zeros(self) -> u32 {
(self as $UnsignedT).trailing_zeros()
assert_eq!(n.rotate_left(", $rot, "), m);
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_rotate")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_rotate"))]
#[inline]
pub const fn rotate_left(self, n: u32) -> Self {
(self as $UnsignedT).rotate_left(n) as Self
assert_eq!(n.rotate_right(", $rot, "), m);
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_rotate")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_rotate"))]
#[inline]
pub const fn rotate_right(self, n: u32) -> Self {
(self as $UnsignedT).rotate_right(n) as Self
assert_eq!(m, ", $swapped, ");
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn swap_bytes(self) -> Self {
(self as $UnsignedT).swap_bytes() as Self
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn from_be(x: Self) -> Self {
#[cfg(target_endian = "big")]
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn from_le(x: Self) -> Self {
#[cfg(target_endian = "little")]
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn to_be(self) -> Self { // or not to be?
#[cfg(target_endian = "big")]
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn to_le(self) -> Self {
#[cfg(target_endian = "little")]
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_add(self, rhs: Self) -> Self {
+ #[cfg(stage0)]
unsafe {
intrinsics::overflowing_add(self, rhs)
}
+ #[cfg(not(stage0))]
+ intrinsics::overflowing_add(self, rhs)
}
}
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
+ #[cfg(stage0)]
unsafe {
intrinsics::overflowing_sub(self, rhs)
}
+ #[cfg(not(stage0))]
+ intrinsics::overflowing_sub(self, rhs)
}
}
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_mul(self, rhs: Self) -> Self {
+ #[cfg(stage0)]
unsafe {
intrinsics::overflowing_mul(self, rhs)
}
+ #[cfg(not(stage0))]
+ intrinsics::overflowing_mul(self, rhs)
}
}
$EndFeature, "
```"),
#[stable(feature = "num_wrapping", since = "1.2.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
unsafe {
$EndFeature, "
```"),
#[stable(feature = "num_wrapping", since = "1.2.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
unsafe {
"::MIN, true));", $EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+ #[cfg(stage0)]
let (a, b) = unsafe {
- intrinsics::add_with_overflow(self as $ActualT,
- rhs as $ActualT)
+ intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT)
};
+ #[cfg(not(stage0))]
+ let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
}
}
"::MAX, true));", $EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+ #[cfg(stage0)]
let (a, b) = unsafe {
- intrinsics::sub_with_overflow(self as $ActualT,
- rhs as $ActualT)
+ intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT)
};
+ #[cfg(not(stage0))]
+ let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
}
}
$EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+ #[cfg(stage0)]
let (a, b) = unsafe {
- intrinsics::mul_with_overflow(self as $ActualT,
- rhs as $ActualT)
+ intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT)
};
+ #[cfg(not(stage0))]
+ let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
}
}
$EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
$EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_sign")]
#[inline]
pub const fn is_positive(self) -> bool { self > 0 }
}
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_sign")]
#[inline]
pub const fn is_negative(self) -> bool { self < 0 }
}
assert_eq!(n.count_ones(), 3);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn count_ones(self) -> u32 {
+ #[cfg(stage0)]
unsafe { intrinsics::ctpop(self as $ActualT) as u32 }
+ #[cfg(not(stage0))]
+ { intrinsics::ctpop(self as $ActualT) as u32 }
}
}
", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 0);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn count_zeros(self) -> u32 {
(!self).count_ones()
assert_eq!(n.leading_zeros(), 2);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn leading_zeros(self) -> u32 {
+ #[cfg(stage0)]
unsafe { intrinsics::ctlz(self as $ActualT) as u32 }
+ #[cfg(not(stage0))]
+ { intrinsics::ctlz(self as $ActualT) as u32 }
}
}
assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn trailing_zeros(self) -> u32 {
+ #[cfg(stage0)]
unsafe { intrinsics::cttz(self) as u32 }
+ #[cfg(not(stage0))]
+ { intrinsics::cttz(self) as u32 }
}
}
assert_eq!(n.rotate_left(", $rot, "), m);
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_rotate")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_rotate"))]
#[inline]
pub const fn rotate_left(self, n: u32) -> Self {
+ #[cfg(stage0)]
unsafe { intrinsics::rotate_left(self, n as $SelfT) }
+ #[cfg(not(stage0))]
+ intrinsics::rotate_left(self, n as $SelfT)
}
}
assert_eq!(n.rotate_right(", $rot, "), m);
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_rotate")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_rotate"))]
#[inline]
pub const fn rotate_right(self, n: u32) -> Self {
+ #[cfg(stage0)]
unsafe { intrinsics::rotate_right(self, n as $SelfT) }
+ #[cfg(not(stage0))]
+ intrinsics::rotate_right(self, n as $SelfT)
}
}
assert_eq!(m, ", $swapped, ");
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn swap_bytes(self) -> Self {
+ #[cfg(stage0)]
unsafe { intrinsics::bswap(self as $ActualT) as Self }
+ #[cfg(not(stage0))]
+ { intrinsics::bswap(self as $ActualT) as Self }
}
}
assert_eq!(m, ", $reversed, ");
```"),
#[unstable(feature = "reverse_bits", issue = "48763")]
- #[rustc_const_unstable(feature = "const_int_conversion")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_conversion"))]
#[inline]
pub const fn reverse_bits(self) -> Self {
+ #[cfg(stage0)]
unsafe { intrinsics::bitreverse(self as $ActualT) as Self }
+ #[cfg(not(stage0))]
+ { intrinsics::bitreverse(self as $ActualT) as Self }
}
}
}", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn from_be(x: Self) -> Self {
#[cfg(target_endian = "big")]
}", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn from_le(x: Self) -> Self {
#[cfg(target_endian = "little")]
}", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn to_be(self) -> Self { // or not to be?
#[cfg(target_endian = "big")]
}", $EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_ops")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_ops"))]
#[inline]
pub const fn to_le(self) -> Self {
#[cfg(target_endian = "little")]
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_add(self, rhs: Self) -> Self {
+ #[cfg(stage0)]
unsafe {
intrinsics::overflowing_add(self, rhs)
}
+ #[cfg(not(stage0))]
+ intrinsics::overflowing_add(self, rhs)
}
}
$EndFeature, "
```"),
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
+ #[cfg(stage0)]
unsafe {
intrinsics::overflowing_sub(self, rhs)
}
+ #[cfg(not(stage0))]
+ intrinsics::overflowing_sub(self, rhs)
}
}
/// assert_eq!(25u8.wrapping_mul(12), 44);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_mul(self, rhs: Self) -> Self {
+ #[cfg(stage0)]
unsafe {
intrinsics::overflowing_mul(self, rhs)
}
+ #[cfg(not(stage0))]
+ intrinsics::overflowing_mul(self, rhs)
}
doc_comment! {
assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, "
```"),
#[stable(feature = "num_wrapping", since = "1.2.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
unsafe {
assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
```"),
#[stable(feature = "num_wrapping", since = "1.2.0")]
- #[rustc_const_unstable(feature = "const_int_wrapping")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_wrapping"))]
#[inline]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
unsafe {
assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
+ #[cfg(stage0)]
let (a, b) = unsafe {
- intrinsics::add_with_overflow(self as $ActualT,
- rhs as $ActualT)
+ intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT)
};
+ #[cfg(not(stage0))]
+ let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
}
}
$EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
+ #[cfg(stage0)]
let (a, b) = unsafe {
- intrinsics::sub_with_overflow(self as $ActualT,
- rhs as $ActualT)
+ intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT)
};
+ #[cfg(not(stage0))]
+ let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
}
}
/// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true));
/// ```
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
+ #[cfg(stage0)]
let (a, b) = unsafe {
- intrinsics::mul_with_overflow(self as $ActualT,
- rhs as $ActualT)
+ intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT)
};
+ #[cfg(not(stage0))]
+ let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
}
assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, "
```"),
#[stable(feature = "wrapping", since = "1.7.0")]
- #[rustc_const_unstable(feature = "const_int_overflowing")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_int_overflowing"))]
#[inline]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
/// # Examples
///
/// ```
- /// #![feature(transpose_result)]
- ///
/// #[derive(Debug, Eq, PartialEq)]
/// struct SomeErr;
///
/// assert_eq!(x, y.transpose());
/// ```
#[inline]
- #[unstable(feature = "transpose_result", issue = "47338")]
+ #[stable(feature = "transpose_result", since = "1.33.0")]
pub fn transpose(self) -> Result<Option<T>, E> {
match self {
Some(Ok(x)) => Ok(Some(x)),
/// Assign a new value to the memory behind the pinned reference.
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
- pub fn set(mut self: Pin<P>, value: P::Target)
+ pub fn set(self: &mut Pin<P>, value: P::Target)
where
P::Target: Sized,
{
- *self.pointer = value;
+ *(self.pointer) = value;
}
}
/// [valid]: ../ptr/index.html#safety
/// [`Copy`]: ../marker/trait.Copy.html
/// [`read`]: ./fn.read.html
+/// [read-ownership]: ./fn.read.html#ownership-of-the-returned-value
///
/// Just like in C, whether an operation is volatile has no bearing whatsoever
/// on questions involving concurrent access from multiple threads. Volatile
/// # Examples
///
/// ```
- /// #![feature(transpose_result)]
- ///
/// #[derive(Debug, Eq, PartialEq)]
/// struct SomeErr;
///
/// assert_eq!(x.transpose(), y);
/// ```
#[inline]
- #[unstable(feature = "transpose_result", issue = "47338")]
+ #[stable(feature = "transpose_result", since = "1.33.0")]
pub fn transpose(self) -> Option<Result<T, E>> {
match self {
Ok(Some(x)) => Some(Ok(x)),
#[allow(missing_docs)]
pub mod lossy;
-/// A trait to abstract the idea of creating a new instance of a type from a
-/// string.
+/// Parse a value from a string
///
/// `FromStr`'s [`from_str`] method is often used implicitly, through
/// [`str`]'s [`parse`] method. See [`parse`]'s documentation for examples.
/// [`str`]: ../../std/primitive.str.html
/// [`parse`]: ../../std/primitive.str.html#method.parse
///
+/// `FromStr` does not have a lifetime parameter, and so you can only parse types
+/// that do not contain a lifetime parameter themselves. In other words, you can
+/// parse an `i32` with `FromStr`, but not a `&i32`. You can parse a struct that
+/// contains an `i32`, but not one that contains an `&i32`.
+///
/// # Examples
///
/// Basic implementation of `FromStr` on an example `Point` type:
#[inline]
fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
let mut utf8_encoded = [0; 4];
- self.encode_utf8(&mut utf8_encoded);
- let utf8_size = self.len_utf8();
+ let utf8_size = self.encode_utf8(&mut utf8_encoded).len();
CharSearcher {
haystack,
finger: 0,
const MICROS_PER_SEC: u64 = 1_000_000;
const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
+/// The duration of one second.
+#[unstable(feature = "duration_constants", issue = "57391")]
+pub const SECOND: Duration = Duration::from_secs(1);
+
+/// The duration of one millisecond.
+#[unstable(feature = "duration_constants", issue = "57391")]
+pub const MILLISECOND: Duration = Duration::from_millis(1);
+
+/// The duration of one microsecond.
+#[unstable(feature = "duration_constants", issue = "57391")]
+pub const MICROSECOND: Duration = Duration::from_micros(1);
+
+/// The duration of one nanosecond.
+#[unstable(feature = "duration_constants", issue = "57391")]
+pub const NANOSECOND: Duration = Duration::from_nanos(1);
+
/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
///
[] UnsafetyCheckResult(DefId),
[] UnsafeDeriveOnReprPacked(DefId),
+ [] CheckModAttrs(DefId),
+ [] CheckModLoops(DefId),
+ [] CheckModUnstableApiUsage(DefId),
+ [] CheckModItemTypes(DefId),
+ [] CollectModItemTypes(DefId),
+
[] Reachability,
[] MirKeys,
[eval_always] CrateVariances,
if let Some(..) = self.data {
ty::tls::with_context_opt(|icx| {
let icx = if let Some(icx) = icx { icx } else { return };
- match *icx.task {
- OpenTask::Ignore => {
- // ignored
- }
- _ => panic!("expected an ignore context")
- }
+ assert!(icx.task_deps.is_none(), "expected no task dependency tracking");
})
}
}
{
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt {
- task: &OpenTask::Ignore,
+ task_deps: None,
..icx.clone()
};
R: HashStable<StableHashingContext<'gcx>>,
{
self.with_task_impl(key, cx, arg, false, task,
- |key| OpenTask::Regular(Lock::new(RegularOpenTask {
- node: key,
+ |_key| Some(TaskDeps {
+ #[cfg(debug_assertions)]
+ node: Some(_key),
reads: SmallVec::new(),
read_set: Default::default(),
- })),
- |data, key, fingerprint, task| data.borrow_mut().complete_task(key, task, fingerprint))
+ }),
+ |data, key, fingerprint, task| {
+ data.borrow_mut().complete_task(key, task.unwrap(), fingerprint)
+ })
}
/// Creates a new dep-graph input with value `input`
}
self.with_task_impl(key, cx, input, true, identity_fn,
- |_| OpenTask::Ignore,
+ |_| None,
|data, key, fingerprint, _| {
data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint)
})
arg: A,
no_tcx: bool,
task: fn(C, A) -> R,
- create_task: fn(DepNode) -> OpenTask,
+ create_task: fn(DepNode) -> Option<TaskDeps>,
finish_task_and_alloc_depnode: fn(&Lock<CurrentDepGraph>,
DepNode,
Fingerprint,
- OpenTask) -> DepNodeIndex
+ Option<TaskDeps>) -> DepNodeIndex
) -> (R, DepNodeIndex)
where
C: DepGraphSafe + StableHashingContextProvider<'gcx>,
R: HashStable<StableHashingContext<'gcx>>,
{
if let Some(ref data) = self.data {
- let open_task = create_task(key);
+ let task_deps = create_task(key).map(|deps| Lock::new(deps));
// In incremental mode, hash the result of the task. We don't
// do anything with the hash yet, but we are computing it
} else {
ty::tls::with_context(|icx| {
let icx = ty::tls::ImplicitCtxt {
- task: &open_task,
+ task_deps: task_deps.as_ref(),
..icx.clone()
};
&data.current,
key,
current_fingerprint,
- open_task
+ task_deps.map(|lock| lock.into_inner()),
);
// Determine the color of the new DepNode.
where OP: FnOnce() -> R
{
if let Some(ref data) = self.data {
- let (result, open_task) = ty::tls::with_context(|icx| {
- let task = OpenTask::Anon(Lock::new(AnonOpenTask {
+ let (result, task_deps) = ty::tls::with_context(|icx| {
+ let task_deps = Lock::new(TaskDeps {
+ #[cfg(debug_assertions)]
+ node: None,
reads: SmallVec::new(),
read_set: Default::default(),
- }));
+ });
let r = {
let icx = ty::tls::ImplicitCtxt {
- task: &task,
+ task_deps: Some(&task_deps),
..icx.clone()
};
})
};
- (r, task)
+ (r, task_deps.into_inner())
});
let dep_node_index = data.current
.borrow_mut()
- .pop_anon_task(dep_kind, open_task);
+ .complete_anon_task(dep_kind, task_deps);
(result, dep_node_index)
} else {
(op(), DepNodeIndex::INVALID)
R: HashStable<StableHashingContext<'gcx>>,
{
self.with_task_impl(key, cx, arg, false, task,
- |key| OpenTask::EvalAlways { node: key },
- |data, key, fingerprint, task| {
- data.borrow_mut().complete_eval_always_task(key, task, fingerprint)
+ |_| None,
+ |data, key, fingerprint, _| {
+ let mut current = data.borrow_mut();
+ let krate_idx = current.node_to_node_index[
+ &DepNode::new_no_params(DepKind::Krate)
+ ];
+ current.alloc_node(key, smallvec![krate_idx], fingerprint)
})
}
#[inline]
pub fn read(&self, v: DepNode) {
if let Some(ref data) = self.data {
- let mut current = data.current.borrow_mut();
+ let current = data.current.borrow_mut();
if let Some(&dep_node_index) = current.node_to_node_index.get(&v) {
- current.read_index(dep_node_index);
+ std::mem::drop(current);
+ data.read_index(dep_node_index);
} else {
bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind)
}
#[inline]
pub fn read_index(&self, dep_node_index: DepNodeIndex) {
if let Some(ref data) = self.data {
- data.current.borrow_mut().read_index(dep_node_index);
+ data.read_index(dep_node_index);
}
}
.cloned()
}
- pub fn edge_deduplication_data(&self) -> (u64, u64) {
- let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
+ pub fn edge_deduplication_data(&self) -> Option<(u64, u64)> {
+ if cfg!(debug_assertions) {
+ let current_dep_graph = self.data.as_ref().unwrap().current.borrow();
- (current_dep_graph.total_read_count, current_dep_graph.total_duplicate_read_count)
+ Some((current_dep_graph.total_read_count,
+ current_dep_graph.total_duplicate_read_count))
+ } else {
+ None
+ }
}
pub fn serialize(&self) -> SerializedDepGraph {
// Promote the previous diagnostics to the current session.
tcx.queries.on_disk_cache
- .store_diagnostics(dep_node_index, diagnostics.clone());
+ .store_diagnostics(dep_node_index, diagnostics.clone().into());
for diagnostic in diagnostics {
DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
pub(super) struct CurrentDepGraph {
data: IndexVec<DepNodeIndex, DepNodeData>,
node_to_node_index: FxHashMap<DepNode, DepNodeIndex>,
+ #[allow(dead_code)]
forbidden_edge: Option<EdgeFilter>,
// Anonymous DepNodes are nodes the ID of which we compute from the list of
fn complete_task(
&mut self,
- key: DepNode,
- task: OpenTask,
+ node: DepNode,
+ task_deps: TaskDeps,
fingerprint: Fingerprint
) -> DepNodeIndex {
- if let OpenTask::Regular(task) = task {
- let RegularOpenTask {
- node,
- read_set: _,
- reads
- } = task.into_inner();
- assert_eq!(node, key);
-
- // If this is an input node, we expect that it either has no
- // dependencies, or that it just depends on DepKind::CrateMetadata
- // or DepKind::Krate. This happens for some "thin wrapper queries"
- // like `crate_disambiguator` which sometimes have zero deps (for
- // when called for LOCAL_CRATE) or they depend on a CrateMetadata
- // node.
- if cfg!(debug_assertions) {
- if node.kind.is_input() && reads.len() > 0 &&
- // FIXME(mw): Special case for DefSpan until Spans are handled
- // better in general.
- node.kind != DepKind::DefSpan &&
- reads.iter().any(|&i| {
- !(self.data[i].node.kind == DepKind::CrateMetadata ||
- self.data[i].node.kind == DepKind::Krate)
- })
- {
- bug!("Input node {:?} with unexpected reads: {:?}",
- node,
- reads.iter().map(|&i| self.data[i].node).collect::<Vec<_>>())
- }
+ // If this is an input node, we expect that it either has no
+ // dependencies, or that it just depends on DepKind::CrateMetadata
+ // or DepKind::Krate. This happens for some "thin wrapper queries"
+ // like `crate_disambiguator` which sometimes have zero deps (for
+ // when called for LOCAL_CRATE) or they depend on a CrateMetadata
+ // node.
+ if cfg!(debug_assertions) {
+ if node.kind.is_input() && task_deps.reads.len() > 0 &&
+ // FIXME(mw): Special case for DefSpan until Spans are handled
+ // better in general.
+ node.kind != DepKind::DefSpan &&
+ task_deps.reads.iter().any(|&i| {
+ !(self.data[i].node.kind == DepKind::CrateMetadata ||
+ self.data[i].node.kind == DepKind::Krate)
+ })
+ {
+ bug!("Input node {:?} with unexpected reads: {:?}",
+ node,
+ task_deps.reads.iter().map(|&i| self.data[i].node).collect::<Vec<_>>())
}
-
- self.alloc_node(node, reads, fingerprint)
- } else {
- bug!("complete_task() - Expected regular task to be popped")
}
- }
-
- fn pop_anon_task(&mut self, kind: DepKind, task: OpenTask) -> DepNodeIndex {
- if let OpenTask::Anon(task) = task {
- let AnonOpenTask {
- read_set: _,
- reads
- } = task.into_inner();
- debug_assert!(!kind.is_input());
-
- let mut fingerprint = self.anon_id_seed;
- let mut hasher = StableHasher::new();
- for &read in reads.iter() {
- let read_dep_node = self.data[read].node;
+ self.alloc_node(node, task_deps.reads, fingerprint)
+ }
- ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher);
+ fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex {
+ debug_assert!(!kind.is_input());
- // Fingerprint::combine() is faster than sending Fingerprint
- // through the StableHasher (at least as long as StableHasher
- // is so slow).
- fingerprint = fingerprint.combine(read_dep_node.hash);
- }
+ let mut fingerprint = self.anon_id_seed;
+ let mut hasher = StableHasher::new();
- fingerprint = fingerprint.combine(hasher.finish());
+ for &read in task_deps.reads.iter() {
+ let read_dep_node = self.data[read].node;
- let target_dep_node = DepNode {
- kind,
- hash: fingerprint,
- };
+ ::std::mem::discriminant(&read_dep_node.kind).hash(&mut hasher);
- self.intern_node(target_dep_node, reads, Fingerprint::ZERO).0
- } else {
- bug!("pop_anon_task() - Expected anonymous task to be popped")
+ // Fingerprint::combine() is faster than sending Fingerprint
+ // through the StableHasher (at least as long as StableHasher
+ // is so slow).
+ fingerprint = fingerprint.combine(read_dep_node.hash);
}
- }
- fn complete_eval_always_task(
- &mut self,
- key: DepNode,
- task: OpenTask,
- fingerprint: Fingerprint
- ) -> DepNodeIndex {
- if let OpenTask::EvalAlways {
- node,
- } = task {
- debug_assert_eq!(node, key);
- let krate_idx = self.node_to_node_index[&DepNode::new_no_params(DepKind::Krate)];
- self.alloc_node(node, smallvec![krate_idx], fingerprint)
- } else {
- bug!("complete_eval_always_task() - Expected eval always task to be popped");
- }
- }
+ fingerprint = fingerprint.combine(hasher.finish());
- fn read_index(&mut self, source: DepNodeIndex) {
- ty::tls::with_context_opt(|icx| {
- let icx = if let Some(icx) = icx { icx } else { return };
- match *icx.task {
- OpenTask::Regular(ref task) => {
- let mut task = task.lock();
- self.total_read_count += 1;
- if task.read_set.insert(source) {
- task.reads.push(source);
-
- if cfg!(debug_assertions) {
- if let Some(ref forbidden_edge) = self.forbidden_edge {
- let target = &task.node;
- let source = self.data[source].node;
- if forbidden_edge.test(&source, &target) {
- bug!("forbidden edge {:?} -> {:?} created",
- source,
- target)
- }
- }
- }
- } else {
- self.total_duplicate_read_count += 1;
- }
- }
- OpenTask::Anon(ref task) => {
- let mut task = task.lock();
- if task.read_set.insert(source) {
- task.reads.push(source);
- }
- }
- OpenTask::Ignore | OpenTask::EvalAlways { .. } => {
- // ignore
- }
- }
- })
+ let target_dep_node = DepNode {
+ kind,
+ hash: fingerprint,
+ };
+
+ self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO).0
}
fn alloc_node(
}
}
-pub struct RegularOpenTask {
- node: DepNode,
- reads: SmallVec<[DepNodeIndex; 8]>,
- read_set: FxHashSet<DepNodeIndex>,
+impl DepGraphData {
+ fn read_index(&self, source: DepNodeIndex) {
+ ty::tls::with_context_opt(|icx| {
+ let icx = if let Some(icx) = icx { icx } else { return };
+ if let Some(task_deps) = icx.task_deps {
+ let mut task_deps = task_deps.lock();
+ if cfg!(debug_assertions) {
+ self.current.lock().total_read_count += 1;
+ }
+ if task_deps.read_set.insert(source) {
+ task_deps.reads.push(source);
+
+ #[cfg(debug_assertions)]
+ {
+ if let Some(target) = task_deps.node {
+ let graph = self.current.lock();
+ if let Some(ref forbidden_edge) = graph.forbidden_edge {
+ let source = graph.data[source].node;
+ if forbidden_edge.test(&source, &target) {
+ bug!("forbidden edge {:?} -> {:?} created",
+ source,
+ target)
+ }
+ }
+ }
+ }
+ } else if cfg!(debug_assertions) {
+ self.current.lock().total_duplicate_read_count += 1;
+ }
+ }
+ })
+ }
}
-pub struct AnonOpenTask {
+pub struct TaskDeps {
+ #[cfg(debug_assertions)]
+ node: Option<DepNode>,
reads: SmallVec<[DepNodeIndex; 8]>,
read_set: FxHashSet<DepNodeIndex>,
}
-pub enum OpenTask {
- Regular(Lock<RegularOpenTask>),
- Anon(Lock<AnonOpenTask>),
- Ignore,
- EvalAlways {
- node: DepNode,
- },
-}
-
// A data structure that stores Option<DepNodeColor> values as a contiguous
// array, using one u32 per entry.
struct DepNodeColorMap {
pub use self::dep_tracking_map::{DepTrackingMap, DepTrackingMapConfig};
pub use self::dep_node::{DepNode, DepKind, DepConstructor, WorkProductId, label_strs};
-pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, OpenTask};
+pub use self::graph::{DepGraph, WorkProduct, DepNodeIndex, DepNodeColor, TaskDeps};
pub use self::graph::WorkProductFileKind;
pub use self::prev::PreviousDepGraph;
pub use self::query::DepGraphQuery;
//! conflicts between multiple such attributes attached to the same
//! item.
+
+use ty::TyCtxt;
+use ty::query::Providers;
+use ty::query::queries;
+
use hir;
+use hir::def_id::DefId;
use hir::intravisit::{self, Visitor, NestedVisitorMap};
-use ty::TyCtxt;
use std::fmt::{self, Display};
use syntax_pos::Span;
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let mut checker = CheckAttrVisitor { tcx };
- tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor());
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::check_mod_attrs::ensure(tcx, tcx.hir().local_def_id(module));
+ }
}
fn is_c_like_enum(item: &hir::Item) -> bool {
false
}
}
+
+fn check_mod_attrs<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(
+ module_def_id,
+ &mut CheckAttrVisitor { tcx }.as_deep_visitor()
+ );
+}
+
+pub(crate) fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ check_mod_attrs,
+ ..*providers
+ };
+}
}
impl NonMacroAttrKind {
- fn descr(self) -> &'static str {
+ pub fn descr(self) -> &'static str {
match self {
NonMacroAttrKind::Builtin => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
use ty;
+use ty::TyCtxt;
use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
use rustc_data_structures::indexed_vec::Idx;
use serialize;
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get
// `CrateNum`s.
BuiltinMacros,
- /// A CrateNum value that indicates that something is wrong.
- Invalid,
/// A special CrateNum that we use for the tcx.rcache when decoding from
/// the incr. comp. cache.
ReservedForIncrCompCache,
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match self {
CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
- CrateNum::Invalid => write!(fmt, "invalid crate"),
CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"),
CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
- CrateNum::Invalid => write!(f, "invalid crate"),
CrateNum::BuiltinMacros => write!(f, "builtin macros crate"),
CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
}
pub fn to_local(self) -> LocalDefId {
LocalDefId::from_def_id(self)
}
+
+ pub fn describe_as_module(&self, tcx: TyCtxt<'_, '_, '_>) -> String {
+ if self.is_local() && self.index == CRATE_DEF_INDEX {
+ format!("top-level module")
+ } else {
+ format!("module `{}`", tcx.item_path_str(*self))
+ }
+ }
}
impl serialize::UseSpecializedEncodable for DefId {}
#[derive(Copy, Clone)]
pub enum FnKind<'a> {
- /// #[xxx] pub async/const/extern "Abi" fn foo()
- ItemFn(Name, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]),
+ /// `#[xxx] pub async/const/extern "Abi" fn foo()`
+ ItemFn(Ident, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]),
- /// fn foo(&self)
+ /// `fn foo(&self)`
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]),
- /// |x, y| {}
+ /// `|x, y| {}`
Closure(&'a [Attribute]),
}
visitor.visit_nested_body(body);
}
ItemKind::Fn(ref declaration, header, ref generics, body_id) => {
- visitor.visit_fn(FnKind::ItemFn(item.ident.name,
+ visitor.visit_fn(FnKind::ItemFn(item.ident,
generics,
header,
&item.vis,
use util::common::FN_OUTPUT_NAME;
use util::nodemap::{DefIdMap, NodeMap};
-use std::collections::BTreeMap;
+use std::collections::{BTreeSet, BTreeMap};
use std::fmt::Debug;
use std::mem;
use smallvec::SmallVec;
trait_impls: BTreeMap<DefId, Vec<NodeId>>,
trait_auto_impl: BTreeMap<DefId, NodeId>,
+ modules: BTreeMap<NodeId, hir::ModuleItems>,
+
is_generator: bool,
catch_scopes: Vec<NodeId>,
// needs to be created for it.
in_scope_lifetimes: Vec<Ident>,
+ current_module: NodeId,
+
type_def_lifetime_params: DefIdMap<usize>,
current_hir_id_owner: Vec<(DefIndex, u32)>,
bodies: BTreeMap::new(),
trait_impls: BTreeMap::new(),
trait_auto_impl: BTreeMap::new(),
+ modules: BTreeMap::new(),
exported_macros: Vec::new(),
catch_scopes: Vec::new(),
loop_scopes: Vec::new(),
is_in_loop_condition: false,
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
type_def_lifetime_params: Default::default(),
+ current_module: CRATE_NODE_ID,
current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
item_local_id_counters: Default::default(),
node_id_to_hir_id: IndexVec::new(),
}
impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
+ fn visit_mod(&mut self, m: &'lcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) {
+ self.lctx.modules.insert(n, hir::ModuleItems {
+ items: BTreeSet::new(),
+ trait_items: BTreeSet::new(),
+ impl_items: BTreeSet::new(),
+ });
+
+ let old = self.lctx.current_module;
+ self.lctx.current_module = n;
+ visit::walk_mod(self, m);
+ self.lctx.current_module = old;
+ }
+
fn visit_item(&mut self, item: &'lcx Item) {
let mut item_lowered = true;
self.lctx.with_hir_id_owner(item.id, |lctx| {
if let Some(hir_item) = lctx.lower_item(item) {
- lctx.items.insert(item.id, hir_item);
+ lctx.insert_item(item.id, hir_item);
} else {
item_lowered = false;
}
let id = hir::TraitItemId { node_id: item.id };
let hir_item = lctx.lower_trait_item(item);
lctx.trait_items.insert(id, hir_item);
+ lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id);
});
visit::walk_trait_item(self, item);
let id = hir::ImplItemId { node_id: item.id };
let hir_item = lctx.lower_impl_item(item);
lctx.impl_items.insert(id, hir_item);
+ lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id);
});
visit::walk_impl_item(self, item);
}
body_ids,
trait_impls: self.trait_impls,
trait_auto_impl: self.trait_auto_impl,
+ modules: self.modules,
}
}
+ fn insert_item(&mut self, id: NodeId, item: hir::Item) {
+ self.items.insert(id, item);
+ self.modules.get_mut(&self.current_module).unwrap().items.insert(id);
+ }
+
fn allocate_hir_id_counter<T: Debug>(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId {
if self.item_local_id_counters.insert(owner, 0).is_some() {
bug!(
// Insert the item into the global list. This usually happens
// automatically for all AST items. But this existential type item
// does not actually exist in the AST.
- lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
+ lctx.insert_item(exist_ty_id.node_id, exist_ty_item);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
};
let vis = respan(vis.span, vis_kind);
- this.items.insert(
+ this.insert_item(
new_id.node_id,
hir::Item {
id: new_id.node_id,
};
let vis = respan(vis.span, vis_kind);
- this.items.insert(
+ this.insert_item(
new_id,
hir::Item {
id: new_id,
use hir::map;
use hir::{Expr, FnDecl, Node};
use hir::intravisit::FnKind;
-use syntax::ast::{Attribute, Ident, Name, NodeId};
+use syntax::ast::{Attribute, Ident, NodeId};
use syntax_pos::Span;
/// An FnLikeNode is a Node that is like a fn, in that it has a decl
/// These are all the components one can extract from a fn item for
/// use when implementing FnLikeNode operations.
struct ItemFnParts<'a> {
- name: Name,
+ ident: Ident,
decl: &'a ast::FnDecl,
header: ast::FnHeader,
vis: &'a ast::Visibility,
pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
- FnKind::ItemFn(p.name, p.generics, p.header, p.vis, p.attrs)
+ FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs)
};
let closure = |c: ClosureParts<'a>| {
FnKind::Closure(c.attrs)
ast::ItemKind::Fn(ref decl, header, ref generics, block) =>
item_fn(ItemFnParts {
id: i.id,
- name: i.ident.name,
+ ident: i.ident,
decl: &decl,
body: block,
vis: &i.vis,
use ich::Fingerprint;
use middle::cstore::CrateStore;
use session::CrateDisambiguator;
+use session::Session;
use std::iter::repeat;
use syntax::ast::{NodeId, CRATE_NODE_ID};
use syntax::source_map::SourceMap;
}
impl<'a, 'hir> NodeCollector<'a, 'hir> {
- pub(super) fn root(krate: &'hir Crate,
+ pub(super) fn root(sess: &'a Session,
+ krate: &'hir Crate,
dep_graph: &'a DepGraph,
definitions: &'a definitions::Definitions,
- mut hcx: StableHashingContext<'a>,
- source_map: &'a SourceMap)
+ mut hcx: StableHashingContext<'a>)
-> NodeCollector<'a, 'hir> {
let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
trait_impls: _,
trait_auto_impl: _,
body_ids: _,
+ modules: _,
} = *krate;
alloc_hir_dep_nodes(
let mut collector = NodeCollector {
krate,
- source_map,
- map: vec![],
+ source_map: sess.source_map(),
+ map: repeat(None).take(sess.current_node_id_count()).collect(),
parent_node: CRATE_NODE_ID,
current_signature_dep_index: root_mod_sig_dep_index,
current_full_dep_index: root_mod_full_dep_index,
fn insert_entry(&mut self, id: NodeId, entry: Entry<'hir>) {
debug!("hir_map: {:?} => {:?}", id, entry);
- let len = self.map.len();
- if id.as_usize() >= len {
- self.map.extend(repeat(None).take(id.as_usize() - len + 1));
- }
self.map[id.as_usize()] = Some(entry);
}
use syntax::ast::NodeId;
use hir::itemlikevisit::ItemLikeVisitor;
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter};
pub fn check_crate<'hir>(hir_map: &hir::map::Map<'hir>) {
- let mut outer_visitor = OuterVisitor {
- hir_map,
- errors: vec![],
- };
-
hir_map.dep_graph.assert_ignored();
- hir_map.krate().visit_all_item_likes(&mut outer_visitor);
- if !outer_visitor.errors.is_empty() {
- let message = outer_visitor
- .errors
+ let errors = Lock::new(Vec::new());
+
+ par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| {
+ hir_map.visit_item_likes_in_module(hir_map.local_def_id(*module_id), &mut OuterVisitor {
+ hir_map,
+ errors: &errors,
+ });
+ });
+
+ let errors = errors.into_inner();
+
+ if !errors.is_empty() {
+ let message = errors
.iter()
.fold(String::new(), |s1, s2| s1 + "\n" + s2);
bug!("{}", message);
hir_map: &'a hir::map::Map<'hir>,
owner_def_index: Option<DefIndex>,
hir_ids_seen: FxHashMap<ItemLocalId, NodeId>,
- errors: Vec<String>,
+ errors: &'a Lock<Vec<String>>,
}
struct OuterVisitor<'a, 'hir: 'a> {
hir_map: &'a hir::map::Map<'hir>,
- errors: Vec<String>,
+ errors: &'a Lock<Vec<String>>,
}
impl<'a, 'hir: 'a> OuterVisitor<'a, 'hir> {
hir_map,
owner_def_index: None,
hir_ids_seen: Default::default(),
- errors: Vec::new(),
+ errors: self.errors,
}
}
}
fn visit_item(&mut self, i: &'hir hir::Item) {
let mut inner_visitor = self.new_inner_visitor(self.hir_map);
inner_visitor.check(i.id, |this| intravisit::walk_item(this, i));
- self.errors.extend(inner_visitor.errors.drain(..));
}
fn visit_trait_item(&mut self, i: &'hir hir::TraitItem) {
let mut inner_visitor = self.new_inner_visitor(self.hir_map);
inner_visitor.check(i.id, |this| intravisit::walk_trait_item(this, i));
- self.errors.extend(inner_visitor.errors.drain(..));
}
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
let mut inner_visitor = self.new_inner_visitor(self.hir_map);
inner_visitor.check(i.id, |this| intravisit::walk_impl_item(this, i));
- self.errors.extend(inner_visitor.errors.drain(..));
}
}
impl<'a, 'hir: 'a> HirIdValidator<'a, 'hir> {
+ #[cold]
+ #[inline(never)]
+ fn error(&self, f: impl FnOnce() -> String) {
+ self.errors.lock().push(f());
+ }
fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self,
node_id: NodeId,
local_id,
self.hir_map.node_to_string(node_id)));
}
- self.errors.push(format!(
+ self.error(|| format!(
"ItemLocalIds not assigned densely in {}. \
Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}",
self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(),
let stable_id = self.hir_map.definitions().node_to_hir_id[node_id];
if stable_id == hir::DUMMY_HIR_ID {
- self.errors.push(format!("HirIdValidator: No HirId assigned for NodeId {}: {:?}",
+ self.error(|| format!("HirIdValidator: No HirId assigned for NodeId {}: {:?}",
node_id,
self.hir_map.node_to_string(node_id)));
return;
}
if owner != stable_id.owner {
- self.errors.push(format!(
+ self.error(|| format!(
"HirIdValidator: The recorded owner of {} is {} instead of {}",
self.hir_map.node_to_string(node_id),
self.hir_map.def_path(DefId::local(stable_id.owner)).to_string_no_crate(),
if let Some(prev) = self.hir_ids_seen.insert(stable_id.local_id, node_id) {
if prev != node_id {
- self.errors.push(format!(
+ self.error(|| format!(
"HirIdValidator: Same HirId {}/{} assigned for nodes {} and {}",
self.hir_map.def_path(DefId::local(stable_id.owner)).to_string_no_crate(),
stable_id.local_id.as_usize(),
use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace};
-use middle::cstore::CrateStore;
+use middle::cstore::CrateStoreDyn;
use rustc_target::spec::abi::Abi;
use rustc_data_structures::svh::Svh;
+use rustc_data_structures::sync::join;
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
use syntax::source_map::Spanned;
use syntax::ext::base::MacroKind;
use syntax_pos::{Span, DUMMY_SP};
use hir::*;
+use hir::itemlikevisit::ItemLikeVisitor;
use hir::print::Nested;
use util::nodemap::FxHashMap;
+use util::common::time;
use std::io;
use std::result::Result::Err;
&self.forest.krate.attrs
}
+ pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
+ where V: ItemLikeVisitor<'hir>
+ {
+ let node_id = self.as_local_node_id(module).unwrap();
+
+ // Read the module so we'll be re-executed if new items
+ // appear immediately under in the module. If some new item appears
+ // in some nested item in the module, we'll be re-executed due to reads
+ // in the expect_* calls the loops below
+ self.read(node_id);
+
+ let module = &self.forest.krate.modules[&node_id];
+
+ for id in &module.items {
+ visitor.visit_item(self.expect_item(*id));
+ }
+
+ for id in &module.trait_items {
+ visitor.visit_trait_item(self.expect_trait_item(id.node_id));
+ }
+
+ for id in &module.impl_items {
+ visitor.visit_impl_item(self.expect_impl_item(id.node_id));
+ }
+ }
+
/// Retrieve the Node corresponding to `id`, panicking if it cannot
/// be found.
pub fn get(&self, id: NodeId) -> Node<'hir> {
impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
pub fn map_crate<'hir>(sess: &::session::Session,
- cstore: &dyn CrateStore,
- forest: &'hir mut Forest,
+ cstore: &CrateStoreDyn,
+ forest: &'hir Forest,
definitions: &'hir Definitions)
-> Map<'hir> {
- let (map, crate_hash) = {
+ let ((map, crate_hash), hir_to_node_id) = join(|| {
let hcx = ::ich::StableHashingContext::new(sess, &forest.krate, definitions, cstore);
- let mut collector = NodeCollector::root(&forest.krate,
+ let mut collector = NodeCollector::root(sess,
+ &forest.krate,
&forest.dep_graph,
&definitions,
- hcx,
- sess.source_map());
+ hcx);
intravisit::walk_crate(&mut collector, &forest.krate);
let crate_disambiguator = sess.local_crate_disambiguator();
let cmdline_args = sess.opts.dep_tracking_hash();
- collector.finalize_and_compute_crate_hash(crate_disambiguator,
- cstore,
- cmdline_args)
- };
+ collector.finalize_and_compute_crate_hash(
+ crate_disambiguator,
+ cstore,
+ cmdline_args
+ )
+ }, || {
+ // Build the reverse mapping of `node_to_hir_id`.
+ definitions.node_to_hir_id.iter_enumerated()
+ .map(|(node_id, &hir_id)| (hir_id, node_id)).collect()
+ });
if log_enabled!(::log::Level::Debug) {
// This only makes sense for ordered stores; note the
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
}
- // Build the reverse mapping of `node_to_hir_id`.
- let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated()
- .map(|(node_id, &hir_id)| (hir_id, node_id)).collect();
-
let map = Map {
forest,
dep_graph: forest.dep_graph.clone(),
definitions,
};
- hir_id_validator::check_crate(&map);
+ time(sess, "validate hir map", || {
+ hir_id_validator::check_crate(&map);
+ });
map
}
use rustc_data_structures::thin_vec::ThinVec;
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
-use std::collections::BTreeMap;
+use std::collections::{BTreeSet, BTreeMap};
use std::fmt;
/// HIR doesn't commit to a concrete storage type and has its own alias for a vector.
pub rhs_ty: P<Ty>,
}
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub struct ModuleItems {
+ // Use BTreeSets here so items are in the same order as in the
+ // list of all items in Crate
+ pub items: BTreeSet<NodeId>,
+ pub trait_items: BTreeSet<TraitItemId>,
+ pub impl_items: BTreeSet<ImplItemId>,
+}
+
/// The top-level data structure that stores the entire contents of
/// the crate currently being compiled.
///
/// in the crate, you should iterate over this list rather than the keys
/// of bodies.
pub body_ids: Vec<BodyId>,
+
+ /// A list of modules written out in the order in which they
+ /// appear in the crate. This includes the main crate module.
+ pub modules: BTreeMap<NodeId, ModuleItems>,
}
impl Crate {
pub fn provide(providers: &mut Providers<'_>) {
+ check_attr::provide(providers);
providers.describe_def = map::describe_def;
}
fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
match cause.code {
+ ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
+ if ty.is_suggestable() { // don't show type `_`
+ err.span_label(span, format!("this match expression has type `{}`", ty));
+ }
+ }
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
hir::MatchSource::IfLetDesugar { .. } => {
let msg = "`if let` arm with an incompatible type";
}
}
},
+ ObligationCauseCode::IfExpression { then, outer, semicolon } => {
+ err.span_label(then, "expected because of this");
+ outer.map(|sp| err.span_label(sp, "if and else have incompatible types"));
+ if let Some(sp) = semicolon {
+ err.span_suggestion_short_with_applicability(
+ sp,
+ "consider removing this semicolon",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
_ => (),
}
}
}
_ => "match arms have incompatible types",
}),
- IfExpression => Error0308("if and else have incompatible types"),
+ IfExpression { .. } => Error0308("if and else have incompatible types"),
IfExpressionWithNoElse => Error0317("if may be missing an else clause"),
MainFunctionType => Error0580("main function has wrong type"),
StartFunctionType => Error0308("start function has wrong type"),
hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
_ => "match arms have compatible types",
},
- IfExpression => "if and else have compatible types",
+ IfExpression { .. } => "if and else have compatible types",
IfExpressionWithNoElse => "if missing an else returns ()",
MainFunctionType => "`main` function has the correct type",
StartFunctionType => "`start` function has the correct type",
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use smallvec::SmallVec;
use std::fmt;
use std::u32;
use ty::fold::TypeFoldable;
match *constraint {
Constraint::RegSubVar(a_region, b_vid) => {
let b_data = var_values.value_mut(b_vid);
- self.expand_node(a_region, b_vid, b_data)
+ (self.expand_node(a_region, b_vid, b_data), false)
}
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
- VarValue::ErrorValue => false,
+ VarValue::ErrorValue => (false, false),
VarValue::Value(a_region) => {
let b_node = var_values.value_mut(b_vid);
- self.expand_node(a_region, b_vid, b_node)
+ let changed = self.expand_node(a_region, b_vid, b_node);
+ let retain = match *b_node {
+ VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
+ _ => true
+ };
+ (changed, retain)
}
},
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
// These constraints are checked after expansion
// is done, in `collect_errors`.
- false
+ (false, false)
}
}
})
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
let tcx = self.tcx();
+
+ // Equal scopes can show up quite often, if the fixed point
+ // iteration converges slowly, skip them
+ if a == b {
+ return a;
+ }
+
match (a, b) {
(&ty::ReClosureBound(..), _)
| (_, &ty::ReClosureBound(..))
fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
where
- F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool,
+ F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool),
{
+ let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect();
let mut iteration = 0;
let mut changed = true;
while changed {
changed = false;
iteration += 1;
debug!("---- {} Iteration {}{}", "#", tag, iteration);
- for (constraint, origin) in &self.data.constraints {
- let edge_changed = body(constraint, origin);
+ constraints.retain(|(constraint, origin)| {
+ let (edge_changed, retain) = body(constraint, origin);
if edge_changed {
debug!("Updated due to constraint {:?}", constraint);
changed = true;
}
- }
+ retain
+ });
}
debug!("---- {} Complete after {} iteration(s)", tag, iteration);
}
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
-#![feature(transpose_result)]
#![recursion_limit="512"]
declare_lint! {
pub IRREFUTABLE_LET_PATTERNS,
- Deny,
+ Warn,
"detects irrefutable patterns in if-let and while-let statements"
}
use hir::def::Def;
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use hir::intravisit::{self, Visitor, NestedVisitorMap};
+use ty::query::Providers;
+use ty::query::queries;
use middle::privacy::AccessLevels;
use session::{DiagnosticMessageId, Session};
use syntax::symbol::Symbol;
}
}
+pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::check_mod_unstable_api_usage::ensure(tcx, tcx.hir().local_def_id(module));
+ }
+}
+
/// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors.
-pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let mut checker = Checker { tcx };
- tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor());
+fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }.as_deep_visitor());
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ check_mod_unstable_api_usage,
+ ..*providers
+ };
}
/// Check whether an item marked with `deprecated(since="X")` is currently
sysroot.join(&relative_target_lib_path(sysroot, target_triple))
}
-pub fn target_lib_path(target_triple: &str) -> PathBuf {
- let mut p = PathBuf::from(RUST_LIB_DIR);
- p.push(target_triple);
- p.push("lib");
- p
-}
-
pub fn get_or_default_sysroot() -> PathBuf {
// Follow symlinks. If the resolved path is relative, make it absolute.
fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
use util::common::ProfileQueriesMsg;
use rustc_data_structures::base_n;
-use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
+use rustc_data_structures::sync::{
+ self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, Ordering,
+ Ordering::SeqCst,
+};
use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
use errors::emitter::{Emitter, EmitterWriter};
use std::path::PathBuf;
use std::time::Duration;
use std::sync::mpsc;
-use std::sync::atomic::{AtomicUsize, Ordering};
mod code_stats;
pub mod config;
pub mod filesearch;
pub mod search_paths;
+pub struct OptimizationFuel {
+ /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
+ remaining: u64,
+ /// We're rejecting all further optimizations.
+ out_of_fuel: bool,
+}
+
/// Represents the data associated with a compilation
/// session for a single crate.
pub struct Session {
/// If -zfuel=crate=n is specified, Some(crate).
optimization_fuel_crate: Option<String>,
- /// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
- optimization_fuel_limit: LockCell<u64>,
- /// We're rejecting all further optimizations.
- out_of_fuel: LockCell<bool>,
+
+ /// Tracks fuel info if If -zfuel=crate=n is specified
+ optimization_fuel: Lock<OptimizationFuel>,
// The next two are public because the driver needs to read them.
/// If -zprint-fuel=crate, Some(crate).
pub print_fuel_crate: Option<String>,
/// Always set to zero and incremented so that we can print fuel expended by a crate.
- pub print_fuel: LockCell<u64>,
+ pub print_fuel: AtomicU64,
/// Loaded up early on in the initialization of this `Session` to avoid
/// false positives about a job server in our environment.
pub fn next_node_id(&self) -> NodeId {
self.reserve_node_ids(1)
}
+ pub(crate) fn current_node_id_count(&self) -> usize {
+ self.next_node_id.get().as_u32() as usize
+ }
pub fn diagnostic<'a>(&'a self) -> &'a errors::Handler {
&self.parse_sess.span_diagnostic
}
if let Some(ref c) = self.optimization_fuel_crate {
if c == crate_name {
assert_eq!(self.query_threads(), 1);
- let fuel = self.optimization_fuel_limit.get();
- ret = fuel != 0;
- if fuel == 0 && !self.out_of_fuel.get() {
+ let mut fuel = self.optimization_fuel.lock();
+ ret = fuel.remaining != 0;
+ if fuel.remaining == 0 && !fuel.out_of_fuel {
eprintln!("optimization-fuel-exhausted: {}", msg());
- self.out_of_fuel.set(true);
- } else if fuel > 0 {
- self.optimization_fuel_limit.set(fuel - 1);
+ fuel.out_of_fuel = true;
+ } else if fuel.remaining > 0 {
+ fuel.remaining -= 1;
}
}
}
if let Some(ref c) = self.print_fuel_crate {
if c == crate_name {
assert_eq!(self.query_threads(), 1);
- self.print_fuel.set(self.print_fuel.get() + 1);
+ self.print_fuel.fetch_add(1, SeqCst);
}
}
ret
local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
- let optimization_fuel_limit =
- LockCell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
+ let optimization_fuel = Lock::new(OptimizationFuel {
+ remaining: sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0),
+ out_of_fuel: false,
+ });
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
- let print_fuel = LockCell::new(0);
+ let print_fuel = AtomicU64::new(0);
let working_dir = env::current_dir().unwrap_or_else(|e|
p_s.span_diagnostic
},
code_stats: Default::default(),
optimization_fuel_crate,
- optimization_fuel_limit,
+ optimization_fuel,
print_fuel_crate,
print_fuel,
- out_of_fuel: LockCell::new(false),
// 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
match *cause_code {
ObligationCauseCode::ExprAssignable |
ObligationCauseCode::MatchExpressionArm { .. } |
- ObligationCauseCode::IfExpression |
+ ObligationCauseCode::MatchExpressionArmPattern { .. } |
+ ObligationCauseCode::IfExpression { .. } |
ObligationCauseCode::IfExpressionWithNoElse |
ObligationCauseCode::MainFunctionType |
ObligationCauseCode::StartFunctionType |
ObligationCauseCode::IntrinsicType |
ObligationCauseCode::MethodReceiver |
ObligationCauseCode::ReturnNoExpression |
- ObligationCauseCode::MiscObligation => {
- }
+ ObligationCauseCode::MiscObligation => {}
ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type");
}
ExprAssignable,
/// Computing common supertype in the arms of a match expression
- MatchExpressionArm { arm_span: Span,
- source: hir::MatchSource },
+ MatchExpressionArm {
+ arm_span: Span,
+ source: hir::MatchSource,
+ },
+
+ /// Computing common supertype in the pattern guard for the arms of a match expression
+ MatchExpressionArmPattern { span: Span, ty: Ty<'tcx> },
/// Computing common supertype in an if expression
- IfExpression,
+ IfExpression {
+ then: Span,
+ outer: Option<Span>,
+ semicolon: Option<Span>,
+ },
/// Computing common supertype of an if expression with no else counter-part
IfExpressionWithNoElse,
method: &ty::AssociatedItem)
-> Option<MethodViolationCode>
{
+ debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
if self.generics_require_sized_self(method.def_id) {
method: &ty::AssociatedItem)
-> bool
{
+ debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite can't be called.
if self.generics_require_sized_self(method.def_id) {
return false;
fn receiver_for_self_ty(
self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
) -> Ty<'tcx> {
+ debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
let substs = Substs::for_item(self, method_def_id, |param, _| {
if param.index == 0 {
self_ty.into()
}
});
- receiver_ty.subst(self, substs)
+ let result = receiver_ty.subst(self, substs);
+ debug!("receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
+ receiver_ty, self_ty, method_def_id, result);
+ result
}
/// creates the object type for the current trait. For example,
);
let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
- .flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
- .filter(|item| item.kind == ty::AssociatedKind::Type)
+ .flat_map(|super_trait_ref| {
+ self.associated_items(super_trait_ref.def_id())
+ .map(move |item| (super_trait_ref, item))
+ })
+ .filter(|(_, item)| item.kind == ty::AssociatedKind::Type)
.collect::<Vec<_>>();
// existential predicates need to be in a specific order
- associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id));
-
- let projection_predicates = associated_types.into_iter().map(|item| {
+ associated_types.sort_by_cached_key(|(_, item)| self.def_path_hash(item.def_id));
+
+ let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
+ // We *can* get bound lifetimes here in cases like
+ // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
+ //
+ // binder moved to (*)...
+ let super_trait_ref = super_trait_ref.skip_binder();
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
- ty: self.mk_projection(item.def_id, trait_ref.substs),
+ ty: self.mk_projection(item.def_id, super_trait_ref.substs),
item_def_id: item.def_id,
- substs: trait_ref.substs,
+ substs: super_trait_ref.substs,
})
});
);
let object_ty = self.mk_dynamic(
- ty::Binder::dummy(existential_predicates),
+ // (*) ... binder re-introduced here
+ ty::Binder::bind(existential_predicates),
lifetime,
);
arm_span,
source: source,
}),
- super::IfExpression => Some(super::IfExpression),
+ super::MatchExpressionArmPattern { span, ty } => {
+ tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
+ }
+ super::IfExpression { then, outer, semicolon } => Some(super::IfExpression {
+ then,
+ outer,
+ semicolon,
+ }),
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
super::MainFunctionType => Some(super::MainFunctionType),
super::StartFunctionType => Some(super::StartFunctionType),
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 local as *const _ as usize == global as *const _ as usize {
+ if ptr::eq(local, global) {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
&ty_struct);
/// All the existential types that are restricted to concrete types
/// by this function
pub concrete_existential_types: FxHashMap<DefId, Ty<'tcx>>,
+
+ /// Given the closure ID this map provides the list of UpvarIDs used by it.
+ /// The upvarID contains the HIR node ID and it also contains the full path
+ /// leading to the member of the struct or tuple that is used instead of the
+ /// entire variable.
+ pub upvar_list: ty::UpvarListMap,
}
impl<'tcx> TypeckTables<'tcx> {
tainted_by_errors: false,
free_region_map: Default::default(),
concrete_existential_types: Default::default(),
+ upvar_list: Default::default(),
}
}
tainted_by_errors,
ref free_region_map,
ref concrete_existential_types,
+ ref upvar_list,
+
} = *self;
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
tainted_by_errors.hash_stable(hcx, hasher);
free_region_map.hash_stable(hcx, hasher);
concrete_existential_types.hash_stable(hcx, hasher);
+ upvar_list.hash_stable(hcx, hasher);
})
}
}
/// Returns true if self is the same as self.global_tcx().
fn is_global(self) -> bool {
- let local = self.interners as *const _;
- let global = &self.global_interners as *const _;
- local as usize == global as usize
+ ptr::eq(self.interners, &self.global_interners)
}
/// Create a type context and call the closure with a `TyCtxt` reference
sync::assert_send_val(&gcx);
- tls::enter_global(gcx, f)
+ let r = tls::enter_global(gcx, f);
+
+ gcx.queries.record_computed_queries(s);
+
+ r
}
pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
let new_icx = ty::tls::ImplicitCtxt {
tcx,
query: icx.query.clone(),
+ diagnostics: icx.diagnostics,
layout_depth: icx.layout_depth,
- task: icx.task,
+ task_deps: icx.task_deps,
};
ty::tls::enter_context(&new_icx, |_| {
f(tcx)
use std::fmt;
use std::mem;
use std::marker::PhantomData;
+ use std::ptr;
use syntax_pos;
use ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
use rustc_data_structures::OnDrop;
use rustc_data_structures::sync::{self, Lrc, Lock};
- use dep_graph::OpenTask;
+ use rustc_data_structures::thin_vec::ThinVec;
+ use dep_graph::TaskDeps;
#[cfg(not(parallel_queries))]
use std::cell::Cell;
/// by `enter_local` with a new local interner
pub tcx: TyCtxt<'tcx, 'gcx, 'tcx>,
- /// The current query job, if any. This is updated by start_job in
+ /// The current query job, if any. This is updated by JobOwner::start in
/// ty::query::plumbing when executing a query
pub query: Option<Lrc<query::QueryJob<'gcx>>>,
+ /// Where to store diagnostics for the current query job, if any.
+ /// This is updated by JobOwner::start in ty::query::plumbing when executing a query
+ pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
+
/// Used to prevent layout from recursing too deeply.
pub layout_depth: usize,
/// The current dep graph task. This is used to add dependencies to queries
/// when executing them
- pub task: &'a OpenTask,
+ pub task_deps: Option<&'a Lock<TaskDeps>>,
}
/// Sets Rayon's thread local variable which is preserved for Rayon jobs
fn track_diagnostic(diagnostic: &Diagnostic) {
with_context_opt(|icx| {
if let Some(icx) = icx {
- if let Some(ref query) = icx.query {
- query.diagnostics.lock().push(diagnostic.clone());
+ if let Some(ref diagnostics) = icx.diagnostics {
+ let mut diagnostics = diagnostics.lock();
+ diagnostics.extend(Some(diagnostic.clone()));
}
}
})
let icx = ImplicitCtxt {
tcx,
query: None,
+ diagnostics: None,
layout_depth: 0,
- task: &OpenTask::Ignore,
+ task_deps: None,
};
enter_context(&icx, |_| {
f(tcx)
};
let icx = ImplicitCtxt {
query: None,
+ diagnostics: None,
tcx,
layout_depth: 0,
- task: &OpenTask::Ignore,
+ task_deps: None,
};
enter_context(&icx, |_| f(tcx))
}
{
with_context(|context| {
unsafe {
- let gcx = tcx.gcx as *const _ as usize;
- assert!(context.tcx.gcx as *const _ as usize == gcx);
+ assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
{
with_context(|context| {
unsafe {
- let gcx = tcx.gcx as *const _ as usize;
- let interners = tcx.interners as *const _ as usize;
- assert!(context.tcx.gcx as *const _ as usize == gcx);
- assert!(context.tcx.interners as *const _ as usize == 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)
}
}
pub fn provide(providers: &mut ty::query::Providers<'_>) {
- // FIXME(#44234): almost all of these queries have no sub-queries and
- // therefore no actual inputs, they're just reading tables calculated in
- // resolve! Does this work? Unsure! That's what the issue is about.
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();
providers.crate_name = |tcx, id| {
return Ok(None);
}
}
- if let FieldPlacement::Array { .. } = layout.fields {
+ if let FieldPlacement::Array { count: original_64_bit_count, .. } = layout.fields {
+ // rust-lang/rust#57038: avoid ICE within FieldPlacement::count when count too big
+ if original_64_bit_count > usize::max_value() as u64 {
+ return Err(LayoutError::SizeOverflow(layout.ty));
+ }
if layout.fields.count() > 0 {
return self.find_niche(layout.field(self, 0)?);
} else {
pub region: ty::Region<'tcx>,
}
+pub type UpvarListMap = FxHashMap<DefId, Vec<UpvarId>>;
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
#[derive(Copy, Clone)]
format!("processing `{}`", tcx.item_path_str(def_id)).into()
} else {
let name = unsafe { ::std::intrinsics::type_name::<M>() };
- format!("processing `{}` applied to `{:?}`", name, def_id).into()
+ format!("processing {:?} with query `{}`", def_id, name).into()
}
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_attrs<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking attributes in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_unstable_api_usage<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking for unstable API usage in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_loops<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking loops in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_item_types<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking item types in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("collecting item types in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> {
fn describe(
_tcx: TyCtxt<'_, '_, '_>,
config::QueryDescription,
};
use ty::context::TyCtxt;
-use errors::Diagnostic;
use std::process;
use std::{fmt, ptr};
/// The parent query job which created this job and is implicitly waiting on it.
pub parent: Option<Lrc<QueryJob<'tcx>>>,
- /// Diagnostic messages which are emitted while the query executes
- pub diagnostics: Lock<Vec<Diagnostic>>,
-
/// The latch which is used to wait on this job
#[cfg(parallel_queries)]
latch: QueryLatch<'tcx>,
/// Creates a new query job
pub fn new(info: QueryInfo<'tcx>, parent: Option<Lrc<QueryJob<'tcx>>>) -> Self {
QueryJob {
- diagnostics: Lock::new(Vec::new()),
info,
parent,
#[cfg(parallel_queries)]
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
use util::common::{ErrorReported};
use util::profiling::ProfileCategory::*;
+use session::Session;
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::indexed_vec::IndexVec;
},
Other {
+ /// Checks the attributes in the module
+ [] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
+
+ [] fn check_mod_unstable_api_usage: CheckModUnstableApiUsage(DefId) -> (),
+
+ /// Checks the loops in the module
+ [] fn check_mod_loops: CheckModLoops(DefId) -> (),
+
+ [] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
+
+ [] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
+
/// Caches CoerceUnsized kinds for impls on custom types.
[] fn coerce_unsized_info: CoerceUnsizedInfo(DefId)
-> ty::adjustment::CoerceUnsizedInfo,
use mir::{self, interpret};
use mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::thin_vec::ThinVec;
use rustc_data_structures::sync::{Lrc, Lock, HashMapExt, Once};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque,
/// Store a diagnostic emitted during the current compilation session.
/// Anything stored like this will be available via `load_diagnostics` in
/// the next compilation session.
+ #[inline(never)]
+ #[cold]
pub fn store_diagnostics(&self,
dep_node_index: DepNodeIndex,
- diagnostics: Vec<Diagnostic>) {
+ diagnostics: ThinVec<Diagnostic>) {
let mut current_diagnostics = self.current_diagnostics.borrow_mut();
- let prev = current_diagnostics.insert(dep_node_index, diagnostics);
+ let prev = current_diagnostics.insert(dep_node_index, diagnostics.into());
debug_assert!(prev.is_none());
}
/// Since many anonymous queries can share the same `DepNode`, we aggregate
/// them -- as opposed to regular queries where we assume that there is a
/// 1:1 relationship between query-key and `DepNode`.
+ #[inline(never)]
+ #[cold]
pub fn store_diagnostics_for_anon_node(&self,
dep_node_index: DepNodeIndex,
- mut diagnostics: Vec<Diagnostic>) {
+ diagnostics: ThinVec<Diagnostic>) {
let mut current_diagnostics = self.current_diagnostics.borrow_mut();
- let x = current_diagnostics.entry(dep_node_index).or_insert_with(|| {
- mem::replace(&mut diagnostics, Vec::new())
- });
+ let x = current_diagnostics.entry(dep_node_index).or_insert(Vec::new());
- x.extend(diagnostics.into_iter());
+ x.extend(Into::<Vec<_>>::into(diagnostics));
}
fn load_indexed<'tcx, T>(&self,
use rustc_data_structures::fx::{FxHashMap};
use rustc_data_structures::sync::{Lrc, Lock};
+use rustc_data_structures::thin_vec::ThinVec;
use std::mem;
use std::ptr;
use std::collections::hash_map::Entry;
let mut lock = cache.borrow_mut();
if let Some(value) = lock.results.get(key) {
profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
- tcx.sess.profiler(|p| {
- p.record_query(Q::CATEGORY);
- p.record_query_hit(Q::CATEGORY);
- });
-
+ tcx.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
let result = Ok((value.value.clone(), value.index));
#[cfg(debug_assertions)]
{
/// Executes a job by changing the ImplicitCtxt to point to the
/// new query job while it executes. It returns the diagnostics
/// captured during execution and the actual result.
+ #[inline(always)]
pub(super) fn start<'lcx, F, R>(
&self,
tcx: TyCtxt<'_, 'tcx, 'lcx>,
+ diagnostics: Option<&Lock<ThinVec<Diagnostic>>>,
compute: F)
- -> (R, Vec<Diagnostic>)
+ -> R
where
F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R
{
// The TyCtxt stored in TLS has the same global interner lifetime
// as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes
// when accessing the ImplicitCtxt
- let r = tls::with_related_context(tcx, move |current_icx| {
+ tls::with_related_context(tcx, move |current_icx| {
// Update the ImplicitCtxt to point to our new query job
let new_icx = tls::ImplicitCtxt {
tcx: tcx.global_tcx(),
query: Some(self.job.clone()),
+ diagnostics,
layout_depth: current_icx.layout_depth,
- task: current_icx.task,
+ task_deps: current_icx.task_deps,
};
// Use the ImplicitCtxt while we execute the query
tls::enter_context(&new_icx, |_| {
compute(tcx)
})
- });
+ })
+ }
- // Extract the diagnostic from the job
- let diagnostics = mem::replace(&mut *self.job.diagnostics.lock(), Vec::new());
+}
- (r, diagnostics)
- }
+#[inline(always)]
+fn with_diagnostics<F, R>(f: F) -> (R, ThinVec<Diagnostic>)
+where
+ F: FnOnce(Option<&Lock<ThinVec<Diagnostic>>>) -> R
+{
+ let diagnostics = Lock::new(ThinVec::new());
+ let result = f(Some(&diagnostics));
+ (result, diagnostics.into_inner())
}
impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
)
);
- self.sess.profiler(|p| p.record_query(Q::CATEGORY));
-
let job = match JobOwner::try_get(self, span, &key) {
TryGetJob::NotYetStarted(job) => job,
TryGetJob::JobCompleted(result) => {
return result.map(|(v, index)| {
- self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
self.dep_graph.read_index(index);
v
})
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
- let res = job.start(self, |tcx| {
- tcx.dep_graph.with_anon_task(dep_node.kind, || {
- Q::compute(tcx.global_tcx(), key)
+ let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
+ job.start(self, diagnostics, |tcx| {
+ tcx.dep_graph.with_anon_task(dep_node.kind, || {
+ Q::compute(tcx.global_tcx(), key)
+ })
})
});
self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
- let ((result, dep_node_index), diagnostics) = res;
self.dep_graph.read_index(dep_node_index);
- self.queries.on_disk_cache
- .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
+ if unlikely!(!diagnostics.is_empty()) {
+ self.queries.on_disk_cache
+ .store_diagnostics_for_anon_node(dep_node_index, diagnostics);
+ }
job.complete(&result, dep_node_index);
if !dep_node.kind.is_input() {
if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
- profq_msg!(self, ProfileQueriesMsg::CacheHit);
- self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
-
return self.load_from_disk_and_cache_in_memory::<Q>(key,
job,
dep_node_index,
};
let result = if let Some(result) = result {
+ profq_msg!(self, ProfileQueriesMsg::CacheHit);
+ self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
+
result
} else {
// We could not load a result from the on-disk cache, so
// recompute.
+ self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
+
// The diagnostics for this query have already been
// promoted to the current session during
// try_mark_green(), so we can ignore them here.
- let (result, _) = job.start(self, |tcx| {
+ let result = job.start(self, None, |tcx| {
// The dep-graph for this computation is already in
// place
tcx.dep_graph.with_ignore(|| {
Q::compute(tcx, key)
})
});
+
+ self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
result
};
for {:?}", dep_node);
}
+ #[inline(always)]
fn force_query_with_job<Q: QueryDescription<'gcx>>(
self,
key: Q::Key,
key, dep_node);
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
- self.sess.profiler(|p| {
- p.start_activity(Q::CATEGORY);
- p.record_query(Q::CATEGORY);
- });
-
- let res = job.start(self, |tcx| {
- if dep_node.kind.is_eval_always() {
- tcx.dep_graph.with_eval_always_task(dep_node,
- tcx,
- key,
- Q::compute)
- } else {
- tcx.dep_graph.with_task(dep_node,
- tcx,
- key,
- Q::compute)
- }
+ self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
+
+ let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
+ job.start(self, diagnostics, |tcx| {
+ if dep_node.kind.is_eval_always() {
+ tcx.dep_graph.with_eval_always_task(dep_node,
+ tcx,
+ key,
+ Q::compute)
+ } else {
+ tcx.dep_graph.with_task(dep_node,
+ tcx,
+ key,
+ Q::compute)
+ }
+ })
});
self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
- let ((result, dep_node_index), diagnostics) = res;
-
if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) {
self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
}
if dep_node.kind != ::dep_graph::DepKind::Null {
- self.queries.on_disk_cache
- .store_diagnostics(dep_node_index, diagnostics);
+ if unlikely!(!diagnostics.is_empty()) {
+ self.queries.on_disk_cache
+ .store_diagnostics(dep_node_index, diagnostics);
+ }
}
job.complete(&result, dep_node_index);
// this introduces should be negligible as we'll immediately hit the
// in-memory cache, or another query down the line will.
- self.sess.profiler(|p| {
- p.start_activity(Q::CATEGORY);
- p.record_query(Q::CATEGORY);
- });
-
let _ = self.get_query::<Q>(DUMMY_SP, key);
-
- self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
+ } else {
+ profq_msg!(self, ProfileQueriesMsg::CacheHit);
+ self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
}
}
}
}
+ pub fn record_computed_queries(&self, sess: &Session) {
+ sess.profiler(|p| {
+ $(
+ p.record_computed_queries(
+ <queries::$name<'_> as QueryConfig<'_>>::CATEGORY,
+ self.$name.lock().results.len()
+ );
+ )*
+ });
+ }
+
#[cfg(parallel_queries)]
pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
let mut jobs = Vec::new();
DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
+ DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
+ DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
+ DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
+ DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); }
+ DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); }
use std::fs;
use std::io::{self, StderrLock, Write};
-use std::time::{Duration, Instant};
+use std::time::Instant;
macro_rules! define_categories {
($($name:ident,)*) => {
let total_time = ($(self.times.$name + )* 0) as f32;
$(
- let (hits, total) = self.query_counts.$name;
+ let (hits, computed) = self.query_counts.$name;
+ let total = hits + computed;
let (hits, total) = if total > 0 {
(format!("{:.2}",
(((hits as f32) / (total as f32)) * 100.0)), total.to_string())
let mut json = String::from("[");
$(
- let (hits, total) = self.query_counts.$name;
+ let (hits, computed) = self.query_counts.$name;
+ let total = hits + computed;
//normalize hits to 0%
let hit_percent =
self.timer_stack.push(category);
}
- pub fn record_query(&mut self, category: ProfileCategory) {
- let (hits, total) = *self.data.query_counts.get(category);
- self.data.query_counts.set(category, (hits, total + 1));
+ pub fn record_computed_queries(&mut self, category: ProfileCategory, count: usize) {
+ let (hits, computed) = *self.data.query_counts.get(category);
+ self.data.query_counts.set(category, (hits, computed + count as u64));
}
pub fn record_query_hit(&mut self, category: ProfileCategory) {
- let (hits, total) = *self.data.query_counts.get(category);
- self.data.query_counts.set(category, (hits + 1, total));
+ let (hits, computed) = *self.data.query_counts.get(category);
+ self.data.query_counts.set(category, (hits + 1, computed));
}
pub fn end_activity(&mut self, category: ProfileCategory) {
}
fn stop_timer(&mut self) -> u64 {
- let elapsed = if cfg!(windows) {
- // On Windows, timers don't always appear to be monotonic (see #51648)
- // which can lead to panics when calculating elapsed time.
- // Work around this by testing to see if the current time is less than
- // our recorded time, and if it is, just returning 0.
- let now = Instant::now();
- if self.current_timer >= now {
- Duration::new(0, 0)
- } else {
- self.current_timer.elapsed()
- }
- } else {
- self.current_timer.elapsed()
- };
+ let elapsed = self.current_timer.elapsed();
self.current_timer = Instant::now();
if new_loan.loan_path.has_fork(&old_loan.loan_path) && common.is_some() {
let nl = self.bccx.loan_path_to_string(&common.unwrap());
let ol = nl.clone();
- let new_loan_msg = format!(" (via `{}`)",
- self.bccx.loan_path_to_string(
- &new_loan.loan_path));
- let old_loan_msg = format!(" (via `{}`)",
- self.bccx.loan_path_to_string(
- &old_loan.loan_path));
+ let new_loan_msg = self.bccx.loan_path_to_string(&new_loan.loan_path);
+ let old_loan_msg = self.bccx.loan_path_to_string(&old_loan.loan_path);
(nl, ol, new_loan_msg, old_loan_msg)
} else {
(self.bccx.loan_path_to_string(&new_loan.loan_path),
impl PartialEq for llvm::Metadata {
fn eq(&self, other: &Self) -> bool {
- self as *const _ == other as *const _
+ ptr::eq(self, other)
}
}
use std::fmt;
use std::cell::RefCell;
+use std::ptr;
use libc::c_uint;
impl PartialEq for Type {
fn eq(&self, other: &Self) -> bool {
- self as *const _ == other as *const _
+ ptr::eq(self, other)
}
}
use std::fmt;
use std::hash::{Hash, Hasher};
+use std::ptr;
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
- self as *const _ == other as *const _
+ ptr::eq(self, other)
}
}
}
LinkerFlavor::Lld(LldFlavor::Wasm) => {
- Box::new(WasmLd {
- cmd,
- sess,
- info: self
- }) as Box<dyn Linker>
+ Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
}
}
}
info: &'a LinkerInfo,
}
+impl<'a> WasmLd<'a> {
+ fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
+ // There have been reports in the wild (rustwasm/wasm-bindgen#119) of
+ // using threads causing weird hangs and bugs. Disable it entirely as
+ // this isn't yet the bottleneck of compilation at all anyway.
+ cmd.arg("--no-threads");
+
+ // By default LLD only gives us one page of stack (64k) which is a
+ // little small. Default to a larger stack closer to other PC platforms
+ // (1MB) and users can always inject their own link-args to override this.
+ cmd.arg("-z").arg("stack-size=1048576");
+
+ // By default LLD's memory layout is:
+ //
+ // 1. First, a blank page
+ // 2. Next, all static data
+ // 3. Finally, the main stack (which grows down)
+ //
+ // This has the unfortunate consequence that on stack overflows you
+ // corrupt static data and can cause some exceedingly weird bugs. To
+ // help detect this a little sooner we instead request that the stack is
+ // placed before static data.
+ //
+ // This means that we'll generate slightly larger binaries as references
+ // to static data will take more bytes in the ULEB128 encoding, but
+ // stack overflow will be guaranteed to trap as it underflows instead of
+ // corrupting static data.
+ cmd.arg("--stack-first");
+
+ // FIXME we probably shouldn't pass this but instead pass an explicit
+ // whitelist of symbols we'll allow to be undefined. Unfortunately
+ // though we can't handle symbols like `log10` that LLVM injects at a
+ // super late date without actually parsing object files. For now let's
+ // stick to this and hopefully fix it before stabilization happens.
+ cmd.arg("--allow-undefined");
+
+ // For now we just never have an entry symbol
+ cmd.arg("--no-entry");
+
+ // Make the default table accessible
+ cmd.arg("--export-table");
+
+ // Rust code should never have warnings, and warnings are often
+ // indicative of bugs, let's prevent them.
+ cmd.arg("--fatal-warnings");
+
+ // The symbol visibility story is a bit in flux right now with LLD.
+ // It's... not entirely clear to me what's going on, but this looks to
+ // make everything work when `export_symbols` isn't otherwise called for
+ // things like executables.
+ cmd.arg("--export-dynamic");
+
+ // LLD only implements C++-like demangling, which doesn't match our own
+ // mangling scheme. Tell LLD to not demangle anything and leave it up to
+ // us to demangle these symbols later.
+ cmd.arg("--no-demangle");
+
+ WasmLd { cmd, sess, info }
+ }
+}
+
impl<'a> Linker for WasmLd<'a> {
fn link_dylib(&mut self, lib: &str) {
self.cmd.arg("-l").arg(lib);
}
fn finalize(&mut self) -> Command {
- // There have been reports in the wild (rustwasm/wasm-bindgen#119) of
- // using threads causing weird hangs and bugs. Disable it entirely as
- // this isn't yet the bottleneck of compilation at all anyway.
- self.cmd.arg("--no-threads");
-
- // By default LLD only gives us one page of stack (64k) which is a
- // little small. Default to a larger stack closer to other PC platforms
- // (1MB) and users can always inject their own link-args to override this.
- self.cmd.arg("-z").arg("stack-size=1048576");
-
- // By default LLD's memory layout is:
- //
- // 1. First, a blank page
- // 2. Next, all static data
- // 3. Finally, the main stack (which grows down)
- //
- // This has the unfortunate consequence that on stack overflows you
- // corrupt static data and can cause some exceedingly weird bugs. To
- // help detect this a little sooner we instead request that the stack is
- // placed before static data.
- //
- // This means that we'll generate slightly larger binaries as references
- // to static data will take more bytes in the ULEB128 encoding, but
- // stack overflow will be guaranteed to trap as it underflows instead of
- // corrupting static data.
- self.cmd.arg("--stack-first");
-
- // FIXME we probably shouldn't pass this but instead pass an explicit
- // whitelist of symbols we'll allow to be undefined. Unfortunately
- // though we can't handle symbols like `log10` that LLVM injects at a
- // super late date without actually parsing object files. For now let's
- // stick to this and hopefully fix it before stabilization happens.
- self.cmd.arg("--allow-undefined");
-
- // For now we just never have an entry symbol
- self.cmd.arg("--no-entry");
-
- // Make the default table accessible
- self.cmd.arg("--export-table");
-
- // Rust code should never have warnings, and warnings are often
- // indicative of bugs, let's prevent them.
- self.cmd.arg("--fatal-warnings");
-
- // The symbol visibility story is a bit in flux right now with LLD.
- // It's... not entirely clear to me what's going on, but this looks to
- // make everything work when `export_symbols` isn't otherwise called for
- // things like executables.
- self.cmd.arg("--export-dynamic");
-
- // LLD only implements C++-like demangling, which doesn't match our own
- // mangling scheme. Tell LLD to not demangle anything and leave it up to
- // us to demangle these symbols later.
- self.cmd.arg("--no-demangle");
-
::std::mem::replace(&mut self.cmd, Command::new(""))
}
#![feature(hash_raw_entry)]
#![feature(stmt_expr_attributes)]
#![feature(core_intrinsics)]
+#![feature(integer_atomics)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(test, feature(test))]
//! It internally uses `parking_lot::RwLock` if cfg!(parallel_queries) is true,
//! `RefCell` otherwise.
//!
-//! `LockCell` is a thread safe version of `Cell`, with `set` and `get` operations.
-//! It can never deadlock. It uses `Cell` when
-//! cfg!(parallel_queries) is false, otherwise it is a `Lock`.
-//!
//! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false.
//!
//! `MTRef` is a immutable reference if cfg!(parallel_queries), and an mutable reference otherwise.
use std::collections::HashMap;
use std::hash::{Hash, BuildHasher};
-use std::cmp::Ordering;
use std::marker::PhantomData;
-use std::fmt::Debug;
-use std::fmt::Formatter;
-use std::fmt;
use std::ops::{Deref, DerefMut};
use owning_ref::{Erased, OwningRef};
f(&SerialScope)
}
+pub use std::sync::atomic::Ordering::SeqCst;
+pub use std::sync::atomic::Ordering;
+
cfg_if! {
if #[cfg(not(parallel_queries))] {
pub auto trait Send {}
}
}
+ use std::ops::Add;
+
+ #[derive(Debug)]
+ pub struct Atomic<T: Copy>(Cell<T>);
+
+ impl<T: Copy> Atomic<T> {
+ pub fn new(v: T) -> Self {
+ Atomic(Cell::new(v))
+ }
+ }
+
+ impl<T: Copy + PartialEq> Atomic<T> {
+ pub fn into_inner(self) -> T {
+ self.0.into_inner()
+ }
+
+ pub fn load(&self, _: Ordering) -> T {
+ self.0.get()
+ }
+
+ pub fn store(&self, val: T, _: Ordering) {
+ self.0.set(val)
+ }
+
+ pub fn swap(&self, val: T, _: Ordering) -> T {
+ self.0.replace(val)
+ }
+
+ pub fn compare_exchange(&self,
+ current: T,
+ new: T,
+ _: Ordering,
+ _: Ordering)
+ -> Result<T, T> {
+ let read = self.0.get();
+ if read == current {
+ self.0.set(new);
+ Ok(read)
+ } else {
+ Err(read)
+ }
+ }
+ }
+
+ impl<T: Add<Output=T> + Copy> Atomic<T> {
+ pub fn fetch_add(&self, val: T, _: Ordering) -> T {
+ let old = self.0.get();
+ self.0.set(old + val);
+ old
+ }
+ }
+
+ pub type AtomicUsize = Atomic<usize>;
+ pub type AtomicBool = Atomic<bool>;
+ pub type AtomicU64 = Atomic<u64>;
+
pub use self::serial_join as join;
pub use self::serial_scope as scope;
MTLock(self.0.clone())
}
}
-
- pub struct LockCell<T>(Cell<T>);
-
- impl<T> LockCell<T> {
- #[inline(always)]
- pub fn new(inner: T) -> Self {
- LockCell(Cell::new(inner))
- }
-
- #[inline(always)]
- pub fn into_inner(self) -> T {
- self.0.into_inner()
- }
-
- #[inline(always)]
- pub fn set(&self, new_inner: T) {
- self.0.set(new_inner);
- }
-
- #[inline(always)]
- pub fn get(&self) -> T where T: Copy {
- self.0.get()
- }
-
- #[inline(always)]
- pub fn set_mut(&mut self, new_inner: T) {
- self.0.set(new_inner);
- }
-
- #[inline(always)]
- pub fn get_mut(&mut self) -> T where T: Copy {
- self.0.get()
- }
- }
-
- impl<T> LockCell<Option<T>> {
- #[inline(always)]
- pub fn take(&self) -> Option<T> {
- unsafe { (*self.0.as_ptr()).take() }
- }
- }
} else {
pub use std::marker::Send as Send;
pub use std::marker::Sync as Sync;
pub use parking_lot::MutexGuard as LockGuard;
pub use parking_lot::MappedMutexGuard as MappedLockGuard;
+ pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64};
+
pub use std::sync::Arc as Lrc;
pub use std::sync::Weak as Weak;
v.erase_send_sync_owner()
}}
}
-
- pub struct LockCell<T>(Lock<T>);
-
- impl<T> LockCell<T> {
- #[inline(always)]
- pub fn new(inner: T) -> Self {
- LockCell(Lock::new(inner))
- }
-
- #[inline(always)]
- pub fn into_inner(self) -> T {
- self.0.into_inner()
- }
-
- #[inline(always)]
- pub fn set(&self, new_inner: T) {
- *self.0.lock() = new_inner;
- }
-
- #[inline(always)]
- pub fn get(&self) -> T where T: Copy {
- *self.0.lock()
- }
-
- #[inline(always)]
- pub fn set_mut(&mut self, new_inner: T) {
- *self.0.get_mut() = new_inner;
- }
-
- #[inline(always)]
- pub fn get_mut(&mut self) -> T where T: Copy {
- *self.0.get_mut()
- }
- }
-
- impl<T> LockCell<Option<T>> {
- #[inline(always)]
- pub fn take(&self) -> Option<T> {
- self.0.lock().take()
- }
- }
}
}
pub fn assert_sync<T: ?Sized + Sync>() {}
+pub fn assert_send<T: ?Sized + Send>() {}
pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
}
}
-impl<T: Copy + Debug> Debug for LockCell<T> {
- fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.debug_struct("LockCell")
- .field("value", &self.get())
- .finish()
- }
-}
-
-impl<T:Default> Default for LockCell<T> {
- /// Creates a `LockCell<T>`, with the `Default` value for T.
- #[inline]
- fn default() -> LockCell<T> {
- LockCell::new(Default::default())
- }
-}
-
-impl<T:PartialEq + Copy> PartialEq for LockCell<T> {
- #[inline]
- fn eq(&self, other: &LockCell<T>) -> bool {
- self.get() == other.get()
- }
-}
-
-impl<T:Eq + Copy> Eq for LockCell<T> {}
-
-impl<T:PartialOrd + Copy> PartialOrd for LockCell<T> {
- #[inline]
- fn partial_cmp(&self, other: &LockCell<T>) -> Option<Ordering> {
- self.get().partial_cmp(&other.get())
- }
-
- #[inline]
- fn lt(&self, other: &LockCell<T>) -> bool {
- self.get() < other.get()
- }
-
- #[inline]
- fn le(&self, other: &LockCell<T>) -> bool {
- self.get() <= other.get()
- }
-
- #[inline]
- fn gt(&self, other: &LockCell<T>) -> bool {
- self.get() > other.get()
- }
-
- #[inline]
- fn ge(&self, other: &LockCell<T>) -> bool {
- self.get() >= other.get()
- }
-}
-
-impl<T:Ord + Copy> Ord for LockCell<T> {
- #[inline]
- fn cmp(&self, other: &LockCell<T>) -> Ordering {
- self.get().cmp(&other.get())
- }
-}
-
#[derive(Debug)]
pub struct Lock<T>(InnerLock<T>);
/// Allows overriding default rustc query providers,
/// after `default_provide` has installed them.
- pub provide: Box<dyn Fn(&mut ty::query::Providers) + 'a>,
+ pub provide: Box<dyn Fn(&mut ty::query::Providers) + 'a + sync::Send>,
/// Same as `provide`, but only for non-local crates,
/// applied after `default_provide_extern`.
- pub provide_extern: Box<dyn Fn(&mut ty::query::Providers) + 'a>,
+ pub provide_extern: Box<dyn Fn(&mut ty::query::Providers) + 'a + sync::Send>,
}
impl<'a> CompileController<'a> {
pub fn basic() -> CompileController<'a> {
+ sync::assert_send::<Self>();
CompileController {
after_parse: PhaseController::basic(),
after_expand: PhaseController::basic(),
// If true then the compiler will try to run the callback even if the phase
// ends with an error. Note that this is not always possible.
pub run_callback_on_error: bool,
- pub callback: Box<dyn Fn(&mut CompileState) + 'a>,
+ pub callback: Box<dyn Fn(&mut CompileState) + 'a + sync::Send>,
}
impl<'a> PhaseController<'a> {
typeck::provide(providers);
ty::provide(providers);
traits::provide(providers);
+ stability::provide(providers);
reachable::provide(providers);
rustc_passes::provide(providers);
rustc_traits::provide(providers);
sess.proc_macro_decls_static
.set(proc_macro_decls::find(&hir_map));
- time(sess, "loop checking", || loops::check_crate(sess, &hir_map));
-
let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
|tcx| {
// Do some initialization of the DepGraph that can only be done with the
// tcx available.
- rustc_incremental::dep_graph_tcx_init(tcx);
+ time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
+
+ time(sess, "loop checking", || loops::check_crate(tcx));
time(sess, "attribute checking", || {
hir::check_attr::check_crate(tcx)
#![feature(slice_sort_by_cached_key)]
#![feature(set_stdio)]
#![feature(no_debug)]
+#![feature(integer_atomics)]
#![recursion_limit="256"]
use rustc_resolve as resolve;
use rustc_save_analysis as save;
use rustc_save_analysis::DumpHandler;
-use rustc_data_structures::sync::{self, Lrc};
+use rustc_data_structures::sync::{self, Lrc, Ordering::SeqCst};
use rustc_data_structures::OnDrop;
use rustc::session::{self, config, Session, build_session, CompileResult};
use rustc::session::CompileIncomplete;
}
let target = session::config::host_triple();
- // get target libdir path based on executable binary path
- let sysroot = filesearch::get_or_default_sysroot();
- let mut libdir_candidates = vec![filesearch::make_target_lib_path(&sysroot, &target)];
+ let mut sysroot_candidates = vec![filesearch::get_or_default_sysroot()];
let path = current_dll_path()
.and_then(|s| s.canonicalize().ok());
if let Some(dll) = path {
- // use `parent` once to chop off the file name
- if let Some(path) = dll.parent() {
+ // use `parent` twice to chop off the file name and then also the
+ // directory containing the dll which should be either `lib` or `bin`.
+ if let Some(path) = dll.parent().and_then(|p| p.parent()) {
// The original `path` pointed at the `rustc_driver` crate's dll.
// Now that dll should only be in one of two locations. The first is
- // in the compiler's libdir, for example `$sysroot/$libdir/*.dll`. The
+ // in the compiler's libdir, for example `$sysroot/lib/*.dll`. The
// other is the target's libdir, for example
- // `$sysroot/$libdir/rustlib/$target/lib/*.dll`.
+ // `$sysroot/lib/rustlib/$target/lib/*.dll`.
//
// We don't know which, so let's assume that if our `path` above
- // doesn't end in `$target` we *could* be in the main libdir, and always
- // assume that we may be in the target libdir.
- libdir_candidates.push(path.to_owned());
-
- if !path.parent().map_or(false, |p| p.ends_with(target)) {
- libdir_candidates.push(path.join(filesearch::target_lib_path(target)));
+ // ends in `$target` we *could* be in the target libdir, and always
+ // assume that we may be in the main libdir.
+ sysroot_candidates.push(path.to_owned());
+
+ if path.ends_with(target) {
+ sysroot_candidates.extend(path.parent() // chop off `$target`
+ .and_then(|p| p.parent()) // chop off `rustlib`
+ .and_then(|p| p.parent()) // chop off `lib`
+ .map(|s| s.to_owned()));
}
}
}
- let sysroot = libdir_candidates.iter()
- .map(|libdir| {
- debug!("Trying target libdir: {}", libdir.display());
- libdir.with_file_name(
+ let sysroot = sysroot_candidates.iter()
+ .map(|sysroot| {
+ let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
+ sysroot.join(libdir).with_file_name(
option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends"))
})
.filter(|f| {
})
.next();
let sysroot = sysroot.unwrap_or_else(|| {
- let candidates = libdir_candidates.iter()
+ let candidates = sysroot_candidates.iter()
.map(|p| p.display().to_string())
.collect::<Vec<_>>()
.join("\n* ");
let err = format!("failed to find a `codegen-backends` folder \
- in the libdir candidates:\n* {}", candidates);
+ in the sysroot candidates:\n* {}", candidates);
early_error(ErrorOutputType::default(), &err);
});
info!("probing {} for a codegen backend", sysroot.display());
let sess = state.session;
eprintln!("Fuel used by {}: {}",
sess.print_fuel_crate.as_ref().unwrap(),
- sess.print_fuel.get());
+ sess.print_fuel.load(SeqCst));
}
}
control
use emitter::{Emitter, EmitterWriter};
-use rustc_data_structures::sync::{self, Lrc, Lock, LockCell};
+use rustc_data_structures::sync::{self, Lrc, Lock, AtomicUsize, AtomicBool, SeqCst};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::StableHasher;
use std::borrow::Cow;
use std::cell::Cell;
use std::{error, fmt};
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering::SeqCst;
use std::panic;
use termcolor::{ColorSpec, Color};
err_count: AtomicUsize,
emitter: Lock<Box<dyn Emitter + sync::Send>>,
- continue_after_error: LockCell<bool>,
+ continue_after_error: AtomicBool,
delayed_span_bugs: Lock<Vec<Diagnostic>>,
// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
flags,
err_count: AtomicUsize::new(0),
emitter: Lock::new(e),
- continue_after_error: LockCell::new(true),
+ continue_after_error: AtomicBool::new(true),
delayed_span_bugs: Lock::new(Vec::new()),
taught_diagnostics: Default::default(),
emitted_diagnostic_codes: Default::default(),
}
pub fn set_continue_after_error(&self, continue_after_error: bool) {
- self.continue_after_error.set(continue_after_error);
+ self.continue_after_error.store(continue_after_error, SeqCst);
}
/// Resets the diagnostic error count as well as the cached emitted diagnostics.
let mut db = DiagnosticBuilder::new(self, lvl, msg);
db.set_span(msp.clone());
db.emit();
- if !self.continue_after_error.get() {
+ if !self.continue_after_error.load(SeqCst) {
self.abort_if_errors();
}
}
let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code), msg);
db.set_span(msp.clone());
db.emit();
- if !self.continue_after_error.get() {
+ if !self.continue_after_error.load(SeqCst) {
self.abort_if_errors();
}
}
let total_node_count = serialized_graph.nodes.len();
let total_edge_count = serialized_graph.edge_list_data.len();
- let (total_edge_reads, total_duplicate_edge_reads) =
- tcx.dep_graph.edge_deduplication_data();
let mut counts: FxHashMap<_, Stat> = FxHashMap::default();
println!("[incremental]");
println!("[incremental] Total Node Count: {}", total_node_count);
println!("[incremental] Total Edge Count: {}", total_edge_count);
- println!("[incremental] Total Edge Reads: {}", total_edge_reads);
- println!("[incremental] Total Duplicate Edge Reads: {}", total_duplicate_edge_reads);
+ if let Some((total_edge_reads,
+ total_duplicate_edge_reads)) = tcx.dep_graph.edge_deduplication_data() {
+ println!("[incremental] Total Edge Reads: {}", total_edge_reads);
+ println!("[incremental] Total Duplicate Edge Reads: {}", total_duplicate_edge_reads);
+ }
println!("[incremental]");
println!("[incremental] {:<36}| {:<17}| {:<12}| {:<17}|",
"Node Kind",
private_traits: FxHashSet<ast::NodeId>,
}
+fn has_doc(attr: &ast::Attribute) -> bool {
+ if !attr.check_name("doc") {
+ return false;
+ }
+
+ if attr.is_value_str() {
+ return true;
+ }
+
+ if let Some(list) = attr.meta_item_list() {
+ for meta in list {
+ if meta.check_name("include") || meta.check_name("hidden") {
+ return true;
+ }
+ }
+ }
+
+ false
+}
+
impl MissingDoc {
pub fn new() -> MissingDoc {
MissingDoc {
}
}
- fn has_doc(attr: &ast::Attribute) -> bool {
- if !attr.check_name("doc") {
- return false;
- }
-
- if attr.is_value_str() {
- return true;
- }
-
- if let Some(list) = attr.meta_item_list() {
- for meta in list {
- if meta.check_name("include") {
- return true;
- }
- }
- }
-
- false
- }
-
let has_doc = attrs.iter().any(|a| has_doc(a));
if !has_doc {
cx.span_lint(MISSING_DOCS,
fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate");
+
+ for macro_def in &krate.exported_macros {
+ let has_doc = macro_def.attrs.iter().any(|a| has_doc(a));
+ if !has_doc {
+ cx.span_lint(MISSING_DOCS,
+ cx.tcx.sess.source_map().def_span(macro_def.span),
+ "missing documentation for macro");
+ }
+ }
}
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
use lint::{EarlyLintPass, LintPass, LateLintPass};
use syntax::ast;
use syntax::attr;
-use syntax_pos::Span;
+use syntax::errors::Applicability;
+use syntax_pos::{BytePos, symbol::Ident, Span};
#[derive(PartialEq)]
pub enum MethodLateContext {
pub struct NonCamelCaseTypes;
impl NonCamelCaseTypes {
- fn check_case(&self, cx: &EarlyContext, sort: &str, name: ast::Name, span: Span) {
+ fn check_case(&self, cx: &EarlyContext, sort: &str, ident: &Ident) {
fn char_has_case(c: char) -> bool {
c.is_lowercase() || c.is_uppercase()
}
- fn is_camel_case(name: ast::Name) -> bool {
- let name = name.as_str();
+ fn is_camel_case(name: &str) -> bool {
let name = name.trim_matches('_');
if name.is_empty() {
return true;
}).0
}
+ let name = &ident.name.as_str();
+
if !is_camel_case(name) {
- let c = to_camel_case(&name.as_str());
- let m = if c.is_empty() {
- format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name)
- } else {
- format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
- };
- cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
+ let c = to_camel_case(name);
+
+ let msg = format!("{} `{}` should have a camel case name", sort, name);
+ cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, &msg)
+ .span_suggestion_with_applicability(
+ ident.span,
+ "convert the identifier to camel case",
+ c,
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
}
}
}
ast::ItemKind::Ty(..) |
ast::ItemKind::Enum(..) |
ast::ItemKind::Struct(..) |
- ast::ItemKind::Union(..) => self.check_case(cx, "type", it.ident.name, it.span),
- ast::ItemKind::Trait(..) => self.check_case(cx, "trait", it.ident.name, it.span),
+ ast::ItemKind::Union(..) => self.check_case(cx, "type", &it.ident),
+ ast::ItemKind::Trait(..) => self.check_case(cx, "trait", &it.ident),
_ => (),
}
}
fn check_variant(&mut self, cx: &EarlyContext, v: &ast::Variant, _: &ast::Generics) {
- self.check_case(cx, "variant", v.node.ident.name, v.span);
+ self.check_case(cx, "variant", &v.node.ident);
}
fn check_generic_param(&mut self, cx: &EarlyContext, param: &ast::GenericParam) {
if let ast::GenericParamKind::Type { .. } = param.kind {
- self.check_case(cx, "type parameter", param.ident.name, param.ident.span);
+ self.check_case(cx, "type parameter", ¶m.ident);
}
}
}
words.join("_")
}
- fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option<Span>) {
+ /// Checks if a given identifier is snake case, and reports a diagnostic if not.
+ fn check_snake_case(&self, cx: &LateContext, sort: &str, ident: &Ident) {
fn is_snake_case(ident: &str) -> bool {
if ident.is_empty() {
return true;
})
}
+ let name = &ident.name.as_str();
+
if !is_snake_case(name) {
let sc = NonSnakeCase::to_snake_case(name);
- let msg = if sc != name {
- format!("{} `{}` should have a snake case name such as `{}`",
- sort,
- name,
- sc)
+
+ let msg = format!("{} `{}` should have a snake case name", sort, name);
+ let mut err = cx.struct_span_lint(NON_SNAKE_CASE, ident.span, &msg);
+
+ // We have a valid span in almost all cases, but we don't have one when linting a crate
+ // name provided via the command line.
+ if !ident.span.is_dummy() {
+ err.span_suggestion_with_applicability(
+ ident.span,
+ "convert the identifier to snake case",
+ sc,
+ Applicability::MaybeIncorrect,
+ );
} else {
- format!("{} `{}` should have a snake case name", sort, name)
- };
- match span {
- Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
- None => cx.lint(NON_SNAKE_CASE, &msg),
+ err.help(&format!("convert the identifier to snake case: `{}`", sc));
}
+
+ err.emit();
}
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
- let attr_crate_name = attr::find_by_name(&cr.attrs, "crate_name")
- .and_then(|at| at.value_str().map(|s| (at, s)));
- if let Some(ref name) = cx.tcx.sess.opts.crate_name {
- self.check_snake_case(cx, "crate", name, None);
- } else if let Some((attr, name)) = attr_crate_name {
- self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span));
+ let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
+ Some(Ident::from_str(name))
+ } else {
+ attr::find_by_name(&cr.attrs, "crate_name")
+ .and_then(|attr| attr.meta())
+ .and_then(|meta| {
+ meta.name_value_literal().and_then(|lit| {
+ if let ast::LitKind::Str(name, ..) = lit.node {
+ // Discard the double quotes surrounding the literal.
+ let sp = cx.sess().source_map().span_to_snippet(lit.span)
+ .ok()
+ .and_then(|snippet| {
+ let left = snippet.find('"')?;
+ let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
+
+ Some(
+ lit.span
+ .with_lo(lit.span.lo() + BytePos(left as u32 + 1))
+ .with_hi(lit.span.hi() - BytePos(right as u32)),
+ )
+ })
+ .unwrap_or_else(|| lit.span);
+
+ Some(Ident::new(name, sp))
+ } else {
+ None
+ }
+ })
+ })
+ };
+
+ if let Some(ident) = &crate_ident {
+ self.check_snake_case(cx, "crate", ident);
}
}
fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) {
- match param.kind {
- GenericParamKind::Lifetime { .. } => {
- let name = param.name.ident().as_str();
- self.check_snake_case(cx, "lifetime", &name, Some(param.span));
- }
- GenericParamKind::Type { .. } => {}
+ if let GenericParamKind::Lifetime { .. } = param.kind {
+ self.check_snake_case(cx, "lifetime", ¶m.name.ident());
}
}
- fn check_fn(&mut self,
- cx: &LateContext,
- fk: FnKind,
- _: &hir::FnDecl,
- _: &hir::Body,
- span: Span,
- id: ast::NodeId) {
- match fk {
- FnKind::Method(name, ..) => {
+ fn check_fn(
+ &mut self,
+ cx: &LateContext,
+ fk: FnKind,
+ _: &hir::FnDecl,
+ _: &hir::Body,
+ _: Span,
+ id: ast::NodeId,
+ ) {
+ match &fk {
+ FnKind::Method(ident, ..) => {
match method_context(cx, id) {
MethodLateContext::PlainImpl => {
- self.check_snake_case(cx, "method", &name.as_str(), Some(span))
+ self.check_snake_case(cx, "method", ident);
}
MethodLateContext::TraitAutoImpl => {
- self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
+ self.check_snake_case(cx, "trait method", ident);
}
_ => (),
}
}
- FnKind::ItemFn(name, _, header, _, attrs) => {
+ FnKind::ItemFn(ident, _, header, _, attrs) => {
// Skip foreign-ABI #[no_mangle] functions (Issue #31924)
- if header.abi != Abi::Rust && attr::find_by_name(attrs, "no_mangle").is_some() {
+ if header.abi != Abi::Rust && attr::contains_name(attrs, "no_mangle") {
return;
}
- self.check_snake_case(cx, "function", &name.as_str(), Some(span))
+ self.check_snake_case(cx, "function", ident);
}
FnKind::Closure(_) => (),
}
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
if let hir::ItemKind::Mod(_) = it.node {
- self.check_snake_case(cx, "module", &it.ident.as_str(), Some(it.span));
+ self.check_snake_case(cx, "module", &it.ident);
}
}
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
- if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(ref pnames)) = item.node {
- self.check_snake_case(cx,
- "trait method",
- &item.ident.as_str(),
- Some(item.span));
+ if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(pnames)) = &item.node {
+ self.check_snake_case(cx, "trait method", &item.ident);
for param_name in pnames {
- self.check_snake_case(cx, "variable", ¶m_name.as_str(), Some(param_name.span));
+ self.check_snake_case(cx, "variable", param_name);
}
}
}
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
- if let &PatKind::Binding(_, _, ref ident, _) = &p.node {
- self.check_snake_case(cx, "variable", &ident.as_str(), Some(p.span));
+ if let &PatKind::Binding(_, _, ident, _) = &p.node {
+ self.check_snake_case(cx, "variable", &ident);
}
}
- fn check_struct_def(&mut self,
- cx: &LateContext,
- s: &hir::VariantData,
- _: ast::Name,
- _: &hir::Generics,
- _: ast::NodeId) {
+ fn check_struct_def(
+ &mut self,
+ cx: &LateContext,
+ s: &hir::VariantData,
+ _: ast::Name,
+ _: &hir::Generics,
+ _: ast::NodeId,
+ ) {
for sf in s.fields() {
- self.check_snake_case(cx, "structure field", &sf.ident.as_str(), Some(sf.span));
+ self.check_snake_case(cx, "structure field", &sf.ident);
}
}
}
pub struct NonUpperCaseGlobals;
impl NonUpperCaseGlobals {
- fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
- if name.as_str().chars().any(|c| c.is_lowercase()) {
- let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase();
- if name != &*uc {
- cx.span_lint(NON_UPPER_CASE_GLOBALS,
- span,
- &format!("{} `{}` should have an upper case name such as `{}`",
- sort,
- name,
- uc));
- } else {
- cx.span_lint(NON_UPPER_CASE_GLOBALS,
- span,
- &format!("{} `{}` should have an upper case name", sort, name));
- }
+ fn check_upper_case(cx: &LateContext, sort: &str, ident: &Ident) {
+ let name = &ident.name.as_str();
+
+ if name.chars().any(|c| c.is_lowercase()) {
+ let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
+
+ let msg = format!("{} `{}` should have an upper case name", sort, name);
+ cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, &msg)
+ .span_suggestion_with_applicability(
+ ident.span,
+ "convert the identifier to upper case",
+ uc,
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
}
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
match it.node {
- hir::ItemKind::Static(..) => {
- if attr::find_by_name(&it.attrs, "no_mangle").is_some() {
- return;
- }
- NonUpperCaseGlobals::check_upper_case(cx, "static variable", it.ident.name,
- it.span);
+ hir::ItemKind::Static(..) if !attr::contains_name(&it.attrs, "no_mangle") => {
+ NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident);
}
hir::ItemKind::Const(..) => {
- NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident.name,
- it.span);
+ NonUpperCaseGlobals::check_upper_case(cx, "constant", &it.ident);
}
_ => {}
}
}
fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
- match ti.node {
- hir::TraitItemKind::Const(..) => {
- NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
- ti.ident.name, ti.span);
- }
- _ => {}
+ if let hir::TraitItemKind::Const(..) = ti.node {
+ NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ti.ident);
}
}
fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
- match ii.node {
- hir::ImplItemKind::Const(..) => {
- NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
- ii.ident.name, ii.span);
- }
- _ => {}
+ if let hir::ImplItemKind::Const(..) = ii.node {
+ NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
}
}
if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
if let Def::Const(..) = path.def {
if path.segments.len() == 1 {
- NonUpperCaseGlobals::check_upper_case(cx,
- "constant in pattern",
- path.segments[0].ident.name,
- path.span);
+ NonUpperCaseGlobals::check_upper_case(
+ cx,
+ "constant in pattern",
+ &path.segments[0].ident
+ );
}
}
}
}
let llvm_static_stdcpp = env::var_os("LLVM_STATIC_STDCPP");
+ let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX");
let stdcppname = if target.contains("openbsd") {
// llvm-config on OpenBSD doesn't mention stdlib=libc++
} else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {
// NetBSD uses a separate library when relocation is required
"stdc++_pic"
+ } else if llvm_use_libcxx.is_some() {
+ "c++"
} else {
"stdc++"
};
"closure"
};
- let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned());
- let tcx = self.infcx.tcx;
-
- let first_borrow_desc;
+ let (desc_place, msg_place, msg_borrow, union_type_name) =
+ self.describe_place_for_conflicting_borrow(place, &issued_borrow.borrowed_place);
let explanation = self.explain_why_borrow_contains_point(context, issued_borrow, None);
let second_borrow_desc = if explanation.is_explained() {
};
// FIXME: supply non-"" `opt_via` when appropriate
+ let tcx = self.infcx.tcx;
+ let first_borrow_desc;
let mut err = match (
gen_borrow_kind,
"immutable",
tcx.cannot_reborrow_already_borrowed(
span,
&desc_place,
- "",
+ &msg_place,
lft,
issued_span,
"it",
rgt,
- "",
+ &msg_borrow,
None,
Origin::Mir,
)
tcx.cannot_reborrow_already_borrowed(
span,
&desc_place,
- "",
+ &msg_place,
lft,
issued_span,
"it",
rgt,
- "",
+ &msg_borrow,
None,
Origin::Mir,
)
tcx.cannot_mutably_borrow_multiply(
span,
&desc_place,
- "",
+ &msg_place,
issued_span,
- "",
+ &msg_borrow,
None,
Origin::Mir,
)
);
}
+ if union_type_name != "" {
+ err.note(&format!(
+ "`{}` is a field of the union `{}`, so it overlaps the field `{}`",
+ msg_place, union_type_name, msg_borrow,
+ ));
+ }
+
explanation
.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);
err.buffer(&mut self.errors_buffer);
}
+ /// Returns the description of the root place for a conflicting borrow and the full
+ /// descriptions of the places that caused the conflict.
+ ///
+ /// In the simplest case, where there are no unions involved, if a mutable borrow of `x` is
+ /// attempted while a shared borrow is live, then this function will return:
+ ///
+ /// ("x", "", "")
+ ///
+ /// In the simple union case, if a mutable borrow of a union field `x.z` is attempted while
+ /// a shared borrow of another field `x.y`, then this function will return:
+ ///
+ /// ("x", "x.z", "x.y")
+ ///
+ /// In the more complex union case, where the union is a field of a struct, then if a mutable
+ /// borrow of a union field in a struct `x.u.z` is attempted while a shared borrow of
+ /// another field `x.u.y`, then this function will return:
+ ///
+ /// ("x.u", "x.u.z", "x.u.y")
+ ///
+ /// This is used when creating error messages like below:
+ ///
+ /// > cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
+ /// > mutable (via `a.u.s.b`) [E0502]
+ pub(super) fn describe_place_for_conflicting_borrow(
+ &self,
+ first_borrowed_place: &Place<'tcx>,
+ second_borrowed_place: &Place<'tcx>,
+ ) -> (String, String, String, String) {
+ // Define a small closure that we can use to check if the type of a place
+ // is a union.
+ let is_union = |place: &Place<'tcx>| -> bool {
+ place.ty(self.mir, self.infcx.tcx)
+ .to_ty(self.infcx.tcx)
+ .ty_adt_def()
+ .map(|adt| adt.is_union())
+ .unwrap_or(false)
+ };
+
+ // Start with an empty tuple, so we can use the functions on `Option` to reduce some
+ // code duplication (particularly around returning an empty description in the failure
+ // case).
+ Some(())
+ .filter(|_| {
+ // If we have a conflicting borrow of the same place, then we don't want to add
+ // an extraneous "via x.y" to our diagnostics, so filter out this case.
+ first_borrowed_place != second_borrowed_place
+ })
+ .and_then(|_| {
+ // We're going to want to traverse the first borrowed place to see if we can find
+ // field access to a union. If we find that, then we will keep the place of the
+ // union being accessed and the field that was being accessed so we can check the
+ // second borrowed place for the same union and a access to a different field.
+ let mut current = first_borrowed_place;
+ while let Place::Projection(box PlaceProjection { base, elem }) = current {
+ match elem {
+ ProjectionElem::Field(field, _) if is_union(base) => {
+ return Some((base, field));
+ },
+ _ => current = base,
+ }
+ }
+ None
+ })
+ .and_then(|(target_base, target_field)| {
+ // With the place of a union and a field access into it, we traverse the second
+ // borrowed place and look for a access to a different field of the same union.
+ let mut current = second_borrowed_place;
+ while let Place::Projection(box PlaceProjection { base, elem }) = current {
+ match elem {
+ ProjectionElem::Field(field, _) if {
+ is_union(base) && field != target_field && base == target_base
+ } => {
+ let desc_base = self.describe_place(base)
+ .unwrap_or_else(|| "_".to_owned());
+ let desc_first = self.describe_place(first_borrowed_place)
+ .unwrap_or_else(|| "_".to_owned());
+ let desc_second = self.describe_place(second_borrowed_place)
+ .unwrap_or_else(|| "_".to_owned());
+
+ // Also compute the name of the union type, eg. `Foo` so we
+ // can add a helpful note with it.
+ let ty = base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+
+ return Some((desc_base, desc_first, desc_second, ty.to_string()));
+ },
+ _ => current = base,
+ }
+ }
+ None
+ })
+ .unwrap_or_else(|| {
+ // If we didn't find a field access into a union, or both places match, then
+ // only return the description of the first place.
+ let desc_place = self.describe_place(first_borrowed_place)
+ .unwrap_or_else(|| "_".to_owned());
+ (desc_place, "".to_string(), "".to_string(), "".to_string())
+ })
+ }
+
/// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
///
/// This means that some data referenced by `borrow` needs to live
block.and(Rvalue::Repeat(value_operand, count))
}
ExprKind::Borrow {
- region,
borrow_kind,
arg,
} => {
BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, arg)),
_ => unpack!(block = this.as_place(block, arg)),
};
- block.and(Rvalue::Ref(region, borrow_kind, arg_place))
+ block.and(Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place))
}
ExprKind::Binary { op, lhs, rhs } => {
let lhs = unpack!(block = this.as_operand(block, scope, lhs));
BorrowKind::Mut {
allow_two_phase_borrow: false,
},
- region,
arg,
} => unpack!(
block = this.limit_capture_mutability(
- upvar.span, upvar.ty, scope, block, arg, region,
+ upvar.span, upvar.ty, scope, block, arg,
)
),
_ => unpack!(block = this.as_operand(block, scope, upvar)),
temp_lifetime: Option<region::Scope>,
mut block: BasicBlock,
arg: ExprRef<'tcx>,
- region: &'tcx ty::RegionKind,
) -> BlockAnd<Operand<'tcx>> {
let this = self;
block,
source_info,
&Place::Local(temp),
- Rvalue::Ref(region, borrow_kind, arg_place),
+ Rvalue::Ref(this.hir.tcx().types.re_erased, borrow_kind, arg_place),
);
// In constants, temp_lifetime is None. We should not need to drop
var_id: NodeId,
var_ty: Ty<'tcx>,
mutability: Mutability,
- binding_mode: BindingMode<'tcx>,
+ binding_mode: BindingMode,
}
/// Indicates that the type of `source` must be a subtype of the
// Assign each of the bindings. Since we are binding for a
// guard expression, this will never trigger moves out of the
// candidate.
- let re_empty = self.hir.tcx().types.re_empty;
+ let re_erased = self.hir.tcx().types.re_erased;
for binding in bindings {
let source_info = self.source_info(binding.span);
self.schedule_drop_for_binding(binding.var_id, binding.span, RefWithinGuard);
match binding.binding_mode {
BindingMode::ByValue => {
- let rvalue = Rvalue::Ref(re_empty, BorrowKind::Shared, binding.source.clone());
+ let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, binding.source.clone());
self.cfg
.push_assign(block, source_info, &ref_for_guard, rvalue);
}
- BindingMode::ByRef(region, borrow_kind) => {
+ BindingMode::ByRef(borrow_kind) => {
// Tricky business: For `ref id` and `ref mut id`
// patterns, we want `id` within the guard to
// correspond to a temp of type `& &T` or `& &mut
allow_two_phase_borrow: true,
},
};
- let rvalue = Rvalue::Ref(region, borrow_kind, binding.source.clone());
+ let rvalue = Rvalue::Ref(re_erased, borrow_kind, binding.source.clone());
self.cfg
.push_assign(block, source_info, &val_for_guard, rvalue);
- let rvalue = Rvalue::Ref(region, BorrowKind::Shared, val_for_guard);
+ let rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, val_for_guard);
self.cfg
.push_assign(block, source_info, &ref_for_guard, rvalue);
}
block, bindings
);
+
+ let re_erased = self.hir.tcx().types.re_erased;
// Assign each of the bindings. This may trigger moves out of the candidate.
for binding in bindings {
let source_info = self.source_info(binding.span);
BindingMode::ByValue => {
Rvalue::Use(self.consume_by_copy_or_move(binding.source.clone()))
}
- BindingMode::ByRef(region, borrow_kind) => {
- Rvalue::Ref(region, borrow_kind, binding.source.clone())
+ BindingMode::ByRef(borrow_kind) => {
+ Rvalue::Ref(re_erased, borrow_kind, binding.source.clone())
}
};
self.cfg.push_assign(block, source_info, &local, rvalue);
let tcx = self.hir.tcx();
let binding_mode = match mode {
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
- BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
+ BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability.into()),
};
debug!("declare_binding: user_ty={:?}", user_ty);
let local = LocalDecl::<'tcx> {
let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
// See previous comment.
mutability: Mutability::Not,
- ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
+ ty: tcx.mk_imm_ref(tcx.types.re_erased, var_ty),
user_ty: UserTypeProjections::none(),
name: Some(name),
source_info,
for (matched_place, borrow_kind) in all_fake_borrows {
let borrowed_input =
- Rvalue::Ref(tcx.types.re_empty, borrow_kind, matched_place.clone());
+ Rvalue::Ref(tcx.types.re_erased, borrow_kind, matched_place.clone());
let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx);
let borrowed_input_temp = self.temp(borrowed_input_ty, source_info.span);
self.cfg.push_assign(
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
let method = self.hir.tcx().intern_lazy_const(ty::LazyConst::Evaluated(method));
+ let re_erased = self.hir.tcx().types.re_erased;
// take the argument by reference
- let region_scope = self.topmost_scope();
- let region = self.hir.tcx().mk_region(ty::ReScope(region_scope));
let tam = ty::TypeAndMut {
ty,
mutbl: Mutability::MutImmutable,
};
- let ref_ty = self.hir.tcx().mk_ref(region, tam);
+ let ref_ty = self.hir.tcx().mk_ref(re_erased, tam);
// let lhs_ref_place = &lhs;
- let ref_rvalue = Rvalue::Ref(region, BorrowKind::Shared, place);
+ let ref_rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, place);
let lhs_ref_place = self.temp(ref_ty, test.span);
self.cfg.push_assign(block, source_info, &lhs_ref_place, ref_rvalue);
let val = Operand::Move(lhs_ref_place);
self.cfg.push_assign(block, source_info, &rhs_place, Rvalue::Use(expect));
// let rhs_ref_place = &rhs_place;
- let ref_rvalue = Rvalue::Ref(region, BorrowKind::Shared, rhs_place);
+ let ref_rvalue = Rvalue::Ref(re_erased, BorrowKind::Shared, rhs_place);
let rhs_ref_place = self.temp(ref_ty, test.span);
self.cfg.push_assign(block, source_info, &rhs_ref_place, ref_rvalue);
let expect = Operand::Move(rhs_ref_place);
use hair::{LintLevel, BindingMode, PatternKind};
use rustc::hir;
use rustc::hir::Node;
-use rustc::hir::def_id::{DefId, LocalDefId};
+use rustc::hir::def_id::DefId;
use rustc::middle::region;
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, TyContext};
let arguments: Vec<_> = arguments.collect();
let tcx = hir.tcx();
- let span = tcx.hir().span(fn_id);
+ let tcx_hir = tcx.hir();
+ let span = tcx_hir.span(fn_id);
+
+ let hir_tables = hir.tables();
+ let fn_def_id = tcx_hir.local_def_id(fn_id);
// Gather the upvars of a closure, if any.
- let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
- freevars.iter().map(|fv| {
- let var_id = fv.var_id();
- let var_hir_id = tcx.hir().node_to_hir_id(var_id);
- let closure_expr_id = tcx.hir().local_def_id(fn_id);
- let capture = hir.tables().upvar_capture(ty::UpvarId {
- var_path: ty::UpvarPath {hir_id: var_hir_id},
- closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
- });
+ // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
+ // closure and we stored in a map called upvar_list in TypeckTables indexed
+ // with the closure's DefId. Here, we run through that vec of UpvarIds for
+ // the given closure and use the necessary information to create UpvarDecl.
+ let upvar_decls: Vec<_> = hir_tables
+ .upvar_list
+ .get(&fn_def_id)
+ .into_iter()
+ .flatten()
+ .map(|upvar_id| {
+ let var_hir_id = upvar_id.var_path.hir_id;
+ let var_node_id = tcx_hir.hir_to_node_id(var_hir_id);
+ let capture = hir_tables.upvar_capture(*upvar_id);
let by_ref = match capture {
ty::UpvarCapture::ByValue => false,
- ty::UpvarCapture::ByRef(..) => true
+ ty::UpvarCapture::ByRef(..) => true,
};
let mut decl = UpvarDecl {
debug_name: keywords::Invalid.name(),
by_ref,
mutability: Mutability::Not,
};
- if let Some(Node::Binding(pat)) = tcx.hir().find(var_id) {
+ if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) {
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
decl.debug_name = ident.name;
-
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
if bm == ty::BindByValue(hir::MutMutable) {
decl.mutability = Mutability::Mut;
}
}
decl
- }).collect()
- });
+ })
+ .collect();
let mut builder = Builder::new(hir,
span,
return_ty_span,
upvar_decls);
- let fn_def_id = tcx.hir().local_def_id(fn_id);
let call_site_scope = region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite
// RustCall pseudo-ABI untuples the last argument.
spread_arg = Some(Local::new(arguments.len()));
}
- let closure_expr_id = tcx.hir().local_def_id(fn_id);
+ let closure_expr_id = tcx_hir.local_def_id(fn_id);
info!("fn_id {:?} has attrs {:?}", closure_expr_id,
tcx.get_attrs(closure_expr_id));
/// Should be a power of two for performance reasons.
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
+/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
+/// The `EvalContext` is only meant to be used to query values from constants and statics.
+///
+/// This function is used during const propagation. We cannot use `mk_eval_cx`, because copy
+/// propagation happens *during* the computation of the MIR of the current function. So if we
+/// tried to call the `optimized_mir` query, we'd get a cycle error because we are (transitively)
+/// inside the `optimized_mir` query of the `Instance` given.
+///
+/// Since we are looking at the MIR of the function in an abstract manner, we don't have a
+/// `ParamEnv` available to us. This function creates a `ParamEnv` for the given instance.
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
debug!("mk_borrowck_eval_cx: {:?}", instance);
let param_env = tcx.param_env(instance.def_id());
+ mk_eval_cx_inner(tcx, instance, mir, span, param_env)
+}
+
+/// This is just a helper function to reduce code duplication between `mk_borrowck_eval_cx` and
+/// `mk_eval_cx`. Do not call this function directly.
+fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ instance: Instance<'tcx>,
+ mir: &'mir mir::Mir<'tcx>,
+ span: Span,
+ param_env: ty::ParamEnv<'tcx>,
+) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
- // insert a stack frame so any queries have the correct substs
- // cannot use `push_stack_frame`; if we do `const_prop` explodes
+ // Insert a stack frame so any queries have the correct substs.
+ // We also avoid all the extra work performed by push_stack_frame,
+ // like initializing local variables
ecx.stack.push(interpret::Frame {
block: mir::START_BLOCK,
locals: IndexVec::new(),
Ok(ecx)
}
-pub fn mk_eval_cx<'a, 'tcx>(
+/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
+/// The `EvalContext` is only meant to be used to do field and index projections into constants for
+/// `simd_shuffle` and const patterns in match arms.
+///
+/// The function containing the `match` that is currently being analyzed may have generic bounds
+/// that inform us about the generic bounds of the constant. E.g. using an associated constant
+/// of a function's generic parameter will require knowledge about the bounds on the generic
+/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
+fn mk_eval_cx<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
let span = tcx.def_span(instance.def_id());
- let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
- let mir = ecx.load_mir(instance.def)?;
- // insert a stack frame so any queries have the correct substs
- ecx.push_stack_frame(
- instance,
- mir.span,
- mir,
- None,
- StackPopCleanup::Goto(None), // never pop
- )?;
- Ok(ecx)
+ let mir = tcx.optimized_mir(instance.def.def_id());
+ mk_eval_cx_inner(tcx, instance, mir, span, param_env)
}
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
"##,
E0162: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
An if-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding instead. For instance:
-```compile_fail,E0162
+```compile_pass
struct Irrefutable(i32);
let irr = Irrefutable(0);
"##,
E0165: r##"
+#### Note: this error code is no longer emitted by the compiler.
+
A while-let pattern attempts to match the pattern, and enters the body if the
match was successful. If the match is irrefutable (when it cannot fail to
match), use a regular `let`-binding inside a `loop` instead. For instance:
-```compile_fail,E0165
+```compile_pass,no_run
struct Irrefutable(i32);
let irr = Irrefutable(0);
```
"##,
-// FIXME(#24111) Change the language here when const fn stabilizes
+// FIXME(#57563) Change the language here when const fn stabilizes
E0015: r##"
The only functions that can be called in static or constant expressions are
`const` functions, and struct/enum constructors. `const` functions are only
Temporaries are not always dropped at the end of the enclosing
statement. In simple cases where the `&` expression is immediately
stored into a variable, the compiler will automatically extend
-the lifetime of the temporary until the end of the enclosinb
+the lifetime of the temporary until the end of the enclosing
block. Therefore, an alternative way to fix the original
program is to write `let tmp = &foo()` and not `let tmp = foo()`:
}),
span,
kind: ExprKind::Borrow {
- region: deref.region,
borrow_kind: deref.mutbl.to_borrow_kind(),
arg: expr.to_ref(),
},
overloaded_place(cx, hir_expr, adjustment.target, Some(call), vec![expr.to_ref()])
}
- Adjust::Borrow(AutoBorrow::Ref(r, m)) => {
+ Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
ExprKind::Borrow {
- region: r,
borrow_kind: m.to_borrow_kind(),
arg: expr.to_ref(),
}
}
Adjust::Borrow(AutoBorrow::RawPtr(m)) => {
// Convert this to a suitable `&foo` and
- // then an unsafe coercion. Limit the region to be just this
- // expression.
- let region = ty::ReScope(region::Scope {
- id: hir_expr.hir_id.local_id,
- data: region::ScopeData::Node
- });
- let region = cx.tcx.mk_region(region);
+ // then an unsafe coercion.
expr = Expr {
temp_lifetime,
- ty: cx.tcx.mk_ref(region,
+ ty: cx.tcx.mk_ref(cx.tcx.types.re_erased,
ty::TypeAndMut {
ty: expr.ty,
mutbl: m,
}),
span,
kind: ExprKind::Borrow {
- region,
borrow_kind: m.to_borrow_kind(),
arg: expr.to_ref(),
},
}
hir::ExprKind::AddrOf(mutbl, ref expr) => {
- let region = match expr_ty.sty {
- ty::Ref(r, _, _) => r,
- _ => span_bug!(expr.span, "type of & not region"),
- };
ExprKind::Borrow {
- region,
borrow_kind: mutbl.to_borrow_kind(),
arg: expr.to_ref(),
}
ty: freevar_ty,
span: closure_expr.span,
kind: ExprKind::Borrow {
- region: upvar_borrow.region,
borrow_kind,
arg: captured_var.to_ref(),
},
use rustc::infer::canonical::Canonical;
use rustc::middle::region;
use rustc::ty::subst::Substs;
-use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const, LazyConst, UserTypeAnnotation};
+use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserTypeAnnotation};
use rustc::ty::layout::VariantIdx;
use rustc::hir;
use syntax::ast;
id: DefId,
},
Borrow {
- region: Region<'tcx>,
borrow_kind: BorrowKind,
arg: ExprRef<'tcx>,
},
let is_visible = adt.is_enum()
|| field.vis.is_accessible_from(cx.module, cx.tcx);
if is_visible {
- field.ty(cx.tcx, substs)
+ let ty = field.ty(cx.tcx, substs);
+ match ty.sty {
+ // If the field type returned is an array of an unknown
+ // size return an TyErr.
+ ty::Array(_, len) if len.assert_usize(cx.tcx).is_none() =>
+ cx.tcx.types.err,
+ _ => ty,
+ }
} else {
// Treat all non-visible fields as TyErr. They
// can't appear in any other pattern from
{
let mut seen = Matrix::empty();
let mut catchall = None;
- let mut printed_if_let_err = false;
for (arm_index, &(ref pats, guard)) in arms.iter().enumerate() {
for &(pat, hir_pat) in pats {
let v = smallvec![pat];
NotUseful => {
match source {
hir::MatchSource::IfLetDesugar { .. } => {
- if cx.tcx.features().irrefutable_let_patterns {
- cx.tcx.lint_node(
- lint::builtin::IRREFUTABLE_LET_PATTERNS,
- hir_pat.id, pat.span,
- "irrefutable if-let pattern");
- } else {
- if printed_if_let_err {
- // we already printed an irrefutable if-let pattern error.
- // We don't want two, that's just confusing.
- } else {
- // find the first arm pattern so we can use its span
- let &(ref first_arm_pats, _) = &arms[0];
- let first_pat = &first_arm_pats[0];
- let span = first_pat.0.span;
- struct_span_err!(cx.tcx.sess, span, E0162,
- "irrefutable if-let pattern")
- .span_label(span, "irrefutable pattern")
- .emit();
- printed_if_let_err = true;
- }
- }
+ cx.tcx.lint_node(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.id,
+ pat.span,
+ "irrefutable if-let pattern",
+ );
}
hir::MatchSource::WhileLetDesugar => {
},
// The arm with the wildcard pattern.
1 => {
- if cx.tcx.features().irrefutable_let_patterns {
- cx.tcx.lint_node(
- lint::builtin::IRREFUTABLE_LET_PATTERNS,
- hir_pat.id, pat.span,
- "irrefutable while-let pattern");
- } else {
- // find the first arm pattern so we can use its span
- let &(ref first_arm_pats, _) = &arms[0];
- let first_pat = &first_arm_pats[0];
- let span = first_pat.0.span;
- struct_span_err!(cx.tcx.sess, span, E0165,
- "irrefutable while-let pattern")
- .span_label(span, "irrefutable pattern")
- .emit();
- }
+ cx.tcx.lint_node(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.id,
+ pat.span,
+ "irrefutable while-let pattern",
+ );
},
_ => bug!(),
}
}
#[derive(Copy, Clone, Debug)]
-pub enum BindingMode<'tcx> {
+pub enum BindingMode {
ByValue,
- ByRef(Region<'tcx>, BorrowKind),
+ ByRef(BorrowKind),
}
#[derive(Clone, Debug)]
Binding {
mutability: Mutability,
name: ast::Name,
- mode: BindingMode<'tcx>,
+ mode: BindingMode,
var: ast::NodeId,
ty: Ty<'tcx>,
subpattern: Option<Pattern<'tcx>>,
PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => {
let is_mut = match mode {
BindingMode::ByValue => mutability == Mutability::Mut,
- BindingMode::ByRef(_, bk) => {
+ BindingMode::ByRef(bk) => {
write!(f, "ref ")?;
match bk { BorrowKind::Mut { .. } => true, _ => false }
}
PatKind::Binding(_, id, ident, ref sub) => {
let var_ty = self.tables.node_id_to_type(pat.hir_id);
- let region = match var_ty.sty {
- ty::Ref(r, _, _) => Some(r),
- ty::Error => { // Avoid ICE
- return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
- }
- _ => None,
+ if let ty::Error = var_ty.sty {
+ // Avoid ICE
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
};
let bm = *self.tables.pat_binding_modes().get(pat.hir_id)
.expect("missing binding mode");
(Mutability::Not, BindingMode::ByValue),
ty::BindByReference(hir::MutMutable) =>
(Mutability::Not, BindingMode::ByRef(
- region.unwrap(), BorrowKind::Mut { allow_two_phase_borrow: false })),
+ BorrowKind::Mut { allow_two_phase_borrow: false })),
ty::BindByReference(hir::MutImmutable) =>
(Mutability::Not, BindingMode::ByRef(
- region.unwrap(), BorrowKind::Shared)),
+ BorrowKind::Shared)),
};
// A ref x pattern is the same node used for x, and as such it has
CloneImpls!{ <'tcx>
Span, Field, Mutability, ast::Name, ast::NodeId, usize, ty::Const<'tcx>,
- Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
+ Region<'tcx>, Ty<'tcx>, BindingMode, &'tcx AdtDef,
&'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>,
UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
}
#![feature(unicode_internals)]
#![feature(step_trait)]
#![feature(slice_concat_ext)]
-#![feature(if_while_or_patterns)]
+#![cfg_attr(stage0, feature(if_while_or_patterns))]
#![feature(try_from)]
#![feature(reverse_bits)]
#![cfg_attr(stage0, feature(underscore_imports))]
use rustc::middle::lang_items;
use rustc::session::config::nightly_options;
use syntax::ast::LitKind;
-use syntax::feature_gate::{UnstableFeatures, feature_err, emit_feature_err, GateIssue};
+use syntax::feature_gate::{UnstableFeatures, emit_feature_err, GateIssue};
use syntax_pos::{Span, DUMMY_SP};
use std::fmt;
param_env: ty::ParamEnv<'tcx>,
local_qualif: IndexVec<Local, Option<Qualif>>,
qualif: Qualif,
- const_fn_arg_vars: BitSet<Local>,
temp_promotion_state: IndexVec<Local, TempState>,
promotion_candidates: Vec<Candidate>
}
param_env,
local_qualif,
qualif: Qualif::empty(),
- const_fn_arg_vars: BitSet::new_empty(mir.local_decls.len()),
temp_promotion_state: temps,
promotion_candidates: vec![]
}
}
}
- /// Error about extra statements in a constant.
- fn statement_like(&mut self) {
- self.add(Qualif::NOT_CONST);
- if self.mode != Mode::Fn {
- let mut err = feature_err(
- &self.tcx.sess.parse_sess,
- "const_let",
- self.span,
- GateIssue::Language,
- &format!("statements in {}s are unstable", self.mode),
- );
- if self.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note("Blocks in constants may only contain items (such as constant, function \
- definition, etc...) and a tail expression.");
- err.help("To avoid it, you have to replace the non-item object.");
- }
- err.emit();
- }
- }
-
/// Add the given qualification to self.qualif.
fn add(&mut self, qualif: Qualif) {
self.qualif = self.qualif | qualif;
return;
}
- if self.tcx.features().const_let {
- let mut dest = dest;
- let index = loop {
- match dest {
- // with `const_let` active, we treat all locals equal
- Place::Local(index) => break *index,
- // projections are transparent for assignments
- // we qualify the entire destination at once, even if just a field would have
- // stricter qualification
- Place::Projection(proj) => {
- // Catch more errors in the destination. `visit_place` also checks various
- // projection rules like union field access and raw pointer deref
- self.visit_place(
- dest,
- PlaceContext::MutatingUse(MutatingUseContext::Store),
- location
- );
- dest = &proj.base;
- },
- Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
- Place::Static(..) => {
- // Catch more errors in the destination. `visit_place` also checks that we
- // do not try to access statics from constants or try to mutate statics
- self.visit_place(
- dest,
- PlaceContext::MutatingUse(MutatingUseContext::Store),
- location
- );
- return;
- }
+ let mut dest = dest;
+ let index = loop {
+ match dest {
+ // We treat all locals equal in constants
+ Place::Local(index) => break *index,
+ // projections are transparent for assignments
+ // we qualify the entire destination at once, even if just a field would have
+ // stricter qualification
+ Place::Projection(proj) => {
+ // Catch more errors in the destination. `visit_place` also checks various
+ // projection rules like union field access and raw pointer deref
+ self.visit_place(
+ dest,
+ PlaceContext::MutatingUse(MutatingUseContext::Store),
+ location
+ );
+ dest = &proj.base;
+ },
+ Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
+ Place::Static(..) => {
+ // Catch more errors in the destination. `visit_place` also checks that we
+ // do not try to access statics from constants or try to mutate statics
+ self.visit_place(
+ dest,
+ PlaceContext::MutatingUse(MutatingUseContext::Store),
+ location
+ );
+ return;
}
- };
- debug!("store to var {:?}", index);
- match &mut self.local_qualif[index] {
- // this is overly restrictive, because even full assignments do not clear the qualif
- // While we could special case full assignments, this would be inconsistent with
- // aggregates where we overwrite all fields via assignments, which would not get
- // that feature.
- Some(ref mut qualif) => *qualif = *qualif | self.qualif,
- // insert new qualification
- qualif @ None => *qualif = Some(self.qualif),
- }
- return;
- }
-
- match *dest {
- Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp ||
- self.mir.local_kind(index) == LocalKind::ReturnPointer => {
- debug!("store to {:?} (temp or return pointer)", index);
- store(&mut self.local_qualif[index])
- }
-
- Place::Projection(box Projection {
- base: Place::Local(index),
- elem: ProjectionElem::Deref
- }) if self.mir.local_kind(index) == LocalKind::Temp
- && self.mir.local_decls[index].ty.is_box()
- && self.local_qualif[index].map_or(false, |qualif| {
- qualif.contains(Qualif::NOT_CONST)
- }) => {
- // Part of `box expr`, we should've errored
- // already for the Box allocation Rvalue.
- }
-
- // This must be an explicit assignment.
- _ => {
- // Catch more errors in the destination.
- self.visit_place(
- dest,
- PlaceContext::MutatingUse(MutatingUseContext::Store),
- location
- );
- self.statement_like();
}
+ };
+ debug!("store to var {:?}", index);
+ match &mut self.local_qualif[index] {
+ // this is overly restrictive, because even full assignments do not clear the qualif
+ // While we could special case full assignments, this would be inconsistent with
+ // aggregates where we overwrite all fields via assignments, which would not get
+ // that feature.
+ Some(ref mut qualif) => *qualif = *qualif | self.qualif,
+ // insert new qualification
+ qualif @ None => *qualif = Some(self.qualif),
}
}
TerminatorKind::FalseUnwind { .. } => None,
TerminatorKind::Return => {
- if !self.tcx.features().const_let {
- // Check for unused values. This usually means
- // there are extra statements in the AST.
- for temp in mir.temps_iter() {
- if self.local_qualif[temp].is_none() {
- continue;
- }
-
- let state = self.temp_promotion_state[temp];
- if let TempState::Defined { location, uses: 0 } = state {
- let data = &mir[location.block];
- let stmt_idx = location.statement_index;
-
- // Get the span for the initialization.
- let source_info = if stmt_idx < data.statements.len() {
- data.statements[stmt_idx].source_info
- } else {
- data.terminator().source_info
- };
- self.span = source_info.span;
-
- // Treat this as a statement in the AST.
- self.statement_like();
- }
- }
-
- // Make sure there are no extra unassigned variables.
- self.qualif = Qualif::NOT_CONST;
- for index in mir.vars_iter() {
- if !self.const_fn_arg_vars.contains(index) {
- debug!("unassigned variable {:?}", index);
- self.assign(&Place::Local(index), Location {
- block: bb,
- statement_index: usize::MAX,
- });
- }
- }
- }
-
break;
}
};
LocalKind::ReturnPointer => {
self.not_const();
}
- LocalKind::Var if !self.tcx.features().const_let => {
- if self.mode != Mode::Fn {
- emit_feature_err(&self.tcx.sess.parse_sess, "const_let",
- self.span, GateIssue::Language,
- &format!("let bindings in {}s are unstable",self.mode));
- }
+ LocalKind::Var if self.mode == Mode::Fn => {
self.add(Qualif::NOT_CONST);
}
LocalKind::Var |
}
}
+ ProjectionElem::ConstantIndex {..} |
+ ProjectionElem::Subslice {..} |
ProjectionElem::Field(..) |
ProjectionElem::Index(_) => {
let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
this.qualif.restrict(ty, this.tcx, this.param_env);
}
- ProjectionElem::ConstantIndex {..} |
- ProjectionElem::Subslice {..} |
ProjectionElem::Downcast(..) => {
this.not_const()
}
err.emit();
}
} else {
- // FIXME(#24111): remove this check when const fn stabilizes.
+ // FIXME(#57563): remove this check when const fn stabilizes.
let (msg, note) = if let UnstableFeatures::Disallow =
self.tcx.sess.opts.unstable_features {
(format!("calls in {}s are limited to \
debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location);
self.visit_rvalue(rvalue, location);
- // Check the allowed const fn argument forms.
- if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
- if self.mir.local_kind(index) == LocalKind::Var &&
- self.const_fn_arg_vars.insert(index) &&
- !self.tcx.features().const_let {
- // Direct use of an argument is permitted.
- match *rvalue {
- Rvalue::Use(Operand::Copy(Place::Local(local))) |
- Rvalue::Use(Operand::Move(Place::Local(local))) => {
- if self.mir.local_kind(local) == LocalKind::Arg {
- return;
- }
- }
- _ => {}
- }
- // Avoid a generic error for other uses of arguments.
- if self.qualif.contains(Qualif::FN_ARGUMENT) {
- let decl = &self.mir.local_decls[index];
- let mut err = feature_err(
- &self.tcx.sess.parse_sess,
- "const_let",
- decl.source_info.span,
- GateIssue::Language,
- "arguments of constant functions can only be immutable by-value bindings"
- );
- if self.tcx.sess.teach(&err.get_code().unwrap()) {
- err.note("Constant functions are not allowed to mutate anything. Thus, \
- binding to an argument with a mutable pattern is not allowed.");
- err.note("Remove any mutable bindings from the argument list to fix this \
- error. In case you need to mutate the argument, try lazily \
- initializing a global variable instead of using a const fn, or \
- refactoring the code to a functional style to avoid mutation if \
- possible.");
- }
- err.emit();
- return;
- }
- }
- }
-
self.assign(dest, location);
}
}
}
- for local in mir.vars_iter() {
- return Err((
- mir.local_decls[local].source_info.span,
- "local variables in const fn are unstable".into(),
- ));
- }
for local in &mir.local_decls {
check_ty(tcx, local.ty, local.source_info.span)?;
}
check_operand(tcx, mir, operand, span)
}
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => {
- check_place(tcx, mir, place, span, PlaceMode::Read)
+ check_place(tcx, mir, place, span)
}
Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
use rustc::ty::cast::CastTy;
}
}
-enum PlaceMode {
- Assign,
- Read,
-}
-
fn check_statement(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &'a Mir<'tcx>,
let span = statement.source_info.span;
match &statement.kind {
StatementKind::Assign(place, rval) => {
- check_place(tcx, mir, place, span, PlaceMode::Assign)?;
+ check_place(tcx, mir, place, span)?;
check_rvalue(tcx, mir, rval, span)
}
- StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span, PlaceMode::Read),
+ StatementKind::FakeRead(_, place) => check_place(tcx, mir, place, span),
// just an assignment
StatementKind::SetDiscriminant { .. } => Ok(()),
) -> McfResult {
match operand {
Operand::Move(place) | Operand::Copy(place) => {
- check_place(tcx, mir, place, span, PlaceMode::Read)
+ check_place(tcx, mir, place, span)
}
Operand::Constant(_) => Ok(()),
}
mir: &'a Mir<'tcx>,
place: &Place<'tcx>,
span: Span,
- mode: PlaceMode,
) -> McfResult {
match place {
- Place::Local(l) => match mode {
- PlaceMode::Assign => match mir.local_kind(*l) {
- LocalKind::Temp | LocalKind::ReturnPointer => Ok(()),
- LocalKind::Arg | LocalKind::Var => {
- Err((span, "assignments in const fn are unstable".into()))
- }
- },
- PlaceMode::Read => Ok(()),
- },
+ Place::Local(_) => Ok(()),
// promoteds are always fine, they are essentially constants
Place::Promoted(_) => Ok(()),
Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
Place::Projection(proj) => {
match proj.elem {
+ | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
| ProjectionElem::Deref | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {
- check_place(tcx, mir, &proj.base, span, mode)
- }
- // slice patterns are unstable
- | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
- return Err((span, "slice patterns in const fn are unstable".into()))
+ check_place(tcx, mir, &proj.base, span)
}
| ProjectionElem::Downcast(..) => {
Err((span, "`match` or `if let` in `const fn` is unstable".into()))
| TerminatorKind::Resume => Ok(()),
TerminatorKind::Drop { location, .. } => {
- check_place(tcx, mir, location, span, PlaceMode::Read)
+ check_place(tcx, mir, location, span)
}
TerminatorKind::DropAndReplace { location, value, .. } => {
- check_place(tcx, mir, location, span, PlaceMode::Read)?;
+ check_place(tcx, mir, location, span)?;
check_operand(tcx, mir, value, span)
},
// some intrinsics are waved through if called inside the
// standard library. Users never need to call them directly
match tcx.fn_sig(def_id).abi() {
- abi::Abi::RustIntrinsic => match &tcx.item_name(def_id).as_str()[..] {
- | "size_of"
- | "min_align_of"
- | "needs_drop"
- => {},
- _ => return Err((
+ abi::Abi::RustIntrinsic => if !is_intrinsic_whitelisted(tcx, def_id) {
+ return Err((
span,
"can only call a curated list of intrinsics in `min_const_fn`".into(),
- )),
+ ))
},
abi::Abi::Rust if tcx.is_min_const_fn(def_id) => {},
abi::Abi::Rust => return Err((
},
}
}
+
+/// Returns true if the `def_id` refers to an intrisic which we've whitelisted
+/// for being called from stable `const fn`s (`min_const_fn`).
+///
+/// Adding more intrinsics requires sign-off from @rust-lang/lang.
+fn is_intrinsic_whitelisted(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
+ match &tcx.item_name(def_id).as_str()[..] {
+ | "size_of"
+ | "min_align_of"
+ | "needs_drop"
+ // Arithmetic:
+ | "add_with_overflow" // ~> .overflowing_add
+ | "sub_with_overflow" // ~> .overflowing_sub
+ | "mul_with_overflow" // ~> .overflowing_mul
+ | "overflowing_add" // ~> .wrapping_add
+ | "overflowing_sub" // ~> .wrapping_sub
+ | "overflowing_mul" // ~> .wrapping_mul
+ | "unchecked_shl" // ~> .wrapping_shl
+ | "unchecked_shr" // ~> .wrapping_shr
+ | "rotate_left" // ~> .rotate_left
+ | "rotate_right" // ~> .rotate_right
+ | "ctpop" // ~> .count_ones
+ | "ctlz" // ~> .leading_zeros
+ | "cttz" // ~> .trailing_zeros
+ | "bswap" // ~> .swap_bytes
+ | "bitreverse" // ~> .reverse_bits
+ => true,
+ _ => false,
+ }
+}
old_load_end_span: Option<Span>,
o: Origin,
) -> DiagnosticBuilder<'cx> {
+ let via = |msg: &str|
+ if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) };
let mut err = struct_span_err!(
self,
new_loan_span,
E0499,
"cannot borrow `{}`{} as mutable more than once at a time{OGN}",
desc,
- opt_via,
+ via(opt_via),
OGN = o
);
if old_loan_span == new_loan_span {
} else {
err.span_label(
old_loan_span,
- format!("first mutable borrow occurs here{}", old_opt_via),
+ format!("first mutable borrow occurs here{}", via(old_opt_via)),
);
err.span_label(
new_loan_span,
- format!("second mutable borrow occurs here{}", opt_via),
+ format!("second mutable borrow occurs here{}", via(opt_via)),
);
if let Some(old_load_end_span) = old_load_end_span {
err.span_label(old_load_end_span, "first borrow ends here");
old_load_end_span: Option<Span>,
o: Origin,
) -> DiagnosticBuilder<'cx> {
+ let via = |msg: &str|
+ if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) };
let mut err = struct_span_err!(
self,
span,
E0502,
- "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
+ "cannot borrow `{}`{} as {} because {} is also borrowed \
+ as {}{}{OGN}",
desc_new,
- msg_new,
+ via(msg_new),
kind_new,
noun_old,
kind_old,
- msg_old,
+ via(msg_old),
OGN = o
);
- err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new));
- err.span_label(
- old_span,
- format!("{} borrow occurs here{}", kind_old, msg_old),
- );
+
+ if msg_new == "" {
+ // If `msg_new` is empty, then this isn't a borrow of a union field.
+ err.span_label(span, format!("{} borrow occurs here", kind_new));
+ err.span_label(old_span, format!("{} borrow occurs here", kind_old));
+ } else {
+ // If `msg_new` isn't empty, then this a borrow of a union field.
+ err.span_label(
+ span,
+ format!(
+ "{} borrow of `{}` -- which overlaps with `{}` -- occurs here",
+ kind_new, msg_new, msg_old,
+ )
+ );
+ err.span_label(
+ old_span,
+ format!("{} borrow occurs here{}", kind_old, via(msg_old)),
+ );
+ }
+
if let Some(old_load_end_span) = old_load_end_span {
err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
}
+
self.cancel_if_wrong_origin(err, o)
}
}
for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate {
- self.err_handler().span_err(predicate.span, "equality constraints are not yet \
- supported in where clauses (#20041)");
+ self.err_handler()
+ .span_err(predicate.span, "equality constraints are not yet \
+ supported in where clauses (see #20041)");
}
}
visit::walk_generics(self, generics)
pub fn provide(providers: &mut Providers) {
rvalue_promotion::provide(providers);
+ loops::provide(providers);
}
use rustc::session::Session;
+use rustc::ty::query::Providers;
+use rustc::ty::query::queries;
+use rustc::ty::TyCtxt;
+use rustc::hir::def_id::DefId;
use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Node, Destination};
cx: Context,
}
-pub fn check_crate(sess: &Session, map: &Map) {
- let krate = map.krate();
- krate.visit_all_item_likes(&mut CheckLoopVisitor {
- sess,
- hir_map: map,
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::check_mod_loops::ensure(tcx, tcx.hir().local_def_id(module));
+ }
+}
+
+fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor {
+ sess: &tcx.sess,
+ hir_map: &tcx.hir(),
cx: Normal,
}.as_deep_visitor());
}
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers {
+ check_mod_loops,
+ ..*providers
+ };
+}
+
impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
NestedVisitorMap::OnlyBodies(&self.hir_map)
}
- fn visit_item(&mut self, i: &'hir hir::Item) {
- self.with_context(Normal, |v| intravisit::walk_item(v, i));
- }
-
- fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
- self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
- }
-
fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
}
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use std::cell::{Cell, RefCell};
-use std::{cmp, fmt, iter, ptr};
+use std::{cmp, fmt, iter, mem, ptr};
use std::collections::BTreeSet;
use std::mem::replace;
use rustc_data_structures::ptr_key::PtrKey;
if ident.name == keywords::Invalid.name() {
return Some(LexicalScopeBinding::Def(Def::Err));
}
- if ns == TypeNS {
- ident.span = if ident.name == keywords::SelfUpper.name() {
- // FIXME(jseyfried) improve `Self` hygiene
- ident.span.with_ctxt(SyntaxContext::empty())
- } else {
- ident.span.modern()
- }
+ ident.span = if ident.name == keywords::SelfUpper.name() {
+ // FIXME(jseyfried) improve `Self` hygiene
+ ident.span.with_ctxt(SyntaxContext::empty())
+ } else if ns == TypeNS {
+ ident.span.modern()
} else {
- ident = ident.modern_and_legacy();
- }
+ ident.span.modern_and_legacy()
+ };
// Walk backwards up the ribs in scope.
let record_used = record_used_id.is_some();
ast::UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
_ => &[TypeNS],
};
+ let report_error = |this: &Self, ns| {
+ let what = if ns == TypeNS { "type parameters" } else { "local variables" };
+ this.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
+ };
+
for &ns in nss {
- if let Some(LexicalScopeBinding::Def(..)) =
- self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
- let what = if ns == TypeNS { "type parameters" } else { "local variables" };
- self.session.span_err(ident.span, &format!("imports cannot refer to {}", what));
+ match self.resolve_ident_in_lexical_scope(ident, ns, None, use_tree.prefix.span) {
+ Some(LexicalScopeBinding::Def(..)) => {
+ report_error(self, ns);
+ }
+ Some(LexicalScopeBinding::Item(binding)) => {
+ let orig_blacklisted_binding =
+ mem::replace(&mut self.blacklisted_binding, Some(binding));
+ if let Some(LexicalScopeBinding::Def(..)) =
+ self.resolve_ident_in_lexical_scope(ident, ns, None,
+ use_tree.prefix.span) {
+ report_error(self, ns);
+ }
+ self.blacklisted_binding = orig_blacklisted_binding;
+ }
+ None => {}
}
}
} else if let ast::UseTreeKind::Nested(use_trees) = &use_tree.kind {
module = Some(ModuleOrUniformRoot::Module(next_module));
record_segment_def(self, def);
} else if def == Def::ToolMod && i + 1 != path.len() {
+ if binding.is_import() {
+ self.session.struct_span_err(
+ ident.span, "cannot use a tool module through an import"
+ ).span_note(
+ binding.span, "the tool module imported here"
+ ).emit();
+ }
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
return PathResult::NonModule(PathResolution::new(def));
} else if def == Def::Err {
}
self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| {
if let Some(binding) = entry.extern_crate_item {
+ if !speculative && entry.introduced_by_item {
+ self.record_use(ident, TypeNS, binding, false);
+ }
Some(binding)
} else {
let crate_id = if !speculative {
.push((path, path_span, kind, parent_scope.clone(), def.ok()));
}
+ self.prohibit_imported_non_macro_attrs(None, def.ok(), path_span);
def
} else {
let binding = self.early_resolve_ident_in_lexical_scope(
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
}
- binding.map(|binding| binding.def())
+ let def = binding.map(|binding| binding.def());
+ self.prohibit_imported_non_macro_attrs(binding.ok(), def.ok(), path_span);
+ def
}
}
// but its `Def` should coincide with a crate passed with `--extern`
// (otherwise there would be ambiguity) and we can skip feature error in this case.
'ok: {
- if !is_import || self.session.features_untracked().uniform_paths {
+ if !is_import || !rust_2015 {
break 'ok;
}
if ns == TypeNS && use_prelude && self.extern_prelude_get(ident, true).is_some() {
break 'ok;
}
- if rust_2015 {
- let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
- let root_module = self.resolve_crate_root(root_ident);
- if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
- orig_ident, ns, None, false, path_span)
- .is_ok() {
- break 'ok;
- }
+ let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span);
+ let root_module = self.resolve_crate_root(root_ident);
+ if self.resolve_ident_in_module_ext(ModuleOrUniformRoot::Module(root_module),
+ orig_ident, ns, None, false, path_span)
+ .is_ok() {
+ break 'ok;
}
- let msg = "imports can only refer to extern crate names \
- passed with `--extern` on stable channel";
- let mut err = feature_err(&self.session.parse_sess, "uniform_paths",
- ident.span, GateIssue::Language, msg);
-
+ let msg = "imports can only refer to extern crate names passed with \
+ `--extern` in macros originating from 2015 edition";
+ let mut err = self.session.struct_span_err(ident.span, msg);
let what = self.binding_description(binding, ident,
flags.contains(Flags::MISC_FROM_PRELUDE));
let note_msg = format!("this import refers to {what}", what = what);
}
}
+ fn prohibit_imported_non_macro_attrs(&self, binding: Option<&'a NameBinding<'a>>,
+ def: Option<Def>, span: Span) {
+ if let Some(Def::NonMacroAttr(kind)) = def {
+ if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) {
+ let msg = format!("cannot use a {} through an import", kind.descr());
+ let mut err = self.session.struct_span_err(span, &msg);
+ if let Some(binding) = binding {
+ err.span_note(binding.span, &format!("the {} imported here", kind.descr()));
+ }
+ err.emit();
+ }
+ }
+ }
+
fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
err: &mut DiagnosticBuilder<'a>, span: Span) {
// First check if this is a locally-defined bang macro.
let ident = ident.modern();
self.macro_names.insert(ident);
let def = Def::Macro(def_id, MacroKind::Bang);
- let vis = ty::Visibility::Invisible; // Doesn't matter for legacy bindings
+ let is_macro_export = attr::contains_name(&item.attrs, "macro_export");
+ let vis = if is_macro_export {
+ ty::Visibility::Public
+ } else {
+ ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
+ };
let binding = (def, vis, item.span, expansion).to_name_binding(self.arenas);
self.set_binding_parent_module(binding, self.current_module);
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
});
*current_legacy_scope = LegacyScope::Binding(legacy_binding);
self.all_macros.insert(ident.name, def);
- if attr::contains_name(&item.attrs, "macro_export") {
+ if is_macro_export {
let module = self.graph_root;
- let vis = ty::Visibility::Public;
self.define(module, ident, MacroNS,
(def, vis, item.span, expansion, IsMacroExport));
} else {
}
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
+ if let Some(blacklisted_binding) = this.blacklisted_binding {
+ if ptr::eq(binding, blacklisted_binding) {
+ return Err((Determined, Weak::No));
+ }
+ }
// `extern crate` are always usable for backwards compatibility, see issue #37020,
// remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
//! recording the output.
use rustc::hir::def::Def as HirDef;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::DefId;
use rustc::session::config::Input;
use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
($save_ctxt:expr, $vis:expr, $id:expr) => {
Access {
public: $vis.node.is_pub(),
- reachable: $save_ctxt.tcx.privacy_access_levels(LOCAL_CRATE).is_reachable($id),
+ reachable: $save_ctxt.access_levels.is_reachable($id),
}
};
($save_ctxt:expr, $item:expr) => {
Access {
public: $item.vis.node.is_pub(),
- reachable: $save_ctxt.tcx.privacy_access_levels(LOCAL_CRATE).is_reachable($item.id),
+ reachable: $save_ctxt.access_levels.is_reachable($item.id),
}
};
}
use rustc::hir::def::Def as HirDef;
use rustc::hir::Node;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::middle::privacy::AccessLevels;
use rustc::middle::cstore::ExternCrate;
use rustc::session::config::{CrateType, Input, OutputType};
use rustc::ty::{self, TyCtxt};
use rustc_typeck::hir_ty_to_ty;
use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
+use rustc_data_structures::sync::Lrc;
use std::cell::Cell;
use std::default::Default;
pub struct SaveContext<'l, 'tcx: 'l> {
tcx: TyCtxt<'l, 'tcx, 'tcx>,
tables: &'l ty::TypeckTables<'tcx>,
+ access_levels: &'l AccessLevels,
analysis: &'l ty::CrateAnalysis,
span_utils: SpanUtils<'tcx>,
config: Config,
Node::Visibility(&Spanned {
node: hir::VisibilityKind::Restricted { ref path, .. }, .. }) => path.def,
- Node::PathSegment(seg) => match seg.def {
- Some(def) => def,
- None => HirDef::Err,
+ Node::PathSegment(seg) => {
+ match seg.def {
+ Some(def) if def != HirDef::Err => def,
+ _ => self.get_path_def(self.tcx.hir().get_parent_node(id)),
+ }
},
Node::Expr(&hir::Expr {
node: hir::ExprKind::Struct(ref qpath, ..),
info!("Dumping crate {}", cratename);
+ // Privacy checking requires and is done after type checking; use a
+ // fallback in case the access levels couldn't have been correctly computed.
+ let access_levels = match tcx.sess.compile_status() {
+ Ok(..) => tcx.privacy_access_levels(LOCAL_CRATE),
+ Err(..) => Lrc::new(AccessLevels::default()),
+ };
+
let save_ctxt = SaveContext {
tcx,
tables: &ty::TypeckTables::empty(None),
analysis,
+ access_levels: &access_levels,
span_utils: SpanUtils::new(&tcx.sess),
config: find_config(config),
impl_counter: Cell::new(0),
use super::report_unexpected_variant_def;
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
- /// The `is_arg` argument indicates whether this pattern is the
- /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
- /// &u32)`, it is true for the `&x` pattern but not `x`). This is
- /// used to tailor error reporting.
+ /// `match_discrim_span` argument having a `Span` indicates that this pattern is part of
+ /// a match expression arm guard, and it points to the match discriminant to add context
+ /// in type errors. In the folloowing example, `match_discrim_span` corresponds to the
+ /// `a + b` expression:
+ ///
+ /// ```text
+ /// error[E0308]: mismatched types
+ /// --> src/main.rs:5:9
+ /// |
+ /// 4 | let temp: usize = match a + b {
+ /// | ----- this expression has type `usize`
+ /// 5 | Ok(num) => num,
+ /// | ^^^^^^^ expected usize, found enum `std::result::Result`
+ /// |
+ /// = note: expected type `usize`
+ /// found type `std::result::Result<_, _>`
+ /// ```
pub fn check_pat_walk(
&self,
pat: &'gcx hir::Pat,
mut expected: Ty<'tcx>,
mut def_bm: ty::BindingMode,
- is_arg: bool)
- {
+ match_discrim_span: Option<Span>,
+ ) {
let tcx = self.tcx;
- debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?},is_arg={})",
- pat, expected, def_bm, is_arg);
+ debug!("check_pat_walk(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm);
let is_non_ref_pat = match pat.node {
PatKind::Struct(..) |
let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
// subtyping doesn't matter here, as the value is some kind of scalar
- self.demand_eqtype(pat.span, expected, lhs_ty);
- self.demand_eqtype(pat.span, expected, rhs_ty);
+ self.demand_eqtype_pat(pat.span, expected, lhs_ty, match_discrim_span);
+ self.demand_eqtype_pat(pat.span, expected, rhs_ty, match_discrim_span);
common_type
}
PatKind::Binding(ba, var_id, _, ref sub) => {
// `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
// required. However, we use equality, which is stronger. See (*) for
// an explanation.
- self.demand_eqtype(pat.span, region_ty, local_ty);
+ self.demand_eqtype_pat(pat.span, region_ty, local_ty, match_discrim_span);
}
// otherwise the type of x is the expected type T
ty::BindByValue(_) => {
// As above, `T <: typeof(x)` is required but we
// use equality, see (*) below.
- self.demand_eqtype(pat.span, expected, local_ty);
+ self.demand_eqtype_pat(pat.span, expected, local_ty, match_discrim_span);
}
}
// what the type of the binding `x` ought to be
if var_id != pat.id {
let vt = self.local_ty(pat.span, var_id).decl_ty;
- self.demand_eqtype(pat.span, vt, local_ty);
+ self.demand_eqtype_pat(pat.span, vt, local_ty, match_discrim_span);
}
if let Some(ref p) = *sub {
- self.check_pat_walk(&p, expected, def_bm, true);
+ self.check_pat_walk(&p, expected, def_bm, match_discrim_span);
}
local_ty
}
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
- self.check_pat_tuple_struct(pat, qpath, &subpats, ddpos, expected, def_bm)
+ self.check_pat_tuple_struct(
+ pat,
+ qpath,
+ &subpats,
+ ddpos,
+ expected,
+ def_bm,
+ match_discrim_span,
+ )
}
PatKind::Path(ref qpath) => {
self.check_pat_path(pat, qpath, expected)
}
PatKind::Struct(ref qpath, ref fields, etc) => {
- self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm)
+ self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, match_discrim_span)
}
PatKind::Tuple(ref elements, ddpos) => {
let mut expected_len = elements.len();
// further errors being emitted when using the bindings. #50333
let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
- self.check_pat_walk(elem, &tcx.types.err, def_bm, true);
+ self.check_pat_walk(elem, &tcx.types.err, def_bm, match_discrim_span);
}
tcx.mk_tup(element_tys_iter)
} else {
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
- self.check_pat_walk(elem, &element_tys[i], def_bm, true);
+ self.check_pat_walk(elem, &element_tys[i], def_bm, match_discrim_span);
}
pat_ty
}
// Here, `demand::subtype` is good enough, but I don't
// think any errors can be introduced by using
// `demand::eqtype`.
- self.demand_eqtype(pat.span, expected, uniq_ty);
- self.check_pat_walk(&inner, inner_ty, def_bm, true);
+ self.demand_eqtype_pat(pat.span, expected, uniq_ty, match_discrim_span);
+ self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
uniq_ty
} else {
- self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
+ self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
tcx.types.err
}
}
// Look for a case like `fn foo(&foo: u32)` and suggest
// `fn foo(foo: &u32)`
if let Some(mut err) = err {
- if is_arg {
- if let PatKind::Binding(..) = inner.node {
- if let Ok(snippet) = tcx.sess.source_map()
- .span_to_snippet(pat.span)
- {
- err.help(&format!("did you mean `{}: &{}`?",
- &snippet[1..],
- expected));
- }
+ if let PatKind::Binding(..) = inner.node {
+ if let Ok(snippet) = tcx.sess.source_map()
+ .span_to_snippet(pat.span)
+ {
+ err.help(&format!("did you mean `{}: &{}`?",
+ &snippet[1..],
+ expected));
}
}
err.emit();
}
};
- self.check_pat_walk(&inner, inner_ty, def_bm, true);
+ self.check_pat_walk(&inner, inner_ty, def_bm, match_discrim_span);
rptr_ty
} else {
- self.check_pat_walk(&inner, tcx.types.err, def_bm, true);
+ self.check_pat_walk(&inner, tcx.types.err, def_bm, match_discrim_span);
tcx.types.err
}
}
};
for elt in before {
- self.check_pat_walk(&elt, inner_ty, def_bm, true);
+ self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
}
if let Some(ref slice) = *slice {
- self.check_pat_walk(&slice, slice_ty, def_bm, true);
+ self.check_pat_walk(&slice, slice_ty, def_bm, match_discrim_span);
}
for elt in after {
- self.check_pat_walk(&elt, inner_ty, def_bm, true);
+ self.check_pat_walk(&elt, inner_ty, def_bm, match_discrim_span);
}
expected_ty
}
true
}
- pub fn check_match(&self,
- expr: &'gcx hir::Expr,
- discrim: &'gcx hir::Expr,
- arms: &'gcx [hir::Arm],
- expected: Expectation<'tcx>,
- match_src: hir::MatchSource) -> Ty<'tcx> {
+ pub fn check_match(
+ &self,
+ expr: &'gcx hir::Expr,
+ discrim: &'gcx hir::Expr,
+ arms: &'gcx [hir::Arm],
+ expected: Expectation<'tcx>,
+ match_src: hir::MatchSource,
+ ) -> Ty<'tcx> {
let tcx = self.tcx;
// Not entirely obvious: if matches may create ref bindings, we want to
let mut all_pats_diverge = Diverges::WarnedAlways;
for p in &arm.pats {
self.diverges.set(Diverges::Maybe);
- self.check_pat_walk(&p, discrim_ty,
- ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
+ self.check_pat_walk(
+ &p,
+ discrim_ty,
+ ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
+ Some(discrim.span),
+ );
all_pats_diverge &= self.diverges.get();
}
coercion.complete(self)
}
- fn check_pat_struct(&self,
- pat: &'gcx hir::Pat,
- qpath: &hir::QPath,
- fields: &'gcx [Spanned<hir::FieldPat>],
- etc: bool,
- expected: Ty<'tcx>,
- def_bm: ty::BindingMode) -> Ty<'tcx>
+ fn check_pat_struct(
+ &self,
+ pat: &'gcx hir::Pat,
+ qpath: &hir::QPath,
+ fields: &'gcx [Spanned<hir::FieldPat>],
+ etc: bool,
+ expected: Ty<'tcx>,
+ def_bm: ty::BindingMode,
+ match_discrim_span: Option<Span>,
+ ) -> Ty<'tcx>
{
// Resolve the path and check the definition for errors.
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.id) {
variant_ty
} else {
for field in fields {
- self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, true);
+ self.check_pat_walk(
+ &field.node.pat,
+ self.tcx.types.err,
+ def_bm,
+ match_discrim_span,
+ );
}
return self.tcx.types.err;
};
// Type-check the path.
- self.demand_eqtype(pat.span, expected, pat_ty);
+ self.demand_eqtype_pat(pat.span, expected, pat_ty, match_discrim_span);
// Type-check subpatterns.
if self.check_struct_pat_fields(pat_ty, pat.id, pat.span, variant, fields, etc, def_bm) {
}
}
- fn check_pat_path(&self,
- pat: &hir::Pat,
- qpath: &hir::QPath,
- expected: Ty<'tcx>) -> Ty<'tcx>
- {
+ fn check_pat_path(
+ &self,
+ pat: &hir::Pat,
+ qpath: &hir::QPath,
+ expected: Ty<'tcx>,
+ ) -> Ty<'tcx> {
let tcx = self.tcx;
// Resolve the path and check the definition for errors.
pat_ty
}
- fn check_pat_tuple_struct(&self,
- pat: &hir::Pat,
- qpath: &hir::QPath,
- subpats: &'gcx [P<hir::Pat>],
- ddpos: Option<usize>,
- expected: Ty<'tcx>,
- def_bm: ty::BindingMode) -> Ty<'tcx>
- {
+ fn check_pat_tuple_struct(
+ &self,
+ pat: &hir::Pat,
+ qpath: &hir::QPath,
+ subpats: &'gcx [P<hir::Pat>],
+ ddpos: Option<usize>,
+ expected: Ty<'tcx>,
+ def_bm: ty::BindingMode,
+ match_arm_pat_span: Option<Span>,
+ ) -> Ty<'tcx> {
let tcx = self.tcx;
let on_error = || {
for pat in subpats {
- self.check_pat_walk(&pat, tcx.types.err, def_bm, true);
+ self.check_pat_walk(&pat, tcx.types.err, def_bm, match_arm_pat_span);
}
};
let report_unexpected_def = |def: Def| {
let pat_ty = pat_ty.fn_sig(tcx).output();
let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
- self.demand_eqtype(pat.span, expected, pat_ty);
+ self.demand_eqtype_pat(pat.span, expected, pat_ty, match_arm_pat_span);
// Type-check subpatterns.
if subpats.len() == variant.fields.len() ||
};
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
- self.check_pat_walk(&subpat, field_ty, def_bm, true);
+ self.check_pat_walk(&subpat, field_ty, def_bm, match_arm_pat_span);
self.tcx.check_stability(variant.fields[i].did, Some(pat.id), subpat.span);
}
}
};
- self.check_pat_walk(&field.pat, field_ty, def_bm, true);
+ self.check_pat_walk(&field.pat, field_ty, def_bm, None);
}
let mut unmentioned_fields = variant.fields
.iter()
fcx.ty_to_string(self.expr_ty),
cast_ty));
if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr.span) {
- err.span_help(self.expr.span,
- &format!("did you mean `*{}`?", snippet));
+ err.span_suggestion_with_applicability(
+ self.expr.span,
+ "dereference the expression",
+ format!("*{}", snippet),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_help(self.expr.span, "dereference the expression with `*`");
}
err.emit();
}
use check::FnCtxt;
use rustc::infer::InferOk;
-use rustc::traits::ObligationCause;
+use rustc::traits::{ObligationCause, ObligationCauseCode};
use syntax::ast;
use syntax::util::parser::PREC_POSTFIX;
}
}
+ pub fn demand_eqtype_pat(
+ &self,
+ cause_span: Span,
+ expected: Ty<'tcx>,
+ actual: Ty<'tcx>,
+ match_expr_span: Option<Span>,
+ ) {
+ let cause = if let Some(span) = match_expr_span {
+ self.cause(
+ cause_span,
+ ObligationCauseCode::MatchExpressionArmPattern { span, ty: expected },
+ )
+ } else {
+ self.misc(cause_span)
+ };
+ self.demand_eqtype_with_origin(&cause, expected, actual).map(|mut err| err.emit());
+ }
+
+
pub fn demand_coerce(&self,
expr: &hir::Expr,
checked_ty: Ty<'tcx>,
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
}
+/// Returns whether the given intrinsic is unsafe to call or not.
+pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
+ match intrinsic {
+ "size_of" | "min_align_of" | "needs_drop" |
+ "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
+ "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
+ "rotate_left" | "rotate_right" |
+ "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse"
+ => hir::Unsafety::Normal,
+ _ => hir::Unsafety::Unsafe,
+ }
+}
+
/// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs,
/// and in libcore/intrinsics.rs
pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} else if &name[..] == "abort" || &name[..] == "unreachable" {
(0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe)
} else {
- let unsafety = match &name[..] {
- "size_of" | "min_align_of" | "needs_drop" => hir::Unsafety::Normal,
- _ => hir::Unsafety::Unsafe,
- };
+ let unsafety = intrisic_operation_unsafety(&name[..]);
let (n_tps, inputs, output) = match &name[..] {
"breakpoint" => (0, Vec::new(), tcx.mk_unit()),
"size_of" |
mod callee;
mod compare_method;
mod generator_interior;
-mod intrinsic;
+pub mod intrinsic;
mod op;
use astconv::{AstConv, PathSeg};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers;
+use rustc::ty::query::queries;
use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts};
use rustc::ty::util::{Representability, IntTypeExt, Discr};
use rustc::ty::layout::VariantIdx;
pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.sess.track_errors(|| {
- tcx.hir().krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx });
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::check_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module));
+ }
})
}
+fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
+}
+
pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> {
tcx.typeck_item_bodies(LOCAL_CRATE)
}
check_item_well_formed,
check_trait_item_well_formed,
check_impl_item_well_formed,
+ check_mod_item_types,
..*providers
};
}
// Add formal parameters.
for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
// Check the pattern.
- fcx.check_pat_walk(&arg.pat, arg_ty,
- ty::BindingMode::BindByValue(hir::Mutability::MutImmutable), true);
+ fcx.check_pat_walk(
+ &arg.pat,
+ arg_ty,
+ ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
+ None,
+ );
// Check that argument is Sized.
// The check for a non-trivial pattern is a hack to avoid duplicate warnings
let coerce_to_ty = expected.coercion_target_type(self, sp);
let mut coerce: DynamicCoerceMany = CoerceMany::new(coerce_to_ty);
- let if_cause = self.cause(sp, ObligationCauseCode::IfExpression);
- coerce.coerce(self, &if_cause, then_expr, then_ty);
+ coerce.coerce(self, &self.misc(sp), then_expr, then_ty);
if let Some(else_expr) = opt_else_expr {
let else_ty = self.check_expr_with_expectation(else_expr, expected);
let else_diverges = self.diverges.get();
+ let mut outer_sp = if self.tcx.sess.source_map().is_multiline(sp) {
+ // The `if`/`else` isn't in one line in the output, include some context to make it
+ // clear it is an if/else expression:
+ // ```
+ // LL | let x = if true {
+ // | _____________-
+ // LL || 10i32
+ // || ----- expected because of this
+ // LL || } else {
+ // LL || 10u32
+ // || ^^^^^ expected i32, found u32
+ // LL || };
+ // ||_____- if and else have incompatible types
+ // ```
+ Some(sp)
+ } else {
+ // The entire expression is in one line, only point at the arms
+ // ```
+ // LL | let x = if true { 10i32 } else { 10u32 };
+ // | ----- ^^^^^ expected i32, found u32
+ // | |
+ // | expected because of this
+ // ```
+ None
+ };
+ let mut remove_semicolon = None;
+ let error_sp = if let ExprKind::Block(block, _) = &else_expr.node {
+ if let Some(expr) = &block.expr {
+ expr.span
+ } else if let Some(stmt) = block.stmts.last() {
+ // possibly incorrect trailing `;` in the else arm
+ remove_semicolon = self.could_remove_semicolon(block, then_ty);
+ stmt.span
+ } else { // empty block, point at its entirety
+ // Avoid overlapping spans that aren't as readable:
+ // ```
+ // 2 | let x = if true {
+ // | _____________-
+ // 3 | | 3
+ // | | - expected because of this
+ // 4 | | } else {
+ // | |____________^
+ // 5 | ||
+ // 6 | || };
+ // | || ^
+ // | ||_____|
+ // | |______if and else have incompatible types
+ // | expected integer, found ()
+ // ```
+ // by not pointing at the entire expression:
+ // ```
+ // 2 | let x = if true {
+ // | ------- if and else have incompatible types
+ // 3 | 3
+ // | - expected because of this
+ // 4 | } else {
+ // | ____________^
+ // 5 | |
+ // 6 | | };
+ // | |_____^ expected integer, found ()
+ // ```
+ if outer_sp.is_some() {
+ outer_sp = Some(self.tcx.sess.source_map().def_span(sp));
+ }
+ else_expr.span
+ }
+ } else { // shouldn't happen unless the parser has done something weird
+ else_expr.span
+ };
+ let then_sp = if let ExprKind::Block(block, _) = &then_expr.node {
+ if let Some(expr) = &block.expr {
+ expr.span
+ } else if let Some(stmt) = block.stmts.last() {
+ // possibly incorrect trailing `;` in the else arm
+ remove_semicolon = remove_semicolon.or(
+ self.could_remove_semicolon(block, else_ty));
+ stmt.span
+ } else { // empty block, point at its entirety
+ outer_sp = None; // same as in `error_sp`, cleanup output
+ then_expr.span
+ }
+ } else { // shouldn't happen unless the parser has done something weird
+ then_expr.span
+ };
+
+ let if_cause = self.cause(error_sp, ObligationCauseCode::IfExpression {
+ then: then_sp,
+ outer: outer_sp,
+ semicolon: remove_semicolon,
+ });
+
coerce.coerce(self, &if_cause, else_expr, else_ty);
// We won't diverge unless both branches do (or the condition does).
}
}
- self.check_pat_walk(&local.pat, t,
- ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
- true);
+ self.check_pat_walk(
+ &local.pat,
+ t,
+ ty::BindingMode::BindByValue(hir::Mutability::MutImmutable),
+ None,
+ );
let pat_ty = self.node_ty(local.pat.hir_id);
if pat_ty.references_error() {
self.write_ty(local.hir_id, pat_ty);
}
}
-
/// A common error is to add an extra semicolon:
///
/// ```
/// This routine checks if the final statement in a block is an
/// expression with an explicit semicolon whose type is compatible
/// with `expected_ty`. If so, it suggests removing the semicolon.
- fn consider_hint_about_removing_semicolon(&self,
- blk: &'gcx hir::Block,
- expected_ty: Ty<'tcx>,
- err: &mut DiagnosticBuilder) {
+ fn consider_hint_about_removing_semicolon(
+ &self,
+ blk: &'gcx hir::Block,
+ expected_ty: Ty<'tcx>,
+ err: &mut DiagnosticBuilder,
+ ) {
+ if let Some(span_semi) = self.could_remove_semicolon(blk, expected_ty) {
+ err.span_suggestion_with_applicability(
+ span_semi,
+ "consider removing this semicolon",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ fn could_remove_semicolon(
+ &self,
+ blk: &'gcx hir::Block,
+ expected_ty: Ty<'tcx>,
+ ) -> Option<Span> {
// Be helpful when the user wrote `{... expr;}` and
// taking the `;` off is enough to fix the error.
let last_stmt = match blk.stmts.last() {
Some(s) => s,
- None => return,
+ None => return None,
};
let last_expr = match last_stmt.node {
hir::StmtKind::Semi(ref e, _) => e,
- _ => return,
+ _ => return None,
};
let last_expr_ty = self.node_ty(last_expr.hir_id);
if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() {
- return;
+ return None;
}
let original_span = original_sp(last_stmt.span, blk.span);
- let span_semi = original_span.with_lo(original_span.hi() - BytePos(1));
- err.span_suggestion_with_applicability(
- span_semi,
- "consider removing this semicolon",
- String::new(),
- Applicability::MachineApplicable);
+ Some(original_span.with_lo(original_span.hi() - BytePos(1)))
}
// Instantiates the given path, which must refer to an item with the given
};
self.tcx.with_freevars(closure_node_id, |freevars| {
+ let mut freevar_list: Vec<ty::UpvarId> = Vec::with_capacity(freevars.len());
for freevar in freevars {
let upvar_id = ty::UpvarId {
var_path: ty::UpvarPath {
- hir_id : self.tcx.hir().node_to_hir_id(freevar.var_id()),
+ hir_id: self.tcx.hir().node_to_hir_id(freevar.var_id()),
},
closure_expr_id: LocalDefId::from_def_id(closure_def_id),
};
debug!("seed upvar_id {:?}", upvar_id);
+ // Adding the upvar Id to the list of Upvars, which will be added
+ // to the map for the closure at the end of the for loop.
+ freevar_list.push(upvar_id);
let capture_kind = match capture_clause {
hir::CaptureByValue => ty::UpvarCapture::ByValue,
.upvar_capture_map
.insert(upvar_id, capture_kind);
}
+ // Add the vector of freevars to the map keyed with the closure id.
+ // This gives us an easier access to them without having to call
+ // with_freevars again..
+ if !freevar_list.is_empty() {
+ self.tables
+ .borrow_mut()
+ .upvar_list
+ .insert(closure_def_id, freevar_list);
+ }
});
let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id());
self.param_env,
region_scope_tree,
&self.tables.borrow(),
- ).consume_body(body);
+ )
+ .consume_body(body);
if let Some(closure_substs) = infer_kind {
// Unify the (as yet unbound) type variable in the closure
let var_hir_id = tcx.hir().node_to_hir_id(var_node_id);
let freevar_ty = self.node_ty(var_hir_id);
let upvar_id = ty::UpvarId {
- var_path: ty::UpvarPath {
- hir_id: var_hir_id,
- },
+ var_path: ty::UpvarPath { hir_id: var_hir_id },
closure_expr_id: LocalDefId::from_def_id(closure_def_index),
};
let capture = self.tables.borrow().upvar_capture(upvar_id);
},
),
}
- }).collect()
+ })
+ .collect()
})
}
}
///////////////////////////////////////////////////////////////////////////
// Entry point
+// During type inference, partially inferred types are
+// represented using Type variables (ty::Infer). These don't appear in
+// the final TypeckTables since all of the types should have been
+// inferred once typeck_tables_of is done.
+// When type inference is running however, having to update the typeck
+// tables every time a new type is inferred would be unreasonably slow,
+// so instead all of the replacement happens at the end in
+// resolve_type_vars_in_body, which creates a new TypeTables which
+// doesn't contain any inference types.
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::TypeckTables<'gcx> {
let item_id = self.tcx.hir().body_owner(body.id());
wbcx.visit_node_id(arg.pat.span, arg.hir_id);
}
wbcx.visit_body(body);
- wbcx.visit_upvar_borrow_map();
+ wbcx.visit_upvar_capture_map();
+ wbcx.visit_upvar_list_map();
wbcx.visit_closures();
wbcx.visit_liberated_fn_sigs();
wbcx.visit_fru_field_types();
}
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
- fn visit_upvar_borrow_map(&mut self) {
+ fn visit_upvar_capture_map(&mut self) {
for (upvar_id, upvar_capture) in self.fcx.tables.borrow().upvar_capture_map.iter() {
let new_upvar_capture = match *upvar_capture {
ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue,
}
}
+ /// Runs through the function context's upvar list map and adds the same to
+ /// the TypeckTables. upvarlist is a hashmap of the list of upvars referred
+ /// to in a closure..
+ fn visit_upvar_list_map(&mut self) {
+ for (closure_def_id, upvar_list) in self.fcx.tables.borrow().upvar_list.iter() {
+ debug!(
+ "UpvarIDs captured by closure {:?} are: {:?}",
+ closure_def_id, upvar_list
+ );
+ self.tables
+ .upvar_list
+ .insert(*closure_def_id, upvar_list.to_vec());
+ }
+ }
+
fn visit_closures(&mut self) {
let fcx_tables = self.fcx.tables.borrow();
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
"only traits defined in the current crate can be \
implemented for arbitrary types")
.span_label(sp, "impl doesn't use types inside crate")
- .note("the impl does not reference any types defined in this crate")
+ .note("the impl does not reference only types defined in this crate")
.note("define and implement a trait or new type instead")
.emit();
return;
use astconv::{AstConv, Bounds};
use constrained_type_params as ctp;
+use check::intrinsic::intrisic_operation_unsafety;
use lint;
use middle::lang_items::SizedTraitLangItem;
use middle::resolve_lifetime as rl;
use middle::weak_lang_items;
use rustc::mir::mono::Linkage;
use rustc::ty::query::Providers;
+use rustc::ty::query::queries;
use rustc::ty::subst::Substs;
use rustc::ty::util::Discr;
use rustc::ty::util::IntTypeExt;
// Main entry point
pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let mut visitor = CollectItemTypesVisitor { tcx };
- tcx.hir()
- .krate()
- .visit_all_item_likes(&mut visitor.as_deep_visitor());
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::collect_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module));
+ }
+}
+
+fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(
+ module_def_id,
+ &mut CollectItemTypesVisitor { tcx }.as_deep_visitor()
+ );
}
pub fn provide(providers: &mut Providers) {
impl_polarity,
is_foreign_item,
codegen_fn_attrs,
+ collect_mod_item_types,
..*providers
};
}
tcx.sess,
span,
E0202,
- "associated types are not allowed in inherent impls"
+ "associated types are not yet supported in inherent impls (see #8995)"
);
}
abi: abi::Abi,
) -> ty::PolyFnSig<'tcx> {
let unsafety = if abi == abi::Abi::RustIntrinsic {
- match &*tcx.item_name(def_id).as_str() {
- "size_of" | "min_align_of" | "needs_drop" => hir::Unsafety::Normal,
- _ => hir::Unsafety::Unsafe,
- }
+ intrisic_operation_unsafety(&*tcx.item_name(def_id).as_str())
} else {
hir::Unsafety::Unsafe
};
let attrs = self.attrs.clean(cx);
let mut items: Vec<Item> = vec![];
- items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
+ items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
items.extend(self.structs.iter().map(|x| x.clean(cx)));
items.extend(self.unions.iter().map(|x| x.clean(cx)));
}
}
-impl Clean<Item> for doctree::ExternCrate {
- fn clean(&self, cx: &DocContext) -> Item {
- Item {
+impl Clean<Vec<Item>> for doctree::ExternCrate {
+ fn clean(&self, cx: &DocContext) -> Vec<Item> {
+
+ let please_inline = self.vis.node.is_pub() && self.attrs.iter().any(|a| {
+ a.name() == "doc" && match a.meta_item_list() {
+ Some(l) => attr::list_contains_name(&l, "inline"),
+ None => false,
+ }
+ });
+
+ if please_inline {
+ let mut visited = FxHashSet::default();
+
+ let def = Def::Mod(DefId {
+ krate: self.cnum,
+ index: CRATE_DEF_INDEX,
+ });
+
+ if let Some(items) = inline::try_inline(cx, def, self.name, &mut visited) {
+ return items;
+ }
+ }
+
+ vec![Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
stability: None,
deprecation: None,
inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
- }
+ }]
}
}
static_files::fira_sans::MEDIUM)?;
write(cx.dst.join("FiraSans-LICENSE.txt"),
static_files::fira_sans::LICENSE)?;
- write(cx.dst.join("Heuristica-Italic.woff"),
- static_files::heuristica::ITALIC)?;
- write(cx.dst.join("Heuristica-LICENSE.txt"),
- static_files::heuristica::LICENSE)?;
- write(cx.dst.join("SourceSerifPro-Regular.woff"),
+ write(cx.dst.join("SourceSerifPro-Regular.ttf.woff"),
static_files::source_serif_pro::REGULAR)?;
- write(cx.dst.join("SourceSerifPro-Bold.woff"),
+ write(cx.dst.join("SourceSerifPro-Bold.ttf.woff"),
static_files::source_serif_pro::BOLD)?;
+ write(cx.dst.join("SourceSerifPro-It.ttf.woff"),
+ static_files::source_serif_pro::ITALIC)?;
write(cx.dst.join("SourceSerifPro-LICENSE.txt"),
static_files::source_serif_pro::LICENSE)?;
write(cx.dst.join("SourceCodePro-Regular.woff"),
let item_type = m.type_();
let id = cx.derive_id(format!("{}.{}", item_type, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
- write!(w, "{extra}<h3 id='{id}' class='method'><code id='{ns_id}'>",
+ write!(w, "<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
extra = render_spotlight_traits(m)?,
id = id,
ns_id = ns_id)?;
let id = format!("{}.{}", ItemType::StructField, name);
write!(w, "<span id=\"{id}\" class=\"{shortty} small-section-header\">\
<a href=\"#{id}\" class=\"anchor field\"></a>\
- <span class='invisible'><code>{name}: {ty}</code></span>\
+ <code>{name}: {ty}</code>\
</span>",
id = id,
name = name,
None => "impl".to_string(),
});
if let Some(use_absolute) = use_absolute {
- write!(w, "<h3 id='{}' class='impl'><span class='in-band'><table class='table-display'>\
- <tbody><tr><td><code>", id)?;
+ write!(w, "<h3 id='{}' class='impl'><code class='in-band'>", id)?;
fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute)?;
if show_def_docs {
for it in &i.inner_impl().items {
}
write!(w, "</code>")?;
} else {
- write!(w, "<h3 id='{}' class='impl'><span class='in-band'><table class='table-display'>\
- <tbody><tr><td><code>{}</code>",
- id, i.inner_impl())?;
+ write!(w, "<h3 id='{}' class='impl'><code class='in-band'>{}</code>",
+ id, i.inner_impl()
+ )?;
}
write!(w, "<a href='#{}' class='anchor'></a>", id)?;
- write!(w, "</td><td><span class='out-of-band'>")?;
let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
+ render_stability_since_raw(w, since, outer_version)?;
if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
- write!(w, "<div class='ghost'></div>")?;
- render_stability_since_raw(w, since, outer_version)?;
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
l, "goto source code")?;
- } else {
- render_stability_since_raw(w, since, outer_version)?;
}
- write!(w, "</span></td></tr></tbody></table></span></h3>")?;
+ write!(w, "</h3>")?;
if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
let mut ids = cx.id_map.borrow_mut();
write!(w, "<div class='docblock'>{}</div>",
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
write!(w, "{}", spotlight_decl(decl)?)?;
- write!(w, "<table id='{}' class='table-display'><tbody><tr><td><code>", ns_id)?;
+ write!(w, "<code id='{}'>", ns_id)?;
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
write!(w, "</code>")?;
+ render_stability_since_raw(w, item.stable_since(), outer_version)?;
if let Some(l) = (Item { cx, item }).src_href() {
- write!(w, "</td><td><span class='out-of-band'>")?;
- write!(w, "<div class='ghost'></div>")?;
- render_stability_since_raw(w, item.stable_since(), outer_version)?;
- write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a></span>",
+ write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
l, "goto source code")?;
- } else {
- write!(w, "</td><td>")?;
- render_stability_since_raw(w, item.stable_since(), outer_version)?;
}
- write!(w, "</td></tr></tbody></table></h4>")?;
+ write!(w, "</h4>")?;
}
}
clean::TypedefItem(ref tydef, _) => {
write!(w, "</code></h4>")?;
}
clean::AssociatedConstItem(ref ty, ref default) => {
- let mut version = String::new();
-
- render_stability_since_raw(&mut version, item.stable_since(), outer_version)?;
-
let id = cx.derive_id(format!("{}.{}", item_type, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
- if !version.is_empty() {
- write!(w, "<table id='{}' class='table-display'><tbody><tr><td><code>", ns_id)?;
- } else {
- write!(w, "<code id='{}'>", ns_id)?;
- }
+ write!(w, "<code id='{}'>", ns_id)?;
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
- if !version.is_empty() {
- write!(w, "</code>")?;
- }
- let src = if let Some(l) = (Item { cx, item }).src_href() {
- if !version.is_empty() {
- write!(w, "</td><td><span class='out-of-band'>")?;
- write!(w, "<div class='ghost'></div>{}", version)?;
- }
- format!("<a class='srclink' href='{}' title='{}'>[src]</a>",
- l, "goto source code")
- } else {
- if !version.is_empty() {
- write!(w, "</td><td>{}", version)?;
- }
- String::new()
- };
- if version.is_empty() {
- write!(w, "</code>{}</h4>", src)?;
- } else {
- write!(w, "{}</span></td></tr></tbody></table></h4>", src)?;
+ write!(w, "</code>")?;
+ render_stability_since_raw(w, item.stable_since(), outer_version)?;
+ if let Some(l) = (Item { cx, item }).src_href() {
+ write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
+ l, "goto source code")?;
}
+ write!(w, "</h4>")?;
}
clean::AssociatedTypeItem(ref bounds, ref default) => {
let id = cx.derive_id(format!("{}.{}", item_type, name));
Licensed under the SIL Open Font License, Version 1.1.
See FiraSans-LICENSE.txt.
-* Heuristica (Heuristica-Italic.woff):
-
- Copyright 1989, 1991 Adobe Systems Incorporated. All rights reserved.
- Utopia is either a registered trademark or trademark of Adobe Systems
- Incorporated in the United States and/or other countries. Used under
- license.
-
- Copyright 2006 Han The Thanh, Vntopia font family, http://vntex.sf.net
-
- Copyright (c) 2008-2012, Andrey V. Panov (panov@canopus.iacp.dvo.ru),
- with Reserved Font Name Heuristica.
-
- Licensed under the SIL Open Font License, Version 1.1.
- See Heuristica-LICENSE.txt.
-
* rustdoc.css, main.js, and playpen.js:
Copyright 2015 The Rust Developers.
Licensed under the SIL Open Font License, Version 1.1.
See SourceCodePro-LICENSE.txt.
-* Source Serif Pro (SourceSerifPro-Regular.woff, SourceSerifPro-Bold.woff):
+* Source Serif Pro (SourceSerifPro-Regular.ttf.woff,
+ SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff):
Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with
Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of
+++ /dev/null
-Copyright 1989, 1991 Adobe Systems Incorporated. All rights reserved.
-Utopia is either a registered trademark or trademark of Adobe Systems
-Incorporated in the United States and/or other countries. Used under
-license.
-
-Copyright 2006 Han The Thanh, Vntopia font family, http://vntex.sf.net
-
-Copyright (c) 2008-2012, Andrey V. Panov (panov@canopus.iacp.dvo.ru),
-with Reserved Font Name Heuristica.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
e.remove();
});
onEachLazy(main.childNodes, function(e) {
+ // Unhide the actual content once loading is complete. Headers get
+ // flex treatment for their horizontal layout, divs get block treatment
+ // for vertical layout (column-oriented flex layout for divs caused
+ // errors in mobile browsers).
if (e.tagName === "H2" || e.tagName === "H3") {
- e.nextElementSibling.style.display = "block";
+ let nextTagName = e.nextElementSibling.tagName;
+ if (nextTagName == "H2" || nextTagName == "H3") {
+ e.nextElementSibling.style.display = "flex";
+ } else {
+ e.nextElementSibling.style.display = "block";
+ }
}
});
}
src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
}
-/* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license and
- * Heuristica-LICENSE.txt for the Heuristica license. */
+/* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license. */
@font-face {
font-family: 'Source Serif Pro';
font-style: normal;
font-weight: 400;
- src: local('Source Serif Pro'), url("SourceSerifPro-Regular.woff") format('woff');
+ src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: italic;
font-weight: 400;
- src: url("Heuristica-Italic.woff") format('woff');
+ src: local('Source Serif Pro Italic'), url("SourceSerifPro-It.ttf.woff") format('woff');
}
@font-face {
font-family: 'Source Serif Pro';
font-style: normal;
font-weight: 700;
- src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
+ src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff');
}
/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */
border-bottom: 1px solid;
}
h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant {
+ flex-basis: 100%;
font-weight: 600;
- margin-top: 10px;
+ margin-top: 16px;
margin-bottom: 10px;
position: relative;
}
#main > .docblock h3, #main > .docblock h4, #main > .docblock h5 { font-size: 1em; }
#main > h2 + div, #main > h2 + h3, #main > h3 + div {
- display: none;
+ display: none; /* Changed to flex or block via js once the page is loaded */
+ flex-wrap: wrap;
}
.docblock h1 { font-size: 1em; }
}
.in-band, code {
- z-index: 5;
+ z-index: -5;
}
.invisible {
margin-top: -8px;
}
+.impl-items {
+ flex-basis: 100%;
+}
+
#main > .stability {
margin-top: 0;
}
top: 0;
}
+.impl-items .since, .impl .since {
+ flex-grow: 0;
+ padding-left: 12px;
+ padding-right: 2px;
+ position: initial;
+}
+
+.impl-items .srclink, .impl .srclink {
+ flex-grow: 0;
+ /* Override header settings otherwise it's too bold */
+ font-size: 17px;
+ font-weight: normal;
+}
+
+.impl-items code, .impl code {
+ flex-grow: 1;
+}
+
+.impl-items h4, h4.impl, h3.impl {
+ display: flex;
+ flex-basis: 100%;
+ font-size: 16px;
+ margin-bottom: 12px;
+ /* Push the src link out to the right edge consistently */
+ justify-content: space-between;
+}
+
.variants_table {
width: 100%;
}
margin-left: 20px;
}
-.ghost {
- display: none;
-}
-
-.ghost + .since {
- position: initial;
- display: table-cell;
-}
-
.since + .srclink {
display: table-cell;
padding-left: 10px;
margin-left: 5px;
top: -5px;
left: 105%;
- z-index: 1;
+ z-index: 10;
}
.tooltip:hover .tooltiptext {
margin-top: 16px;
}
-.content > .methods > div.important-traits {
+.content > .methods > .method > div.important-traits {
position: absolute;
+ font-weight: 400;
left: -42px;
margin-top: 2px;
}
pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt");
}
-/// Files related to the Heuristica font.
-pub mod heuristica {
- /// The file `Heuristica-Italic.woff`, the Italic variant of the Heuristica font.
- pub static ITALIC: &'static [u8] = include_bytes!("static/Heuristica-Italic.woff");
-
- /// The file `Heuristica-LICENSE.txt`, the license text for the Heuristica font.
- pub static LICENSE: &'static [u8] = include_bytes!("static/Heuristica-LICENSE.txt");
-}
-
/// Files related to the Source Serif Pro font.
pub mod source_serif_pro {
- /// The file `SourceSerifPro-Regular.woff`, the Regular variant of the Source Serif Pro font.
- pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.woff");
+ /// The file `SourceSerifPro-Regular.ttf.woff`, the Regular variant of the Source Serif Pro
+ /// font.
+ pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff");
+
+ /// The file `SourceSerifPro-Bold.ttf.woff`, the Bold variant of the Source Serif Pro font.
+ pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff");
- /// The file `SourceSerifPro-Bold.woff`, the Bold variant of the Source Serif Pro font.
- pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.woff");
+ /// The file `SourceSerifPro-It.ttf.woff`, the Italic variant of the Source Serif Pro font.
+ pub static ITALIC: &'static [u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff");
/// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font.
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.txt");
// Uses libsyntax to parse the doctest and find if there's a main fn and the extern
// crate already is included.
- let (already_has_main, already_has_extern_crate) = crate::syntax::with_globals(|| {
+ let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| {
use crate::syntax::{ast, parse::{self, ParseSess}, source_map::FilePathMapping};
use crate::syntax_pos::FileName;
use errors::emitter::EmitterWriter;
let mut found_main = false;
let mut found_extern_crate = cratename.is_none();
+ let mut found_macro = false;
let mut parser = match parse::maybe_new_parser_from_source_str(&sess, filename, source) {
Ok(p) => p,
err.cancel();
}
- return (found_main, found_extern_crate);
+ return (found_main, found_extern_crate, found_macro);
}
};
}
}
+ if !found_macro {
+ if let ast::ItemKind::Mac(..) = item.node {
+ found_macro = true;
+ }
+ }
+
if found_main && found_extern_crate {
break;
}
}
}
- (found_main, found_extern_crate)
+ (found_main, found_extern_crate, found_macro)
});
+ // If a doctest's `fn main` is being masked by a wrapper macro, the parsing loop above won't
+ // see it. In that case, run the old text-based scan to see if they at least have a main
+ // function written inside a macro invocation. See
+ // https://github.com/rust-lang/rust/issues/56898
+ let already_has_main = if found_macro && !already_has_main {
+ s.lines()
+ .map(|line| {
+ let comment = line.find("//");
+ if let Some(comment_begins) = comment {
+ &line[0..comment_begins]
+ } else {
+ line
+ }
+ })
+ .any(|code| code.contains("fn main"))
+ } else {
+ already_has_main
+ };
+
// Don't inject `extern crate std` because it's already injected by the
// compiler.
if !already_has_extern_crate && !opts.no_crate_inject && cratename != Some("std") {
let output = make_test(input, Some("asdf"), false, &opts);
assert_eq!(output, (expected, 3));
}
+
+ #[test]
+ fn make_test_main_in_macro() {
+ let opts = TestOptions::default();
+ let input =
+"#[macro_use] extern crate my_crate;
+test_wrapper! {
+ fn main() {}
+}";
+ let expected =
+"#![allow(unused)]
+#[macro_use] extern crate my_crate;
+test_wrapper! {
+ fn main() {}
+}".to_string();
+
+ let output = make_test(input, Some("my_crate"), false, &opts);
+ assert_eq!(output, (expected, 1));
+ }
}
/// themselves through the [`Display`] and [`Debug`] traits, and may provide
/// cause chain information:
///
-/// The [`cause`] method is generally used when errors cross "abstraction
-/// boundaries", i.e., when a one module must report an error that is "caused"
-/// by an error from a lower-level module. This setup makes it possible for the
-/// high-level module to provide its own errors that do not commit to any
-/// particular implementation, but also reveal some of its implementation for
-/// debugging via [`cause`] chains.
+/// The [`source`] method is generally used when errors cross "abstraction
+/// boundaries". If one module must report an error that is caused by an error
+/// from a lower-level module, it can allow access to that error via the
+/// [`source`] method. This makes it possible for the high-level module to
+/// provide its own errors while also revealing some of the implementation for
+/// debugging via [`source`] chains.
///
/// [`Result<T, E>`]: ../result/enum.Result.html
/// [`Display`]: ../fmt/trait.Display.html
/// [`Debug`]: ../fmt/trait.Debug.html
-/// [`cause`]: trait.Error.html#method.cause
+/// [`source`]: trait.Error.html#method.source
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display {
/// **This method is soft-deprecated.**
//! [`println!`]: ../macro.println.html
//! [`Lines`]: struct.Lines.html
//! [`io::Result`]: type.Result.html
-//! [`?` operator]: ../../book/first-edition/syntax-index.html
+//! [`?` operator]: ../../book/appendix-02-operators.html
//! [`Read::read`]: trait.Read.html#tymethod.read
//! [`Result`]: ../result/enum.Result.html
//! [`.unwrap()`]: ../result/enum.Result.html#method.unwrap
#![feature(char_error_internals)]
#![feature(compiler_builtins_lib)]
#![feature(concat_idents)]
-#![feature(const_int_ops)]
-#![feature(const_ip)]
+#![cfg_attr(stage0, feature(const_int_ops))]
+#![cfg_attr(stage0, feature(const_ip))]
#![feature(const_raw_ptr_deref)]
#![feature(const_cstr_unchecked)]
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
+#![feature(duration_constants)]
#![feature(exact_size_is_empty)]
#![feature(external_doc)]
#![feature(fixed_size_array)]
#![feature(maybe_uninit)]
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
feature(global_asm, range_contains, slice_index_methods,
- decl_macro, coerce_unsized, sgx_platform))]
+ decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
#![default_lib_allocator]
}
}
+/// A macro to await on an async call.
#[macro_export]
#[unstable(feature = "await_macro", issue = "50547")]
#[allow_internal_unstable]
/// let addr = Ipv4Addr::new(127, 0, 0, 1);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_ip")]
+ #[cfg_attr(stage0, rustc_const_unstable(feature = "const_ip"))]
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
Ipv4Addr {
inner: c::in_addr {
/// `a/b` all have `a` and `b` as components, but `./a/b` starts with
/// an additional [`CurDir`] component.
///
+ /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
+ ///
/// Note that no other normalization takes place; in particular, `a/c`
/// and `a/b/../c` are distinct, to account for the possibility that `b`
/// is a symbolic link (so its parent isn't `a`).
#[doc(alias = "[")]
#[doc(alias = "]")]
#[doc(alias = "[]")]
-//
/// A dynamically-sized view into a contiguous sequence, `[T]`.
///
/// *[See also the `std::slice` module](slice/index.html).*
/// points to:
///
/// ```
-/// let x = &mut [1, 2, 3];
+/// let mut x = [1, 2, 3];
+/// let x = &mut x[..]; // Take a full slice of `x`.
/// x[1] = 7;
/// assert_eq!(x, &[1, 7, 3]);
/// ```
-///
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_slice { }
}
}
+ pub fn actually_monotonic() -> bool {
+ true
+ }
+
+ pub const fn zero() -> Instant {
+ Instant { t: 0 }
+ }
+
pub fn sub_instant(&self, other: &Instant) -> Duration {
let diff = self.t
.checked_sub(other.t)
Instant { t: now(syscall::CLOCK_MONOTONIC) }
}
+ pub const fn zero() -> Instant {
+ Instant { t: Timespec { t: syscall::TimeSpec { tv_sec: 0, tv_nsec: 0 } } }
+ }
+
+ pub fn actually_monotonic() -> bool {
+ false
+ }
+
pub fn sub_instant(&self, other: &Instant) -> Duration {
self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
panic!("specified instant was later than self")
// Do not remove inline: will result in relocation failure
// For the same reason we use inline ASM here instead of an extern static to
// locate the base
+/// Returns address at which current enclave is loaded.
#[inline(always)]
-fn image_base() -> u64 {
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub fn image_base() -> u64 {
let base;
unsafe { asm!("lea IMAGE_BASE(%rip),$0":"=r"(base)) };
base
use io;
-use sys::unsupported;
+use error::Error;
+use libc;
use sys_common::backtrace::Frame;
+use unwind as uw;
+use sys::sgx::abi::mem::image_base;
pub struct BacktraceContext;
-pub fn unwind_backtrace(_frames: &mut [Frame])
- -> io::Result<(usize, BacktraceContext)>
-{
- unsupported()
+struct Context<'a> {
+ idx: usize,
+ frames: &'a mut [Frame],
+}
+
+#[derive(Debug)]
+struct UnwindError(uw::_Unwind_Reason_Code);
+
+impl Error for UnwindError {
+ fn description(&self) -> &'static str {
+ "unexpected return value while unwinding"
+ }
+}
+
+impl ::fmt::Display for UnwindError {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ write!(f, "{}: {:?}", self.description(), self.0)
+ }
+}
+
+#[inline(never)] // this function call can be skipped it when tracing.
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
+ let mut cx = Context { idx: 0, frames };
+ let result_unwind =
+ unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
+ // See libunwind:src/unwind/Backtrace.c for the return values.
+ // No, there is no doc.
+ let res = match result_unwind {
+ // These return codes seem to be benign and need to be ignored for backtraces
+ // to show up properly on all tested platforms.
+ uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
+ Ok((cx.idx, BacktraceContext))
+ }
+ _ => Err(io::Error::new(
+ io::ErrorKind::Other,
+ UnwindError(result_unwind),
+ )),
+ };
+ res
+}
+
+extern "C" fn trace_fn(
+ ctx: *mut uw::_Unwind_Context,
+ arg: *mut libc::c_void,
+) -> uw::_Unwind_Reason_Code {
+ let cx = unsafe { &mut *(arg as *mut Context) };
+ if cx.idx >= cx.frames.len() {
+ return uw::_URC_NORMAL_STOP;
+ }
+
+ let mut ip_before_insn = 0;
+ let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
+ if !ip.is_null() && ip_before_insn == 0 {
+ // this is a non-signaling frame, so `ip` refers to the address
+ // after the calling instruction. account for that.
+ ip = (ip as usize - 1) as *mut _;
+ }
+
+ let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
+ cx.frames[cx.idx] = Frame {
+ symbol_addr: symaddr as *mut u8,
+ exact_position: ip as *mut u8,
+ inline_context: 0,
+ };
+ cx.idx += 1;
+
+ uw::_URC_NO_REASON
}
-pub fn resolve_symname<F>(_frame: Frame,
- _callback: F,
+// To reduce TCB size in Sgx enclave, we do not want to implement resolve_symname functionality.
+// Rather, we print the offset of the address here, which could be later mapped to correct function.
+pub fn resolve_symname<F>(frame: Frame,
+ callback: F,
_: &BacktraceContext) -> io::Result<()>
where F: FnOnce(Option<&str>) -> io::Result<()>
{
- unsupported()
+ callback(Some(&format!("0x{:x}",
+ (frame.symbol_addr.wrapping_offset_from(image_base() as _)))))
}
pub fn foreach_symbol_fileline<F>(_: Frame,
_: &BacktraceContext) -> io::Result<bool>
where F: FnMut(&[u8], u32) -> io::Result<()>
{
- unsupported()
+ Ok(false)
}
: "={eax}"(error)
: "{eax}"(ENCLU_EGETKEY),
"{rbx}"(request),
- "{rcx}"(out.get_mut())
+ "{rcx}"(out.as_mut_ptr())
: "flags"
);
: "{eax}"(ENCLU_EREPORT),
"{rbx}"(targetinfo),
"{rcx}"(reportdata),
- "{rdx}"(report.get_mut())
+ "{rdx}"(report.as_mut_ptr())
);
report.into_inner()
}
impl Timespec {
+ const fn zero() -> Timespec {
+ Timespec {
+ t: libc::timespec { tv_sec: 0, tv_nsec: 0 },
+ }
+ }
+
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
}
pub const UNIX_EPOCH: SystemTime = SystemTime {
- t: Timespec {
- t: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- },
+ t: Timespec::zero(),
};
impl Instant {
Instant { t: unsafe { libc::mach_absolute_time() } }
}
+ pub const fn zero() -> Instant {
+ Instant { t: 0 }
+ }
+
+ pub fn actually_monotonic() -> bool {
+ true
+ }
+
pub fn sub_instant(&self, other: &Instant) -> Duration {
let info = info();
let diff = self.t.checked_sub(other.t)
}
pub const UNIX_EPOCH: SystemTime = SystemTime {
- t: Timespec {
- t: libc::timespec {
- tv_sec: 0,
- tv_nsec: 0,
- },
- },
+ t: Timespec::zero(),
};
impl Instant {
Instant { t: now(libc::CLOCK_MONOTONIC) }
}
+ pub const fn zero() -> Instant {
+ Instant {
+ t: Timespec::zero(),
+ }
+ }
+
+ pub fn actually_monotonic() -> bool {
+ (cfg!(target_os = "linux") && cfg!(target_arch = "x86_64")) ||
+ (cfg!(target_os = "linux") && cfg!(target_arch = "x86")) ||
+ false // last clause, used so `||` is always trailing above
+ }
+
pub fn sub_instant(&self, other: &Instant) -> Duration {
self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
panic!("specified instant was later than self")
Instant(TimeSysCall::perform(TimeClock::Monotonic))
}
+ pub const fn zero() -> Instant {
+ Instant(Duration::from_secs(0))
+ }
+
+ pub fn actually_monotonic() -> bool {
+ false
+ }
+
pub fn sub_instant(&self, other: &Instant) -> Duration {
self.0 - other.0
}
impl fmt::Display for ExitStatus {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "exit code: {}", self.0)
+ // Windows exit codes with the high bit set typically mean some form of
+ // unhandled exception or warning. In this scenario printing the exit
+ // code in decimal doesn't always make sense because it's a very large
+ // and somewhat gibberish number. The hex code is a bit more
+ // recognizable and easier to search for, so print that.
+ if self.0 & 0x80000000 != 0 {
+ write!(f, "exit code: {:#x}", self.0)
+ } else {
+ write!(f, "exit code: {}", self.0)
+ }
}
}
t
}
+ pub fn actually_monotonic() -> bool {
+ false
+ }
+
+ pub const fn zero() -> Instant {
+ Instant { t: 0 }
+ }
+
pub fn sub_instant(&self, other: &Instant) -> Duration {
// Values which are +- 1 need to be considered as basically the same
// units in time due to various measurement oddities, according to
#![stable(feature = "time", since = "1.3.0")]
+use cmp;
use error::Error;
use fmt;
use ops::{Add, Sub, AddAssign, SubAssign};
use sys::time;
use sys_common::FromInner;
+use sys_common::mutex::Mutex;
#[stable(feature = "time", since = "1.3.0")]
pub use core::time::Duration;
+#[unstable(feature = "duration_constants", issue = "57391")]
+pub use core::time::{SECOND, MILLISECOND, MICROSECOND, NANOSECOND};
+
/// A measurement of a monotonically nondecreasing clock.
/// Opaque and useful only with `Duration`.
///
/// ```
#[stable(feature = "time2", since = "1.8.0")]
pub fn now() -> Instant {
- Instant(time::Instant::now())
+ let os_now = time::Instant::now();
+
+ // And here we come upon a sad state of affairs. The whole point of
+ // `Instant` is that it's monotonically increasing. We've found in the
+ // wild, however, that it's not actually monotonically increasing for
+ // one reason or another. These appear to be OS and hardware level bugs,
+ // and there's not really a whole lot we can do about them. Here's a
+ // taste of what we've found:
+ //
+ // * #48514 - OpenBSD, x86_64
+ // * #49281 - linux arm64 and s390x
+ // * #51648 - windows, x86
+ // * #56560 - windows, x86_64, AWS
+ // * #56612 - windows, x86, vm (?)
+ // * #56940 - linux, arm64
+ // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar
+ // Firefox bug
+ //
+ // It simply seems that this it just happens so that a lot in the wild
+ // we're seeing panics across various platforms where consecutive calls
+ // to `Instant::now`, such as via the `elapsed` function, are panicking
+ // as they're going backwards. Placed here is a last-ditch effort to try
+ // to fix things up. We keep a global "latest now" instance which is
+ // returned instead of what the OS says if the OS goes backwards.
+ //
+ // To hopefully mitigate the impact of this though a few platforms are
+ // whitelisted as "these at least haven't gone backwards yet".
+ if time::Instant::actually_monotonic() {
+ return Instant(os_now)
+ }
+
+ static LOCK: Mutex = Mutex::new();
+ static mut LAST_NOW: time::Instant = time::Instant::zero();
+ unsafe {
+ let _lock = LOCK.lock();
+ let now = cmp::max(LAST_NOW, os_now);
+ LAST_NOW = now;
+ Instant(now)
+ }
}
/// Returns the amount of time elapsed from another instant to this one.
Token::from_ast_ident(segment.ident)).into());
last_pos = segment.ident.span.hi();
}
- idents.push(self.node.tokens(self.span));
+ self.node.tokens(self.span).append_to_tree_and_joint_vec(&mut idents);
TokenStream::new(idents)
}
match *self {
MetaItemKind::Word => TokenStream::empty(),
MetaItemKind::NameValue(ref lit) => {
- TokenStream::new(vec![TokenTree::Token(span, Token::Eq).into(), lit.tokens()])
+ let mut vec = vec![TokenTree::Token(span, Token::Eq).into()];
+ lit.tokens().append_to_tree_and_joint_vec(&mut vec);
+ TokenStream::new(vec)
}
MetaItemKind::List(ref list) => {
let mut tokens = Vec::new();
if i > 0 {
tokens.push(TokenTree::Token(span, Token::Comma).into());
}
- tokens.push(item.node.tokens());
+ item.node.tokens().append_to_tree_and_joint_vec(&mut tokens);
}
TokenTree::Delimited(
DelimSpan::from_single(span),
Features,
get_features,
GateIssue,
- emit_feature_err,
};
use {fold, attr};
use ast;
return vec![attr];
}
- let gate_cfg_attr_multi = if let Some(ref features) = self.features {
- !features.cfg_attr_multi
- } else {
- false
- };
- let cfg_attr_span = attr.span;
-
let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| {
parser.expect(&token::OpenDelim(token::Paren))?;
// Check feature gate and lint on zero attributes in source. Even if the feature is gated,
// we still compute as if it wasn't, since the emitted error will stop compilation further
// along the compilation.
- match (expanded_attrs.len(), gate_cfg_attr_multi) {
- (0, false) => {
- // FIXME: Emit unused attribute lint here.
- },
- (1, _) => {},
- (_, true) => {
- emit_feature_err(
- self.sess,
- "cfg_attr_multi",
- cfg_attr_span,
- GateIssue::Language,
- "cfg_attr with zero or more than one attributes is experimental",
- );
- },
- (_, false) => {}
+ if expanded_attrs.len() == 0 {
+ // FIXME: Emit unused attribute lint here.
}
if attr::cfg_matches(&cfg_predicate, self.sess, self.features) {
));
}
});
- let sym = Ident::with_empty_ctxt(Symbol::gensym(&format!(
- "__register_diagnostic_{}", code
- )));
+
+ let span = span.apply_mark(ecx.current_expansion.mark);
+
+ let sym = Ident::new(Symbol::gensym(&format!("__register_diagnostic_{}", code)), span);
+
MacEager::items(smallvec![
ecx.item_mod(
span,
span,
sym,
- Vec::new(),
- Vec::new()
+ vec![],
+ vec![],
)
])
}
self.span, token::Token::from_ast_ident(segment.ident)
).into());
}
- inner.push(self.tokens.clone());
+ self.tokens.clone().append_to_tree_and_joint_vec(&mut inner);
let delim_span = DelimSpan::from_single(self.span);
r.push(TokenTree::Delimited(
Success(T),
/// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected
/// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
- Failure(syntax_pos::Span, Token, String),
+ Failure(syntax_pos::Span, Token, &'static str),
/// Fatal error (malformed macro?). Abort compilation.
Error(syntax_pos::Span, String),
}
sess.source_map().next_point(parser.span)
},
token::Eof,
- "missing tokens in macro arguments".to_string(),
+ "missing tokens in macro arguments",
);
}
}
return Failure(
parser.span,
parser.token,
- "no rules expected this token in macro call".to_string(),
+ "no rules expected this token in macro call",
);
}
// Dump all possible `next_items` into `cur_items` for the next iteration.
let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers"));
let span = best_fail_spot.substitute_dummy(sp);
let mut err = cx.struct_span_err(span, &best_fail_msg);
- err.span_label(span, best_fail_text.unwrap_or(best_fail_msg));
+ err.span_label(span, best_fail_text.unwrap_or(&best_fail_msg));
if let Some(sp) = def_span {
if cx.source_map().span_to_filename(sp).is_real() && !sp.is_dummy() {
err.span_label(cx.source_map().def_span(sp), "when calling this macro");
use parse::token::{self, Token, NtTT};
use smallvec::SmallVec;
use syntax_pos::DUMMY_SP;
-use tokenstream::{TokenStream, TokenTree, DelimSpan};
+use tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
let mut stack: SmallVec<[Frame; 1]> = smallvec![Frame::new(src)];
let interpolations = interp.unwrap_or_else(FxHashMap::default); /* just a convenience */
let mut repeats = Vec::new();
- let mut result: Vec<TokenStream> = Vec::new();
+ let mut result: Vec<TreeAndJoint> = Vec::new();
let mut result_stack = Vec::new();
loop {
if let Some(sep) = sep.clone() {
// repeat same span, I guess
let prev_span = match result.last() {
- Some(stream) => stream.trees().next().unwrap().span(),
+ Some((tt, _)) => tt.span(),
None => DUMMY_SP,
};
result.push(TokenTree::Token(prev_span, sep).into());
(active, slice_patterns, "1.0.0", Some(23121), None),
// Allows the definition of `const` functions with some advanced features.
- (active, const_fn, "1.2.0", Some(24111), None),
-
- // Allows let bindings and destructuring in `const` functions and constants.
- (active, const_let, "1.22.1", Some(48821), None),
+ (active, const_fn, "1.2.0", Some(57563), None),
// Allows accessing fields of unions inside `const` functions.
(active, const_fn_union, "1.27.0", Some(51909), None),
// Infer static outlives requirements (RFC 2093).
(active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
- // Multiple patterns with `|` in `if let` and `while let`.
- (active, if_while_or_patterns, "1.26.0", Some(48215), None),
-
// Allows macro invocations in `extern {}` blocks.
(active, macros_in_extern, "1.27.0", Some(49476), None),
// `#[doc(alias = "...")]`
(active, doc_alias, "1.27.0", Some(50146), None),
- // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
- (active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
-
// inconsistent bounds in where clauses
(active, trivial_bounds, "1.28.0", Some(48214), None),
// support for arbitrary delimited token streams in non-macro attributes
(active, unrestricted_attribute_tokens, "1.30.0", Some(55208), None),
- // Allows `use x::y;` to resolve through `self::x`, not just `::x`.
- (active, uniform_paths, "1.30.0", Some(53130), None),
-
// Allows unsized rvalues at arguments and parameters.
(active, unsized_locals, "1.30.0", Some(48055), None),
// Allows `impl Trait` in bindings (`let`, `const`, `static`).
(active, impl_trait_in_bindings, "1.30.0", Some(34511), None),
- // `#[cfg_attr(predicate, multiple, attributes, here)]`
- (active, cfg_attr_multi, "1.31.0", Some(54881), None),
-
// Allows `const _: TYPE = VALUE`.
(active, underscore_const_names, "1.31.0", Some(54912), None),
(accepted, underscore_imports, "1.33.0", Some(48216), None),
// Allows `#[repr(packed(N))]` attribute on structs.
(accepted, repr_packed, "1.33.0", Some(33158), None),
+ // Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
+ (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None),
// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
(accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None),
+ // Allows let bindings, assignments and destructuring in `const` functions and constants.
+ // As long as control flow is not implemented in const eval, `&&` and `||` may not be used
+ // at the same time as let bindings.
+ (accepted, const_let, "1.33.0", Some(48821), None),
+ // `#[cfg_attr(predicate, multiple, attributes, here)]`
+ (accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
+ // Top level or-patterns (`p | q`) in `if let` and `while let`.
+ (accepted, if_while_or_patterns, "1.33.0", Some(48215), None),
+ // Allows `use x::y;` to search `x` in the current scope.
+ (accepted, uniform_paths, "1.32.0", Some(53130), None),
);
// If you change this, please modify `src/doc/unstable-book` as well. You must
ast::ExprKind::TryBlock(_) => {
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
}
- ast::ExprKind::IfLet(ref pats, ..) | ast::ExprKind::WhileLet(ref pats, ..) => {
- if pats.len() > 1 {
- gate_feature_post!(&self, if_while_or_patterns, e.span,
- "multiple patterns in `if let` and `while let` are unstable");
- }
- }
ast::ExprKind::Block(_, opt_label) => {
if let Some(label) = opt_label {
gate_feature_post!(&self, label_break_value, label.ident.span,
use print::pprust::token_to_string;
use parse::lexer::StringReader;
use parse::{token, PResult};
-use tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree};
+use tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree, TreeAndJoint};
impl<'a> StringReader<'a> {
// Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
}
}
- fn parse_token_tree(&mut self) -> PResult<'a, TokenStream> {
+ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
let sm = self.sess.source_map();
match self.token {
token::Eof => {
Ok(TokenTree::Delimited(
delim_span,
delim,
- tts.into(),
+ tts.into()
).into())
},
token::CloseDelim(_) => {
let raw = self.span_src_raw;
self.real_token();
let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token);
- Ok(TokenStream::Tree(tt, if is_joint { Joint } else { NonJoint }))
+ Ok((tt, if is_joint { Joint } else { NonJoint }))
}
}
}
TokenTree::Delimited(
frame.span,
frame.delim,
- frame.tree_cursor.original_stream().into(),
+ frame.tree_cursor.stream.into(),
)
},
token::CloseDelim(_) | token::Eof => unreachable!(),
maybe_whole!(self, NtArm, |x| x);
let attrs = self.parse_outer_attributes()?;
- // Allow a '|' before the pats (RFC 1925)
- self.eat(&token::BinOp(token::Or));
let pats = self.parse_pats()?;
let guard = if self.eat_keyword(keywords::If) {
Some(Guard::If(self.parse_expr()?))
/// Parse patterns, separated by '|' s
fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> {
+ // Allow a '|' before the pats (RFC 1925 + RFC 2530)
+ self.eat(&token::BinOp(token::Or));
+
let mut pats = Vec::new();
loop {
pats.push(self.parse_top_level_pat()?);
pub enum TokenStream {
Empty,
Tree(TokenTree, IsJoint),
- Stream(Lrc<Vec<TokenStream>>),
+ Stream(Lrc<Vec<TreeAndJoint>>),
}
+pub type TreeAndJoint = (TokenTree, IsJoint);
+
// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
while let Some((pos, ts)) = iter.next() {
if let Some((_, next)) = iter.peek() {
let sp = match (&ts, &next) {
- (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint), _) |
- (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint))
- => continue,
- (TokenStream::Tree(TokenTree::Token(sp, _), NonJoint), _) => *sp,
- (TokenStream::Tree(TokenTree::Delimited(sp, ..), NonJoint), _) =>
- sp.entire(),
+ ((TokenTree::Token(_, token::Token::Comma), NonJoint), _) |
+ (_, (TokenTree::Token(_, token::Token::Comma), NonJoint)) => continue,
+ ((TokenTree::Token(sp, _), NonJoint), _) => *sp,
+ ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
_ => continue,
};
let sp = sp.shrink_to_hi();
- let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma), NonJoint);
+ let comma = (TokenTree::Token(sp, token::Comma), NonJoint);
suggestion = Some((pos, comma, sp));
}
}
}
impl From<TokenTree> for TokenStream {
- fn from(tt: TokenTree) -> TokenStream {
- TokenStream::Tree(tt, NonJoint)
+ fn from(tree: TokenTree) -> TokenStream {
+ TokenStream::Tree(tree, NonJoint)
+ }
+}
+
+impl From<TokenTree> for TreeAndJoint {
+ fn from(tree: TokenTree) -> TreeAndJoint {
+ (tree, NonJoint)
}
}
impl<T: Into<TokenStream>> iter::FromIterator<T> for TokenStream {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
- TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<_>>())
- }
-}
-
-impl Extend<TokenStream> for TokenStream {
- fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) {
- let iter = iter.into_iter();
- let this = mem::replace(self, TokenStream::Empty);
-
- // Vector of token streams originally in self.
- let tts: Vec<TokenStream> = match this {
- TokenStream::Empty => {
- let mut vec = Vec::new();
- vec.reserve(iter.size_hint().0);
- vec
- }
- TokenStream::Tree(..) => {
- let mut vec = Vec::new();
- vec.reserve(1 + iter.size_hint().0);
- vec.push(this);
- vec
- }
- TokenStream::Stream(rc_vec) => match Lrc::try_unwrap(rc_vec) {
- Ok(mut vec) => {
- // Extend in place using the existing capacity if possible.
- // This is the fast path for libraries like `quote` that
- // build a token stream.
- vec.reserve(iter.size_hint().0);
- vec
- }
- Err(rc_vec) => {
- // Self is shared so we need to copy and extend that.
- let mut vec = Vec::new();
- vec.reserve(rc_vec.len() + iter.size_hint().0);
- vec.extend_from_slice(&rc_vec);
- vec
- }
- }
- };
-
- // Perform the extend, joining tokens as needed along the way.
- let mut builder = TokenStreamBuilder(tts);
- for stream in iter {
- builder.push(stream);
- }
-
- // Build the resulting token stream. If it contains more than one token,
- // preserve capacity in the vector in anticipation of the caller
- // performing additional calls to extend.
- *self = TokenStream::new(builder.0);
+ TokenStream::from_streams(iter.into_iter().map(Into::into).collect::<Vec<_>>())
}
}
}
}
- pub fn new(mut streams: Vec<TokenStream>) -> TokenStream {
+ fn from_streams(mut streams: Vec<TokenStream>) -> TokenStream {
match streams.len() {
0 => TokenStream::empty(),
1 => streams.pop().unwrap(),
+ _ => {
+ let mut vec = vec![];
+ for stream in streams {
+ match stream {
+ TokenStream::Empty => {},
+ TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
+ TokenStream::Stream(stream2) => vec.extend(stream2.iter().cloned()),
+ }
+ }
+ TokenStream::new(vec)
+ }
+ }
+ }
+
+ pub fn new(mut streams: Vec<TreeAndJoint>) -> TokenStream {
+ match streams.len() {
+ 0 => TokenStream::empty(),
+ 1 => {
+ let (tree, is_joint) = streams.pop().unwrap();
+ TokenStream::Tree(tree, is_joint)
+ }
_ => TokenStream::Stream(Lrc::new(streams)),
}
}
+ pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
+ match self {
+ TokenStream::Empty => {}
+ TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
+ TokenStream::Stream(stream) => vec.extend(stream.iter().cloned()),
+ }
+ }
+
pub fn trees(&self) -> Cursor {
self.clone().into_trees()
}
t1.next().is_none() && t2.next().is_none()
}
- /// Precondition: `self` consists of a single token tree.
- /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`.
- pub fn as_tree(self) -> (TokenTree, bool /* joint? */) {
- match self {
- TokenStream::Tree(tree, is_joint) => (tree, is_joint == Joint),
- _ => unreachable!(),
- }
- }
-
pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
- let mut trees = self.into_trees();
- let mut result = Vec::new();
- let mut i = 0;
- while let Some(stream) = trees.next_as_stream() {
- result.push(match stream {
- TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(i, tree), is_joint),
- _ => unreachable!()
- });
- i += 1;
+ match self {
+ TokenStream::Empty => TokenStream::Empty,
+ TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(0, tree), is_joint),
+ TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+ stream
+ .iter()
+ .enumerate()
+ .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
+ .collect()
+ )),
}
- TokenStream::new(result)
}
pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
- let mut trees = self.into_trees();
- let mut result = Vec::new();
- while let Some(stream) = trees.next_as_stream() {
- result.push(match stream {
- TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
- _ => unreachable!()
- });
+ match self {
+ TokenStream::Empty => TokenStream::Empty,
+ TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
+ TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+ stream
+ .iter()
+ .map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
+ .collect()
+ )),
}
- TokenStream::new(result)
}
fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
match self {
TokenStream::Empty => None,
TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)),
- TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(),
+ TokenStream::Stream(ref stream) => Some(stream.first().unwrap().clone())
}
}
fn last_tree_if_joint(&self) -> Option<TokenTree> {
match self {
- TokenStream::Empty | TokenStream::Tree(_, NonJoint) => None,
- TokenStream::Tree(ref tree, Joint) => Some(tree.clone()),
- TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(),
+ TokenStream::Empty => None,
+ TokenStream::Tree(ref tree, is_joint) => {
+ if *is_joint == Joint {
+ Some(tree.clone())
+ } else {
+ None
+ }
+ }
+ TokenStream::Stream(ref stream) => {
+ if let (tree, Joint) = stream.last().unwrap() {
+ Some(tree.clone())
+ } else {
+ None
+ }
+ }
}
}
}
self.0.push(stream);
}
- pub fn add<T: Into<TokenStream>>(mut self, stream: T) -> Self {
- self.push(stream);
- self
- }
-
pub fn build(self) -> TokenStream {
- TokenStream::new(self.0)
+ TokenStream::from_streams(self.0)
}
fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
let len = streams.len();
match len {
1 => {}
- 2 => self.0.push(streams[0].clone().into()),
- _ => self.0.push(TokenStream::new(streams[0 .. len - 1].to_vec())),
+ 2 => self.0.push(TokenStream::Tree(streams[0].0.clone(), streams[0].1)),
+ _ => self.0.push(TokenStream::Stream(Lrc::new(streams[0 .. len - 1].to_vec()))),
}
- self.push_all_but_last_tree(&streams[len - 1])
}
}
let len = streams.len();
match len {
1 => {}
- 2 => self.0.push(streams[1].clone().into()),
- _ => self.0.push(TokenStream::new(streams[1 .. len].to_vec())),
+ 2 => self.0.push(TokenStream::Tree(streams[1].0.clone(), streams[1].1)),
+ _ => self.0.push(TokenStream::Stream(Lrc::new(streams[1 .. len].to_vec()))),
}
- self.push_all_but_first_tree(&streams[0])
}
}
}
#[derive(Clone)]
-pub struct Cursor(CursorKind);
-
-#[derive(Clone)]
-enum CursorKind {
- Empty,
- Tree(TokenTree, IsJoint, bool /* consumed? */),
- Stream(StreamCursor),
-}
-
-#[derive(Clone)]
-struct StreamCursor {
- stream: Lrc<Vec<TokenStream>>,
+pub struct Cursor {
+ pub stream: TokenStream,
index: usize,
- stack: Vec<(Lrc<Vec<TokenStream>>, usize)>,
-}
-
-impl StreamCursor {
- fn new(stream: Lrc<Vec<TokenStream>>) -> Self {
- StreamCursor { stream: stream, index: 0, stack: Vec::new() }
- }
-
- fn next_as_stream(&mut self) -> Option<TokenStream> {
- loop {
- if self.index < self.stream.len() {
- self.index += 1;
- let next = self.stream[self.index - 1].clone();
- match next {
- TokenStream::Empty => {}
- TokenStream::Tree(..) => return Some(next),
- TokenStream::Stream(stream) => self.insert(stream),
- }
- } else if let Some((stream, index)) = self.stack.pop() {
- self.stream = stream;
- self.index = index;
- } else {
- return None;
- }
- }
- }
-
- fn insert(&mut self, stream: Lrc<Vec<TokenStream>>) {
- self.stack.push((mem::replace(&mut self.stream, stream),
- mem::replace(&mut self.index, 0)));
- }
}
impl Iterator for Cursor {
type Item = TokenTree;
fn next(&mut self) -> Option<TokenTree> {
- self.next_as_stream().map(|stream| match stream {
- TokenStream::Tree(tree, _) => tree,
- _ => unreachable!()
- })
+ self.next_with_joint().map(|(tree, _)| tree)
}
}
impl Cursor {
fn new(stream: TokenStream) -> Self {
- Cursor(match stream {
- TokenStream::Empty => CursorKind::Empty,
- TokenStream::Tree(tree, is_joint) => CursorKind::Tree(tree, is_joint, false),
- TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)),
- })
- }
-
- pub fn next_as_stream(&mut self) -> Option<TokenStream> {
- let (stream, consumed) = match self.0 {
- CursorKind::Tree(ref tree, ref is_joint, ref mut consumed @ false) =>
- (TokenStream::Tree(tree.clone(), *is_joint), consumed),
- CursorKind::Stream(ref mut cursor) => return cursor.next_as_stream(),
- _ => return None,
- };
-
- *consumed = true;
- Some(stream)
+ Cursor { stream, index: 0 }
}
- pub fn insert(&mut self, stream: TokenStream) {
- match self.0 {
- _ if stream.is_empty() => return,
- CursorKind::Empty => *self = stream.trees(),
- CursorKind::Tree(_, _, consumed) => {
- *self = TokenStream::new(vec![self.original_stream(), stream]).trees();
- if consumed {
- self.next();
+ pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
+ match self.stream {
+ TokenStream::Empty => None,
+ TokenStream::Tree(ref tree, ref is_joint) => {
+ if self.index == 0 {
+ self.index = 1;
+ Some((tree.clone(), *is_joint))
+ } else {
+ None
}
}
- CursorKind::Stream(ref mut cursor) => {
- cursor.insert(ThinTokenStream::from(stream).0.unwrap());
+ TokenStream::Stream(ref stream) => {
+ if self.index < stream.len() {
+ self.index += 1;
+ Some(stream[self.index - 1].clone())
+ } else {
+ None
+ }
}
}
}
- pub fn original_stream(&self) -> TokenStream {
- match self.0 {
- CursorKind::Empty => TokenStream::empty(),
- CursorKind::Tree(ref tree, ref is_joint, _) =>
- TokenStream::Tree(tree.clone(), *is_joint),
- CursorKind::Stream(ref cursor) => TokenStream::Stream(
- cursor.stack.get(0).cloned().map(|(stream, _)| stream)
- .unwrap_or_else(|| cursor.stream.clone())
- ),
+ pub fn append(&mut self, new_stream: TokenStream) {
+ if new_stream.is_empty() {
+ return;
}
+ let index = self.index;
+ let stream = mem::replace(&mut self.stream, TokenStream::Empty);
+ *self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
+ self.index = index;
}
pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
- fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize> {
- for stream in streams {
- n = match stream {
- TokenStream::Tree(ref tree, _) if n == 0 => return Ok(tree.clone()),
- TokenStream::Tree(..) => n - 1,
- TokenStream::Stream(ref stream) => match look_ahead(stream, n) {
- Ok(tree) => return Ok(tree),
- Err(n) => n,
- },
- _ => n,
- };
+ match self.stream {
+ TokenStream::Empty => None,
+ TokenStream::Tree(ref tree, _) => {
+ if n == 0 && self.index == 0 {
+ Some(tree.clone())
+ } else {
+ None
+ }
}
- Err(n)
+ TokenStream::Stream(ref stream) =>
+ stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
}
-
- match self.0 {
- CursorKind::Empty |
- CursorKind::Tree(_, _, true) => Err(n),
- CursorKind::Tree(ref tree, _, false) => look_ahead(&[tree.clone().into()], n),
- CursorKind::Stream(ref cursor) => {
- look_ahead(&cursor.stream[cursor.index ..], n).or_else(|mut n| {
- for &(ref stream, index) in cursor.stack.iter().rev() {
- n = match look_ahead(&stream[index..], n) {
- Ok(tree) => return Ok(tree),
- Err(n) => n,
- }
- }
-
- Err(n)
- })
- }
- }.ok()
}
}
/// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
/// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
#[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<Lrc<Vec<TokenStream>>>);
+pub struct ThinTokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
impl ThinTokenStream {
pub fn stream(&self) -> TokenStream {
fn from(stream: TokenStream) -> ThinTokenStream {
ThinTokenStream(match stream {
TokenStream::Empty => None,
- TokenStream::Tree(..) => Some(Lrc::new(vec![stream])),
+ TokenStream::Tree(tree, is_joint) => Some(Lrc::new(vec![(tree, is_joint)])),
TokenStream::Stream(stream) => Some(stream),
})
}
let test_res = string_to_ts("foo::bar::baz");
let test_fst = string_to_ts("foo::bar");
let test_snd = string_to_ts("::baz");
- let eq_res = TokenStream::new(vec![test_fst, test_snd]);
+ let eq_res = TokenStream::from_streams(vec![test_fst, test_snd]);
assert_eq!(test_res.trees().count(), 5);
assert_eq!(eq_res.trees().count(), 5);
assert_eq!(test_res.eq_unspanned(&eq_res), true);
assert!(stream.eq_unspanned(&string_to_ts("...")));
assert_eq!(stream.trees().count(), 1);
}
-
- #[test]
- fn test_extend_empty() {
- with_globals(|| {
- // Append a token onto an empty token stream.
- let mut stream = TokenStream::empty();
- stream.extend(vec![string_to_ts("t")]);
-
- let expected = string_to_ts("t");
- assert!(stream.eq_unspanned(&expected));
- });
- }
-
- #[test]
- fn test_extend_nothing() {
- with_globals(|| {
- // Append nothing onto a token stream containing one token.
- let mut stream = string_to_ts("t");
- stream.extend(vec![]);
-
- let expected = string_to_ts("t");
- assert!(stream.eq_unspanned(&expected));
- });
- }
-
- #[test]
- fn test_extend_single() {
- with_globals(|| {
- // Append a token onto token stream containing a single token.
- let mut stream = string_to_ts("t1");
- stream.extend(vec![string_to_ts("t2")]);
-
- let expected = string_to_ts("t1 t2");
- assert!(stream.eq_unspanned(&expected));
- });
- }
-
- #[test]
- fn test_extend_in_place() {
- with_globals(|| {
- // Append a token onto token stream containing a reference counted
- // vec of tokens. The token stream has a reference count of 1 so
- // this can happen in place.
- let mut stream = string_to_ts("t1 t2");
- stream.extend(vec![string_to_ts("t3")]);
-
- let expected = string_to_ts("t1 t2 t3");
- assert!(stream.eq_unspanned(&expected));
- });
- }
-
- #[test]
- fn test_extend_copy() {
- with_globals(|| {
- // Append a token onto token stream containing a reference counted
- // vec of tokens. The token stream is shared so the extend takes
- // place on a copy.
- let mut stream = string_to_ts("t1 t2");
- let _incref = stream.clone();
- stream.extend(vec![string_to_ts("t3")]);
-
- let expected = string_to_ts("t1 t2 t3");
- assert!(stream.eq_unspanned(&expected));
- });
- }
-
- #[test]
- fn test_extend_no_join() {
- with_globals(|| {
- let first = TokenTree::Token(DUMMY_SP, Token::Dot);
- let second = TokenTree::Token(DUMMY_SP, Token::Dot);
-
- // Append a dot onto a token stream containing a dot, but do not
- // join them.
- let mut stream = TokenStream::from(first);
- stream.extend(vec![TokenStream::from(second)]);
-
- let expected = string_to_ts(". .");
- assert!(stream.eq_unspanned(&expected));
-
- let unexpected = string_to_ts("..");
- assert!(!stream.eq_unspanned(&unexpected));
- });
- }
-
- #[test]
- fn test_extend_join() {
- with_globals(|| {
- let first = TokenTree::Token(DUMMY_SP, Token::Dot).joint();
- let second = TokenTree::Token(DUMMY_SP, Token::Dot);
-
- // Append a dot onto a token stream containing a dot, forming a
- // dotdot.
- let mut stream = first;
- stream.extend(vec![TokenStream::from(second)]);
-
- let expected = string_to_ts("..");
- assert!(stream.eq_unspanned(&expected));
-
- let unexpected = string_to_ts(". .");
- assert!(!stream.eq_unspanned(&unexpected));
- });
- }
}
};
let name: &str = &ident.as_str();
- p.expect(&token::Eq).unwrap();
+ p.expect(&token::Eq)?;
let e = p.parse_expr()?;
if let Some(prev) = names.get(name) {
ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name))
use syntax::ext::base::ExtCtxt;
use syntax::parse::lexer::comments;
use syntax::parse::{self, token, ParseSess};
-use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream};
+use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint};
use syntax_pos::hygiene::{SyntaxContext, Transparency};
use syntax_pos::symbol::{keywords, Symbol};
use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
}
}
-impl FromInternal<(TokenStream, &'_ ParseSess, &'_ mut Vec<Self>)>
+impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec<Self>)>
for TokenTree<Group, Punct, Ident, Literal>
{
- fn from_internal((stream, sess, stack): (TokenStream, &ParseSess, &mut Vec<Self>)) -> Self {
+ fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec<Self>))
+ -> Self {
use syntax::parse::token::*;
- let (tree, joint) = stream.as_tree();
+ let joint = is_joint == Joint;
let (span, token) = match tree {
tokenstream::TokenTree::Delimited(span, delim, tts) => {
let delimiter = Delimiter::from_internal(delim);
) -> Option<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
loop {
let tree = iter.stack.pop().or_else(|| {
- let next = iter.cursor.next_as_stream()?;
+ let next = iter.cursor.next_with_joint()?;
Some(TokenTree::from_internal((next, self.sess, &mut iter.stack)))
})?;
// HACK: The condition "dummy span + group with empty delimiter" represents an AST
// and not doing the roundtrip through AST.
if let TokenTree::Group(ref group) = tree {
if group.delimiter == Delimiter::None && group.span.entire().is_dummy() {
- iter.cursor.insert(group.stream.clone());
+ iter.cursor.append(group.stream.clone());
continue;
}
}
])
};
- let mut test_const = cx.item(sp, item.ident.gensym(),
+ let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name.gensymed(), sp),
vec![
// #[cfg(test)]
cx.attribute(attr_sp, cx.meta_list(attr_sp, Symbol::intern("cfg"), vec![
cx.meta_list_item_word(attr_sp, Symbol::intern("test"))
])),
// #[rustc_test_marker]
- cx.attribute(attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker")))
+ cx.attribute(attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker"))),
],
// const $ident: test::TestDescAndFn =
ast::ItemKind::Const(cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
-Subproject commit ddb30221d7985e813b4214d14c2a560ed6ee0991
+Subproject commit 269d0ba959f70e9b692e528311c78b8f9601d4af
-#![feature(const_fn, const_let)]
+#![feature(const_fn)]
const X : usize = 2;
+++ /dev/null
-// run-pass
-#![feature(irrefutable_let_patterns)]
-
-// must-compile-successfully-irrefutable_let_patterns_with_gate
-#[allow(irrefutable_let_patterns)]
-fn main() {
- if let _ = 5 {}
-
- while let _ = 5 {
- break;
- }
-}
+++ /dev/null
-// run-pass
-// Issue #7526: lowercase static constants in patterns look like bindings
-
-// This is similar to compile-fail/match-static-const-lc, except it
-// shows the expected usual workaround (choosing a different name for
-// the static definition) and also demonstrates that one can work
-// around this problem locally by renaming the constant in the `use`
-// form to an uppercase identifier that placates the lint.
-
-
-#![deny(non_upper_case_globals)]
-
-pub const A : isize = 97;
-
-fn f() {
- let r = match (0,0) {
- (0, A) => 0,
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 1);
- let r = match (0,97) {
- (0, A) => 0,
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 0);
-}
-
-mod m {
- #[allow(non_upper_case_globals)]
- pub const aha : isize = 7;
-}
-
-fn g() {
- use self::m::aha as AHA;
- let r = match (0,0) {
- (0, AHA) => 0,
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 1);
- let r = match (0,7) {
- (0, AHA) => 0,
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 0);
-}
-
-fn h() {
- let r = match (0,0) {
- (0, self::m::aha) => 0,
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 1);
- let r = match (0,7) {
- (0, self::m::aha) => 0,
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 0);
-}
-
-pub fn main () {
- f();
- g();
- h();
-}
-#![feature(const_int_conversion, const_int_ops, reverse_bits)]
+#![feature(const_int_conversion, reverse_bits)]
const REVERSE: u32 = 0x12345678_u32.reverse_bits();
const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
assert_eq!(TO_LE_BYTES, ident([0x78, 0x56, 0x34, 0x12]));
assert_eq!(TO_NE_BYTES, ident([0x80, 0, 0, 0]));
}
-
-#![feature(const_int_overflowing)]
-
const ADD_A: (u32, bool) = 5u32.overflowing_add(2);
const ADD_B: (u32, bool) = u32::max_value().overflowing_add(1);
-#![feature(const_int_rotate)]
-
const LEFT: u32 = 0x10000b3u32.rotate_left(8);
const RIGHT: u32 = 0xb301u32.rotate_right(8);
-#![feature(const_int_sign)]
-
const NEGATIVE_A: bool = (-10i32).is_negative();
const NEGATIVE_B: bool = 10i32.is_negative();
const POSITIVE_A: bool= (-10i32).is_positive();
-#![feature(const_int_wrapping)]
-
const ADD_A: u32 = 200u32.wrapping_add(55);
const ADD_B: u32 = 200u32.wrapping_add(u32::max_value());
// run-pass
-#![feature(const_int_ops)]
#![feature(test)]
extern crate test;
const BE_U32: u32 = 55u32.to_be();
const LE_U32: u32 = 55u32.to_le();
-
fn main() {
assert_eq!(BE_U32, b(55u32).to_be());
assert_eq!(LE_U32, b(55u32).to_le());
use std::intrinsics;
-const SWAPPED_U8: u8 = unsafe { intrinsics::bswap(0x12_u8) };
-const SWAPPED_U16: u16 = unsafe { intrinsics::bswap(0x12_34_u16) };
-const SWAPPED_I32: i32 = unsafe { intrinsics::bswap(0x12_34_56_78_i32) };
+const SWAPPED_U8: u8 = intrinsics::bswap(0x12_u8);
+const SWAPPED_U16: u16 = intrinsics::bswap(0x12_34_u16);
+const SWAPPED_I32: i32 = intrinsics::bswap(0x12_34_56_78_i32);
fn main() {
assert_eq!(SWAPPED_U8, 0x12);
// run-pass
#![allow(dead_code)]
-#![feature(const_let)]
-
type Array = [u32; { let x = 2; 5 }];
-pub fn main() {}
+pub fn main() {
+ let _: Array = [0; 5];
+}
// run-pass
#![allow(dead_code)]
-#![feature(const_let)]
-
+#[repr(u8)]
enum Foo {
Bar = { let x = 1; 3 }
}
-pub fn main() {}
+pub fn main() {
+ assert_eq!(3, Foo::Bar as u8);
+}
#![allow(dead_code)]
#![allow(unused_variables)]
-#![feature(const_fn, const_let)]
+#![feature(const_fn)]
const fn x() {
let t = true;
// https://github.com/rust-lang/rust/issues/48821
-#![feature(const_fn, const_let)]
-
const fn foo(i: usize) -> usize {
let x = i;
x
+++ /dev/null
-#![feature(irrefutable_let_patterns)]
-#![feature(type_alias_enum_variants)]
-
-#![allow(irrefutable_let_patterns)]
-
-#[allow(dead_code)]
-enum Enum<T> { TSVariant(T), SVariant { v: T } }
-type Alias<T> = Enum<T>;
-type AliasFixed = Enum<()>;
-
-macro_rules! is_variant {
- (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
- (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
- (@check $variant:ident, $matcher:tt, $expr:expr) => (
- assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
- "expr does not have correct type");
- );
-}
-
-fn main() {
- // Tuple struct variant
-
- is_variant!(TSVariant, Enum::TSVariant(()));
- is_variant!(TSVariant, Enum::TSVariant::<()>(()));
- is_variant!(TSVariant, Enum::<()>::TSVariant(()));
-
- is_variant!(TSVariant, Alias::TSVariant(()));
- is_variant!(TSVariant, Alias::<()>::TSVariant(()));
-
- is_variant!(TSVariant, AliasFixed::TSVariant(()));
-
- // Struct variant
-
- is_variant!(SVariant, Enum::SVariant { v: () });
- is_variant!(SVariant, Enum::SVariant::<()> { v: () });
- is_variant!(SVariant, Enum::<()>::SVariant { v: () });
-
- is_variant!(SVariant, Alias::SVariant { v: () });
- is_variant!(SVariant, Alias::<()>::SVariant { v: () });
-
- is_variant!(SVariant, AliasFixed::SVariant { v: () });
-}
}
pub fn main() {
- unsafe {
- use rusti::*;
-
- assert_eq!(ctpop(0u8), 0); assert_eq!(ctpop(0i8), 0);
- assert_eq!(ctpop(0u16), 0); assert_eq!(ctpop(0i16), 0);
- assert_eq!(ctpop(0u32), 0); assert_eq!(ctpop(0i32), 0);
- assert_eq!(ctpop(0u64), 0); assert_eq!(ctpop(0i64), 0);
- assert_eq!(ctpop(0u128), 0); assert_eq!(ctpop(0i128), 0);
-
- assert_eq!(ctpop(1u8), 1); assert_eq!(ctpop(1i8), 1);
- assert_eq!(ctpop(1u16), 1); assert_eq!(ctpop(1i16), 1);
- assert_eq!(ctpop(1u32), 1); assert_eq!(ctpop(1i32), 1);
- assert_eq!(ctpop(1u64), 1); assert_eq!(ctpop(1i64), 1);
- assert_eq!(ctpop(1u128), 1); assert_eq!(ctpop(1i128), 1);
-
- assert_eq!(ctpop(10u8), 2); assert_eq!(ctpop(10i8), 2);
- assert_eq!(ctpop(10u16), 2); assert_eq!(ctpop(10i16), 2);
- assert_eq!(ctpop(10u32), 2); assert_eq!(ctpop(10i32), 2);
- assert_eq!(ctpop(10u64), 2); assert_eq!(ctpop(10i64), 2);
- assert_eq!(ctpop(10u128), 2); assert_eq!(ctpop(10i128), 2);
-
- assert_eq!(ctpop(100u8), 3); assert_eq!(ctpop(100i8), 3);
- assert_eq!(ctpop(100u16), 3); assert_eq!(ctpop(100i16), 3);
- assert_eq!(ctpop(100u32), 3); assert_eq!(ctpop(100i32), 3);
- assert_eq!(ctpop(100u64), 3); assert_eq!(ctpop(100i64), 3);
- assert_eq!(ctpop(100u128), 3); assert_eq!(ctpop(100i128), 3);
-
- assert_eq!(ctpop(-1i8 as u8), 8); assert_eq!(ctpop(-1i8), 8);
- assert_eq!(ctpop(-1i16 as u16), 16); assert_eq!(ctpop(-1i16), 16);
- assert_eq!(ctpop(-1i32 as u32), 32); assert_eq!(ctpop(-1i32), 32);
- assert_eq!(ctpop(-1i64 as u64), 64); assert_eq!(ctpop(-1i64), 64);
- assert_eq!(ctpop(-1i128 as u128), 128); assert_eq!(ctpop(-1i128), 128);
-
- assert_eq!(ctlz(0u8), 8); assert_eq!(ctlz(0i8), 8);
- assert_eq!(ctlz(0u16), 16); assert_eq!(ctlz(0i16), 16);
- assert_eq!(ctlz(0u32), 32); assert_eq!(ctlz(0i32), 32);
- assert_eq!(ctlz(0u64), 64); assert_eq!(ctlz(0i64), 64);
- assert_eq!(ctlz(0u128), 128); assert_eq!(ctlz(0i128), 128);
-
- assert_eq!(ctlz(1u8), 7); assert_eq!(ctlz(1i8), 7);
- assert_eq!(ctlz(1u16), 15); assert_eq!(ctlz(1i16), 15);
- assert_eq!(ctlz(1u32), 31); assert_eq!(ctlz(1i32), 31);
- assert_eq!(ctlz(1u64), 63); assert_eq!(ctlz(1i64), 63);
- assert_eq!(ctlz(1u128), 127); assert_eq!(ctlz(1i128), 127);
-
- assert_eq!(ctlz(10u8), 4); assert_eq!(ctlz(10i8), 4);
- assert_eq!(ctlz(10u16), 12); assert_eq!(ctlz(10i16), 12);
- assert_eq!(ctlz(10u32), 28); assert_eq!(ctlz(10i32), 28);
- assert_eq!(ctlz(10u64), 60); assert_eq!(ctlz(10i64), 60);
- assert_eq!(ctlz(10u128), 124); assert_eq!(ctlz(10i128), 124);
-
- assert_eq!(ctlz(100u8), 1); assert_eq!(ctlz(100i8), 1);
- assert_eq!(ctlz(100u16), 9); assert_eq!(ctlz(100i16), 9);
- assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25);
- assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57);
- assert_eq!(ctlz(100u128), 121); assert_eq!(ctlz(100i128), 121);
+ use rusti::*;
+
+ assert_eq!(ctpop(0u8), 0); assert_eq!(ctpop(0i8), 0);
+ assert_eq!(ctpop(0u16), 0); assert_eq!(ctpop(0i16), 0);
+ assert_eq!(ctpop(0u32), 0); assert_eq!(ctpop(0i32), 0);
+ assert_eq!(ctpop(0u64), 0); assert_eq!(ctpop(0i64), 0);
+ assert_eq!(ctpop(0u128), 0); assert_eq!(ctpop(0i128), 0);
+
+ assert_eq!(ctpop(1u8), 1); assert_eq!(ctpop(1i8), 1);
+ assert_eq!(ctpop(1u16), 1); assert_eq!(ctpop(1i16), 1);
+ assert_eq!(ctpop(1u32), 1); assert_eq!(ctpop(1i32), 1);
+ assert_eq!(ctpop(1u64), 1); assert_eq!(ctpop(1i64), 1);
+ assert_eq!(ctpop(1u128), 1); assert_eq!(ctpop(1i128), 1);
+
+ assert_eq!(ctpop(10u8), 2); assert_eq!(ctpop(10i8), 2);
+ assert_eq!(ctpop(10u16), 2); assert_eq!(ctpop(10i16), 2);
+ assert_eq!(ctpop(10u32), 2); assert_eq!(ctpop(10i32), 2);
+ assert_eq!(ctpop(10u64), 2); assert_eq!(ctpop(10i64), 2);
+ assert_eq!(ctpop(10u128), 2); assert_eq!(ctpop(10i128), 2);
+
+ assert_eq!(ctpop(100u8), 3); assert_eq!(ctpop(100i8), 3);
+ assert_eq!(ctpop(100u16), 3); assert_eq!(ctpop(100i16), 3);
+ assert_eq!(ctpop(100u32), 3); assert_eq!(ctpop(100i32), 3);
+ assert_eq!(ctpop(100u64), 3); assert_eq!(ctpop(100i64), 3);
+ assert_eq!(ctpop(100u128), 3); assert_eq!(ctpop(100i128), 3);
+
+ assert_eq!(ctpop(-1i8 as u8), 8); assert_eq!(ctpop(-1i8), 8);
+ assert_eq!(ctpop(-1i16 as u16), 16); assert_eq!(ctpop(-1i16), 16);
+ assert_eq!(ctpop(-1i32 as u32), 32); assert_eq!(ctpop(-1i32), 32);
+ assert_eq!(ctpop(-1i64 as u64), 64); assert_eq!(ctpop(-1i64), 64);
+ assert_eq!(ctpop(-1i128 as u128), 128); assert_eq!(ctpop(-1i128), 128);
+
+ assert_eq!(ctlz(0u8), 8); assert_eq!(ctlz(0i8), 8);
+ assert_eq!(ctlz(0u16), 16); assert_eq!(ctlz(0i16), 16);
+ assert_eq!(ctlz(0u32), 32); assert_eq!(ctlz(0i32), 32);
+ assert_eq!(ctlz(0u64), 64); assert_eq!(ctlz(0i64), 64);
+ assert_eq!(ctlz(0u128), 128); assert_eq!(ctlz(0i128), 128);
+
+ assert_eq!(ctlz(1u8), 7); assert_eq!(ctlz(1i8), 7);
+ assert_eq!(ctlz(1u16), 15); assert_eq!(ctlz(1i16), 15);
+ assert_eq!(ctlz(1u32), 31); assert_eq!(ctlz(1i32), 31);
+ assert_eq!(ctlz(1u64), 63); assert_eq!(ctlz(1i64), 63);
+ assert_eq!(ctlz(1u128), 127); assert_eq!(ctlz(1i128), 127);
+
+ assert_eq!(ctlz(10u8), 4); assert_eq!(ctlz(10i8), 4);
+ assert_eq!(ctlz(10u16), 12); assert_eq!(ctlz(10i16), 12);
+ assert_eq!(ctlz(10u32), 28); assert_eq!(ctlz(10i32), 28);
+ assert_eq!(ctlz(10u64), 60); assert_eq!(ctlz(10i64), 60);
+ assert_eq!(ctlz(10u128), 124); assert_eq!(ctlz(10i128), 124);
+
+ assert_eq!(ctlz(100u8), 1); assert_eq!(ctlz(100i8), 1);
+ assert_eq!(ctlz(100u16), 9); assert_eq!(ctlz(100i16), 9);
+ assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25);
+ assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57);
+ assert_eq!(ctlz(100u128), 121); assert_eq!(ctlz(100i128), 121);
+ unsafe {
assert_eq!(ctlz_nonzero(1u8), 7); assert_eq!(ctlz_nonzero(1i8), 7);
assert_eq!(ctlz_nonzero(1u16), 15); assert_eq!(ctlz_nonzero(1i16), 15);
assert_eq!(ctlz_nonzero(1u32), 31); assert_eq!(ctlz_nonzero(1i32), 31);
assert_eq!(ctlz_nonzero(100u32), 25); assert_eq!(ctlz_nonzero(100i32), 25);
assert_eq!(ctlz_nonzero(100u64), 57); assert_eq!(ctlz_nonzero(100i64), 57);
assert_eq!(ctlz_nonzero(100u128), 121); assert_eq!(ctlz_nonzero(100i128), 121);
+ }
- assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0);
- assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0);
- assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0);
- assert_eq!(cttz(-1i64 as u64), 0); assert_eq!(cttz(-1i64), 0);
- assert_eq!(cttz(-1i128 as u128), 0); assert_eq!(cttz(-1i128), 0);
-
- assert_eq!(cttz(0u8), 8); assert_eq!(cttz(0i8), 8);
- assert_eq!(cttz(0u16), 16); assert_eq!(cttz(0i16), 16);
- assert_eq!(cttz(0u32), 32); assert_eq!(cttz(0i32), 32);
- assert_eq!(cttz(0u64), 64); assert_eq!(cttz(0i64), 64);
- assert_eq!(cttz(0u128), 128); assert_eq!(cttz(0i128), 128);
-
- assert_eq!(cttz(1u8), 0); assert_eq!(cttz(1i8), 0);
- assert_eq!(cttz(1u16), 0); assert_eq!(cttz(1i16), 0);
- assert_eq!(cttz(1u32), 0); assert_eq!(cttz(1i32), 0);
- assert_eq!(cttz(1u64), 0); assert_eq!(cttz(1i64), 0);
- assert_eq!(cttz(1u128), 0); assert_eq!(cttz(1i128), 0);
-
- assert_eq!(cttz(10u8), 1); assert_eq!(cttz(10i8), 1);
- assert_eq!(cttz(10u16), 1); assert_eq!(cttz(10i16), 1);
- assert_eq!(cttz(10u32), 1); assert_eq!(cttz(10i32), 1);
- assert_eq!(cttz(10u64), 1); assert_eq!(cttz(10i64), 1);
- assert_eq!(cttz(10u128), 1); assert_eq!(cttz(10i128), 1);
-
- assert_eq!(cttz(100u8), 2); assert_eq!(cttz(100i8), 2);
- assert_eq!(cttz(100u16), 2); assert_eq!(cttz(100i16), 2);
- assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2);
- assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2);
- assert_eq!(cttz(100u128), 2); assert_eq!(cttz(100i128), 2);
+ assert_eq!(cttz(-1i8 as u8), 0); assert_eq!(cttz(-1i8), 0);
+ assert_eq!(cttz(-1i16 as u16), 0); assert_eq!(cttz(-1i16), 0);
+ assert_eq!(cttz(-1i32 as u32), 0); assert_eq!(cttz(-1i32), 0);
+ assert_eq!(cttz(-1i64 as u64), 0); assert_eq!(cttz(-1i64), 0);
+ assert_eq!(cttz(-1i128 as u128), 0); assert_eq!(cttz(-1i128), 0);
+
+ assert_eq!(cttz(0u8), 8); assert_eq!(cttz(0i8), 8);
+ assert_eq!(cttz(0u16), 16); assert_eq!(cttz(0i16), 16);
+ assert_eq!(cttz(0u32), 32); assert_eq!(cttz(0i32), 32);
+ assert_eq!(cttz(0u64), 64); assert_eq!(cttz(0i64), 64);
+ assert_eq!(cttz(0u128), 128); assert_eq!(cttz(0i128), 128);
+
+ assert_eq!(cttz(1u8), 0); assert_eq!(cttz(1i8), 0);
+ assert_eq!(cttz(1u16), 0); assert_eq!(cttz(1i16), 0);
+ assert_eq!(cttz(1u32), 0); assert_eq!(cttz(1i32), 0);
+ assert_eq!(cttz(1u64), 0); assert_eq!(cttz(1i64), 0);
+ assert_eq!(cttz(1u128), 0); assert_eq!(cttz(1i128), 0);
+
+ assert_eq!(cttz(10u8), 1); assert_eq!(cttz(10i8), 1);
+ assert_eq!(cttz(10u16), 1); assert_eq!(cttz(10i16), 1);
+ assert_eq!(cttz(10u32), 1); assert_eq!(cttz(10i32), 1);
+ assert_eq!(cttz(10u64), 1); assert_eq!(cttz(10i64), 1);
+ assert_eq!(cttz(10u128), 1); assert_eq!(cttz(10i128), 1);
+
+ assert_eq!(cttz(100u8), 2); assert_eq!(cttz(100i8), 2);
+ assert_eq!(cttz(100u16), 2); assert_eq!(cttz(100i16), 2);
+ assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2);
+ assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2);
+ assert_eq!(cttz(100u128), 2); assert_eq!(cttz(100i128), 2);
+ unsafe {
assert_eq!(cttz_nonzero(-1i8 as u8), 0); assert_eq!(cttz_nonzero(-1i8), 0);
assert_eq!(cttz_nonzero(-1i16 as u16), 0); assert_eq!(cttz_nonzero(-1i16), 0);
assert_eq!(cttz_nonzero(-1i32 as u32), 0); assert_eq!(cttz_nonzero(-1i32), 0);
assert_eq!(cttz_nonzero(100u32), 2); assert_eq!(cttz_nonzero(100i32), 2);
assert_eq!(cttz_nonzero(100u64), 2); assert_eq!(cttz_nonzero(100i64), 2);
assert_eq!(cttz_nonzero(100u128), 2); assert_eq!(cttz_nonzero(100i128), 2);
-
- assert_eq!(bswap(0x0Au8), 0x0A); // no-op
- assert_eq!(bswap(0x0Ai8), 0x0A); // no-op
- assert_eq!(bswap(0x0A0Bu16), 0x0B0A);
- assert_eq!(bswap(0x0A0Bi16), 0x0B0A);
- assert_eq!(bswap(0x0ABBCC0Du32), 0x0DCCBB0A);
- assert_eq!(bswap(0x0ABBCC0Di32), 0x0DCCBB0A);
- assert_eq!(bswap(0x0122334455667708u64), 0x0877665544332201);
- assert_eq!(bswap(0x0122334455667708i64), 0x0877665544332201);
- assert_eq!(bswap(0x0122334455667708u128), 0x08776655443322010000000000000000);
- assert_eq!(bswap(0x0122334455667708i128), 0x08776655443322010000000000000000);
-
- assert_eq!(bitreverse(0x0Au8), 0x50);
- assert_eq!(bitreverse(0x0Ai8), 0x50);
- assert_eq!(bitreverse(0x0A0Cu16), 0x3050);
- assert_eq!(bitreverse(0x0A0Ci16), 0x3050);
- assert_eq!(bitreverse(0x0ABBCC0Eu32), 0x7033DD50);
- assert_eq!(bitreverse(0x0ABBCC0Ei32), 0x7033DD50);
- assert_eq!(bitreverse(0x0122334455667708u64), 0x10EE66AA22CC4480);
- assert_eq!(bitreverse(0x0122334455667708i64), 0x10EE66AA22CC4480);
- assert_eq!(bitreverse(0x0122334455667708u128), 0x10EE66AA22CC44800000000000000000);
- assert_eq!(bitreverse(0x0122334455667708i128), 0x10EE66AA22CC44800000000000000000);
}
+
+ assert_eq!(bswap(0x0Au8), 0x0A); // no-op
+ assert_eq!(bswap(0x0Ai8), 0x0A); // no-op
+ assert_eq!(bswap(0x0A0Bu16), 0x0B0A);
+ assert_eq!(bswap(0x0A0Bi16), 0x0B0A);
+ assert_eq!(bswap(0x0ABBCC0Du32), 0x0DCCBB0A);
+ assert_eq!(bswap(0x0ABBCC0Di32), 0x0DCCBB0A);
+ assert_eq!(bswap(0x0122334455667708u64), 0x0877665544332201);
+ assert_eq!(bswap(0x0122334455667708i64), 0x0877665544332201);
+ assert_eq!(bswap(0x0122334455667708u128), 0x08776655443322010000000000000000);
+ assert_eq!(bswap(0x0122334455667708i128), 0x08776655443322010000000000000000);
+
+ assert_eq!(bitreverse(0x0Au8), 0x50);
+ assert_eq!(bitreverse(0x0Ai8), 0x50);
+ assert_eq!(bitreverse(0x0A0Cu16), 0x3050);
+ assert_eq!(bitreverse(0x0A0Ci16), 0x3050);
+ assert_eq!(bitreverse(0x0ABBCC0Eu32), 0x7033DD50);
+ assert_eq!(bitreverse(0x0ABBCC0Ei32), 0x7033DD50);
+ assert_eq!(bitreverse(0x0122334455667708u64), 0x10EE66AA22CC4480);
+ assert_eq!(bitreverse(0x0122334455667708i64), 0x10EE66AA22CC4480);
+ assert_eq!(bitreverse(0x0122334455667708u128), 0x10EE66AA22CC44800000000000000000);
+ assert_eq!(bitreverse(0x0122334455667708i128), 0x10EE66AA22CC44800000000000000000);
}
+++ /dev/null
-//
-#![allow(dead_code)]
-
-
-#![forbid(non_camel_case_types)]
-#![forbid(non_upper_case_globals)]
-#![feature(non_ascii_idents)]
-
-// Some scripts (e.g., hiragana) don't have a concept of
-// upper/lowercase
-
-struct ヒ;
-
-static ラ: usize = 0;
-
-pub fn main() {}
+++ /dev/null
-#![allow(dead_code)]
-// This is ok because we often use the trailing underscore to mean 'prime'
-
-// pretty-expanded FIXME #23616
-
-#[forbid(non_camel_case_types)]
-type Foo_ = isize;
-
-pub fn main() { }
-#![feature(transpose_result)]
-
#[derive(Copy, Clone, Debug, PartialEq)]
struct BadNumErr;
// run-pass
#![allow(dead_code)]
-#![feature(if_while_or_patterns)]
enum E {
V(u8),
assert_eq!(x, 10);
e = W;
}
+
+ // Accept leading `|`:
+
+ let mut e = V(10);
+
+ if let | V(x) | U(x) = e {
+ assert_eq!(x, 10);
+ }
+ while let | V(x) | U(x) = e {
+ assert_eq!(x, 10);
+ e = W;
+ }
}
+++ /dev/null
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-#![feature(non_ascii_idents)]
-#![deny(non_snake_case)]
-
-// This name is neither upper nor lower case
-fn ä½ å¥½() {}
-
-fn main() {}
+++ /dev/null
-#![deny(non_camel_case_types)]
-
-pub enum Foo {
- #[allow(non_camel_case_types)]
- bar
-}
-
-fn main() {}
// edition:2018
-#![feature(uniform_paths)]
-
mod m { pub fn f() {} }
mod n { pub fn g() {} }
-// run-pass
-#![allow(unused_imports)]
-#![allow(non_camel_case_types)]
+// This test is similar to `basic.rs`, but nested in modules.
+// run-pass
// edition:2018
-#![feature(decl_macro, uniform_paths)]
+#![feature(decl_macro)]
-// This test is similar to `basic.rs`, but nested in modules.
+#![allow(unused_imports)]
+#![allow(non_camel_case_types)]
mod foo {
// Test that ambiguity errors are not emitted between `self::test` and
// run-pass
-#![allow(unused_imports)]
-#![allow(non_camel_case_types)]
-
// edition:2018
-#![feature(uniform_paths)]
+#![allow(unused_imports)]
+#![allow(non_camel_case_types)]
// Test that ambiguity errors are not emitted between `self::test` and
// `::test`, assuming the latter (crate) is not in `extern_prelude`.
-// run-pass
-#![allow(non_camel_case_types)]
+// This test is similar to `macros.rs`, but nested in modules.
+// run-pass
// edition:2018
-#![feature(uniform_paths)]
-
-// This test is similar to `macros.rs`, but nested in modules.
+#![allow(non_camel_case_types)]
mod foo {
// Test that ambiguity errors are not emitted between `self::test` and
-// run-pass
-#![allow(non_camel_case_types)]
+// This test is similar to `basic.rs`, but with macros defining local items.
+// run-pass
// edition:2018
-#![feature(uniform_paths)]
-
-// This test is similar to `basic.rs`, but with macros defining local items.
+#![allow(non_camel_case_types)]
// Test that ambiguity errors are not emitted between `self::test` and
// `::test`, assuming the latter (crate) is not in `extern_prelude`.
// run-pass
-
// edition:2018
-#![feature(uniform_paths)]
-
pub const A: usize = 0;
pub mod foo {
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(missing_docs)] //~ ERROR
+
+pub struct Foo; //~ ERROR
--- /dev/null
+error: missing documentation for crate
+ --> $DIR/deny-missing-docs-crate.rs:11:1
+ |
+LL | / #![deny(missing_docs)] //~ ERROR
+LL | |
+LL | | pub struct Foo; //~ ERROR
+ | |_______________^
+ |
+note: lint level defined here
+ --> $DIR/deny-missing-docs-crate.rs:11:9
+ |
+LL | #![deny(missing_docs)] //~ ERROR
+ | ^^^^^^^^^^^^
+
+error: missing documentation for a struct
+ --> $DIR/deny-missing-docs-crate.rs:13:1
+ |
+LL | pub struct Foo; //~ ERROR
+ | ^^^^^^^^^^^^^^^
+
+error: Compilation failed, aborting rustdoc
+
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! foo
+
+#![deny(missing_docs)]
+
+#[macro_export]
+macro_rules! foo { //~ ERROR
+ () => {}
+}
--- /dev/null
+error: missing documentation for macro
+ --> $DIR/deny-missing-docs-macro.rs:16:1
+ |
+LL | macro_rules! foo { //~ ERROR
+ | ^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/deny-missing-docs-macro.rs:13:9
+ |
+LL | #![deny(missing_docs)]
+ | ^^^^^^^^^^^^
+
+error: Compilation failed, aborting rustdoc
+
pub struct SomeStruct;
impl SomeStruct {
- // @has 'foo/struct.SomeStruct.html' '//*[@id="SOME_CONST.v"]//div[@class="since"]' '1.1.2'
+ // @has 'foo/struct.SomeStruct.html' '//*[@id="associatedconstant.SOME_CONST"]//div[@class="since"]' '1.1.2'
#[stable(since="1.1.2", feature="rust2")]
pub const SOME_CONST: usize = 0;
}
--- /dev/null
+#![crate_name = "inner"]
+pub struct SomeStruct;
pub struct Foo;
impl Foo {
- // @has const/struct.Foo.html '//*[@id="new.v"]//code' 'const unsafe fn new'
+ // @has const/struct.Foo.html '//code[@id="new.v"]' 'const unsafe fn new'
pub const unsafe fn new() -> Foo {
Foo
}
impl Foo<u8> {
// @has - '//*[@id="method.pass"]//code' 'fn pass()'
- // @has - '//*[@id="pass.v"]//code' 'fn pass()'
+ // @has - '//code[@id="pass.v"]' 'fn pass()'
pub fn pass() {}
}
impl Foo<u16> {
// @has - '//*[@id="method.pass-1"]//code' 'fn pass() -> usize'
- // @has - '//*[@id="pass.v-1"]//code' 'fn pass() -> usize'
+ // @has - '//code[@id="pass.v-1"]' 'fn pass() -> usize'
pub fn pass() -> usize { 42 }
}
impl Foo<u32> {
// @has - '//*[@id="method.pass-2"]//code' 'fn pass() -> isize'
- // @has - '//*[@id="pass.v-2"]//code' 'fn pass() -> isize'
+ // @has - '//code[@id="pass.v-2"]' 'fn pass() -> isize'
pub fn pass() -> isize { 42 }
}
// 'Deprecated since 1.0.0: text'
// @has - '<code>test</code> <a href="http://issue_url/32374">#32374</a>'
// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \
-// '🔬 This is a nightly-only experimental API. \(test #32374\)$'
+// '🔬 This is a nightly-only experimental API. \(test\s#32374\)$'
/// Docs
#[rustc_deprecated(since = "1.0.0", reason = "text")]
#[unstable(feature = "test", issue = "32374")]
}
// @has issue_51236/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> Send for \
// Owned<T> where <T as Owned<'static>>::Reader: Send"
pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
// @has issue_54705/struct.ScopeFutureContents.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'scope, S> \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'scope, S> \
// Send for ScopeFutureContents<'scope, S> where S: Sync"
//
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'scope, S> \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'scope, S> \
// Sync for ScopeFutureContents<'scope, S> where S: Sync"
pub struct ScopeFutureContents<'scope, S>
where S: ScopeHandle<'scope>,
#![feature(optin_builtin_traits)]
// @has issue_55321/struct.A.html
-// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Send for A"
-// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Sync for A"
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' "impl !Send for A"
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' "impl !Sync for A"
pub struct A();
impl !Send for A {}
impl !Sync for A {}
// @has issue_55321/struct.B.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
// B<T>"
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Sync for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Sync for \
// B<T>"
pub struct B<T: ?Sized>(A, Box<T>);
}
// @has issue_56822/struct.Parser.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'a> Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a> Send for \
// Parser<'a>"
pub struct Parser<'a> {
field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output
--- /dev/null
+// aux-build:pub-extern-crate.rs
+
+// @has pub_extern_crate/index.html
+// @!has - '//code' 'pub extern crate inner'
+// @has - '//a/@href' 'inner/index.html'
+// @has pub_extern_crate/inner/index.html
+// @has pub_extern_crate/inner/struct.SomeStruct.html
+#[doc(inline)]
+pub extern crate inner;
}
// @has complex/struct.NotOuter.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'a, T, K: \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'a, T, K: \
// ?Sized> Send for NotOuter<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
{}
// @has lifetimes/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Send \
// for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
//
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Sync \
// for Foo<'c, K> where K: Sync"
pub struct Foo<'c, K: 'c> {
inner_field: Inner<'c, K>,
// @has manual/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl<T> Sync for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' 'impl<T> Sync for \
// Foo<T> where T: Sync'
//
-// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' \
+// @has - '//*[@id="implementations-list"]/*[@class="impl"]//code' \
// 'impl<T> Send for Foo<T>'
//
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
}
// @has negative/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
// Outer<T>"
//
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> \
// !Sync for Outer<T>"
pub struct Outer<T: Copy> {
inner_field: Inner<T>,
}
// @has nested/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' 'impl<T> Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' 'impl<T> Send for \
// Foo<T> where T: Copy'
//
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' \
// 'impl<T> Sync for Foo<T> where T: Sync'
pub struct Foo<T> {
inner_field: Inner<T>,
}
// @has no_redundancy/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> Send for \
// Outer<T> where T: Copy + Send"
pub struct Outer<T> {
inner_field: Inner<T>,
}
// @has project/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Send \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Send \
// for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
//
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<'c, K> Sync \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<'c, K> Sync \
// for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, 'c: 'static,"
pub struct Foo<'c, K: 'c> {
inner_field: Inner<'c, K>,
// @has self_referential/struct.WriteAndThen.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<P1> Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<P1> Send for \
// WriteAndThen<P1> where <P1 as Pattern>::Value: Send"
pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
where P1: Pattern;
}
// @has static_region/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> Send for \
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> Send for \
// Owned<T> where <T as OwnedTrait<'static>>::Reader: Send"
pub struct Owned<T> where T: OwnedTrait<'static> {
marker: <T as OwnedTrait<'static>>::Reader,
-// Test associated types are forbidden in inherent impls.
+// Test associated types are, until #8995 is implemented, forbidden in inherent impls.
struct Foo;
impl Foo {
- type Bar = isize; //~ERROR associated types are not allowed in inherent impls
+ type Bar = isize; //~ERROR associated types are not yet supported in inherent impls (see #8995)
}
fn main() {}
-error[E0202]: associated types are not allowed in inherent impls
+error[E0202]: associated types are not yet supported in inherent impls (see #8995)
--> $DIR/assoc-inherent.rs:6:5
|
-LL | type Bar = isize; //~ERROR associated types are not allowed in inherent impls
+LL | type Bar = isize; //~ERROR associated types are not yet supported in inherent impls (see #8995)
| ^^^^^^^^^^^^^^^^^
error: aborting due to previous error
+++ /dev/null
-#![deny(non_upper_case_globals)]
-#![allow(dead_code)]
-
-struct Foo;
-
-impl Foo {
- const not_upper: bool = true;
-}
-//~^^ ERROR associated constant `not_upper` should have an upper case name such as `NOT_UPPER`
-
-fn main() {}
+++ /dev/null
-error: associated constant `not_upper` should have an upper case name such as `NOT_UPPER`
- --> $DIR/associated-const-upper-case-lint.rs:7:5
- |
-LL | const not_upper: bool = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: lint level defined here
- --> $DIR/associated-const-upper-case-lint.rs:1:9
- |
-LL | #![deny(non_upper_case_globals)]
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
#[derive(Copy, Clone)]
pub struct Foo(i64);
-pub unsafe fn test_cttz(v: Foo) -> Foo {
+pub fn test_cttz(v: Foo) -> Foo {
intrinsics::cttz(v)
//~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo`
}
error[E0308]: mismatched types
--> $DIR/issue-13624.rs:22:9
|
+LL | match enum_struct_variant {
+ | ------------------- this match expression has type `()`
LL | a::Enum::EnumStructVariant { x, y, z } => {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
|
LL | let bar1 = &mut foo.bar1;
| -------- mutable borrow occurs here (via `foo.bar1`)
LL | let _foo1 = &foo.bar2; //~ ERROR cannot borrow
- | ^^^^^^^^ immutable borrow occurs here (via `foo.bar2`)
+ | ^^^^^^^^ immutable borrow of `foo.bar2` -- which overlaps with `foo.bar1` -- occurs here
LL | *bar1;
LL | }
| - mutable borrow ends here
LL | let _x = &mut a.x;
| --- mutable borrow occurs here (via `a.x`)
LL | let _y = &a.y; //[ast]~ ERROR cannot borrow
- | ^^^ immutable borrow occurs here (via `a.y`)
+ | ^^^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
...
LL | }
| - mutable borrow ends here
LL | let _x = &a.x;
| --- immutable borrow occurs here (via `a.x`)
LL | let _y = &mut a.y; //[ast]~ ERROR cannot borrow
- | ^^^ mutable borrow occurs here (via `a.y`)
+ | ^^^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
...
LL | }
| - immutable borrow ends here
let mut a: Box<_> = box A { x: box 0, y: 1 };
let _x = &mut a.x;
let _y = &a.y; //[ast]~ ERROR cannot borrow
- //[ast]~^ immutable borrow occurs here (via `a.y`)
+ //[ast]~^ immutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
use_mut(_x);
}
fn mut_borrow_after_borrow() {
let mut a: Box<_> = box A { x: box 0, y: 1 };
let _x = &a.x;
let _y = &mut a.y; //[ast]~ ERROR cannot borrow
- //[ast]~^ mutable borrow occurs here (via `a.y`)
+ //[ast]~^ mutable borrow of `a.y` -- which overlaps with `a.x` -- occurs here
use_imm(_x);
}
fn copy_after_move_nested() {
+++ /dev/null
-error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
- --> $DIR/borrowck-union-borrow.rs:27:23
- |
-LL | let ra = &u.a;
- | ---- immutable borrow occurs here
-LL | let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
- | ^^^^^^^^ mutable borrow occurs here
-LL | //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
-LL | drop(ra);
- | -- immutable borrow later used here
-
-error[E0506]: cannot assign to `u.a` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:33:13
- |
-LL | let ra = &u.a;
- | ---- borrow of `u.a` occurs here
-LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.a` occurs here
-LL | //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
-LL | drop(ra);
- | -- borrow later used here
-
-error[E0502]: cannot borrow `u.b` as mutable because it is also borrowed as immutable
- --> $DIR/borrowck-union-borrow.rs:50:23
- |
-LL | let ra = &u.a;
- | ---- immutable borrow occurs here
-LL | let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
- | ^^^^^^^^ mutable borrow occurs here
-LL | //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
-LL | drop(ra);
- | -- immutable borrow later used here
-
-error[E0506]: cannot assign to `u.b` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:56:13
- |
-LL | let ra = &u.a;
- | ---- borrow of `u.b` occurs here
-LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.b` occurs here
-LL | //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
-LL | drop(ra);
- | -- borrow later used here
-
-error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
- --> $DIR/borrowck-union-borrow.rs:63:22
- |
-LL | let rma = &mut u.a;
- | -------- mutable borrow occurs here
-LL | let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
- | ^^^^ immutable borrow occurs here
-LL | //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
-LL | drop(rma);
- | --- mutable borrow later used here
-
-error[E0503]: cannot use `u.a` because it was mutably borrowed
- --> $DIR/borrowck-union-borrow.rs:69:21
- |
-LL | let ra = &mut u.a;
- | -------- borrow of `u.a` occurs here
-LL | let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
- | ^^^ use of borrowed `u.a`
-LL | //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
-LL | drop(ra);
- | -- borrow later used here
-
-error[E0499]: cannot borrow `u.a` as mutable more than once at a time
- --> $DIR/borrowck-union-borrow.rs:75:24
- |
-LL | let rma = &mut u.a;
- | -------- first mutable borrow occurs here
-LL | let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
- | ^^^^^^^^ second mutable borrow occurs here
-LL | //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
-LL | drop(rma);
- | --- first borrow later used here
-
-error[E0506]: cannot assign to `u.a` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:81:13
- |
-LL | let rma = &mut u.a;
- | -------- borrow of `u.a` occurs here
-LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.a` occurs here
-LL | //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
-LL | drop(rma);
- | --- borrow later used here
-
-error[E0502]: cannot borrow `u.b` as immutable because it is also borrowed as mutable
- --> $DIR/borrowck-union-borrow.rs:88:22
- |
-LL | let rma = &mut u.a;
- | -------- mutable borrow occurs here
-LL | let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
- | ^^^^ immutable borrow occurs here
-LL | //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
-LL | drop(rma);
- | --- mutable borrow later used here
-
-error[E0503]: cannot use `u.b` because it was mutably borrowed
- --> $DIR/borrowck-union-borrow.rs:94:21
- |
-LL | let ra = &mut u.a;
- | -------- borrow of `u.a` occurs here
-LL | let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
- | ^^^ use of borrowed `u.a`
-...
-LL | drop(ra);
- | -- borrow later used here
-
-error[E0499]: cannot borrow `u.b` as mutable more than once at a time
- --> $DIR/borrowck-union-borrow.rs:101:24
- |
-LL | let rma = &mut u.a;
- | -------- first mutable borrow occurs here
-LL | let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
- | ^^^^^^^^ second mutable borrow occurs here
-LL | //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
-LL | drop(rma);
- | --- first borrow later used here
-
-error[E0506]: cannot assign to `u.b` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:107:13
- |
-LL | let rma = &mut u.a;
- | -------- borrow of `u.b` occurs here
-LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.b` occurs here
-LL | //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
-LL | drop(rma);
- | --- borrow later used here
-
-error: aborting due to 12 previous errors
-
-Some errors occurred: E0499, E0502, E0503, E0506.
-For more information about an error, try `rustc --explain E0499`.
+++ /dev/null
-error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
- --> $DIR/borrowck-union-borrow.rs:27:28
- |
-LL | let ra = &u.a;
- | --- immutable borrow occurs here
-LL | let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
- | ^^^ mutable borrow occurs here
-...
-LL | }
- | - immutable borrow ends here
-
-error[E0506]: cannot assign to `u.a` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:33:13
- |
-LL | let ra = &u.a;
- | --- borrow of `u.a` occurs here
-LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.a` occurs here
-
-error[E0502]: cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
- --> $DIR/borrowck-union-borrow.rs:50:28
- |
-LL | let ra = &u.a;
- | --- immutable borrow occurs here (via `u.a`)
-LL | let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
- | ^^^ mutable borrow occurs here (via `u.b`)
-...
-LL | }
- | - immutable borrow ends here
-
-error[E0506]: cannot assign to `u.b` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:56:13
- |
-LL | let ra = &u.a;
- | --- borrow of `u.b` occurs here
-LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.b` occurs here
-
-error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
- --> $DIR/borrowck-union-borrow.rs:63:23
- |
-LL | let rma = &mut u.a;
- | --- mutable borrow occurs here
-LL | let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
- | ^^^ immutable borrow occurs here
-...
-LL | }
- | - mutable borrow ends here
-
-error[E0503]: cannot use `u.a` because it was mutably borrowed
- --> $DIR/borrowck-union-borrow.rs:69:17
- |
-LL | let ra = &mut u.a;
- | --- borrow of `u.a` occurs here
-LL | let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
- | ^ use of borrowed `u.a`
-
-error[E0499]: cannot borrow `u.a` as mutable more than once at a time
- --> $DIR/borrowck-union-borrow.rs:75:29
- |
-LL | let rma = &mut u.a;
- | --- first mutable borrow occurs here
-LL | let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
- | ^^^ second mutable borrow occurs here
-...
-LL | }
- | - first borrow ends here
-
-error[E0506]: cannot assign to `u.a` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:81:13
- |
-LL | let rma = &mut u.a;
- | --- borrow of `u.a` occurs here
-LL | u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.a` occurs here
-
-error[E0502]: cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
- --> $DIR/borrowck-union-borrow.rs:88:23
- |
-LL | let rma = &mut u.a;
- | --- mutable borrow occurs here (via `u.a`)
-LL | let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
- | ^^^ immutable borrow occurs here (via `u.b`)
-...
-LL | }
- | - mutable borrow ends here
-
-error[E0503]: cannot use `u.b` because it was mutably borrowed
- --> $DIR/borrowck-union-borrow.rs:94:17
- |
-LL | let ra = &mut u.a;
- | --- borrow of `u.a` occurs here
-LL | let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
- | ^ use of borrowed `u.a`
-
-error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
- --> $DIR/borrowck-union-borrow.rs:101:29
- |
-LL | let rma = &mut u.a;
- | --- first mutable borrow occurs here (via `u.a`)
-LL | let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
- | ^^^ second mutable borrow occurs here (via `u.b`)
-...
-LL | }
- | - first borrow ends here
-
-error[E0506]: cannot assign to `u.b` because it is borrowed
- --> $DIR/borrowck-union-borrow.rs:107:13
- |
-LL | let rma = &mut u.a;
- | --- borrow of `u.b` occurs here
-LL | u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
- | ^^^^^^^ assignment to borrowed `u.b` occurs here
-
-error: aborting due to 12 previous errors
-
-Some errors occurred: E0499, E0502, E0503, E0506.
-For more information about an error, try `rustc --explain E0499`.
--- /dev/null
+error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
+ --> $DIR/borrowck-union-borrow.rs:25:23
+ |
+LL | let ra = &u.a;
+ | ---- immutable borrow occurs here
+LL | let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+ | ^^^^^^^^ mutable borrow occurs here
+LL | drop(ra);
+ | -- immutable borrow later used here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:30:13
+ |
+LL | let ra = &u.a;
+ | ---- borrow of `u.a` occurs here
+LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.a` occurs here
+LL | drop(ra);
+ | -- borrow later used here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as mutable because it is also borrowed as immutable (via `u.a`)
+ --> $DIR/borrowck-union-borrow.rs:46:23
+ |
+LL | let ra = &u.a;
+ | ---- immutable borrow occurs here (via `u.a`)
+LL | let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+ | ^^^^^^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL | drop(ra);
+ | -- immutable borrow later used here
+ |
+ = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:51:13
+ |
+LL | let ra = &u.a;
+ | ---- borrow of `u.b` occurs here
+LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.b` occurs here
+LL | drop(ra);
+ | -- borrow later used here
+
+error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
+ --> $DIR/borrowck-union-borrow.rs:57:22
+ |
+LL | let rma = &mut u.a;
+ | -------- mutable borrow occurs here
+LL | let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+ | ^^^^ immutable borrow occurs here
+LL | drop(rma);
+ | --- mutable borrow later used here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+ --> $DIR/borrowck-union-borrow.rs:62:21
+ |
+LL | let ra = &mut u.a;
+ | -------- borrow of `u.a` occurs here
+LL | let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
+ | ^^^ use of borrowed `u.a`
+LL | drop(ra);
+ | -- borrow later used here
+
+error[E0499]: cannot borrow `u.a` as mutable more than once at a time
+ --> $DIR/borrowck-union-borrow.rs:67:24
+ |
+LL | let rma = &mut u.a;
+ | -------- first mutable borrow occurs here
+LL | let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
+ | ^^^^^^^^ second mutable borrow occurs here
+LL | drop(rma);
+ | --- first borrow later used here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:72:13
+ |
+LL | let rma = &mut u.a;
+ | -------- borrow of `u.a` occurs here
+LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.a` occurs here
+LL | drop(rma);
+ | --- borrow later used here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as immutable because it is also borrowed as mutable (via `u.a`)
+ --> $DIR/borrowck-union-borrow.rs:78:22
+ |
+LL | let rma = &mut u.a;
+ | -------- mutable borrow occurs here (via `u.a`)
+LL | let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+ | ^^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL | drop(rma);
+ | --- mutable borrow later used here
+ |
+ = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
+
+error[E0503]: cannot use `u.b` because it was mutably borrowed
+ --> $DIR/borrowck-union-borrow.rs:83:21
+ |
+LL | let ra = &mut u.a;
+ | -------- borrow of `u.a` occurs here
+LL | let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
+ | ^^^ use of borrowed `u.a`
+LL |
+LL | drop(ra);
+ | -- borrow later used here
+
+error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
+ --> $DIR/borrowck-union-borrow.rs:89:24
+ |
+LL | let rma = &mut u.a;
+ | -------- first mutable borrow occurs here (via `u.a`)
+LL | let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
+ | ^^^^^^^^ second mutable borrow occurs here (via `u.b`)
+LL | drop(rma);
+ | --- first borrow later used here
+ |
+ = note: `u.b` is a field of the union `U`, so it overlaps the field `u.a`
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:94:13
+ |
+LL | let rma = &mut u.a;
+ | -------- borrow of `u.b` occurs here
+LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.b` occurs here
+LL | drop(rma);
+ | --- borrow later used here
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0499, E0502, E0503, E0506.
+For more information about an error, try `rustc --explain E0499`.
// ignore-tidy-linelength
-// revisions: ast mir
-//[mir]compile-flags: -Z borrowck=mir
#[derive(Clone, Copy)]
union U {
}
{
let ra = &u.a;
- let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
- //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+ let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
drop(ra);
}
{
let ra = &u.a;
- u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
- //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
+ u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
drop(ra);
}
// Imm borrow, other field
}
{
let ra = &u.a;
- let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
- //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
+ let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
drop(ra);
}
{
let ra = &u.a;
- u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
- //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
+ u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
drop(ra);
}
// Mut borrow, same field
{
let rma = &mut u.a;
- let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
- //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+ let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
drop(rma);
}
{
let ra = &mut u.a;
- let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
- //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed
+ let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
drop(ra);
}
{
let rma = &mut u.a;
- let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
- //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
+ let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
drop(rma);
}
{
let rma = &mut u.a;
- u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
- //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed
+ u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
drop(rma);
}
// Mut borrow, other field
{
let rma = &mut u.a;
- let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
- //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
+ let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
drop(rma);
}
{
let ra = &mut u.a;
- let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed
- //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed
+ let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
drop(ra);
}
{
let rma = &mut u.a;
- let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
- //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
+ let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
drop(rma);
}
{
let rma = &mut u.a;
- u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed
- //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed
+ u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
drop(rma);
}
}
--- /dev/null
+error[E0502]: cannot borrow `u.a` as mutable because it is also borrowed as immutable
+ --> $DIR/borrowck-union-borrow.rs:25:28
+ |
+LL | let ra = &u.a;
+ | --- immutable borrow occurs here
+LL | let rma = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
+ | ^^^ mutable borrow occurs here
+LL | drop(ra);
+LL | }
+ | - immutable borrow ends here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:30:13
+ |
+LL | let ra = &u.a;
+ | --- borrow of `u.a` occurs here
+LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.a` occurs here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+ --> $DIR/borrowck-union-borrow.rs:46:28
+ |
+LL | let ra = &u.a;
+ | --- immutable borrow occurs here (via `u.a`)
+LL | let rmb = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`)
+ | ^^^ mutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL | drop(ra);
+LL | }
+ | - immutable borrow ends here
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:51:13
+ |
+LL | let ra = &u.a;
+ | --- borrow of `u.b` occurs here
+LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.b` occurs here
+
+error[E0502]: cannot borrow `u.a` as immutable because it is also borrowed as mutable
+ --> $DIR/borrowck-union-borrow.rs:57:23
+ |
+LL | let rma = &mut u.a;
+ | --- mutable borrow occurs here
+LL | let ra = &u.a; //~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
+ | ^^^ immutable borrow occurs here
+LL | drop(rma);
+LL | }
+ | - mutable borrow ends here
+
+error[E0503]: cannot use `u.a` because it was mutably borrowed
+ --> $DIR/borrowck-union-borrow.rs:62:17
+ |
+LL | let ra = &mut u.a;
+ | --- borrow of `u.a` occurs here
+LL | let a = u.a; //~ ERROR cannot use `u.a` because it was mutably borrowed
+ | ^ use of borrowed `u.a`
+
+error[E0499]: cannot borrow `u.a` as mutable more than once at a time
+ --> $DIR/borrowck-union-borrow.rs:67:29
+ |
+LL | let rma = &mut u.a;
+ | --- first mutable borrow occurs here
+LL | let rma2 = &mut u.a; //~ ERROR cannot borrow `u.a` as mutable more than once at a time
+ | ^^^ second mutable borrow occurs here
+LL | drop(rma);
+LL | }
+ | - first borrow ends here
+
+error[E0506]: cannot assign to `u.a` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:72:13
+ |
+LL | let rma = &mut u.a;
+ | --- borrow of `u.a` occurs here
+LL | u.a = 1; //~ ERROR cannot assign to `u.a` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.a` occurs here
+
+error[E0502]: cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+ --> $DIR/borrowck-union-borrow.rs:78:23
+ |
+LL | let rma = &mut u.a;
+ | --- mutable borrow occurs here (via `u.a`)
+LL | let rb = &u.b; //~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`)
+ | ^^^ immutable borrow of `u.b` -- which overlaps with `u.a` -- occurs here
+LL | drop(rma);
+LL | }
+ | - mutable borrow ends here
+
+error[E0503]: cannot use `u.b` because it was mutably borrowed
+ --> $DIR/borrowck-union-borrow.rs:83:17
+ |
+LL | let ra = &mut u.a;
+ | --- borrow of `u.a` occurs here
+LL | let b = u.b; //~ ERROR cannot use `u.b` because it was mutably borrowed
+ | ^ use of borrowed `u.a`
+
+error[E0499]: cannot borrow `u` (via `u.b`) as mutable more than once at a time
+ --> $DIR/borrowck-union-borrow.rs:89:29
+ |
+LL | let rma = &mut u.a;
+ | --- first mutable borrow occurs here (via `u.a`)
+LL | let rmb2 = &mut u.b; //~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time
+ | ^^^ second mutable borrow occurs here (via `u.b`)
+LL | drop(rma);
+LL | }
+ | - first borrow ends here
+
+error[E0506]: cannot assign to `u.b` because it is borrowed
+ --> $DIR/borrowck-union-borrow.rs:94:13
+ |
+LL | let rma = &mut u.a;
+ | --- borrow of `u.b` occurs here
+LL | u.b = 1; //~ ERROR cannot assign to `u.b` because it is borrowed
+ | ^^^^^^^ assignment to borrowed `u.b` occurs here
+
+error: aborting due to 12 previous errors
+
+Some errors occurred: E0499, E0502, E0503, E0506.
+For more information about an error, try `rustc --explain E0499`.
LL | static STATIC11: Box<MyOwned> = box MyOwned;
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:79:37
+ |
+LL | static STATIC11: Box<MyOwned> = box MyOwned;
+ | ^^^^^^^
+
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
- --> $DIR/check-static-values-constraints.rs:89:32
+ --> $DIR/check-static-values-constraints.rs:90:32
|
LL | field2: SafeEnum::Variant4("str".to_string())
| ^^^^^^^^^^^^^^^^^
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:94:5
+ --> $DIR/check-static-values-constraints.rs:95:5
|
LL | box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:95:9
+ |
+LL | box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:95:5
+ --> $DIR/check-static-values-constraints.rs:97:5
|
LL | box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:97:9
+ |
+LL | box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:99:6
+ --> $DIR/check-static-values-constraints.rs:102:6
|
LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:102:10
+ |
+LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:100:6
+ --> $DIR/check-static-values-constraints.rs:104:6
|
LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:104:10
+ |
+LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:106:5
+ --> $DIR/check-static-values-constraints.rs:111:5
|
LL | box 3;
| ^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:111:9
+ |
+LL | box 3;
+ | ^
+
error[E0507]: cannot move out of static item
- --> $DIR/check-static-values-constraints.rs:110:45
+ --> $DIR/check-static-values-constraints.rs:116:45
|
LL | let y = { static x: Box<isize> = box 3; x };
| ^
| help: consider borrowing here: `&x`
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:110:38
+ --> $DIR/check-static-values-constraints.rs:116:38
|
LL | let y = { static x: Box<isize> = box 3; x };
| ^^^^^ allocation not allowed in statics
-error: aborting due to 10 previous errors
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:116:42
+ |
+LL | let y = { static x: Box<isize> = box 3; x };
+ | ^
+
+error: aborting due to 17 previous errors
-Some errors occurred: E0010, E0015, E0493, E0507.
+Some errors occurred: E0010, E0015, E0019, E0493, E0507.
For more information about an error, try `rustc --explain E0010`.
static STATIC11: Box<MyOwned> = box MyOwned;
//~^ ERROR allocations are not allowed in statics
+//~| ERROR static contains unimplemented expression type
static mut STATIC12: UnsafeStruct = UnsafeStruct;
static STATIC15: &'static [Box<MyOwned>] = &[
box MyOwned, //~ ERROR allocations are not allowed in statics
+ //~| ERROR contains unimplemented expression
box MyOwned, //~ ERROR allocations are not allowed in statics
+ //~| ERROR contains unimplemented expression
];
static STATIC16: (&'static Box<MyOwned>, &'static Box<MyOwned>) = (
&box MyOwned, //~ ERROR allocations are not allowed in statics
+ //~| ERROR contains unimplemented expression
&box MyOwned, //~ ERROR allocations are not allowed in statics
+ //~| ERROR contains unimplemented expression
);
static mut STATIC17: SafeEnum = SafeEnum::Variant1;
static STATIC19: Box<isize> =
box 3;
//~^ ERROR allocations are not allowed in statics
+ //~| ERROR contains unimplemented expression
pub fn main() {
let y = { static x: Box<isize> = box 3; x };
//~^ ERROR allocations are not allowed in statics
- //~^^ ERROR cannot move out of static item
+ //~| ERROR cannot move out of static item
+ //~| ERROR contains unimplemented expression
}
LL | static STATIC11: Box<MyOwned> = box MyOwned;
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:79:37
+ |
+LL | static STATIC11: Box<MyOwned> = box MyOwned;
+ | ^^^^^^^
+
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
- --> $DIR/check-static-values-constraints.rs:89:32
+ --> $DIR/check-static-values-constraints.rs:90:32
|
LL | field2: SafeEnum::Variant4("str".to_string())
| ^^^^^^^^^^^^^^^^^
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:94:5
+ --> $DIR/check-static-values-constraints.rs:95:5
|
LL | box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:95:9
+ |
+LL | box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:95:5
+ --> $DIR/check-static-values-constraints.rs:97:5
|
LL | box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:97:9
+ |
+LL | box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:99:6
+ --> $DIR/check-static-values-constraints.rs:102:6
|
LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:102:10
+ |
+LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:100:6
+ --> $DIR/check-static-values-constraints.rs:104:6
|
LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
| ^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:104:10
+ |
+LL | &box MyOwned, //~ ERROR allocations are not allowed in statics
+ | ^^^^^^^
+
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:106:5
+ --> $DIR/check-static-values-constraints.rs:111:5
|
LL | box 3;
| ^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:111:9
+ |
+LL | box 3;
+ | ^
+
error[E0507]: cannot move out of static item
- --> $DIR/check-static-values-constraints.rs:110:45
+ --> $DIR/check-static-values-constraints.rs:116:45
|
LL | let y = { static x: Box<isize> = box 3; x };
| ^ cannot move out of static item
error[E0010]: allocations are not allowed in statics
- --> $DIR/check-static-values-constraints.rs:110:38
+ --> $DIR/check-static-values-constraints.rs:116:38
|
LL | let y = { static x: Box<isize> = box 3; x };
| ^^^^^ allocation not allowed in statics
-error: aborting due to 10 previous errors
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/check-static-values-constraints.rs:116:42
+ |
+LL | let y = { static x: Box<isize> = box 3; x };
+ | ^
+
+error: aborting due to 17 previous errors
-Some errors occurred: E0010, E0015, E0493, E0507.
+Some errors occurred: E0010, E0015, E0019, E0493, E0507.
For more information about an error, try `rustc --explain E0010`.
LL | impl<T> Remote for Pair<T,Cover<T>> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl<T> Remote for Pair<Cover<T>,T> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl<T,U> Remote for Pair<Cover<T>,U> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl Misc for dyn Fundamental<Local> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl Misc for dyn Fundamental<Local> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl Copy for i32 {}
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Copy for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Copy for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Copy for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 10 previous errors
LL | impl Copy for i32 {}
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Copy for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Copy for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Copy for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 10 previous errors
LL | unsafe impl Send for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static NotSync`
LL | unsafe impl Send for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | unsafe impl Send for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 4 previous errors
LL | unsafe impl Send for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static NotSync`
LL | unsafe impl Send for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | unsafe impl Send for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 4 previous errors
LL | impl Sized for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Sized for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Sized for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 9 previous errors
LL | impl Sized for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Sized for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl Sized for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 9 previous errors
LL | impl TheTrait<usize> for isize { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl !Send for Vec<isize> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 2 previous errors
LL | impl TheTrait<usize> for isize { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl !Send for Vec<isize> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 2 previous errors
LL | impl<T> Remote for lib::Pair<T,Foo> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl<T, U> Remote1<Pair<T, Local<U>>> for i32 { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl<T,U> Remote for Pair<T,Local<U>> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl<T> Remote for Vec<Local<T>> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl Remote for Vec<Local> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl Remote for Vec<Local> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl lib::MyCopy for lib::MyStruct<MyType> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl lib::MyCopy for (MyType,) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
LL | impl lib::MyCopy for (MyType,) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to previous error
// compile-pass
#![warn(unused_must_use)]
-#![feature(cfg_attr_multi)]
#[cfg_attr(any(), deprecated, must_use)]
struct Struct {}
// compile-flags: --cfg broken
-#![feature(cfg_attr_multi)]
#![crate_type = "lib"]
#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
error[E0658]: no_core is experimental (see issue #29639)
- --> $DIR/cfg-attr-multi-invalid-1.rs:5:21
+ --> $DIR/cfg-attr-multi-invalid-1.rs:4:21
|
LL | #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental
| ^^^^^^^
// compile-flags: --cfg broken
-#![feature(cfg_attr_multi)]
#![crate_type = "lib"]
#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
error[E0658]: no_core is experimental (see issue #29639)
- --> $DIR/cfg-attr-multi-invalid-2.rs:5:29
+ --> $DIR/cfg-attr-multi-invalid-2.rs:4:29
|
LL | #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental
| ^^^^^^^
// compile-pass
#![warn(unused_must_use)]
-#![feature(cfg_attr_multi)]
#[cfg_attr(all(), deprecated, must_use)]
struct MustUseDeprecated {}
warning: use of deprecated item 'MustUseDeprecated'
- --> $DIR/cfg-attr-multi-true.rs:13:6
+ --> $DIR/cfg-attr-multi-true.rs:12:6
|
LL | impl MustUseDeprecated { //~ warning: use of deprecated item
| ^^^^^^^^^^^^^^^^^
= note: #[warn(deprecated)] on by default
warning: use of deprecated item 'MustUseDeprecated'
- --> $DIR/cfg-attr-multi-true.rs:20:5
+ --> $DIR/cfg-attr-multi-true.rs:19:5
|
LL | MustUseDeprecated::new(); //~ warning: use of deprecated item
| ^^^^^^^^^^^^^^^^^^^^^^
warning: use of deprecated item 'MustUseDeprecated'
- --> $DIR/cfg-attr-multi-true.rs:14:17
+ --> $DIR/cfg-attr-multi-true.rs:13:17
|
LL | fn new() -> MustUseDeprecated { //~ warning: use of deprecated item
| ^^^^^^^^^^^^^^^^^
warning: use of deprecated item 'MustUseDeprecated'
- --> $DIR/cfg-attr-multi-true.rs:15:9
+ --> $DIR/cfg-attr-multi-true.rs:14:9
|
LL | MustUseDeprecated {} //~ warning: use of deprecated item
| ^^^^^^^^^^^^^^^^^
warning: unused `MustUseDeprecated` that must be used
- --> $DIR/cfg-attr-multi-true.rs:20:5
+ --> $DIR/cfg-attr-multi-true.rs:19:5
|
LL | MustUseDeprecated::new(); //~ warning: use of deprecated item
| ^^^^^^^^^^^^^^^^^^^^^^^^^
// Parse `cfg_attr` with varying numbers of attributes and trailing commas
-#![feature(cfg_attr_multi)]
-
// Completely empty `cfg_attr` input
#[cfg_attr()] //~ error: expected identifier, found `)`
struct NoConfigurationPredicate;
error: expected identifier, found `)`
- --> $DIR/cfg-attr-parse.rs:6:12
+ --> $DIR/cfg-attr-parse.rs:4:12
|
LL | #[cfg_attr()] //~ error: expected identifier, found `)`
| ^ expected identifier
error: expected `,`, found `)`
- --> $DIR/cfg-attr-parse.rs:10:17
+ --> $DIR/cfg-attr-parse.rs:8:17
|
LL | #[cfg_attr(all())] //~ error: expected `,`, found `)`
| ^ expected `,`
error: expected identifier, found `,`
- --> $DIR/cfg-attr-parse.rs:18:18
+ --> $DIR/cfg-attr-parse.rs:16:18
|
LL | #[cfg_attr(all(),,)] //~ ERROR expected identifier
| ^ expected identifier
error: expected identifier, found `,`
- --> $DIR/cfg-attr-parse.rs:30:28
+ --> $DIR/cfg-attr-parse.rs:28:28
|
LL | #[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier
| ^ expected identifier
error: expected identifier, found `,`
- --> $DIR/cfg-attr-parse.rs:42:40
+ --> $DIR/cfg-attr-parse.rs:40:40
|
LL | #[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier
| ^ expected identifier
+++ /dev/null
-const A: usize = { 1; 2 };
-//~^ ERROR statements in constants are unstable
-
-const B: usize = { { } 2 };
-//~^ ERROR statements in constants are unstable
-
-macro_rules! foo {
- () => (()) //~ ERROR statements in constants are unstable
-}
-const C: usize = { foo!(); 2 };
-
-const D: usize = { let x = 4; 2 };
-//~^ ERROR let bindings in constants are unstable
-//~| ERROR statements in constants are unstable
-//~| ERROR let bindings in constants are unstable
-//~| ERROR statements in constants are unstable
-
-pub fn main() {}
+++ /dev/null
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:1:20
- |
-LL | const A: usize = { 1; 2 };
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:4:20
- |
-LL | const B: usize = { { } 2 };
- | ^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:8:12
- |
-LL | () => (()) //~ ERROR statements in constants are unstable
- | ^^
-LL | }
-LL | const C: usize = { foo!(); 2 };
- | ------- in this macro invocation
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:12:28
- |
-LL | const D: usize = { let x = 4; 2 };
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:12:28
- |
-LL | const D: usize = { let x = 4; 2 };
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:12:1
- |
-LL | const D: usize = { let x = 4; 2 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-2.rs:12:1
- |
-LL | const D: usize = { let x = 4; 2 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 7 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-type Array = [u32; { let x = 2; 5 }];
-//~^ ERROR let bindings in constants are unstable
-//~| ERROR statements in constants are unstable
-//~| ERROR let bindings in constants are unstable
-//~| ERROR statements in constants are unstable
-
-pub fn main() {}
+++ /dev/null
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-3.rs:1:31
- |
-LL | type Array = [u32; { let x = 2; 5 }];
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-3.rs:1:31
- |
-LL | type Array = [u32; { let x = 2; 5 }];
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-3.rs:1:20
- |
-LL | type Array = [u32; { let x = 2; 5 }];
- | ^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement-3.rs:1:20
- |
-LL | type Array = [u32; { let x = 2; 5 }];
- | ^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
+// compile-pass
+
enum Foo {
Bar = { let x = 1; 3 }
- //~^ ERROR let bindings in constants are unstable
- //~| ERROR statements in constants are unstable
- //~| ERROR let bindings in constants are unstable
- //~| ERROR statements in constants are unstable
}
+
+const A: usize = { 1; 2 };
+
+const B: usize = { { } 2 };
+
+macro_rules! foo {
+ () => (())
+}
+
+const C: usize = { foo!(); 2 };
+
+const D: usize = { let x = 4; 2 };
+
+type Array = [u32; { let x = 2; 5 }];
+type Array2 = [u32; { let mut x = 2; x = 3; x}];
+
pub fn main() {}
+++ /dev/null
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement.rs:2:21
- |
-LL | Bar = { let x = 1; 3 }
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement.rs:2:21
- |
-LL | Bar = { let x = 1; 3 }
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement.rs:2:11
- |
-LL | Bar = { let x = 1; 3 }
- | ^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/const-block-non-item-statement.rs:2:11
- |
-LL | Bar = { let x = 1; 3 }
- | ^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
// The test should never compile successfully
#![feature(const_raw_ptr_deref)]
-#![feature(const_let)]
use std::cell::UnsafeCell;
error[E0019]: static contains unimplemented expression type
- --> $DIR/assign-to-static-within-other-static-2.rs:17:5
+ --> $DIR/assign-to-static-within-other-static-2.rs:16:5
|
LL | *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
| ^^^^^^^^^^^^^^^^
// The test should never compile successfully
#![feature(const_raw_ptr_deref)]
-#![feature(const_let)]
use std::cell::UnsafeCell;
error: cannot mutate statics in the initializer of another static
- --> $DIR/assign-to-static-within-other-static.rs:11:5
+ --> $DIR/assign-to-static-within-other-static.rs:10:5
|
LL | FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static
| ^^^^^^^
-#![feature(const_let)]
-
fn main() {}
struct FakeNeedsDrop;
error[E0019]: constant contains unimplemented expression type
- --> $DIR/const_let.rs:15:55
+ --> $DIR/const_let.rs:13:55
|
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
| ^
error[E0019]: constant contains unimplemented expression type
- --> $DIR/const_let.rs:19:35
+ --> $DIR/const_let.rs:17:35
|
LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
| ^
-#![feature(const_let)]
-
fn main() {
// Tests the Collatz conjecture with an incorrect base case (0 instead of 1).
// The value of `n` will loop indefinitely (4 - 2 - 1 - 4).
error[E0019]: constant contains unimplemented expression type
- --> $DIR/infinite_loop.rs:9:9
+ --> $DIR/infinite_loop.rs:7:9
|
LL | / while n != 0 { //~ ERROR constant contains unimplemented expression type
LL | | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
| |_________^
warning: Constant evaluating a complex constant, this might take some time
- --> $DIR/infinite_loop.rs:6:18
+ --> $DIR/infinite_loop.rs:4:18
|
LL | let _ = [(); {
| __________________^
| |_____^
error[E0080]: evaluation of constant value failed
- --> $DIR/infinite_loop.rs:10:20
+ --> $DIR/infinite_loop.rs:8:20
|
LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
| ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
-#![feature(const_let)]
-
fn main() {
let _ = [(); {
//~^ WARNING Constant evaluating a complex constant, this might take some time
error[E0019]: constant contains unimplemented expression type
- --> $DIR/issue-52475.rs:8:9
+ --> $DIR/issue-52475.rs:6:9
|
LL | / while n < 5 { //~ ERROR constant contains unimplemented expression type
LL | | n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
| |_________^
warning: Constant evaluating a complex constant, this might take some time
- --> $DIR/issue-52475.rs:4:18
+ --> $DIR/issue-52475.rs:2:18
|
LL | let _ = [(); {
| __________________^
| |_____^
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-52475.rs:9:17
+ --> $DIR/issue-52475.rs:7:17
|
LL | n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
| ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
// The test should never compile successfully
#![feature(const_raw_ptr_deref)]
-#![feature(const_let)]
use std::cell::UnsafeCell;
error[E0019]: static contains unimplemented expression type
- --> $DIR/mod-static-with-const-fn.rs:19:5
+ --> $DIR/mod-static-with-const-fn.rs:18:5
|
LL | *FOO.0.get() = 5;
| ^^^^^^^^^^^^^^^^
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
- --> $DIR/mod-static-with-const-fn.rs:22:5
+ --> $DIR/mod-static-with-const-fn.rs:21:5
|
LL | foo();
| ^^^^^
-#![feature(const_transmute,const_let)]
+#![feature(const_transmute)]
#![allow(const_err)] // make sure we cannot allow away the errors tested here
use std::mem;
-// test that certain things are disallowed in constant functions
+// compile-pass
-#![feature(const_fn)]
-
-// no destructuring
-const fn i((
- a,
- //~^ ERROR arguments of constant functions can only be immutable by-value bindings
- b
- //~^ ERROR arguments of constant functions can only be immutable by-value bindings
- ): (u32, u32)) -> u32 {
+const fn i((a, b): (u32, u32)) -> u32 {
a + b
- //~^ ERROR let bindings in constant functions are unstable
- //~| ERROR let bindings in constant functions are unstable
}
fn main() {}
+++ /dev/null
-error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821)
- --> $DIR/const-fn-destructuring-arg.rs:7:13
- |
-LL | a,
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821)
- --> $DIR/const-fn-destructuring-arg.rs:9:13
- |
-LL | b
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-destructuring-arg.rs:12:5
- |
-LL | a + b
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-destructuring-arg.rs:12:9
- |
-LL | a + b
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
}
const fn get() -> u32 {
- let x = 22; //~ ERROR let bindings in constant functions are unstable
-//~^ ERROR statements in constant functions
- let y = 44; //~ ERROR let bindings in constant functions are unstable
-//~^ ERROR statements in constant functions
+ let x = 22;
+ let y = 44;
x + y
-//~^ ERROR let bindings in constant functions are unstable
-//~| ERROR let bindings in constant functions are unstable
}
fn main() {}
LL | &Y
| ^^
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-not-safe-for-const.rs:30:13
- |
-LL | let x = 22; //~ ERROR let bindings in constant functions are unstable
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-not-safe-for-const.rs:30:13
- |
-LL | let x = 22; //~ ERROR let bindings in constant functions are unstable
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-not-safe-for-const.rs:32:13
- |
-LL | let y = 44; //~ ERROR let bindings in constant functions are unstable
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-not-safe-for-const.rs:32:13
- |
-LL | let y = 44; //~ ERROR let bindings in constant functions are unstable
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-not-safe-for-const.rs:34:5
- |
-LL | x + y
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constant functions are unstable (see issue #48821)
- --> $DIR/const-fn-not-safe-for-const.rs:34:9
- |
-LL | x + y
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 9 previous errors
+error: aborting due to 3 previous errors
-Some errors occurred: E0013, E0015, E0658.
+Some errors occurred: E0013, E0015.
For more information about an error, try `rustc --explain E0013`.
use std::intrinsics;
-const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
+// The documentation of `unchecked_shl` states that it:
+//
+// Performs an unchecked left shift, resulting in undefined behavior when
+// y < 0 or y >= N, where N is the width of T in bits.
+//
+// So we check this for a few `y`.
+
+// unsigned types:
+
+const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// signed types:
+
+const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// and make sure we capture y < 0:
+
+const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
+//~^ ERROR any use of this value will cause an error
+
+// and that there's no special relation to the value -1 by picking some
+// negative values at random:
+
+const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
+//~^ ERROR any use of this value will cause an error
+const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
+//~^ ERROR any use of this value will cause an error
+
+// Repeat it all over for `unchecked_shr`
+
+// unsigned types:
+
+const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// signed types:
+
+const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
+//~^ ERROR any use of this value will cause an error
+
+// and make sure we capture y < 0:
+
+const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
+//~^ ERROR any use of this value will cause an error
+
+// and that there's no special relation to the value -1 by picking some
+// negative values at random:
+
+const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
+//~^ ERROR any use of this value will cause an error
+const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
//~^ ERROR any use of this value will cause an error
-const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
+const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
//~^ ERROR any use of this value will cause an error
-fn main() {
-}
+fn main() {}
error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:5:1
+ --> $DIR/const-int-unchecked.rs:14:1
|
-LL | const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
- | |
- | Overflowing shift by 8 in unchecked_shr
+LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+ | |
+ | Overflowing shift by 8 in unchecked_shl
|
= note: #[deny(const_err)] on by default
error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:7:1
+ --> $DIR/const-int-unchecked.rs:16:1
|
-LL | const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
- | |
- | Overflowing shift by 8 in unchecked_shl
+LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 16 in unchecked_shl
-error: aborting due to 2 previous errors
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:18:1
+ |
+LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 32 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:20:1
+ |
+LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 64 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:22:1
+ |
+LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------^^^
+ | |
+ | Overflowing shift by 128 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:27:1
+ |
+LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+ | |
+ | Overflowing shift by 8 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:29:1
+ |
+LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 16 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:31:1
+ |
+LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 32 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:33:1
+ |
+LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 64 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:35:1
+ |
+LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------^^^
+ | |
+ | Overflowing shift by 128 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:40:1
+ |
+LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 255 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:42:1
+ |
+LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 65535 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:44:1
+ |
+LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 4294967295 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:46:1
+ |
+LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 18446744073709551615 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:48:1
+ |
+LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+ | |
+ | Overflowing shift by 340282366920938463463374607431768211455 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:54:1
+ |
+LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 250 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:56:1
+ |
+LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 65523 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:58:1
+ |
+LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+ | |
+ | Overflowing shift by 4294967271 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:60:1
+ |
+LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+ | |
+ | Overflowing shift by 18446744073709551586 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:62:1
+ |
+LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------^^^
+ | |
+ | Overflowing shift by 340282366920938463463374607431768211363 in unchecked_shl
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:69:1
+ |
+LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+ | |
+ | Overflowing shift by 8 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:71:1
+ |
+LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 16 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:73:1
+ |
+LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 32 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:75:1
+ |
+LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 64 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:77:1
+ |
+LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------^^^
+ | |
+ | Overflowing shift by 128 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:82:1
+ |
+LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
+ | |
+ | Overflowing shift by 8 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:84:1
+ |
+LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 16 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:86:1
+ |
+LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 32 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:88:1
+ |
+LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 64 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:90:1
+ |
+LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------^^^
+ | |
+ | Overflowing shift by 128 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:95:1
+ |
+LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 255 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:97:1
+ |
+LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 65535 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:99:1
+ |
+LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 4294967295 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:101:1
+ |
+LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 18446744073709551615 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:103:1
+ |
+LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+ | |
+ | Overflowing shift by 340282366920938463463374607431768211455 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:109:1
+ |
+LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------------^^^
+ | |
+ | Overflowing shift by 250 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:111:1
+ |
+LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | Overflowing shift by 65523 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:113:1
+ |
+LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+ | |
+ | Overflowing shift by 4294967271 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:115:1
+ |
+LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------------------------------^^^
+ | |
+ | Overflowing shift by 18446744073709551586 in unchecked_shr
+
+error: any use of this value will cause an error
+ --> $DIR/const-int-unchecked.rs:117:1
+ |
+LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------^^^
+ | |
+ | Overflowing shift by 340282366920938463463374607431768211363 in unchecked_shr
+
+error: aborting due to 40 previous errors
// compile-pass
-#![feature(const_let)]
-
struct S(i32);
const A: () = {
// compile-pass
-#![feature(const_let)]
-#![feature(const_fn)]
-
pub struct AA {
pub data: [u8; 10],
}
-#![feature(const_let)]
#![feature(const_fn)]
struct S {
s
};
+type Array = [u32; {
+ let mut x = 2;
+ let y = &mut x;
+//~^ ERROR references in constants may only refer to immutable values
+ *y = 42;
+//~^ ERROR constant contains unimplemented expression type
+ *y
+}];
+
fn main() {
assert_eq!(FOO.state, 3);
}
error[E0019]: constant function contains unimplemented expression type
- --> $DIR/const_let_assign3.rs:10:9
+ --> $DIR/const_let_assign3.rs:9:9
|
LL | self.state = x;
| ^^^^^^^^^^^^^^
error[E0017]: references in constants may only refer to immutable values
- --> $DIR/const_let_assign3.rs:17:5
+ --> $DIR/const_let_assign3.rs:16:5
|
LL | s.foo(3); //~ ERROR references in constants may only refer to immutable values
| ^ constants require immutable values
-error: aborting due to 2 previous errors
+error[E0017]: references in constants may only refer to immutable values
+ --> $DIR/const_let_assign3.rs:22:13
+ |
+LL | let y = &mut x;
+ | ^^^^^^ constants require immutable values
+
+error[E0019]: constant contains unimplemented expression type
+ --> $DIR/const_let_assign3.rs:24:5
+ |
+LL | *y = 42;
+ | ^^^^^^^
+
+error: aborting due to 4 previous errors
Some errors occurred: E0017, E0019.
For more information about an error, try `rustc --explain E0017`.
-#![feature(const_let, const_fn)]
-
// run-pass
struct Foo<T>(T);
// compile-pass
-#![feature(const_let, const_fn)]
+#![feature(const_fn)]
struct Foo<T>(T);
struct Bar<T> { x: T }
--- /dev/null
+// compile-pass
+
+fn main() {}
+
+const fn tup((a, b): (i32, i32)) -> i32 {
+ a + b
+}
+
+const fn array([a, b]: [i32; 2]) -> i32 {
+ a + b
+}
--- /dev/null
+fn main() {}
+
+const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument
+ a + b
+}
--- /dev/null
+error[E0005]: refutable pattern in function argument: `&[]` not covered
+ --> $DIR/const_let_refutable.rs:3:16
+ |
+LL | const fn slice([a, b]: &[i32]) -> i32 { //~ ERROR refutable pattern in function argument
+ | ^^^^^^ pattern `&[]` not covered
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0005`.
-#![feature(underscore_const_names, const_let)]
+#![feature(underscore_const_names)]
const _: bool = false && false;
const _: bool = true && false;
// https://github.com/rust-lang/rust/issues/55223
-#![feature(const_let)]
-
union Foo<'a> {
y: &'a (),
long_live_the_unit: &'static (),
error: any use of this value will cause an error
- --> $DIR/dangling-alloc-id-ice.rs:10:1
+ --> $DIR/dangling-alloc-id-ice.rs:8:1
|
LL | / const FOO: &() = { //~ ERROR any use of this value will cause an error
LL | | let y = ();
-#![feature(const_let)]
-
const FOO: *const u32 = { //~ ERROR any use of this value will cause an error
let x = 42;
&x
error: any use of this value will cause an error
- --> $DIR/dangling_raw_ptr.rs:3:1
+ --> $DIR/dangling_raw_ptr.rs:1:1
|
LL | / const FOO: *const u32 = { //~ ERROR any use of this value will cause an error
LL | | let x = 42;
LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
| ^^^^^^^^^^^
-error: local variables in const fn are unstable
- --> $DIR/min_const_fn.rs:99:34
- |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
- | ^
-
error: `if`, `match`, `&&` and `||` are not stable in const fn
--> $DIR/min_const_fn.rs:100:44
|
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
| ^^^^
-error: aborting due to 35 previous errors
+error: aborting due to 34 previous errors
Some errors occurred: E0493, E0515.
For more information about an error, try `rustc --explain E0493`.
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
-const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
+const fn foo30_6() -> bool { let x = true; x }
const fn foo36(a: bool, b: bool) -> bool { a && b }
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
const fn foo37(a: bool, b: bool) -> bool { a || b }
LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
| ^^^^^^^^^^^
-error: local variables in const fn are unstable
- --> $DIR/min_const_fn.rs:99:34
- |
-LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
- | ^
-
error: `if`, `match`, `&&` and `||` are not stable in const fn
--> $DIR/min_const_fn.rs:100:44
|
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
| ^^^^
-error: aborting due to 35 previous errors
+error: aborting due to 34 previous errors
For more information about this error, try `rustc --explain E0493`.
const fn mutable_ref_in_const() -> u8 {
- let mut a = 0; //~ ERROR local variables in const fn
- let b = &mut a;
+ let mut a = 0;
+ let b = &mut a; //~ ERROR mutable references in const fn
*b
}
impl X {
const fn inherent_mutable_ref_in_const() -> u8 {
- let mut a = 0; //~ ERROR local variables in const fn
- let b = &mut a;
+ let mut a = 0;
+ let b = &mut a; //~ ERROR mutable references in const fn
*b
}
}
-error: local variables in const fn are unstable
- --> $DIR/mutable_borrow.rs:2:9
+error: mutable references in const fn are unstable
+ --> $DIR/mutable_borrow.rs:3:9
|
-LL | let mut a = 0; //~ ERROR local variables in const fn
- | ^^^^^
+LL | let b = &mut a; //~ ERROR mutable references in const fn
+ | ^
-error: local variables in const fn are unstable
- --> $DIR/mutable_borrow.rs:11:13
+error: mutable references in const fn are unstable
+ --> $DIR/mutable_borrow.rs:12:13
|
-LL | let mut a = 0; //~ ERROR local variables in const fn
- | ^^^^^
+LL | let b = &mut a; //~ ERROR mutable references in const fn
+ | ^
error: aborting due to 2 previous errors
-#![feature(const_let)]
-
use std::cell::Cell;
const FOO: &(Cell<usize>, bool) = {
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
- --> $DIR/partial_qualif.rs:8:5
+ --> $DIR/partial_qualif.rs:6:5
|
LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
| ^^^^
-#![feature(const_let)]
-
use std::cell::Cell;
const FOO: &u32 = {
error[E0017]: references in constants may only refer to immutable values
- --> $DIR/projection_qualif.rs:8:27
+ --> $DIR/projection_qualif.rs:6:27
|
LL | let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
| ^^^^^^ constants require immutable values
error[E0019]: constant contains unimplemented expression type
- --> $DIR/projection_qualif.rs:9:18
+ --> $DIR/projection_qualif.rs:7:18
|
LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
| ^^^^^^
error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
- --> $DIR/projection_qualif.rs:9:18
+ --> $DIR/projection_qualif.rs:7:18
|
LL | unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
| ^^^^^^
error[E0597]: `y` does not live long enough
- --> $DIR/promote_const_let.rs:6:9
+ --> $DIR/promote_const_let.rs:4:9
|
LL | let x: &'static u32 = {
| ------------ type annotation requires that `y` is borrowed for `'static`
LL | };
| - `y` dropped here while still borrowed
-error: aborting due to previous error
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote_const_let.rs:6:28
+ |
+LL | let x: &'static u32 = &{ //~ ERROR does not live long enough
+ | ____________------------____^
+ | | |
+ | | type annotation requires that borrow lasts for `'static`
+LL | | let y = 42;
+LL | | y
+LL | | };
+ | |_____^ creates a temporary which is freed while still in use
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0597`.
+Some errors occurred: E0597, E0716.
+For more information about an error, try `rustc --explain E0597`.
-#![feature(const_let)]
-
fn main() {
let x: &'static u32 = {
let y = 42;
&y //~ ERROR does not live long enough
};
+ let x: &'static u32 = &{ //~ ERROR does not live long enough
+ let y = 42;
+ y
+ };
}
error[E0597]: `y` does not live long enough
- --> $DIR/promote_const_let.rs:6:10
+ --> $DIR/promote_const_let.rs:4:10
|
LL | &y //~ ERROR does not live long enough
| ^ borrowed value does not live long enough
|
= note: borrowed value must be valid for the static lifetime...
-error: aborting due to previous error
+error[E0597]: borrowed value does not live long enough
+ --> $DIR/promote_const_let.rs:6:28
+ |
+LL | let x: &'static u32 = &{ //~ ERROR does not live long enough
+ | ____________________________^
+LL | | let y = 42;
+LL | | y
+LL | | };
+ | |_____^ temporary value does not live long enough
+LL | }
+ | - temporary value only lives until here
+ |
+ = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.
-#![feature(const_let)]
-
use std::cell::Cell;
// this is overly conservative. The reset to `None` should clear `a` of all qualifications
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
- --> $DIR/qualif_overwrite.rs:12:5
+ --> $DIR/qualif_overwrite.rs:10:5
|
LL | &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
| ^^^^
-#![feature(const_let)]
-
use std::cell::Cell;
// const qualification is not smart enough to know about fields and always assumes that there might
error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
- --> $DIR/qualif_overwrite_2.rs:10:5
+ --> $DIR/qualif_overwrite_2.rs:8:5
|
LL | &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
| ^^^^^^
-#![feature(const_let)]
-
static mut STDERR_BUFFER_SPACE: u8 = 0;
pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
error[E0017]: references in statics may only refer to immutable values
- --> $DIR/static_mut_containing_mut_ref2.rs:5:46
+ --> $DIR/static_mut_containing_mut_ref2.rs:3:46
|
LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
error[E0019]: static contains unimplemented expression type
- --> $DIR/static_mut_containing_mut_ref2.rs:5:45
+ --> $DIR/static_mut_containing_mut_ref2.rs:3:45
|
LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#![feature(const_let)]
-
static mut FOO: (u8, u8) = (42, 43);
static mut BAR: () = unsafe { FOO.0 = 99; };
error[E0080]: could not evaluate static initializer
- --> $DIR/static_mut_containing_mut_ref3.rs:5:31
+ --> $DIR/static_mut_containing_mut_ref3.rs:3:31
|
LL | static mut BAR: () = unsafe { FOO.0 = 99; };
| ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer
| ^^^
|
= note: ...which again requires processing `Foo::X`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/cycle-trait-default-type-trait.rs:4:1
+ |
+LL | trait Foo<X = Box<Foo>> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
| ^^^^^^^^^^
|
= note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/cycle-trait-supertrait-direct.rs:3:1
+ |
+LL | trait Chromosome: Chromosome {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
LL | impl<'a> Drop for &'a mut isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 2 previous errors
// aux-build:edition-imports-2018.rs
// aux-build:absolute.rs
-#![feature(uniform_paths)]
-
#[macro_use]
extern crate edition_imports_2018;
error: cannot glob-import all possible crates
- --> $DIR/edition-imports-2015.rs:25:5
+ --> $DIR/edition-imports-2015.rs:23:5
|
LL | gen_glob!(); //~ ERROR cannot glob-import all possible crates
| ^^^^^^^^^^^^
-error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
+error: imports can only refer to extern crate names passed with `--extern` in macros originating from 2015 edition
--> <::edition_imports_2015::gen_gated macros>:1:50
|
LL | ( ) => { fn check_gated ( ) { enum E { A } use E :: * ; } }
LL | gen_gated!();
| ------------- not an extern crate passed with `--extern`
|
- = help: add #![feature(uniform_paths)] to the crate attributes to enable
note: this import refers to the enum defined here
--> $DIR/edition-imports-virtual-2015-gated.rs:9:5
|
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0658`.
-error: function `BOGUS` should have a snake case name such as `bogus`
- --> $DIR/enable-unstable-lib-feature.rs:12:1
+error: function `BOGUS` should have a snake case name
+ --> $DIR/enable-unstable-lib-feature.rs:12:8
|
LL | pub fn BOGUS() { } //~ ERROR
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^ help: convert the identifier to snake case: `bogus`
|
note: lint level defined here
--> $DIR/enable-unstable-lib-feature.rs:6:9
#![allow(warnings)]
const CON : Box<i32> = box 0; //~ ERROR E0010
+//~^ ERROR constant contains unimplemented expression type
fn main() {}
|
= note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
-error: aborting due to previous error
+error[E0019]: constant contains unimplemented expression type
+ --> $DIR/E0010-teach.rs:6:28
+ |
+LL | const CON : Box<i32> = box 0; //~ ERROR E0010
+ | ^
+ |
+ = note: A function call isn't allowed in the const's initialization expression because the expression's value must be known at compile-time.
+ = note: Remember: you can't use a function call inside a const's initialization expression! However, you can use it anywhere else.
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0010`.
+Some errors occurred: E0010, E0019.
+For more information about an error, try `rustc --explain E0010`.
#![allow(warnings)]
const CON : Box<i32> = box 0; //~ ERROR E0010
+//~^ ERROR constant contains unimplemented expression type
fn main() {}
LL | const CON : Box<i32> = box 0; //~ ERROR E0010
| ^^^^^ allocation not allowed in constants
-error: aborting due to previous error
+error[E0019]: constant contains unimplemented expression type
+ --> $DIR/E0010.rs:4:28
+ |
+LL | const CON : Box<i32> = box 0; //~ ERROR E0010
+ | ^
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0010`.
+Some errors occurred: E0010, E0019.
+For more information about an error, try `rustc --explain E0010`.
LL | impl Drop for u32 {} //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 2 previous errors
+++ /dev/null
-struct Irrefutable(i32);
-
-fn main() {
- let irr = Irrefutable(0);
- if let Irrefutable(x) = irr { //~ ERROR E0162
- println!("{}", x);
- }
-}
+++ /dev/null
-error[E0162]: irrefutable if-let pattern
- --> $DIR/E0162.rs:5:12
- |
-LL | if let Irrefutable(x) = irr { //~ ERROR E0162
- | ^^^^^^^^^^^^^^ irrefutable pattern
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0162`.
+++ /dev/null
-struct Irrefutable(i32);
-
-fn main() {
- let irr = Irrefutable(0);
- while let Irrefutable(x) = irr { //~ ERROR E0165
- //~| irrefutable pattern
- // ...
- }
-}
+++ /dev/null
-error[E0165]: irrefutable while-let pattern
- --> $DIR/E0165.rs:5:15
- |
-LL | while let Irrefutable(x) = irr { //~ ERROR E0165
- | ^^^^^^^^^^^^^^ irrefutable pattern
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0165`.
LL | impl Copy for Foo { }
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 3 previous errors
error[E0308]: mismatched types
--> $DIR/E0308-4.rs:4:9
|
+LL | match x {
+ | - this match expression has type `u8`
LL | 0u8..=3i8 => (), //~ ERROR E0308
| ^^^^^^^^^ expected u8, found i8
--> $DIR/E0606.rs:2:5
|
LL | &0u8 as u8; //~ ERROR E0606
- | ^^^^^^^^^^ cannot cast `&u8` as `u8`
- |
-help: did you mean `*&0u8`?
- --> $DIR/E0606.rs:2:5
- |
-LL | &0u8 as u8; //~ ERROR E0606
- | ^^^^
+ | ----^^^^^^
+ | |
+ | cannot cast `&u8` as `u8`
+ | help: dereference the expression: `*&0u8`
error: aborting due to previous error
--> $DIR/error-festival.rs:37:18
|
LL | let y: u32 = x as u32;
- | ^^^^^^^^ cannot cast `&u8` as `u32`
- |
-help: did you mean `*x`?
- --> $DIR/error-festival.rs:37:18
- |
-LL | let y: u32 = x as u32;
- | ^
+ | -^^^^^^^
+ | |
+ | cannot cast `&u8` as `u32`
+ | help: dereference the expression: `*x`
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
--> $DIR/error-festival.rs:41:5
LL | fn bar(x: Foo) -> Foo { x }
| ^^^^^
= note: ...which again requires processing `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/no_inferrable_concrete_type.rs:4:1
+ |
+LL | / #![feature(existential_type)]
+LL | |
+LL | | existential type Foo: Copy; //~ cycle detected
+LL | |
+... |
+LL | | let _: Foo = std::mem::transmute(0u8);
+LL | | }
+ | |_^
error: aborting due to previous error
-error: variable `X` should have a snake case name such as `x`
+error: variable `X` should have a snake case name
--> $DIR/expr_attr_paren_order.rs:19:17
|
LL | let X = 0; //~ ERROR snake case name
- | ^
+ | ^ help: convert the identifier to snake case: `x`
|
note: lint level defined here
--> $DIR/expr_attr_paren_order.rs:17:17
+++ /dev/null
-// gate-test-cfg_attr_multi
-
-#![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
-//~^ ERROR cfg_attr with zero or more than one attributes is experimental
-fn main() {}
+++ /dev/null
-error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881)
- --> $DIR/feature-gate-cfg-attr-multi-1.rs:3:1
- |
-LL | #![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(cfg_attr_multi)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-#![cfg_attr(all(),)]
-//~^ ERROR cfg_attr with zero or more than one attributes is experimental
-fn main() {}
+++ /dev/null
-error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881)
- --> $DIR/feature-gate-cfg-attr-multi-2.rs:1:1
- |
-LL | #![cfg_attr(all(),)]
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = help: add #![feature(cfg_attr_multi)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-// Test that settingt the featute gate while using its functionality doesn't error.
-
-// compile-pass
-
-#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
-
-fn main() {}
+++ /dev/null
-// Test that settingt the featute gate while using its functionality doesn't error.
-// Specifically, if there's a cfg-attr *before* the feature gate.
-
-// compile-pass
-
-#![cfg_attr(all(),)]
-#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")]
-
-fn main() {}
LL | const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
| ^^^^^ trait fns cannot be const
-error[E0658]: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #57563)
--> $DIR/feature-gate-const_fn.rs:6:5
|
LL | const fn foo() -> u32; //~ ERROR const fn is unstable
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error[E0658]: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #57563)
--> $DIR/feature-gate-const_fn.rs:8:5
|
LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
+++ /dev/null
-// Test use of const let without feature gate.
-
-const FOO: usize = {
- //~^ ERROR statements in constants are unstable
- //~| ERROR: let bindings in constants are unstable
- let x = 42;
- //~^ ERROR statements in constants are unstable
- //~| ERROR: let bindings in constants are unstable
- 42
-};
-
-static BAR: usize = {
- //~^ ERROR statements in statics are unstable
- //~| ERROR: let bindings in statics are unstable
- let x = 42;
- //~^ ERROR statements in statics are unstable
- //~| ERROR: let bindings in statics are unstable
- 42
-};
-
-fn main() {}
+++ /dev/null
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:6:13
- |
-LL | let x = 42;
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:6:13
- |
-LL | let x = 42;
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:3:1
- |
-LL | / const FOO: usize = {
-LL | | //~^ ERROR statements in constants are unstable
-LL | | //~| ERROR: let bindings in constants are unstable
-LL | | let x = 42;
-... |
-LL | | 42
-LL | | };
- | |__^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:3:1
- |
-LL | / const FOO: usize = {
-LL | | //~^ ERROR statements in constants are unstable
-LL | | //~| ERROR: let bindings in constants are unstable
-LL | | let x = 42;
-... |
-LL | | 42
-LL | | };
- | |__^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in statics are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:15:13
- |
-LL | let x = 42;
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:15:13
- |
-LL | let x = 42;
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in statics are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:12:1
- |
-LL | / static BAR: usize = {
-LL | | //~^ ERROR statements in statics are unstable
-LL | | //~| ERROR: let bindings in statics are unstable
-LL | | let x = 42;
-... |
-LL | | 42
-LL | | };
- | |__^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/feature-gate-const_let.rs:12:1
- |
-LL | / static BAR: usize = {
-LL | | //~^ ERROR statements in statics are unstable
-LL | | //~| ERROR: let bindings in statics are unstable
-LL | | let x = 42;
-... |
-LL | | 42
-LL | | };
- | |__^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-fn main() {
- if let 0 | 1 = 0 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
- ;
- }
- while let 0 | 1 = 1 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
- break;
- }
-}
+++ /dev/null
-error[E0658]: multiple patterns in `if let` and `while let` are unstable (see issue #48215)
- --> $DIR/feature-gate-if_while_or_patterns.rs:2:5
- |
-LL | / if let 0 | 1 = 0 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
-LL | | ;
-LL | | }
- | |_____^
- |
- = help: add #![feature(if_while_or_patterns)] to the crate attributes to enable
-
-error[E0658]: multiple patterns in `if let` and `while let` are unstable (see issue #48215)
- --> $DIR/feature-gate-if_while_or_patterns.rs:5:5
- |
-LL | / while let 0 | 1 = 1 { //~ ERROR multiple patterns in `if let` and `while let` are unstable
-LL | | break;
-LL | | }
- | |_____^
- |
- = help: add #![feature(if_while_or_patterns)] to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
LL | const fn foo() -> u32 { 0 } //~ ERROR trait fns cannot be declared const
| ^^^^^ trait fns cannot be const
-error[E0658]: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #57563)
--> $DIR/feature-gate-min_const_fn.rs:6:5
|
LL | const fn foo() -> u32; //~ ERROR const fn is unstable
|
= help: add #![feature(const_fn)] to the crate attributes to enable
-error[E0658]: const fn is unstable (see issue #24111)
+error[E0658]: const fn is unstable (see issue #57563)
--> $DIR/feature-gate-min_const_fn.rs:8:5
|
LL | const fn bar() -> u32 { 0 } //~ ERROR const fn is unstable
-#![feature(const_let)]
-
trait Trt {}
struct Str {}
error[E0658]: naming constants with `_` is unstable (see issue #54912)
- --> $DIR/feature-gate-underscore_const_names.rs:8:1
+ --> $DIR/feature-gate-underscore_const_names.rs:6:1
|
LL | / const _ : () = {
LL | | //~^ ERROR is unstable
+++ /dev/null
-// edition:2018
-
-pub mod foo {
- pub use bar::Bar; //~ ERROR imports can only refer to extern crate names
-
- pub mod bar {
- pub struct Bar;
- }
-}
-
-use inline; //~ ERROR imports can only refer to extern crate names
-
-use Vec; //~ ERROR imports can only refer to extern crate names
-
-use vec; //~ ERROR imports can only refer to extern crate names
-
-fn main() {
- let _ = foo::Bar;
-}
+++ /dev/null
-error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
- --> $DIR/feature-gate-uniform-paths.rs:4:13
- |
-LL | pub use bar::Bar; //~ ERROR imports can only refer to extern crate names
- | ^^^
-LL |
-LL | / pub mod bar {
-LL | | pub struct Bar;
-LL | | }
- | |_____- not an extern crate passed with `--extern`
- |
- = help: add #![feature(uniform_paths)] to the crate attributes to enable
-note: this import refers to the module defined here
- --> $DIR/feature-gate-uniform-paths.rs:6:5
- |
-LL | / pub mod bar {
-LL | | pub struct Bar;
-LL | | }
- | |_____^
-
-error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
- --> $DIR/feature-gate-uniform-paths.rs:11:5
- |
-LL | use inline; //~ ERROR imports can only refer to extern crate names
- | ^^^^^^ not an extern crate passed with `--extern`
- |
- = help: add #![feature(uniform_paths)] to the crate attributes to enable
- = note: this import refers to a built-in attribute
-
-error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
- --> $DIR/feature-gate-uniform-paths.rs:13:5
- |
-LL | use Vec; //~ ERROR imports can only refer to extern crate names
- | ^^^ not an extern crate passed with `--extern`
- |
- = help: add #![feature(uniform_paths)] to the crate attributes to enable
- = note: this import refers to a struct from prelude
-
-error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
- --> $DIR/feature-gate-uniform-paths.rs:15:5
- |
-LL | use vec; //~ ERROR imports can only refer to extern crate names
- | ^^^ not an extern crate passed with `--extern`
- |
- = help: add #![feature(uniform_paths)] to the crate attributes to enable
- = note: this import refers to a macro from prelude
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-// gate-test-irrefutable_let_patterns
-
-
-#[allow(irrefutable_let_patterns)]
-fn main() {
- if let _ = 5 {}
- //~^ ERROR irrefutable if-let pattern [E0162]
-}
+++ /dev/null
-error[E0162]: irrefutable if-let pattern
- --> $DIR/feature-gate-without_gate_irrefutable_pattern.rs:6:12
- |
-LL | if let _ = 5 {}
- | ^ irrefutable pattern
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0162`.
--- /dev/null
+fn main() {
+ let _ = if true {
+ 1i32
+ } else {
+ 2u32
+ };
+ //~^^ ERROR if and else have incompatible types
+ let _ = if true { 42i32 } else { 42u32 };
+ //~^ ERROR if and else have incompatible types
+ let _ = if true {
+ 3u32;
+ } else {
+ 4u32
+ };
+ //~^^ ERROR if and else have incompatible types
+ let _ = if true {
+ 5u32
+ } else {
+ 6u32;
+ };
+ //~^^ ERROR if and else have incompatible types
+ let _ = if true {
+ 7i32;
+ } else {
+ 8u32
+ };
+ //~^^ ERROR if and else have incompatible types
+ let _ = if true {
+ 9i32
+ } else {
+ 10u32;
+ };
+ //~^^ ERROR if and else have incompatible types
+ let _ = if true {
+
+ } else {
+ 11u32
+ };
+ //~^^ ERROR if and else have incompatible types
+ let _ = if true {
+ 12i32
+ } else {
+
+ };
+ //~^^^ ERROR if and else have incompatible types
+}
--- /dev/null
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:5:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | | 1i32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 2u32
+ | | ^^^^ expected i32, found u32
+LL | | };
+ | |_____- if and else have incompatible types
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:8:38
+ |
+LL | let _ = if true { 42i32 } else { 42u32 };
+ | ----- ^^^^^ expected i32, found u32
+ | |
+ | expected because of this
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:13:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | | 3u32;
+ | | -----
+ | | | |
+ | | | help: consider removing this semicolon
+ | | expected because of this
+LL | | } else {
+LL | | 4u32
+ | | ^^^^ expected (), found u32
+LL | | };
+ | |_____- if and else have incompatible types
+ |
+ = note: expected type `()`
+ found type `u32`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:19:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | | 5u32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 6u32;
+ | | ^^^^-
+ | | | |
+ | | | help: consider removing this semicolon
+ | | expected u32, found ()
+LL | | };
+ | |_____- if and else have incompatible types
+ |
+ = note: expected type `u32`
+ found type `()`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:25:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | | 7i32;
+ | | ----- expected because of this
+LL | | } else {
+LL | | 8u32
+ | | ^^^^ expected (), found u32
+LL | | };
+ | |_____- if and else have incompatible types
+ |
+ = note: expected type `()`
+ found type `u32`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:31:9
+ |
+LL | let _ = if true {
+ | _____________-
+LL | | 9i32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 10u32;
+ | | ^^^^^^ expected i32, found ()
+LL | | };
+ | |_____- if and else have incompatible types
+ |
+ = note: expected type `i32`
+ found type `()`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:37:9
+ |
+LL | let _ = if true {
+ | _____________________-
+LL | |
+LL | | } else {
+ | |_____- expected because of this
+LL | 11u32
+ | ^^^^^ expected (), found u32
+ |
+ = note: expected type `()`
+ found type `u32`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/if-else-type-mismatch.rs:42:12
+ |
+LL | let _ = if true {
+ | ------- if and else have incompatible types
+LL | 12i32
+ | ----- expected because of this
+LL | } else {
+ | ____________^
+LL | |
+LL | | };
+ | |_____^ expected i32, found ()
+ |
+ = note: expected type `i32`
+ found type `()`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
error[E0308]: if and else have incompatible types
- --> $DIR/if-branch-types.rs:2:13
+ --> $DIR/if-branch-types.rs:2:38
|
LL | let x = if true { 10i32 } else { 10u32 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i32, found u32
+ | ----- ^^^^^ expected i32, found u32
+ | |
+ | expected because of this
|
= note: expected type `i32`
found type `u32`
+// compile-pass
+
fn macros() {
macro_rules! foo{
($p:pat, $e:expr, $b:block) => {{
}}
}
- foo!(a, 1, { //~ ERROR irrefutable if-let
+ foo!(a, 1, { //~ WARN irrefutable if-let
println!("irrefutable pattern");
});
- bar!(a, 1, { //~ ERROR irrefutable if-let
+ bar!(a, 1, { //~ WARN irrefutable if-let
println!("irrefutable pattern");
});
}
pub fn main() {
- if let a = 1 { //~ ERROR irrefutable if-let
+ if let a = 1 { //~ WARN irrefutable if-let
println!("irrefutable pattern");
}
- if let a = 1 { //~ ERROR irrefutable if-let
+ if let a = 1 { //~ WARN irrefutable if-let
println!("irrefutable pattern");
} else if true {
println!("else-if in irrefutable if-let");
if let 1 = 2 {
println!("refutable pattern");
- } else if let a = 1 { //~ ERROR irrefutable if-let
+ } else if let a = 1 { //~ WARN irrefutable if-let
println!("irrefutable pattern");
}
if true {
println!("if");
- } else if let a = 1 { //~ ERROR irrefutable if-let
+ } else if let a = 1 { //~ WARN irrefutable if-let
println!("irrefutable pattern");
}
}
-error[E0162]: irrefutable if-let pattern
- --> $DIR/if-let.rs:13:10
+warning: irrefutable if-let pattern
+ --> $DIR/if-let.rs:6:13
|
-LL | foo!(a, 1, { //~ ERROR irrefutable if-let
- | ^ irrefutable pattern
-
-error[E0162]: irrefutable if-let pattern
- --> $DIR/if-let.rs:16:10
+LL | if let $p = $e $b
+ | ^^
+...
+LL | / foo!(a, 1, { //~ WARN irrefutable if-let
+LL | | println!("irrefutable pattern");
+LL | | });
+ | |_______- in this macro invocation
|
-LL | bar!(a, 1, { //~ ERROR irrefutable if-let
- | ^ irrefutable pattern
+ = note: #[warn(irrefutable_let_patterns)] on by default
-error[E0162]: irrefutable if-let pattern
- --> $DIR/if-let.rs:22:12
+warning: irrefutable if-let pattern
+ --> $DIR/if-let.rs:6:13
|
-LL | if let a = 1 { //~ ERROR irrefutable if-let
- | ^ irrefutable pattern
+LL | if let $p = $e $b
+ | ^^
+...
+LL | / bar!(a, 1, { //~ WARN irrefutable if-let
+LL | | println!("irrefutable pattern");
+LL | | });
+ | |_______- in this macro invocation
-error[E0162]: irrefutable if-let pattern
- --> $DIR/if-let.rs:26:12
+warning: irrefutable if-let pattern
+ --> $DIR/if-let.rs:24:5
|
-LL | if let a = 1 { //~ ERROR irrefutable if-let
- | ^ irrefutable pattern
+LL | / if let a = 1 { //~ WARN irrefutable if-let
+LL | | println!("irrefutable pattern");
+LL | | }
+ | |_____^
-error[E0162]: irrefutable if-let pattern
- --> $DIR/if-let.rs:36:19
+warning: irrefutable if-let pattern
+ --> $DIR/if-let.rs:28:5
|
-LL | } else if let a = 1 { //~ ERROR irrefutable if-let
- | ^ irrefutable pattern
+LL | / if let a = 1 { //~ WARN irrefutable if-let
+LL | | println!("irrefutable pattern");
+LL | | } else if true {
+LL | | println!("else-if in irrefutable if-let");
+LL | | } else {
+LL | | println!("else in irrefutable if-let");
+LL | | }
+ | |_____^
-error[E0162]: irrefutable if-let pattern
- --> $DIR/if-let.rs:42:19
+warning: irrefutable if-let pattern
+ --> $DIR/if-let.rs:38:12
|
-LL | } else if let a = 1 { //~ ERROR irrefutable if-let
- | ^ irrefutable pattern
+LL | } else if let a = 1 { //~ WARN irrefutable if-let
+ | ____________^
+LL | | println!("irrefutable pattern");
+LL | | }
+ | |_____^
-error: aborting due to 6 previous errors
+warning: irrefutable if-let pattern
+ --> $DIR/if-let.rs:44:12
+ |
+LL | } else if let a = 1 { //~ WARN irrefutable if-let
+ | ____________^
+LL | | println!("irrefutable pattern");
+LL | | }
+ | |_____^
-For more information about this error, try `rustc --explain E0162`.
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
= note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle
+note: cycle used when checking item types in top-level module
+ --> $DIR/auto-trait-leak.rs:3:1
+ |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+... |
+LL | | Rc::new(String::from("foo"))
+LL | | }
+ | |_^
error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}`
--> $DIR/auto-trait-leak.rs:14:16
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle
+note: cycle used when checking item types in top-level module
+ --> $DIR/auto-trait-leak.rs:3:1
+ |
+LL | / use std::cell::Cell;
+LL | | use std::rc::Rc;
+LL | |
+LL | | fn send<T: Send>(_: T) {}
+... |
+LL | | Rc::new(String::from("foo"))
+LL | | }
+ | |_^
error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
--> $DIR/auto-trait-leak.rs:17:5
--- /dev/null
+// Extern crate items are marked as used if they are used
+// through extern prelude entries introduced by them.
+
+// edition:2018
+
+#![deny(unused_extern_crates)]
+
+extern crate core as iso1; //~ ERROR `extern crate` is not idiomatic in the new edition
+extern crate core as iso2; //~ ERROR `extern crate` is not idiomatic in the new edition
+extern crate core as iso3; //~ ERROR `extern crate` is not idiomatic in the new edition
+extern crate core as iso4; //~ ERROR `extern crate` is not idiomatic in the new edition
+
+// Doesn't introduce its extern prelude entry, so it's still considered unused.
+extern crate core; //~ ERROR unused extern crate
+
+mod m {
+ use iso1::any as are_you_okay1;
+ use ::iso2::any as are_you_okay2;
+ type AreYouOkay1 = iso3::any::Any;
+ type AreYouOkay2 = ::iso4::any::Any;
+
+ use core::any as are_you_okay3;
+ use ::core::any as are_you_okay4;
+ type AreYouOkay3 = core::any::Any;
+ type AreYouOkay4 = ::core::any::Any;
+}
+
+fn main() {}
--- /dev/null
+error: `extern crate` is not idiomatic in the new edition
+ --> $DIR/extern-crate-used.rs:8:1
+ |
+LL | extern crate core as iso1; //~ ERROR `extern crate` is not idiomatic in the new edition
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+ |
+note: lint level defined here
+ --> $DIR/extern-crate-used.rs:6:9
+ |
+LL | #![deny(unused_extern_crates)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: `extern crate` is not idiomatic in the new edition
+ --> $DIR/extern-crate-used.rs:9:1
+ |
+LL | extern crate core as iso2; //~ ERROR `extern crate` is not idiomatic in the new edition
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: `extern crate` is not idiomatic in the new edition
+ --> $DIR/extern-crate-used.rs:10:1
+ |
+LL | extern crate core as iso3; //~ ERROR `extern crate` is not idiomatic in the new edition
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: `extern crate` is not idiomatic in the new edition
+ --> $DIR/extern-crate-used.rs:11:1
+ |
+LL | extern crate core as iso4; //~ ERROR `extern crate` is not idiomatic in the new edition
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+
+error: unused extern crate
+ --> $DIR/extern-crate-used.rs:14:1
+ |
+LL | extern crate core; //~ ERROR unused extern crate
+ | ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 5 previous errors
+
// compile-flags:--extern issue_56125
// aux-build:issue-56125.rs
-#![feature(uniform_paths)]
-
mod m1 {
use issue_56125::last_segment::*;
//~^ ERROR `issue_56125` is ambiguous
error[E0432]: unresolved import `empty::issue_56125`
- --> $DIR/issue-56125.rs:19:9
+ --> $DIR/issue-56125.rs:17:9
|
LL | use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125`
| ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
- --> $DIR/issue-56125.rs:8:9
+ --> $DIR/issue-56125.rs:6:9
|
LL | use issue_56125::last_segment::*;
| ^^^^^^^^^^^ ambiguous name
= note: `issue_56125` could refer to an extern crate passed with `--extern`
= help: use `::issue_56125` to refer to this extern crate unambiguously
note: `issue_56125` could also refer to the module imported here
- --> $DIR/issue-56125.rs:8:9
+ --> $DIR/issue-56125.rs:6:9
|
LL | use issue_56125::last_segment::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use `self::issue_56125` to refer to this module unambiguously
error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
- --> $DIR/issue-56125.rs:13:9
+ --> $DIR/issue-56125.rs:11:9
|
LL | use issue_56125::non_last_segment::non_last_segment::*;
| ^^^^^^^^^^^ ambiguous name
= note: `issue_56125` could refer to an extern crate passed with `--extern`
= help: use `::issue_56125` to refer to this extern crate unambiguously
note: `issue_56125` could also refer to the module imported here
- --> $DIR/issue-56125.rs:13:9
+ --> $DIR/issue-56125.rs:11:9
|
LL | use issue_56125::non_last_segment::non_last_segment::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use `self::issue_56125` to refer to this module unambiguously
error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
- --> $DIR/issue-56125.rs:20:9
+ --> $DIR/issue-56125.rs:18:9
|
LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous
| ^^^^^^^^^^^ ambiguous name
= note: `issue_56125` could refer to an extern crate passed with `--extern`
= help: use `::issue_56125` to refer to this extern crate unambiguously
note: `issue_56125` could also refer to the module imported here
- --> $DIR/issue-56125.rs:20:9
+ --> $DIR/issue-56125.rs:18:9
|
LL | use issue_56125::*; //~ ERROR `issue_56125` is ambiguous
| ^^^^^^^^^^^^^^
| ^
|
= note: ...which again requires processing `X`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/infinite-vec-type-recursion.rs:1:1
+ |
+LL | / type X = Vec<X>;
+LL | | //~^ ERROR cycle detected
+LL | |
+LL | | fn main() { let b: X = Vec::new(); }
+ | |____________________________________^
error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/issue-11844.rs:6:9
|
+LL | match a {
+ | - this match expression has type `std::option::Option<std::boxed::Box<{integer}>>`
LL | Ok(a) => //~ ERROR: mismatched types
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
LL | trait T2 : T1 {
| ^^
= note: ...which again requires computing the supertraits of `T1`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/issue-12511.rs:1:1
+ |
+LL | trait T1 : T2 {
+ | ^^^^^^^^^^^^^
error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/issue-12552.rs:6:5
|
+LL | match t {
+ | - this match expression has type `std::result::Result<_, {integer}>`
LL | Some(k) => match k { //~ ERROR mismatched types
| ^^^^^^^ expected enum `std::result::Result`, found enum `std::option::Option`
|
error[E0308]: mismatched types
--> $DIR/issue-13466.rs:8:9
|
+LL | let _x: usize = match Some(1) {
+ | ------- this match expression has type `std::option::Option<{integer}>`
LL | Ok(u) => u,
| ^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
error[E0308]: mismatched types
--> $DIR/issue-13466.rs:14:9
|
+LL | let _x: usize = match Some(1) {
+ | ------- this match expression has type `std::option::Option<{integer}>`
+...
LL | Err(e) => panic!(e)
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
error[E0308]: mismatched types
--> $DIR/issue-15896.rs:11:11
|
+LL | let u = match e {
+ | - this match expression has type `main::R`
+LL | E::B(
LL | Tau{t: x},
| ^^^^^^^^^ expected enum `main::R`, found struct `main::Tau`
|
error[E0308]: mismatched types
--> $DIR/issue-16401.rs:8:9
|
+LL | match () {
+ | -- this match expression has type `()`
LL | Slice { data: data, len: len } => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found struct `Slice`
|
--> $DIR/issue-17263.rs:21:32
|
LL | let (c, d) = (&mut foo.a, &foo.b);
- | ----- ^^^^^ immutable borrow occurs here (via `foo.b`)
+ | ----- ^^^^^ immutable borrow of `foo.b` -- which overlaps with `foo.a` -- occurs here
| |
| mutable borrow occurs here (via `foo.a`)
...
#![warn(unused)]
-#[deny(warnings)]
+#![deny(warnings)]
const foo: isize = 3;
-//~^ ERROR: should have an upper case name such as
+//~^ ERROR: should have an upper case name
//~^^ ERROR: constant item is never used
fn main() {}
| ^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
- --> $DIR/issue-17718-const-naming.rs:2:8
+ --> $DIR/issue-17718-const-naming.rs:2:9
|
-LL | #[deny(warnings)]
- | ^^^^^^^^
+LL | #![deny(warnings)]
+ | ^^^^^^^^
= note: #[deny(dead_code)] implied by #[deny(warnings)]
-error: constant `foo` should have an upper case name such as `FOO`
- --> $DIR/issue-17718-const-naming.rs:4:1
+error: constant `foo` should have an upper case name
+ --> $DIR/issue-17718-const-naming.rs:4:7
|
LL | const foo: isize = 3;
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^ help: convert the identifier to upper case: `FOO`
|
note: lint level defined here
- --> $DIR/issue-17718-const-naming.rs:2:8
+ --> $DIR/issue-17718-const-naming.rs:2:9
|
-LL | #[deny(warnings)]
- | ^^^^^^^^
+LL | #![deny(warnings)]
+ | ^^^^^^^^
= note: #[deny(non_upper_case_globals)] implied by #[deny(warnings)]
error: aborting due to 2 previous errors
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:5:17
- |
-LL | let p = 3;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:5:17
- |
-LL | let p = 3;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:8:9
- |
-LL | &p //~ ERROR `p` does not live long enough
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:2:5
- |
-LL | / const z: &'static isize = {
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | //~| ERROR statements in constants are unstable
-LL | | let p = 3;
-... |
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | };
- | |______^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:2:5
- |
-LL | / const z: &'static isize = {
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | //~| ERROR statements in constants are unstable
-LL | | let p = 3;
-... |
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | };
- | |______^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
error[E0597]: `p` does not live long enough
- --> $DIR/issue-18118.rs:8:9
+ --> $DIR/issue-18118.rs:4:9
|
LL | &p //~ ERROR `p` does not live long enough
| ^^
| |
| borrowed value does not live long enough
| using this value as a constant requires that `p` is borrowed for `'static`
-LL | //~^ ERROR let bindings in constants are unstable
LL | };
| - `p` dropped here while still borrowed
-error: aborting due to 6 previous errors
+error: aborting due to previous error
-Some errors occurred: E0597, E0658.
-For more information about an error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0597`.
pub fn main() {
const z: &'static isize = {
- //~^ ERROR let bindings in constants are unstable
- //~| ERROR statements in constants are unstable
let p = 3;
- //~^ ERROR let bindings in constants are unstable
- //~| ERROR statements in constants are unstable
&p //~ ERROR `p` does not live long enough
- //~^ ERROR let bindings in constants are unstable
};
}
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:5:17
- |
-LL | let p = 3;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:5:17
- |
-LL | let p = 3;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:8:9
- |
-LL | &p //~ ERROR `p` does not live long enough
- | ^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: let bindings in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:2:5
- |
-LL | / const z: &'static isize = {
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | //~| ERROR statements in constants are unstable
-LL | | let p = 3;
-... |
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | };
- | |______^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-18118.rs:2:5
- |
-LL | / const z: &'static isize = {
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | //~| ERROR statements in constants are unstable
-LL | | let p = 3;
-... |
-LL | | //~^ ERROR let bindings in constants are unstable
-LL | | };
- | |______^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
error[E0597]: `p` does not live long enough
- --> $DIR/issue-18118.rs:8:10
+ --> $DIR/issue-18118.rs:4:10
|
LL | &p //~ ERROR `p` does not live long enough
| ^ borrowed value does not live long enough
-LL | //~^ ERROR let bindings in constants are unstable
LL | };
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
-error: aborting due to 6 previous errors
+error: aborting due to previous error
-Some errors occurred: E0597, E0658.
-For more information about an error, try `rustc --explain E0597`.
+For more information about this error, try `rustc --explain E0597`.
| |__^
|
= note: ...which again requires computing the supertraits of `T`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/issue-20772.rs:1:1
+ |
+LL | / trait T : Iterator<Item=Self::Item>
+LL | | //~^ ERROR cycle detected
+LL | | //~| ERROR associated type `Item` not found for `Self`
+LL | | {}
+ | |__^
error[E0220]: associated type `Item` not found for `Self`
--> $DIR/issue-20772.rs:1:25
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: ...which again requires computing the supertraits of `Processor`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/issue-20825.rs:5:1
+ |
+LL | pub trait Processor: Subscriber<Input = Self::Input> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: ...which again requires computing the supertraits of `Expr`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/issue-22673.rs:1:1
+ |
+LL | trait Expr : PartialEq<Self::Item> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
// ignore-tidy-linelength
-#![feature(const_fn)]
-
const bad : u32 = {
{
5;
- //~^ ERROR statements in constants are unstable
0
}
};
const bad_two : u32 = {
{
invalid();
- //~^ ERROR statements in constants are unstable
- //~^^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
+ //~^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
0
}
};
const bad_three : u32 = {
{
valid();
- //~^ ERROR statements in constants are unstable
0
}
};
static bad_four : u32 = {
{
5;
- //~^ ERROR statements in statics are unstable
0
}
};
{
invalid();
//~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
- //~| ERROR statements in statics are unstable
0
}
};
static bad_six : u32 = {
{
valid();
- //~^ ERROR statements in statics are unstable
0
}
};
static mut bad_seven : u32 = {
{
5;
- //~^ ERROR statements in statics are unstable
0
}
};
static mut bad_eight : u32 = {
{
invalid();
- //~^ ERROR statements in statics are unstable
- //~| ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
+ //~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
0
}
};
static mut bad_nine : u32 = {
{
valid();
- //~^ ERROR statements in statics are unstable
0
}
};
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:7:9
- |
-LL | 5;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
- --> $DIR/issue-32829-2.rs:15:9
+ --> $DIR/issue-32829-2.rs:12:9
|
LL | invalid();
| ^^^^^^^^^
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:15:9
- |
-LL | invalid();
- | ^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in constants are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:24:9
- |
-LL | valid();
- | ^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:32:9
- |
-LL | 5;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
- --> $DIR/issue-32829-2.rs:40:9
+ --> $DIR/issue-32829-2.rs:34:9
|
LL | invalid();
| ^^^^^^^^^
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:40:9
- |
-LL | invalid();
- | ^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:49:9
- |
-LL | valid();
- | ^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:57:9
- |
-LL | 5;
- | ^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
- --> $DIR/issue-32829-2.rs:65:9
+ --> $DIR/issue-32829-2.rs:56:9
|
LL | invalid();
| ^^^^^^^^^
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:65:9
- |
-LL | invalid();
- | ^^^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error[E0658]: statements in statics are unstable (see issue #48821)
- --> $DIR/issue-32829-2.rs:74:9
- |
-LL | valid();
- | ^^^^^^^
- |
- = help: add #![feature(const_let)] to the crate attributes to enable
-
-error: aborting due to 12 previous errors
+error: aborting due to 3 previous errors
-Some errors occurred: E0015, E0658.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0015`.
LL | type DefaultFoo = Foo;
| ^^^
= note: ...which again requires processing `Foo::T`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/issue-34373.rs:1:1
+ |
+LL | / #![allow(warnings)]
+LL | |
+LL | | trait Trait<T> {
+LL | | fn foo(_: T) {}
+... |
+LL | | fn main() {
+LL | | }
+ | |_^
error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/issue-3680.rs:3:9
|
+LL | match None {
+ | ---- this match expression has type `std::option::Option<_>`
LL | Err(_) => ()
| ^^^^^^ expected enum `std::option::Option`, found enum `std::result::Result`
|
const fn x() {
- let t = true; //~ ERROR local variables in const fn
- let x = || t;
+ let t = true;
+ let x = || t; //~ ERROR function pointers in const fn are unstable
}
fn main() {}
-error: local variables in const fn are unstable
- --> $DIR/issue-37550.rs:2:9
+error: function pointers in const fn are unstable
+ --> $DIR/issue-37550.rs:3:9
|
-LL | let t = true; //~ ERROR local variables in const fn
+LL | let x = || t; //~ ERROR function pointers in const fn are unstable
| ^
error: aborting due to previous error
#![allow(unused)]
#![feature(nll)]
+// ignore-tidy-linelength
+
#[derive(Clone, Copy, Default)]
struct S {
a: u8,
*mref = 22;
let nref = &u.z.c;
- //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
+ //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
println!("{} {}", mref, nref)
}
}
-
-error[E0502]: cannot borrow `u.z.c` as immutable because it is also borrowed as mutable
- --> $DIR/issue-45157.rs:27:20
+error[E0502]: cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`)
+ --> $DIR/issue-45157.rs:29:20
|
LL | let mref = &mut u.s.a;
- | ---------- mutable borrow occurs here
+ | ---------- mutable borrow occurs here (via `u.s.a`)
...
LL | let nref = &u.z.c;
- | ^^^^^^ immutable borrow occurs here
-LL | //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
+ | ^^^^^^ immutable borrow of `u.z.c` -- which overlaps with `u.s.a` -- occurs here
+LL | //~^ ERROR cannot borrow `u` (via `u.z.c`) as immutable because it is also borrowed as mutable (via `u.s.a`) [E0502]
LL | println!("{} {}", mref, nref)
| ---- mutable borrow later used here
+ |
+ = note: `u.z.c` is a field of the union `U`, so it overlaps the field `u.s.a`
error: aborting due to previous error
error[E0308]: mismatched types
--> $DIR/issue-5100.rs:33:9
|
+LL | match (true, false) {
+ | ------------- this match expression has type `(bool, bool)`
LL | box (true, false) => ()
| ^^^^^^^^^^^^^^^^^ expected tuple, found struct `std::boxed::Box`
|
[(); return while let Some(n) = Some(0) {}];
//~^ ERROR return statement outside of function body
- //~^^ ERROR irrefutable while-let pattern
+ //~^^ WARN irrefutable while-let pattern
}
LL | [(); return while let Some(n) = Some(0) {}];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0165]: irrefutable while-let pattern
- --> $DIR/issue-51714.rs:11:27
+warning: irrefutable while-let pattern
+ --> $DIR/issue-51714.rs:11:17
|
LL | [(); return while let Some(n) = Some(0) {}];
- | ^^^^^^^ irrefutable pattern
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: #[warn(irrefutable_let_patterns)] on by default
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
-Some errors occurred: E0165, E0572.
-For more information about an error, try `rustc --explain E0165`.
+For more information about this error, try `rustc --explain E0572`.
error[E0308]: mismatched types
--> $DIR/issue-5358-1.rs:6:9
|
+LL | match S(Either::Left(5)) {
+ | ------------------ this match expression has type `S`
LL | Either::Right(_) => {}
| ^^^^^^^^^^^^^^^^ expected struct `S`, found enum `Either`
|
--- /dev/null
+// compile-pass
+
+trait Foo<Args> {
+ type Output;
+}
+
+trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> {
+ fn cb(&self) -> Box<dyn Bar<'a, T, Output=bool>>;
+}
+
+impl<'s> Foo<&'s ()> for () {
+ type Output = bool;
+}
+
+impl<'a> Bar<'a, ()> for () {
+ fn cb(&self) -> Box<dyn Bar<'a, (), Output=bool>> {
+ Box::new(*self)
+ }
+}
+
+fn main() {
+ let _t = ().cb();
+}
--- /dev/null
+#![crate_type="lib"]
+#![deny(unreachable_patterns)]
+
+mod test_struct {
+ // Test the exact copy of the minimal example
+ // posted in the issue.
+ pub struct Punned {
+ foo: [u8; 1],
+ bar: [u8; 1],
+ }
+
+ pub fn test(punned: Punned) {
+ match punned {
+ Punned { foo: [_], .. } => println!("foo"),
+ Punned { bar: [_], .. } => println!("bar"),
+ //~^ ERROR unreachable pattern [unreachable_patterns]
+ }
+ }
+}
+
+mod test_union {
+ // Test the same thing using a union.
+ pub union Punned {
+ foo: [u8; 1],
+ bar: [u8; 1],
+ }
+
+ pub fn test(punned: Punned) {
+ match punned {
+ Punned { foo: [_] } => println!("foo"),
+ Punned { bar: [_] } => println!("bar"),
+ //~^ ERROR unreachable pattern [unreachable_patterns]
+ }
+ }
+}
--- /dev/null
+error: unreachable pattern
+ --> $DIR/issue-57472.rs:15:13
+ |
+LL | Punned { bar: [_], .. } => println!("bar"),
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/issue-57472.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/issue-57472.rs:31:13
+ |
+LL | Punned { bar: [_] } => println!("bar"),
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
error[E0308]: mismatched types
--> $DIR/issue-7092.rs:6:9
|
+LL | match x {
+ | - this match expression has type `Whatever`
LL | Some(field) =>
| ^^^^^^^^^^^ expected enum `Whatever`, found enum `std::option::Option`
|
static boxed: Box<RefCell<isize>> = box RefCell::new(0);
//~^ ERROR allocations are not allowed in statics
//~| ERROR `std::cell::RefCell<isize>` cannot be shared between threads safely [E0277]
+//~| ERROR static contains unimplemented expression type
fn main() { }
LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
| ^^^^^^^^^^^^^^^^^^^ allocation not allowed in statics
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/issue-7364.rs:6:41
+ |
+LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
+ | ^^^^^^^^^^^^^^^
+
error[E0277]: `std::cell::RefCell<isize>` cannot be shared between threads safely
--> $DIR/issue-7364.rs:6:1
|
= note: required because it appears within the type `std::boxed::Box<std::cell::RefCell<isize>>`
= note: shared static variables must have a type that implements `Sync`
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
-Some errors occurred: E0010, E0277.
+Some errors occurred: E0010, E0019, E0277.
For more information about an error, try `rustc --explain E0010`.
-error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
+error: variable `_InappropriateCamelCasing` should have a snake case name
--> $DIR/command-line-lint-group-deny.rs:4:9
|
LL | let _InappropriateCamelCasing = true; //~ ERROR should have a snake
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
|
= note: `-D non-snake-case` implied by `-D bad-style`
-error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
+error: variable `_InappropriateCamelCasing` should have a snake case name
--> $DIR/command-line-lint-group-forbid.rs:4:9
|
LL | let _InappropriateCamelCasing = true; //~ ERROR should have a snake
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
|
= note: `-F non-snake-case` implied by `-F bad-style`
-warning: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing`
+warning: variable `_InappropriateCamelCasing` should have a snake case name
--> $DIR/command-line-lint-group-warn.rs:5:9
|
LL | let _InappropriateCamelCasing = true;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
|
= note: `-W non-snake-case` implied by `-W bad-style`
-warning: type `snake_case` should have a camel case name such as `SnakeCase`
- --> $DIR/lint-group-nonstandard-style.rs:22:9
+warning: type `snake_case` should have a camel case name
+ --> $DIR/lint-group-nonstandard-style.rs:22:16
|
LL | struct snake_case; //~ WARN should have a camel
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^ help: convert the identifier to camel case: `SnakeCase`
|
note: lint level defined here
--> $DIR/lint-group-nonstandard-style.rs:18:17
| ^^^^^^^^^^^^^^^^^
= note: #[warn(non_camel_case_types)] implied by #[warn(nonstandard_style)]
-error: function `CamelCase` should have a snake case name such as `camel_case`
- --> $DIR/lint-group-nonstandard-style.rs:4:1
+error: function `CamelCase` should have a snake case name
+ --> $DIR/lint-group-nonstandard-style.rs:4:4
|
LL | fn CamelCase() {} //~ ERROR should have a snake
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
|
note: lint level defined here
--> $DIR/lint-group-nonstandard-style.rs:1:9
| ^^^^^^^^^^^^^^^^^
= note: #[deny(non_snake_case)] implied by #[deny(nonstandard_style)]
-error: function `CamelCase` should have a snake case name such as `camel_case`
- --> $DIR/lint-group-nonstandard-style.rs:12:9
+error: function `CamelCase` should have a snake case name
+ --> $DIR/lint-group-nonstandard-style.rs:12:12
|
LL | fn CamelCase() {} //~ ERROR should have a snake
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
|
note: lint level defined here
--> $DIR/lint-group-nonstandard-style.rs:10:14
| ^^^^^^^^^^^^^^^^^
= note: #[forbid(non_snake_case)] implied by #[forbid(nonstandard_style)]
-error: static variable `bad` should have an upper case name such as `BAD`
- --> $DIR/lint-group-nonstandard-style.rs:14:9
+error: static variable `bad` should have an upper case name
+ --> $DIR/lint-group-nonstandard-style.rs:14:16
|
LL | static bad: isize = 1; //~ ERROR should have an upper
- | ^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^ help: convert the identifier to upper case: `BAD`
|
note: lint level defined here
--> $DIR/lint-group-nonstandard-style.rs:10:14
| ^^^^^^^^^^^^^^^^^
= note: #[forbid(non_upper_case_globals)] implied by #[forbid(nonstandard_style)]
-warning: function `CamelCase` should have a snake case name such as `camel_case`
- --> $DIR/lint-group-nonstandard-style.rs:20:9
+warning: function `CamelCase` should have a snake case name
+ --> $DIR/lint-group-nonstandard-style.rs:20:12
|
LL | fn CamelCase() {} //~ WARN should have a snake
- | ^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^ help: convert the identifier to snake case: `camel_case`
|
note: lint level defined here
--> $DIR/lint-group-nonstandard-style.rs:18:17
--- /dev/null
+// compile-pass
+// Issue #7526: lowercase static constants in patterns look like bindings
+
+// This is similar to lint-lowercase-static-const-pattern.rs, except it
+// shows the expected usual workaround (choosing a different name for
+// the static definition) and also demonstrates that one can work
+// around this problem locally by renaming the constant in the `use`
+// form to an uppercase identifier that placates the lint.
+
+#![deny(non_upper_case_globals)]
+
+pub const A : isize = 97;
+
+fn f() {
+ let r = match (0,0) {
+ (0, A) => 0,
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 1);
+ let r = match (0,97) {
+ (0, A) => 0,
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 0);
+}
+
+mod m {
+ #[allow(non_upper_case_globals)]
+ pub const aha : isize = 7;
+}
+
+fn g() {
+ use self::m::aha as AHA;
+ let r = match (0,0) {
+ (0, AHA) => 0,
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 1);
+ let r = match (0,7) {
+ (0, AHA) => 0,
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 0);
+}
+
+fn h() {
+ let r = match (0,0) {
+ (0, self::m::aha) => 0,
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 1);
+ let r = match (0,7) {
+ (0, self::m::aha) => 0,
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 0);
+}
+
+pub fn main () {
+ f();
+ g();
+ h();
+}
--- /dev/null
+// Issue #7526: lowercase static constants in patterns look like bindings
+
+#![allow(dead_code)]
+#![deny(non_upper_case_globals)]
+
+#[allow(non_upper_case_globals)]
+pub const a : isize = 97;
+
+fn f() {
+ let r = match (0,0) {
+ (0, a) => 0,
+ //~^ ERROR constant in pattern `a` should have an upper case name
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 1);
+}
+
+mod m {
+ #[allow(non_upper_case_globals)]
+ pub const aha : isize = 7;
+}
+
+fn g() {
+ use self::m::aha;
+ let r = match (0,0) {
+ (0, aha) => 0,
+ //~^ ERROR constant in pattern `aha` should have an upper case name
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 1);
+}
+
+mod n {
+ pub const OKAY : isize = 8;
+}
+
+fn h() {
+ use self::n::OKAY as not_okay;
+ let r = match (0,0) {
+ (0, not_okay) => 0,
+//~^ ERROR constant in pattern `not_okay` should have an upper case name
+ (x, y) => 1 + x + y,
+ };
+ assert_eq!(r, 1);
+}
+
+fn main () {
+ f();
+ g();
+ h();
+}
--- /dev/null
+error: constant in pattern `a` should have an upper case name
+ --> $DIR/lint-lowercase-static-const-pattern.rs:11:13
+ |
+LL | (0, a) => 0,
+ | ^ help: convert the identifier to upper case: `A`
+ |
+note: lint level defined here
+ --> $DIR/lint-lowercase-static-const-pattern.rs:4:9
+ |
+LL | #![deny(non_upper_case_globals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant in pattern `aha` should have an upper case name
+ --> $DIR/lint-lowercase-static-const-pattern.rs:26:13
+ |
+LL | (0, aha) => 0,
+ | ^^^ help: convert the identifier to upper case: `AHA`
+
+error: constant in pattern `not_okay` should have an upper case name
+ --> $DIR/lint-lowercase-static-const-pattern.rs:40:13
+ |
+LL | (0, not_okay) => 0,
+ | ^^^^^^^^ help: convert the identifier to upper case: `NOT_OKAY`
+
+error: aborting due to 3 previous errors
+
#![allow(dead_code)]
struct ONE_TWO_THREE;
-//~^ ERROR type `ONE_TWO_THREE` should have a camel case name such as `OneTwoThree`
+//~^ ERROR type `ONE_TWO_THREE` should have a camel case name
-struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo`
+struct foo { //~ ERROR type `foo` should have a camel case name
bar: isize,
}
-enum foo2 { //~ ERROR type `foo2` should have a camel case name such as `Foo2`
+enum foo2 { //~ ERROR type `foo2` should have a camel case name
Bar
}
-struct foo3 { //~ ERROR type `foo3` should have a camel case name such as `Foo3`
+struct foo3 { //~ ERROR type `foo3` should have a camel case name
bar: isize
}
-type foo4 = isize; //~ ERROR type `foo4` should have a camel case name such as `Foo4`
+type foo4 = isize; //~ ERROR type `foo4` should have a camel case name
enum Foo5 {
- bar //~ ERROR variant `bar` should have a camel case name such as `Bar`
+ bar //~ ERROR variant `bar` should have a camel case name
}
-trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6`
+trait foo6 { //~ ERROR trait `foo6` should have a camel case name
fn dummy(&self) { }
}
-fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty`
+fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name
#[repr(C)]
struct foo7 {
struct X86_64;
-struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64`
+struct X86__64; //~ ERROR type `X86__64` should have a camel case name
-struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123`
+struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name
-struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3`
+struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name
fn main() { }
-error: type `ONE_TWO_THREE` should have a camel case name such as `OneTwoThree`
- --> $DIR/lint-non-camel-case-types.rs:4:1
+error: type `ONE_TWO_THREE` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:4:8
|
LL | struct ONE_TWO_THREE;
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^ help: convert the identifier to camel case: `OneTwoThree`
|
note: lint level defined here
--> $DIR/lint-non-camel-case-types.rs:1:11
LL | #![forbid(non_camel_case_types)]
| ^^^^^^^^^^^^^^^^^^^^
-error: type `foo` should have a camel case name such as `Foo`
- --> $DIR/lint-non-camel-case-types.rs:7:1
+error: type `foo` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:7:8
|
-LL | / struct foo { //~ ERROR type `foo` should have a camel case name such as `Foo`
-LL | | bar: isize,
-LL | | }
- | |_^
+LL | struct foo { //~ ERROR type `foo` should have a camel case name
+ | ^^^ help: convert the identifier to camel case: `Foo`
-error: type `foo2` should have a camel case name such as `Foo2`
- --> $DIR/lint-non-camel-case-types.rs:11:1
+error: type `foo2` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:11:6
|
-LL | / enum foo2 { //~ ERROR type `foo2` should have a camel case name such as `Foo2`
-LL | | Bar
-LL | | }
- | |_^
+LL | enum foo2 { //~ ERROR type `foo2` should have a camel case name
+ | ^^^^ help: convert the identifier to camel case: `Foo2`
-error: type `foo3` should have a camel case name such as `Foo3`
- --> $DIR/lint-non-camel-case-types.rs:15:1
+error: type `foo3` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:15:8
|
-LL | / struct foo3 { //~ ERROR type `foo3` should have a camel case name such as `Foo3`
-LL | | bar: isize
-LL | | }
- | |_^
+LL | struct foo3 { //~ ERROR type `foo3` should have a camel case name
+ | ^^^^ help: convert the identifier to camel case: `Foo3`
-error: type `foo4` should have a camel case name such as `Foo4`
- --> $DIR/lint-non-camel-case-types.rs:19:1
+error: type `foo4` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:19:6
|
-LL | type foo4 = isize; //~ ERROR type `foo4` should have a camel case name such as `Foo4`
- | ^^^^^^^^^^^^^^^^^^
+LL | type foo4 = isize; //~ ERROR type `foo4` should have a camel case name
+ | ^^^^ help: convert the identifier to camel case: `Foo4`
-error: variant `bar` should have a camel case name such as `Bar`
+error: variant `bar` should have a camel case name
--> $DIR/lint-non-camel-case-types.rs:22:5
|
-LL | bar //~ ERROR variant `bar` should have a camel case name such as `Bar`
- | ^^^
+LL | bar //~ ERROR variant `bar` should have a camel case name
+ | ^^^ help: convert the identifier to camel case: `Bar`
-error: trait `foo6` should have a camel case name such as `Foo6`
- --> $DIR/lint-non-camel-case-types.rs:25:1
+error: trait `foo6` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:25:7
|
-LL | / trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6`
-LL | | fn dummy(&self) { }
-LL | | }
- | |_^
+LL | trait foo6 { //~ ERROR trait `foo6` should have a camel case name
+ | ^^^^ help: convert the identifier to camel case: `Foo6`
-error: type parameter `ty` should have a camel case name such as `Ty`
+error: type parameter `ty` should have a camel case name
--> $DIR/lint-non-camel-case-types.rs:29:6
|
-LL | fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty`
- | ^^
+LL | fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name
+ | ^^ help: convert the identifier to camel case: `Ty`
-error: type `X86__64` should have a camel case name such as `X86_64`
- --> $DIR/lint-non-camel-case-types.rs:38:1
+error: type `X86__64` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:38:8
|
-LL | struct X86__64; //~ ERROR type `X86__64` should have a camel case name such as `X86_64`
- | ^^^^^^^^^^^^^^^
+LL | struct X86__64; //~ ERROR type `X86__64` should have a camel case name
+ | ^^^^^^^ help: convert the identifier to camel case: `X86_64`
-error: type `Abc_123` should have a camel case name such as `Abc123`
- --> $DIR/lint-non-camel-case-types.rs:40:1
+error: type `Abc_123` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:40:8
|
-LL | struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name such as `Abc123`
- | ^^^^^^^^^^^^^^^
+LL | struct Abc_123; //~ ERROR type `Abc_123` should have a camel case name
+ | ^^^^^^^ help: convert the identifier to camel case: `Abc123`
-error: type `A1_b2_c3` should have a camel case name such as `A1B2C3`
- --> $DIR/lint-non-camel-case-types.rs:42:1
+error: type `A1_b2_c3` should have a camel case name
+ --> $DIR/lint-non-camel-case-types.rs:42:8
|
-LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name such as `A1B2C3`
- | ^^^^^^^^^^^^^^^^
+LL | struct A1_b2_c3; //~ ERROR type `A1_b2_c3` should have a camel case name
+ | ^^^^^^^^ help: convert the identifier to camel case: `A1B2C3`
error: aborting due to 11 previous errors
--- /dev/null
+// compile-pass
+
+#![deny(non_camel_case_types)]
+
+pub enum Foo {
+ #[allow(non_camel_case_types)]
+ bar
+}
+
+fn main() {}
--- /dev/null
+// compile-pass
+
+#![allow(dead_code)]
+// This is ok because we often use the trailing underscore to mean 'prime'
+
+// pretty-expanded FIXME #23616
+
+#[forbid(non_camel_case_types)]
+type Foo_ = isize;
+
+pub fn main() { }
// compile-flags: --crate-name NonSnakeCase
-// error-pattern: crate `NonSnakeCase` should have a snake case name such as `non_snake_case`
+// error-pattern: crate `NonSnakeCase` should have a snake case name
#![deny(non_snake_case)]
-error: crate `NonSnakeCase` should have a snake case name such as `non_snake_case`
+error: crate `NonSnakeCase` should have a snake case name
|
note: lint level defined here
--> $DIR/lint-non-snake-case-crate-2.rs:4:9
|
LL | #![deny(non_snake_case)]
| ^^^^^^^^^^^^^^
+ = help: convert the identifier to snake case: `non_snake_case`
error: aborting due to previous error
#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name such as `non_snake_case`
+//~^ ERROR crate `NonSnakeCase` should have a snake case name
#![deny(non_snake_case)]
fn main() {}
-error: crate `NonSnakeCase` should have a snake case name such as `non_snake_case`
- --> $DIR/lint-non-snake-case-crate.rs:1:1
+error: crate `NonSnakeCase` should have a snake case name
+ --> $DIR/lint-non-snake-case-crate.rs:1:18
|
LL | #![crate_name = "NonSnakeCase"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
|
note: lint level defined here
--> $DIR/lint-non-snake-case-crate.rs:3:9
impl Foo {
fn Foo_Method() {}
- //~^ ERROR method `Foo_Method` should have a snake case name such as `foo_method`
+ //~^ ERROR method `Foo_Method` should have a snake case name
// Don't allow two underscores in a row
fn foo__method(&self) {}
- //~^ ERROR method `foo__method` should have a snake case name such as `foo_method`
+ //~^ ERROR method `foo__method` should have a snake case name
pub fn xyZ(&mut self) {}
- //~^ ERROR method `xyZ` should have a snake case name such as `xy_z`
+ //~^ ERROR method `xyZ` should have a snake case name
fn render_HTML() {}
- //~^ ERROR method `render_HTML` should have a snake case name such as `render_html`
+ //~^ ERROR method `render_HTML` should have a snake case name
}
trait X {
fn ABC();
- //~^ ERROR trait method `ABC` should have a snake case name such as `abc`
+ //~^ ERROR trait method `ABC` should have a snake case name
fn a_b_C(&self) {}
- //~^ ERROR trait method `a_b_C` should have a snake case name such as `a_b_c`
+ //~^ ERROR trait method `a_b_C` should have a snake case name
fn something__else(&mut self);
- //~^ ERROR trait method `something__else` should have a snake case name such as `something_else`
+ //~^ ERROR trait method `something__else` should have a snake case name
}
impl X for Foo {
}
fn Cookie() {}
-//~^ ERROR function `Cookie` should have a snake case name such as `cookie`
+//~^ ERROR function `Cookie` should have a snake case name
pub fn bi_S_Cuit() {}
-//~^ ERROR function `bi_S_Cuit` should have a snake case name such as `bi_s_cuit`
+//~^ ERROR function `bi_S_Cuit` should have a snake case name
fn main() { }
-error: method `Foo_Method` should have a snake case name such as `foo_method`
- --> $DIR/lint-non-snake-case-functions.rs:7:5
+error: method `Foo_Method` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:7:8
|
LL | fn Foo_Method() {}
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^ help: convert the identifier to snake case: `foo_method`
|
note: lint level defined here
--> $DIR/lint-non-snake-case-functions.rs:1:9
LL | #![deny(non_snake_case)]
| ^^^^^^^^^^^^^^
-error: method `foo__method` should have a snake case name such as `foo_method`
- --> $DIR/lint-non-snake-case-functions.rs:11:5
+error: method `foo__method` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:11:8
|
LL | fn foo__method(&self) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^ help: convert the identifier to snake case: `foo_method`
-error: method `xyZ` should have a snake case name such as `xy_z`
- --> $DIR/lint-non-snake-case-functions.rs:14:5
+error: method `xyZ` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:14:12
|
LL | pub fn xyZ(&mut self) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^ help: convert the identifier to snake case: `xy_z`
-error: method `render_HTML` should have a snake case name such as `render_html`
- --> $DIR/lint-non-snake-case-functions.rs:17:5
+error: method `render_HTML` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:17:8
|
LL | fn render_HTML() {}
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^ help: convert the identifier to snake case: `render_html`
-error: trait method `ABC` should have a snake case name such as `abc`
- --> $DIR/lint-non-snake-case-functions.rs:22:5
+error: trait method `ABC` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:22:8
|
LL | fn ABC();
- | ^^^^^^^^^
+ | ^^^ help: convert the identifier to snake case: `abc`
-error: trait method `a_b_C` should have a snake case name such as `a_b_c`
- --> $DIR/lint-non-snake-case-functions.rs:25:5
+error: trait method `a_b_C` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:25:8
|
LL | fn a_b_C(&self) {}
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^ help: convert the identifier to snake case: `a_b_c`
-error: trait method `something__else` should have a snake case name such as `something_else`
- --> $DIR/lint-non-snake-case-functions.rs:28:5
+error: trait method `something__else` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:28:8
|
LL | fn something__else(&mut self);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `something_else`
-error: function `Cookie` should have a snake case name such as `cookie`
- --> $DIR/lint-non-snake-case-functions.rs:38:1
+error: function `Cookie` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:38:4
|
LL | fn Cookie() {}
- | ^^^^^^^^^^^^^^
+ | ^^^^^^ help: convert the identifier to snake case: `cookie`
-error: function `bi_S_Cuit` should have a snake case name such as `bi_s_cuit`
- --> $DIR/lint-non-snake-case-functions.rs:41:1
+error: function `bi_S_Cuit` should have a snake case name
+ --> $DIR/lint-non-snake-case-functions.rs:41:8
|
LL | pub fn bi_S_Cuit() {}
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^ help: convert the identifier to snake case: `bi_s_cuit`
error: aborting due to 9 previous errors
#![deny(non_snake_case)]
#![allow(dead_code)]
-fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name such as `'foo_bar`
+fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name
_: &'FooBar ()
) {}
-error: lifetime `'FooBar` should have a snake case name such as `'foo_bar`
+error: lifetime `'FooBar` should have a snake case name
--> $DIR/lint-non-snake-case-lifetimes.rs:4:6
|
-LL | fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name such as `'foo_bar`
- | ^^^^^^^
+LL | fn f<'FooBar>( //~ ERROR lifetime `'FooBar` should have a snake case name
+ | ^^^^^^^ help: convert the identifier to snake case: `'foo_bar`
|
note: lint level defined here
--> $DIR/lint-non-snake-case-lifetimes.rs:1:9
#![deny(non_snake_case)]
#![allow(dead_code)]
-mod FooBar { //~ ERROR module `FooBar` should have a snake case name such as `foo_bar`
+mod FooBar { //~ ERROR module `FooBar` should have a snake case name
pub struct S;
}
-error: module `FooBar` should have a snake case name such as `foo_bar`
- --> $DIR/lint-non-snake-case-modules.rs:4:1
+error: module `FooBar` should have a snake case name
+ --> $DIR/lint-non-snake-case-modules.rs:4:5
|
-LL | / mod FooBar { //~ ERROR module `FooBar` should have a snake case name such as `foo_bar`
-LL | | pub struct S;
-LL | | }
- | |_^
+LL | mod FooBar { //~ ERROR module `FooBar` should have a snake case name
+ | ^^^^^^ help: convert the identifier to snake case: `foo_bar`
|
note: lint level defined here
--> $DIR/lint-non-snake-case-modules.rs:1:9
--- /dev/null
+// compile-pass
+
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+#![feature(non_ascii_idents)]
+#![deny(non_snake_case)]
+
+// This name is neither upper nor lower case
+fn ä½ å¥½() {}
+
+fn main() {}
--- /dev/null
+#![deny(non_upper_case_globals)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+ const not_upper: bool = true;
+}
+//~^^ ERROR associated constant `not_upper` should have an upper case name
+
+fn main() {}
--- /dev/null
+error: associated constant `not_upper` should have an upper case name
+ --> $DIR/lint-non-uppercase-associated-const.rs:7:11
+ |
+LL | const not_upper: bool = true;
+ | ^^^^^^^^^ help: convert the identifier to upper case: `NOT_UPPER`
+ |
+note: lint level defined here
+ --> $DIR/lint-non-uppercase-associated-const.rs:1:9
+ |
+LL | #![deny(non_upper_case_globals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
#![forbid(non_upper_case_globals)]
#![allow(dead_code)]
-static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name such as `FOO`
+static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name
-static mut bar: isize = 1;
- //~^ ERROR static variable `bar` should have an upper case name such as `BAR`
+static mut bar: isize = 1; //~ ERROR static variable `bar` should have an upper case name
#[no_mangle]
pub static extern_foo: isize = 1; // OK, because #[no_mangle] supersedes the warning
-error: static variable `foo` should have an upper case name such as `FOO`
- --> $DIR/lint-non-uppercase-statics.rs:4:1
+error: static variable `foo` should have an upper case name
+ --> $DIR/lint-non-uppercase-statics.rs:4:8
|
-LL | static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name such as `FOO`
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | static foo: isize = 1; //~ ERROR static variable `foo` should have an upper case name
+ | ^^^ help: convert the identifier to upper case: `FOO`
|
note: lint level defined here
--> $DIR/lint-non-uppercase-statics.rs:1:11
LL | #![forbid(non_upper_case_globals)]
| ^^^^^^^^^^^^^^^^^^^^^^
-error: static variable `bar` should have an upper case name such as `BAR`
- --> $DIR/lint-non-uppercase-statics.rs:6:1
+error: static variable `bar` should have an upper case name
+ --> $DIR/lint-non-uppercase-statics.rs:6:12
|
-LL | static mut bar: isize = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static mut bar: isize = 1; //~ ERROR static variable `bar` should have an upper case name
+ | ^^^ help: convert the identifier to upper case: `BAR`
error: aborting due to 2 previous errors
--- /dev/null
+// compile-pass
+
+#![allow(dead_code)]
+
+#![forbid(non_camel_case_types)]
+#![forbid(non_upper_case_globals)]
+#![feature(non_ascii_idents)]
+
+// Some scripts (e.g., hiragana) don't have a concept of
+// upper/lowercase
+
+struct ヒ;
+
+static ラ: usize = 0;
+
+pub fn main() {}
}
struct Something {
- X: usize //~ ERROR structure field `X` should have a snake case name such as `x`
+ X: usize //~ ERROR structure field `X` should have a snake case name
}
-fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name such as `xx`
+fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name
println!("{}", Xx);
}
fn main() {
- let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name such as `test`
+ let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name
println!("{}", Test);
match foo::Foo::Foo {
Foo => {}
-//~^ ERROR variable `Foo` should have a snake case name such as `foo`
+//~^ ERROR variable `Foo` should have a snake case name
//~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo`
//~^^^ WARN unused variable: `Foo`
}
| ^^^^^^
= note: #[warn(unused_variables)] implied by #[warn(unused)]
-error: structure field `X` should have a snake case name such as `x`
+error: structure field `X` should have a snake case name
--> $DIR/lint-uppercase-variables.rs:10:5
|
-LL | X: usize //~ ERROR structure field `X` should have a snake case name such as `x`
- | ^^^^^^^^
+LL | X: usize //~ ERROR structure field `X` should have a snake case name
+ | ^ help: convert the identifier to snake case: `x`
|
note: lint level defined here
--> $DIR/lint-uppercase-variables.rs:3:9
LL | #![deny(non_snake_case)]
| ^^^^^^^^^^^^^^
-error: variable `Xx` should have a snake case name such as `xx`
+error: variable `Xx` should have a snake case name
--> $DIR/lint-uppercase-variables.rs:13:9
|
-LL | fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name such as `xx`
- | ^^
+LL | fn test(Xx: usize) { //~ ERROR variable `Xx` should have a snake case name
+ | ^^ help: convert the identifier to snake case: `xx`
-error: variable `Test` should have a snake case name such as `test`
+error: variable `Test` should have a snake case name
--> $DIR/lint-uppercase-variables.rs:18:9
|
-LL | let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name such as `test`
- | ^^^^
+LL | let Test: usize = 0; //~ ERROR variable `Test` should have a snake case name
+ | ^^^^ help: convert the identifier to snake case: `test`
-error: variable `Foo` should have a snake case name such as `foo`
+error: variable `Foo` should have a snake case name
--> $DIR/lint-uppercase-variables.rs:22:9
|
LL | Foo => {}
- | ^^^
+ | ^^^ help: convert the identifier to snake case: `foo`
error: aborting due to 4 previous errors
LL | #![warn(elided_lifetimes_in_paths,
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: variable `Social_exchange_psychology` should have a snake case name such as `social_exchange_psychology`
+warning: variable `Social_exchange_psychology` should have a snake case name
--> $DIR/reasons.rs:30:9
|
LL | let Social_exchange_psychology = CheaterDetectionMechanism {};
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `social_exchange_psychology`
|
= note: people shouldn't have to change their usual style habits
to contribute to our project
format!(); //~ ERROR requires at least a format string argument
format!(struct); //~ ERROR expected expression
format!("s", name =); //~ ERROR expected expression
+ format!("s", foo = foo, bar); //~ ERROR expected `=`
format!("s", foo = struct); //~ ERROR expected expression
format!("s", struct); //~ ERROR expected expression
LL | format!("s", name =); //~ ERROR expected expression
| ^ expected expression
+error: expected `=`, found `<eof>`
+ --> $DIR/format-parse-errors.rs:5:29
+ |
+LL | format!("s", foo = foo, bar); //~ ERROR expected `=`
+ | ^^^ expected `=`
+
error: expected expression, found keyword `struct`
- --> $DIR/format-parse-errors.rs:5:24
+ --> $DIR/format-parse-errors.rs:6:24
|
LL | format!("s", foo = struct); //~ ERROR expected expression
| ^^^^^^ expected expression
error: expected expression, found keyword `struct`
- --> $DIR/format-parse-errors.rs:6:18
+ --> $DIR/format-parse-errors.rs:7:18
|
LL | format!("s", struct); //~ ERROR expected expression
| ^^^^^^ expected expression
error: format argument must be a string literal
- --> $DIR/format-parse-errors.rs:9:13
+ --> $DIR/format-parse-errors.rs:10:13
|
LL | format!(123); //~ ERROR format argument must be a string literal
| ^^^
LL | format!("{}", 123); //~ ERROR format argument must be a string literal
| ^^^^^
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
+++ /dev/null
-// Issue #7526: lowercase static constants in patterns look like bindings
-
-#![allow(dead_code)]
-#![deny(non_upper_case_globals)]
-
-#[allow(non_upper_case_globals)]
-pub const a : isize = 97;
-
-fn f() {
- let r = match (0,0) {
- (0, a) => 0,
- //~^ ERROR constant in pattern `a` should have an upper case name such as `A`
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 1);
-}
-
-mod m {
- #[allow(non_upper_case_globals)]
- pub const aha : isize = 7;
-}
-
-fn g() {
- use self::m::aha;
- let r = match (0,0) {
- (0, aha) => 0,
- //~^ ERROR constant in pattern `aha` should have an upper case name such as `AHA`
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 1);
-}
-
-mod n {
- pub const OKAY : isize = 8;
-}
-
-fn h() {
- use self::n::OKAY as not_okay;
- let r = match (0,0) {
- (0, not_okay) => 0,
-//~^ ERROR constant in pattern `not_okay` should have an upper case name such as `NOT_OKAY`
- (x, y) => 1 + x + y,
- };
- assert_eq!(r, 1);
-}
-
-fn main () {
- f();
- g();
- h();
-}
+++ /dev/null
-error: constant in pattern `a` should have an upper case name such as `A`
- --> $DIR/match-static-const-lc.rs:11:13
- |
-LL | (0, a) => 0,
- | ^
- |
-note: lint level defined here
- --> $DIR/match-static-const-lc.rs:4:9
- |
-LL | #![deny(non_upper_case_globals)]
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: constant in pattern `aha` should have an upper case name such as `AHA`
- --> $DIR/match-static-const-lc.rs:26:13
- |
-LL | (0, aha) => 0,
- | ^^^
-
-error: constant in pattern `not_okay` should have an upper case name such as `NOT_OKAY`
- --> $DIR/match-static-const-lc.rs:40:13
- |
-LL | (0, not_okay) => 0,
- | ^^^^^^^^
-
-error: aborting due to 3 previous errors
-
error[E0308]: mismatched types
--> $DIR/match-struct.rs:6:9
|
+LL | match (S { a: 1 }) {
+ | ------------ this match expression has type `S`
LL | E::C(_) => (),
| ^^^^^^^ expected struct `S`, found enum `E`
|
--> $DIR/match-tag-unary.rs:4:43
|
LL | fn main() { let x: A = A::A(0); match x { B::B(y) => { } } } //~ ERROR mismatched types
- | ^^^^^^^ expected enum `A`, found enum `B`
+ | - ^^^^^^^ expected enum `A`, found enum `B`
+ | |
+ | this match expression has type `A`
|
= note: expected type `A`
found type `B`
--> $DIR/cast-rfc0401.rs:71:30
|
LL | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>(); //~ ERROR is invalid
- | ^^^^^^^^ cannot cast `&{float}` as `f32`
- |
-help: did you mean `*s`?
- --> $DIR/cast-rfc0401.rs:71:30
- |
-LL | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>(); //~ ERROR is invalid
- | ^
+ | -^^^^^^^
+ | |
+ | cannot cast `&{float}` as `f32`
+ | help: dereference the expression: `*s`
error: aborting due to 34 previous errors
--- /dev/null
+#![allow(unused)]
+#![feature(nll)]
+
+// ignore-tidy-linelength
+
+// This tests the error messages for borrows of union fields when the unions are embedded in other
+// structs or unions.
+
+#[derive(Clone, Copy, Default)]
+struct Leaf {
+ l1_u8: u8,
+ l2_u8: u8,
+}
+
+#[derive(Clone, Copy)]
+union First {
+ f1_leaf: Leaf,
+ f2_leaf: Leaf,
+ f3_union: Second,
+}
+
+#[derive(Clone, Copy)]
+union Second {
+ s1_leaf: Leaf,
+ s2_leaf: Leaf,
+}
+
+struct Root {
+ r1_u8: u8,
+ r2_union: First,
+}
+
+// Borrow a different field of the nested union.
+fn nested_union() {
+ unsafe {
+ let mut r = Root {
+ r1_u8: 3,
+ r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } }
+ };
+
+ let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8;
+ // ^^^^^^^
+ *mref = 22;
+ let nref = &r.r2_union.f3_union.s2_leaf.l1_u8;
+ // ^^^^^^^
+ //~^^ ERROR cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`) [E0502]
+ println!("{} {}", mref, nref)
+ }
+}
+
+// Borrow a different field of the first union.
+fn first_union() {
+ unsafe {
+ let mut r = Root {
+ r1_u8: 3,
+ r2_union: First { f3_union: Second { s2_leaf: Leaf { l1_u8: 8, l2_u8: 4 } } }
+ };
+
+ let mref = &mut r.r2_union.f2_leaf.l1_u8;
+ // ^^^^^^^
+ *mref = 22;
+ let nref = &r.r2_union.f1_leaf.l1_u8;
+ // ^^^^^^^
+ //~^^ ERROR cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`) [E0502]
+ println!("{} {}", mref, nref)
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0502]: cannot borrow `r.r2_union.f3_union` (via `r.r2_union.f3_union.s2_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f3_union.s1_leaf.l1_u8`)
+ --> $DIR/issue-57100.rs:44:20
+ |
+LL | let mref = &mut r.r2_union.f3_union.s1_leaf.l1_u8;
+ | -------------------------------------- mutable borrow occurs here (via `r.r2_union.f3_union.s1_leaf.l1_u8`)
+...
+LL | let nref = &r.r2_union.f3_union.s2_leaf.l1_u8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f3_union.s2_leaf.l1_u8` -- which overlaps with `r.r2_union.f3_union.s1_leaf.l1_u8` -- occurs here
+...
+LL | println!("{} {}", mref, nref)
+ | ---- mutable borrow later used here
+ |
+ = note: `r.r2_union.f3_union.s2_leaf.l1_u8` is a field of the union `Second`, so it overlaps the field `r.r2_union.f3_union.s1_leaf.l1_u8`
+
+error[E0502]: cannot borrow `r.r2_union` (via `r.r2_union.f1_leaf.l1_u8`) as immutable because it is also borrowed as mutable (via `r.r2_union.f2_leaf.l1_u8`)
+ --> $DIR/issue-57100.rs:62:20
+ |
+LL | let mref = &mut r.r2_union.f2_leaf.l1_u8;
+ | ----------------------------- mutable borrow occurs here (via `r.r2_union.f2_leaf.l1_u8`)
+...
+LL | let nref = &r.r2_union.f1_leaf.l1_u8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow of `r.r2_union.f1_leaf.l1_u8` -- which overlaps with `r.r2_union.f2_leaf.l1_u8` -- occurs here
+...
+LL | println!("{} {}", mref, nref)
+ | ---- mutable borrow later used here
+ |
+ = note: `r.r2_union.f1_leaf.l1_u8` is a field of the union `First`, so it overlaps the field `r.r2_union.f2_leaf.l1_u8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0502`.
--- /dev/null
+#![deny(irrefutable_let_patterns)]
+
+fn main() {
+ if let _ = 5 {} //~ ERROR irrefutable if-let pattern
+
+ while let _ = 5 { //~ ERROR irrefutable while-let pattern
+ break;
+ }
+}
--- /dev/null
+error: irrefutable if-let pattern
+ --> $DIR/deny-irrefutable-let-patterns.rs:4:5
+ |
+LL | if let _ = 5 {} //~ ERROR irrefutable if-let pattern
+ | ^^^^^^^^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/deny-irrefutable-let-patterns.rs:1:9
+ |
+LL | #![deny(irrefutable_let_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: irrefutable while-let pattern
+ --> $DIR/deny-irrefutable-let-patterns.rs:6:5
+ |
+LL | / while let _ = 5 { //~ ERROR irrefutable while-let pattern
+LL | | break;
+LL | | }
+ | |_____^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// run-pass
+
+#![feature(type_alias_enum_variants)]
+
+#![allow(irrefutable_let_patterns)]
+
+#[allow(dead_code)]
+enum Enum<T> { TSVariant(T), SVariant { v: T } }
+type Alias<T> = Enum<T>;
+type AliasFixed = Enum<()>;
+
+macro_rules! is_variant {
+ (TSVariant, $expr:expr) => (is_variant!(@check TSVariant, (_), $expr));
+ (SVariant, $expr:expr) => (is_variant!(@check SVariant, { v: _ }, $expr));
+ (@check $variant:ident, $matcher:tt, $expr:expr) => (
+ assert!(if let Enum::$variant::<()> $matcher = $expr { true } else { false },
+ "expr does not have correct type");
+ );
+}
+
+fn main() {
+ // Tuple struct variant
+
+ is_variant!(TSVariant, Enum::TSVariant(()));
+ is_variant!(TSVariant, Enum::TSVariant::<()>(()));
+ is_variant!(TSVariant, Enum::<()>::TSVariant(()));
+
+ is_variant!(TSVariant, Alias::TSVariant(()));
+ is_variant!(TSVariant, Alias::<()>::TSVariant(()));
+
+ is_variant!(TSVariant, AliasFixed::TSVariant(()));
+
+ // Struct variant
+
+ is_variant!(SVariant, Enum::SVariant { v: () });
+ is_variant!(SVariant, Enum::SVariant::<()> { v: () });
+ is_variant!(SVariant, Enum::<()>::SVariant { v: () });
+
+ is_variant!(SVariant, Alias::SVariant { v: () });
+ is_variant!(SVariant, Alias::<()>::SVariant { v: () });
+
+ is_variant!(SVariant, AliasFixed::SVariant { v: () });
+}
--- /dev/null
+// run-pass
+
+#![allow(irrefutable_let_patterns)]
+
+fn main() {
+ if let _ = 5 {}
+
+ while let _ = 5 {
+ break;
+ }
+}
error[E0308]: mismatched types
--> $DIR/pattern-error-continue.rs:22:9
|
+LL | match 'c' {
+ | --- this match expression has type `char`
LL | S { .. } => (),
| ^^^^^^^^ expected char, found struct `S`
|
error[E0308]: mismatched types
--> $DIR/pattern-tyvar.rs:5:18
|
+LL | match t {
+ | - this match expression has type `std::option::Option<std::vec::Vec<isize>>`
LL | Bar::T1(_, Some::<isize>(x)) => { //~ ERROR mismatched types
| ^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found isize
|
#[my_attr] //~ ERROR `my_attr` is ambiguous
#[derive(MyTrait)]
-struct S;
+struct S {
+ // FIXME No ambiguity, attributes in non-macro positions are not resolved properly
+ #[my_attr]
+ field: [u8; {
+ // FIXME No ambiguity, derive helpers are not put into scope for non-attributes
+ use my_attr;
-fn main() {}
+ // FIXME No ambiguity, derive helpers are not put into scope for inner items
+ #[my_attr]
+ struct U;
+
+ mod inner {
+ #[my_attr] //~ ERROR attribute `my_attr` is currently unknown
+ struct V;
+ }
+
+ 0
+ }]
+}
+
+fn main() {
+ let s = S { field: [] };
+}
+error[E0658]: The attribute `my_attr` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+ --> $DIR/derive-helper-shadowing.rs:20:15
+ |
+LL | #[my_attr] //~ ERROR attribute `my_attr` is currently unknown
+ | ^^^^^^^
+ |
+ = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
error[E0659]: `my_attr` is ambiguous (derive helper attribute vs any other name)
--> $DIR/derive-helper-shadowing.rs:6:3
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use `crate::my_attr` to refer to this attribute macro unambiguously
-error: aborting due to previous error
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0659`.
+Some errors occurred: E0658, E0659.
+For more information about an error, try `rustc --explain E0658`.
error[E0308]: if and else have incompatible types
- --> $DIR/region-invariant-static-error-reporting.rs:14:15
+ --> $DIR/region-invariant-static-error-reporting.rs:17:9
|
LL | let bad = if x.is_some() {
- | _______________^
+ | _______________-
LL | | x.unwrap()
+ | | ---------- expected because of this
LL | | } else {
LL | | mk_static()
+ | | ^^^^^^^^^^^ lifetime mismatch
LL | | };
- | |_____^ lifetime mismatch
+ | |_____- if and else have incompatible types
|
= note: expected type `Invariant<'a>`
found type `Invariant<'static>`
#![allow(dead_code)]
#![allow(unused_variables)]
+#![allow(non_snake_case)]
struct S;
+++ /dev/null
-warning: function `want_F` should have a snake case name such as `want_f`
- --> $DIR/regions-fn-subtyping-return-static.rs:18:1
- |
-LL | fn want_F(f: F) { }
- | ^^^^^^^^^^^^^^^^^^^
- |
- = note: #[warn(non_snake_case)] on by default
-
-warning: function `want_G` should have a snake case name such as `want_g`
- --> $DIR/regions-fn-subtyping-return-static.rs:22:1
- |
-LL | fn want_G(f: G) { }
- | ^^^^^^^^^^^^^^^^^^^
-
-warning: function `supply_F` should have a snake case name such as `supply_f`
- --> $DIR/regions-fn-subtyping-return-static.rs:39:1
- |
-LL | / fn supply_F() {
-LL | | want_F(foo);
-LL | |
-LL | | want_F(bar);
-LL | |
-LL | | want_F(baz);
-LL | | }
- | |_^
-
| ^^^^
|
= note: ...which again requires processing `<impl at $DIR/issue-23305.rs:5:1: 5:20>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/issue-23305.rs:1:1
+ |
+LL | pub trait ToNbt<T> {
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
--- /dev/null
+// compile-pass
+
+struct S(u8);
+
+impl S {
+ fn method1() -> Self {
+ Self(0)
+ }
+}
+
+macro_rules! define_method { () => {
+ impl S {
+ fn method2() -> Self {
+ Self(0) // OK
+ }
+ }
+}}
+
+define_method!();
+
+fn main() {}
| ^^^^
|
= note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/resolve-self-in-impl.rs:1:1
+ |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>`
--> $DIR/resolve-self-in-impl.rs:15:15
| ^^^^
|
= note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/resolve-self-in-impl.rs:1:1
+ |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>`
--> $DIR/resolve-self-in-impl.rs:16:6
| ^^^^
|
= note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/resolve-self-in-impl.rs:1:1
+ |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>`
--> $DIR/resolve-self-in-impl.rs:17:8
| ^^^^
|
= note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/resolve-self-in-impl.rs:1:1
+ |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
error[E0391]: cycle detected when processing `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>`
--> $DIR/resolve-self-in-impl.rs:18:1
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: ...which again requires processing `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/resolve-self-in-impl.rs:1:1
+ |
+LL | / #![feature(associated_type_defaults)]
+LL | |
+LL | | struct S<T = u8>(T);
+LL | | trait Tr<T = u8> {
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
error: aborting due to 5 previous errors
// edition:2018
-#![feature(uniform_paths)]
-
// Tests that arbitrary crates (other than `core`, `std` and `meta`)
// aren't allowed without `--extern`, even if they're in the sysroot.
use alloc; //~ ERROR unresolved import `alloc`
error: cannot import a built-in macro
- --> $DIR/not-whitelisted.rs:8:5
+ --> $DIR/not-whitelisted.rs:6:5
|
LL | use test; //~ ERROR cannot import a built-in macro
| ^^^^
error[E0432]: unresolved import `alloc`
- --> $DIR/not-whitelisted.rs:7:5
+ --> $DIR/not-whitelisted.rs:5:5
|
LL | use alloc; //~ ERROR unresolved import `alloc`
| ^^^^^ no `alloc` external crate
// Enabling `ireffutable_let_patterns` isn't necessary for what this tests, but it makes coming up
// with examples easier.
-#![feature(irrefutable_let_patterns)]
#[allow(irrefutable_let_patterns)]
fn main() {
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2015.rs:11:47
+ --> $DIR/syntax-ambiguity-2015.rs:10:47
|
LL | if let Range { start: _, end: _ } = true..true && false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `||`
- --> $DIR/syntax-ambiguity-2015.rs:14:47
+ --> $DIR/syntax-ambiguity-2015.rs:13:47
|
LL | if let Range { start: _, end: _ } = true..true || false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2015.rs:17:50
+ --> $DIR/syntax-ambiguity-2015.rs:16:50
|
LL | while let Range { start: _, end: _ } = true..true && false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `||`
- --> $DIR/syntax-ambiguity-2015.rs:20:50
+ --> $DIR/syntax-ambiguity-2015.rs:19:50
|
LL | while let Range { start: _, end: _ } = true..true || false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2015.rs:23:19
+ --> $DIR/syntax-ambiguity-2015.rs:22:19
|
LL | if let true = false && false { }
| ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2015.rs:26:22
+ --> $DIR/syntax-ambiguity-2015.rs:25:22
|
LL | while let true = (1 == 2) && false { }
| ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
// Enabling `ireffutable_let_patterns` isn't necessary for what this tests, but it makes coming up
// with examples easier.
-#![feature(irrefutable_let_patterns)]
#[allow(irrefutable_let_patterns)]
fn main() {
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2018.rs:11:47
+ --> $DIR/syntax-ambiguity-2018.rs:10:47
|
LL | if let Range { start: _, end: _ } = true..true && false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `||`
- --> $DIR/syntax-ambiguity-2018.rs:14:47
+ --> $DIR/syntax-ambiguity-2018.rs:13:47
|
LL | if let Range { start: _, end: _ } = true..true || false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2018.rs:17:50
+ --> $DIR/syntax-ambiguity-2018.rs:16:50
|
LL | while let Range { start: _, end: _ } = true..true && false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true && false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `||`
- --> $DIR/syntax-ambiguity-2018.rs:20:50
+ --> $DIR/syntax-ambiguity-2018.rs:19:50
|
LL | while let Range { start: _, end: _ } = true..true || false { }
| ^^^^^^^^^^^^^ help: consider adding parentheses: `(true || false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2018.rs:23:19
+ --> $DIR/syntax-ambiguity-2018.rs:22:19
|
LL | if let true = false && false { }
| ^^^^^^^^^^^^^^ help: consider adding parentheses: `(false && false)`
= note: see rust-lang/rust#53668 for more information
error: ambiguous use of `&&`
- --> $DIR/syntax-ambiguity-2018.rs:26:22
+ --> $DIR/syntax-ambiguity-2018.rs:25:22
|
LL | while let true = (1 == 2) && false { }
| ^^^^^^^^^^^^^^^^^ help: consider adding parentheses: `((1 == 2) && false)`
// Full example of enumerate iterator
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
+#[must_use = "iterators are lazy and do nothing unless consumed"]
struct StreamEnumerate<I> {
iter: I,
count: usize,
// edition:2018
-#![feature(uniform_paths)]
#![allow(non_camel_case_types)]
mod T {
}
fn self_import<T>() {
- use T; // FIXME Should be an error, but future-proofing fails due to `T` being "self-shadowed"
+ use T; //~ ERROR imports cannot refer to type parameters
}
fn let_binding() {
error: imports cannot refer to type parameters
- --> $DIR/future-proofing-locals.rs:14:9
+ --> $DIR/future-proofing-locals.rs:13:9
|
LL | use T as _; //~ ERROR imports cannot refer to type parameters
| ^
error: imports cannot refer to type parameters
- --> $DIR/future-proofing-locals.rs:15:9
+ --> $DIR/future-proofing-locals.rs:14:9
|
LL | use T::U; //~ ERROR imports cannot refer to type parameters
| ^
error: imports cannot refer to type parameters
- --> $DIR/future-proofing-locals.rs:16:9
+ --> $DIR/future-proofing-locals.rs:15:9
|
LL | use T::*; //~ ERROR imports cannot refer to type parameters
| ^
+error: imports cannot refer to type parameters
+ --> $DIR/future-proofing-locals.rs:19:9
+ |
+LL | use T; //~ ERROR imports cannot refer to type parameters
+ | ^
+
error: imports cannot refer to local variables
- --> $DIR/future-proofing-locals.rs:26:9
+ --> $DIR/future-proofing-locals.rs:25:9
|
LL | use x as _; //~ ERROR imports cannot refer to local variables
| ^
error: imports cannot refer to local variables
- --> $DIR/future-proofing-locals.rs:32:9
+ --> $DIR/future-proofing-locals.rs:31:9
|
LL | use x; //~ ERROR imports cannot refer to local variables
| ^
error: imports cannot refer to local variables
- --> $DIR/future-proofing-locals.rs:38:17
+ --> $DIR/future-proofing-locals.rs:37:17
|
LL | use x; //~ ERROR imports cannot refer to local variables
| ^
error: imports cannot refer to type parameters
- --> $DIR/future-proofing-locals.rs:46:10
+ --> $DIR/future-proofing-locals.rs:45:10
|
LL | use {T as _, x}; //~ ERROR imports cannot refer to type parameters
| ^
error: imports cannot refer to local variables
- --> $DIR/future-proofing-locals.rs:46:18
+ --> $DIR/future-proofing-locals.rs:45:18
|
LL | use {T as _, x}; //~ ERROR imports cannot refer to type parameters
| ^
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
// compile-flags:--extern baz
// edition:2018
-#![feature(uniform_paths)]
-
mod foo {
pub type Bar = u32;
}
error[E0432]: unresolved import `foo`
- --> $DIR/local-path-suggestions-2018.rs:12:9
+ --> $DIR/local-path-suggestions-2018.rs:10:9
|
LL | use foo::Bar; //~ ERROR unresolved import `foo`
| ^^^ did you mean `crate::foo`?
= note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
error[E0432]: unresolved import `foobar`
- --> $DIR/local-path-suggestions-2018.rs:21:5
+ --> $DIR/local-path-suggestions-2018.rs:19:5
|
LL | use foobar::Baz; //~ ERROR unresolved import `foobar`
| ^^^^^^ did you mean `baz::foobar`?
// edition:2018
-#![feature(uniform_paths)]
-
mod my {
pub mod sub {
pub fn bar() {}
error[E0659]: `sub` is ambiguous (name vs any other name during import resolution)
- --> $DIR/block-scoped-shadow-nested.rs:18:13
+ --> $DIR/block-scoped-shadow-nested.rs:16:13
|
LL | use sub::bar; //~ ERROR `sub` is ambiguous
| ^^^ ambiguous name
|
note: `sub` could refer to the module imported here
- --> $DIR/block-scoped-shadow-nested.rs:16:9
+ --> $DIR/block-scoped-shadow-nested.rs:14:9
|
LL | use my::sub;
| ^^^^^^^
note: `sub` could also refer to the module defined here
- --> $DIR/block-scoped-shadow-nested.rs:11:1
+ --> $DIR/block-scoped-shadow-nested.rs:9:1
|
LL | / mod sub {
LL | | pub fn bar() {}
// compile-pass
// edition:2018
-#![feature(uniform_paths)]
-
fn main() {
enum E { A, B, C }
+++ /dev/null
-// edition:2018
-
-#![deny(unused)]
-
-use std::fmt;
-
-// No "unresolved import" + "unused import" combination here.
-use fmt::Write; //~ ERROR imports can only refer to extern crate names
- //~| ERROR unused import: `fmt::Write`
-
-fn main() {}
+++ /dev/null
-error[E0658]: imports can only refer to extern crate names passed with `--extern` on stable channel (see issue #53130)
- --> $DIR/issue-54390.rs:8:5
- |
-LL | use std::fmt;
- | -------- not an extern crate passed with `--extern`
-...
-LL | use fmt::Write; //~ ERROR imports can only refer to extern crate names
- | ^^^
- |
- = help: add #![feature(uniform_paths)] to the crate attributes to enable
-note: this import refers to the module imported here
- --> $DIR/issue-54390.rs:5:5
- |
-LL | use std::fmt;
- | ^^^^^^^^
-
-error: unused import: `fmt::Write`
- --> $DIR/issue-54390.rs:8:5
- |
-LL | use fmt::Write; //~ ERROR imports can only refer to extern crate names
- | ^^^^^^^^^^
- |
-note: lint level defined here
- --> $DIR/issue-54390.rs:3:9
- |
-LL | #![deny(unused)]
- | ^^^^^^
- = note: #[deny(unused_imports)] implied by #[deny(unused)]
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
// edition:2018
-// For the time being `macro_rules` items are treated as *very* private...
-
-#![feature(decl_macro, uniform_paths)]
-#![allow(non_camel_case_types)]
+#![feature(decl_macro)]
mod m1 {
+ // Non-exported legacy macros are treated as `pub(crate)`.
macro_rules! legacy_macro { () => () }
- // ... so they can't be imported by themselves, ...
- use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
+ use legacy_macro as _; // OK
+ pub(crate) use legacy_macro as _; // OK
+ pub use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
}
mod m2 {
macro_rules! legacy_macro { () => () }
+ #[allow(non_camel_case_types)]
type legacy_macro = u8;
- // ... but don't prevent names from other namespaces from being imported, ...
+ // Legacy macro imports don't prevent names from other namespaces from being imported.
use legacy_macro as _; // OK
}
fn f() {
macro_rules! legacy_macro { () => () }
- // ... but still create ambiguities with other names in the same namespace.
+ // Legacy macro imports create ambiguities with other names in the same namespace.
use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
- //~| ERROR `legacy_macro` is private, and cannot be re-exported
}
}
mod exported {
- // Exported macros are treated as private as well,
- // some better rules need to be figured out later.
+ // Exported legacy macros are treated as `pub`.
#[macro_export]
macro_rules! legacy_macro { () => () }
- use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
+ pub use legacy_macro as _; // OK
}
fn main() {}
error[E0364]: `legacy_macro` is private, and cannot be re-exported
- --> $DIR/macro-rules.rs:12:9
+ --> $DIR/macro-rules.rs:11:13
|
-LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
- | ^^^^^^^^^^^^^^^^^
- |
-note: consider marking `legacy_macro` as `pub` in the imported module
- --> $DIR/macro-rules.rs:12:9
- |
-LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
- | ^^^^^^^^^^^^^^^^^
-
-error[E0364]: `legacy_macro` is private, and cannot be re-exported
- --> $DIR/macro-rules.rs:31:13
- |
-LL | use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
+LL | pub use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
| ^^^^^^^^^^^^^^^^^
|
note: consider marking `legacy_macro` as `pub` in the imported module
- --> $DIR/macro-rules.rs:31:13
+ --> $DIR/macro-rules.rs:11:13
|
-LL | use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
+LL | pub use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
| ^^^^^^^^^^^^^^^^^
-error[E0364]: `legacy_macro` is private, and cannot be re-exported
- --> $DIR/macro-rules.rs:42:9
- |
-LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
- | ^^^^^^^^^^^^^^^^^
- |
-note: consider marking `legacy_macro` as `pub` in the imported module
- --> $DIR/macro-rules.rs:42:9
- |
-LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
- | ^^^^^^^^^^^^^^^^^
-
error[E0659]: `legacy_macro` is ambiguous (name vs any other name during import resolution)
--> $DIR/macro-rules.rs:31:13
|
| ^^^^^^^^^^^^^^^^^^^^^^^
= help: use `self::legacy_macro` to refer to this macro unambiguously
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
Some errors occurred: E0364, E0659.
For more information about an error, try `rustc --explain E0364`.
--- /dev/null
+// edition:2018
+
+// Built-in attribute
+use inline as imported_inline;
+mod builtin {
+ pub use inline as imported_inline;
+}
+
+// Tool module
+use rustfmt as imported_rustfmt;
+mod tool_mod {
+ pub use rustfmt as imported_rustfmt;
+}
+
+#[imported_inline] //~ ERROR cannot use a built-in attribute through an import
+#[builtin::imported_inline] //~ ERROR cannot use a built-in attribute through an import
+#[imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+#[tool_mod::imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+fn main() {}
--- /dev/null
+error: cannot use a built-in attribute through an import
+ --> $DIR/prelude-fail-2.rs:15:3
+ |
+LL | #[imported_inline] //~ ERROR cannot use a built-in attribute through an import
+ | ^^^^^^^^^^^^^^^
+ |
+note: the built-in attribute imported here
+ --> $DIR/prelude-fail-2.rs:4:5
+ |
+LL | use inline as imported_inline;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a built-in attribute through an import
+ --> $DIR/prelude-fail-2.rs:16:3
+ |
+LL | #[builtin::imported_inline] //~ ERROR cannot use a built-in attribute through an import
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+ --> $DIR/prelude-fail-2.rs:17:3
+ |
+LL | #[imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the tool module imported here
+ --> $DIR/prelude-fail-2.rs:10:5
+ |
+LL | use rustfmt as imported_rustfmt;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot use a tool module through an import
+ --> $DIR/prelude-fail-2.rs:18:13
+ |
+LL | #[tool_mod::imported_rustfmt::skip] //~ ERROR cannot use a tool module through an import
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the tool module imported here
+ --> $DIR/prelude-fail-2.rs:12:13
+ |
+LL | pub use rustfmt as imported_rustfmt;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
// edition:2018
-#![feature(uniform_paths)]
-
// Built-in macro
use env as env_imported; //~ ERROR cannot import a built-in macro
error: cannot import a built-in macro
- --> $DIR/prelude-fail.rs:6:5
+ --> $DIR/prelude-fail.rs:4:5
|
LL | use env as env_imported; //~ ERROR cannot import a built-in macro
| ^^^^^^^^^^^^^^^^^^^
error[E0432]: unresolved import `rustfmt`
- --> $DIR/prelude-fail.rs:9:5
+ --> $DIR/prelude-fail.rs:7:5
|
LL | use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt`
| ^^^^^^^ not a module `rustfmt`
// compile-pass
// edition:2018
-#![feature(uniform_paths)]
-
// Macro imported with `#[macro_use] extern crate`
use vec as imported_vec;
-// Built-in attribute
-use inline as imported_inline;
-
-// Tool module
-use rustfmt as imported_rustfmt;
-
// Standard library prelude
use Vec as ImportedVec;
type A = imported_u8;
-#[imported_inline]
-#[imported_rustfmt::skip]
fn main() {
imported_vec![0];
ImportedVec::<u8>::new();
+++ /dev/null
-// should-fail-irrefutable_let_patterns
-fn main() {
- if let _ = 5 {}
- //~^ ERROR irrefutable if-let pattern [E0162]
-}
+++ /dev/null
-error[E0162]: irrefutable if-let pattern
- --> $DIR/should-fail-no_gate_irrefutable_if_let_pattern.rs:3:12
- |
-LL | if let _ = 5 {}
- | ^ irrefutable pattern
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0162`.
+++ /dev/null
-#![feature(irrefutable_let_patterns)]
-
-// should-fail-irrefutable_let_patterns_with_gate
-fn main() {
- if let _ = 5 {}
- //~^ ERROR irrefutable if-let pattern [irrefutable_let_patterns]
-}
+++ /dev/null
-error: irrefutable if-let pattern
- --> $DIR/should-fail-with_gate_irrefutable_pattern_deny.rs:5:5
- |
-LL | if let _ = 5 {}
- | ^^^^^^^^^^^^^^^
- |
- = note: #[deny(irrefutable_let_patterns)] on by default
-
-error: aborting due to previous error
-
-error[E0442]: intrinsic argument 1 has wrong type: found `u16`, expected `i16`
- --> $DIR/simd-intrinsic-declaration-type.rs:33:9
- |
-LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0442]: intrinsic argument 2 has wrong type: found `u16`, expected `i16`
- --> $DIR/simd-intrinsic-declaration-type.rs:33:9
- |
-LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0442]: intrinsic return value has wrong type: found `u16`, expected `i16`
- --> $DIR/simd-intrinsic-declaration-type.rs:33:9
- |
-LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0442]: intrinsic argument 1 has wrong type: found `i16`, expected `u16`
- --> $DIR/simd-intrinsic-declaration-type.rs:37:9
- |
-LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0442]: intrinsic argument 2 has wrong type: found `i16`, expected `u16`
- --> $DIR/simd-intrinsic-declaration-type.rs:37:9
- |
-LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0442]: intrinsic return value has wrong type: found `i16`, expected `u16`
- --> $DIR/simd-intrinsic-declaration-type.rs:37:9
- |
-LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
error[E0442]: intrinsic argument 1 has wrong type: found vector with length 16, expected length 8
--> $DIR/simd-intrinsic-declaration-type.rs:45:5
|
LL | fn x86_mm_max_ps(x: i32x4, y: i32x4) -> i32x4;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+error[E0442]: intrinsic argument 1 has wrong type: found `u16`, expected `i16`
+ --> $DIR/simd-intrinsic-declaration-type.rs:33:9
+ |
+LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0442]: intrinsic argument 2 has wrong type: found `u16`, expected `i16`
+ --> $DIR/simd-intrinsic-declaration-type.rs:33:9
+ |
+LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0442]: intrinsic return value has wrong type: found `u16`, expected `i16`
+ --> $DIR/simd-intrinsic-declaration-type.rs:33:9
+ |
+LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0442]: intrinsic argument 1 has wrong type: found `i16`, expected `u16`
+ --> $DIR/simd-intrinsic-declaration-type.rs:37:9
+ |
+LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0442]: intrinsic argument 2 has wrong type: found `i16`, expected `u16`
+ --> $DIR/simd-intrinsic-declaration-type.rs:37:9
+ |
+LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0442]: intrinsic return value has wrong type: found `i16`, expected `u16`
+ --> $DIR/simd-intrinsic-declaration-type.rs:37:9
+ |
+LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0442`.
| ^^^^^^
= note: #[warn(unused_variables)] implied by #[warn(unused)]
-warning: variable `theTwo` should have a snake case name such as `the_two`
+warning: variable `theTwo` should have a snake case name
--> $DIR/issue-24690.rs:12:9
|
LL | let theTwo = 2; //~ WARN should have a snake case name
- | ^^^^^^
+ | ^^^^^^ help: convert the identifier to snake case: `the_two`
|
= note: #[warn(non_snake_case)] on by default
-warning: variable `theOtherTwo` should have a snake case name such as `the_other_two`
+warning: variable `theOtherTwo` should have a snake case name
--> $DIR/issue-24690.rs:13:9
|
LL | let theOtherTwo = 2; //~ WARN should have a snake case name
- | ^^^^^^^^^^^
+ | ^^^^^^^^^^^ help: convert the identifier to snake case: `the_other_two`
static mut a: Box<isize> = box 3;
//~^ ERROR allocations are not allowed in statics
+//~| ERROR static contains unimplemented expression type
fn main() {}
LL | static mut a: Box<isize> = box 3;
| ^^^^^ allocation not allowed in statics
-error: aborting due to previous error
+error[E0019]: static contains unimplemented expression type
+ --> $DIR/static-mut-not-constant.rs:3:32
+ |
+LL | static mut a: Box<isize> = box 3;
+ | ^
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0010`.
+Some errors occurred: E0010, E0019.
+For more information about an error, try `rustc --explain E0010`.
error[E0308]: if and else have incompatible types
- --> $DIR/str-array-assignment.rs:3:11
+ --> $DIR/str-array-assignment.rs:3:37
|
LL | let t = if true { s[..2] } else { s };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found &str
+ | ------ ^ expected str, found &str
+ | |
+ | expected because of this
|
= note: expected type `str`
found type `&str`
error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:54:9
|
+LL | match (Point { x: 1, y: 2 }) {
+ | ---------------------- this match expression has type `Point<{integer}>`
LL | PointF::<u32> { .. } => {} //~ ERROR wrong number of type arguments
| ^^^^^^^^^^^^^^^^^^^^ expected integer, found f32
|
error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:59:9
|
+LL | match (Point { x: 1, y: 2 }) {
+ | ---------------------- this match expression has type `Point<{integer}>`
LL | PointF { .. } => {} //~ ERROR mismatched types
| ^^^^^^^^^^^^^ expected integer, found f32
|
error[E0308]: mismatched types
--> $DIR/structure-constructor-type-mismatch.rs:67:9
|
+LL | match (Pair { x: 1, y: 2 }) {
+ | --------------------- this match expression has type `Pair<{integer}, {integer}>`
LL | PairF::<u32> { .. } => {} //~ ERROR mismatched types
| ^^^^^^^^^^^^^^^^^^^ expected integer, found f32
|
LL | impl DefaultedTrait for (A,) { } //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
LL | impl !DefaultedTrait for (B,) { } //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error[E0321]: cross-crate traits with a default impl, like `lib::DefaultedTrait`, can only be implemented for a struct/enum type defined in the current crate
LL | impl DefaultedTrait for lib::Something<C> { } //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
- = note: the impl does not reference any types defined in this crate
+ = note: the impl does not reference only types defined in this crate
= note: define and implement a trait or new type instead
error: aborting due to 4 previous errors
// compile-pass
-#![feature(const_let)]
#![feature(underscore_const_names)]
trait Trt {}
-error[E0502]: cannot borrow `u.y` as immutable because it is also borrowed as mutable
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0`)
--> $DIR/union-borrow-move-parent-sibling.rs:15:13
|
LL | let a = &mut u.x.0;
- | ---------- mutable borrow occurs here
+ | ---------- mutable borrow occurs here (via `u.x.0`)
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
- | ^^^^ immutable borrow occurs here
+ | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0` -- occurs here
LL | use_borrow(a);
| - mutable borrow later used here
+ |
+ = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:22:13
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
-error[E0502]: cannot borrow `u.y` as immutable because it is also borrowed as mutable
+error[E0502]: cannot borrow `u` (via `u.y`) as immutable because it is also borrowed as mutable (via `u.x.0.0`)
--> $DIR/union-borrow-move-parent-sibling.rs:28:13
|
LL | let a = &mut (u.x.0).0;
- | -------------- mutable borrow occurs here
+ | -------------- mutable borrow occurs here (via `u.x.0.0`)
LL | let b = &u.y; //~ ERROR cannot borrow `u.y`
- | ^^^^ immutable borrow occurs here
+ | ^^^^ immutable borrow of `u.y` -- which overlaps with `u.x.0.0` -- occurs here
LL | use_borrow(a);
| - mutable borrow later used here
+ |
+ = note: `u.y` is a field of the union `U`, so it overlaps the field `u.x.0.0`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:35:13
|
= note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
-error[E0502]: cannot borrow `u.x` as immutable because it is also borrowed as mutable
+error[E0502]: cannot borrow `u` (via `u.x`) as immutable because it is also borrowed as mutable (via `*u.y`)
--> $DIR/union-borrow-move-parent-sibling.rs:41:13
|
LL | let a = &mut *u.y;
- | --------- mutable borrow occurs here
+ | --------- mutable borrow occurs here (via `*u.y`)
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
- | ^^^^ immutable borrow occurs here
+ | ^^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here
LL | use_borrow(a);
| - mutable borrow later used here
+ |
+ = note: `u.x` is a field of the union `U`, so it overlaps the field `*u.y`
error[E0382]: use of moved value: `u`
--> $DIR/union-borrow-move-parent-sibling.rs:48:13
LL | let a = &mut *u.y;
| ---- mutable borrow occurs here (via `*u.y`)
LL | let b = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
- | ^^^ immutable borrow occurs here (via `u.x`)
+ | ^^^ immutable borrow of `u.x` -- which overlaps with `*u.y` -- occurs here
LL | use_borrow(a);
LL | }
| - mutable borrow ends here
-#![feature(rustc_attrs, const_let, const_fn)]
+#![feature(rustc_attrs)]
#[rustc_layout_scalar_valid_range_start(1)]
#[repr(transparent)]
const fn foo() -> NonZero<u32> {
let mut x = unsafe { NonZero(1) };
- let y = &mut x.0; //~ ERROR references in constant functions may only refer to immutable
+ let y = &mut x.0; //~ ERROR references in const fn are unstable
//~^ ERROR mutation of layout constrained field is unsafe
unsafe { NonZero(1) }
}
const fn bar() -> NonZero<u32> {
let mut x = unsafe { NonZero(1) };
- let y = unsafe { &mut x.0 }; //~ ERROR references in constant functions may only refer to immut
+ let y = unsafe { &mut x.0 }; //~ ERROR mutable references in const fn are unstable
unsafe { NonZero(1) }
}
-error[E0017]: references in constant functions may only refer to immutable values
- --> $DIR/ranged_ints2_const.rs:11:13
+error: mutable references in const fn are unstable
+ --> $DIR/ranged_ints2_const.rs:11:9
|
-LL | let y = &mut x.0; //~ ERROR references in constant functions may only refer to immutable
- | ^^^^^^^^ constant functions require immutable values
+LL | let y = &mut x.0; //~ ERROR references in const fn are unstable
+ | ^
-error[E0017]: references in constant functions may only refer to immutable values
- --> $DIR/ranged_ints2_const.rs:18:22
+error: mutable references in const fn are unstable
+ --> $DIR/ranged_ints2_const.rs:18:9
|
-LL | let y = unsafe { &mut x.0 }; //~ ERROR references in constant functions may only refer to immut
- | ^^^^^^^^ constant functions require immutable values
+LL | let y = unsafe { &mut x.0 }; //~ ERROR mutable references in const fn are unstable
+ | ^
error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
--> $DIR/ranged_ints2_const.rs:11:13
|
-LL | let y = &mut x.0; //~ ERROR references in constant functions may only refer to immutable
+LL | let y = &mut x.0; //~ ERROR references in const fn are unstable
| ^^^^^^^^ mutation of layout constrained field
|
= note: mutating layout constrained fields cannot statically be checked for valid values
error: aborting due to 3 previous errors
-Some errors occurred: E0017, E0133.
-For more information about an error, try `rustc --explain E0017`.
+For more information about this error, try `rustc --explain E0133`.
-#![feature(rustc_attrs, const_let, const_fn)]
+#![feature(rustc_attrs)]
use std::cell::Cell;
-#![feature(rustc_attrs, const_let, const_fn)]
+#![feature(rustc_attrs)]
#[rustc_layout_scalar_valid_range_start(1)]
#[repr(transparent)]
fn foo<
'β, //~ ERROR non-ascii idents are not fully supported
γ //~ ERROR non-ascii idents are not fully supported
- //~^ WARN type parameter `γ` should have a camel case name such as `Γ`
+ //~^ WARN type parameter `γ` should have a camel case name
>() {}
struct X {
|
= help: add #![feature(non_ascii_idents)] to the crate attributes to enable
-warning: type parameter `γ` should have a camel case name such as `Γ`
+warning: type parameter `γ` should have a camel case name
--> $DIR/utf8_idents.rs:5:5
|
LL | γ //~ ERROR non-ascii idents are not fully supported
- | ^
+ | ^ help: convert the identifier to camel case: `Γ`
|
= note: #[warn(non_camel_case_types)] on by default
-error: equality constraints are not yet supported in where clauses (#20041)
+error: equality constraints are not yet supported in where clauses (see #20041)
--> $DIR/where-equality-constraints.rs:1:14
|
LL | fn f() where u8 = u16 {}
| ^^^^^^^^
-error: equality constraints are not yet supported in where clauses (#20041)
+error: equality constraints are not yet supported in where clauses (see #20041)
--> $DIR/where-equality-constraints.rs:3:14
|
LL | fn g() where for<'a> &'static (u8,) == u16, {}
+// run-pass
+
fn macros() {
macro_rules! foo{
($p:pat, $e:expr, $b:block) => {{
}}
}
- foo!(a, 1, { //~ ERROR irrefutable while-let
+ foo!(a, 1, { //~ WARN irrefutable while-let
println!("irrefutable pattern");
});
- bar!(a, 1, { //~ ERROR irrefutable while-let
+ bar!(a, 1, { //~ WARN irrefutable while-let
println!("irrefutable pattern");
});
}
pub fn main() {
- while let a = 1 { //~ ERROR irrefutable while-let
+ while let a = 1 { //~ WARN irrefutable while-let
println!("irrefutable pattern");
+ break;
}
}
-error[E0165]: irrefutable while-let pattern
- --> $DIR/while-let.rs:13:10
+warning: irrefutable while-let pattern
+ --> $DIR/while-let.rs:6:13
|
-LL | foo!(a, 1, { //~ ERROR irrefutable while-let
- | ^ irrefutable pattern
-
-error[E0165]: irrefutable while-let pattern
- --> $DIR/while-let.rs:16:10
+LL | while let $p = $e $b
+ | ^^^^^
+...
+LL | / foo!(a, 1, { //~ WARN irrefutable while-let
+LL | | println!("irrefutable pattern");
+LL | | });
+ | |_______- in this macro invocation
|
-LL | bar!(a, 1, { //~ ERROR irrefutable while-let
- | ^ irrefutable pattern
+ = note: #[warn(irrefutable_let_patterns)] on by default
-error[E0165]: irrefutable while-let pattern
- --> $DIR/while-let.rs:22:15
+warning: irrefutable while-let pattern
+ --> $DIR/while-let.rs:6:13
|
-LL | while let a = 1 { //~ ERROR irrefutable while-let
- | ^ irrefutable pattern
+LL | while let $p = $e $b
+ | ^^^^^
+...
+LL | / bar!(a, 1, { //~ WARN irrefutable while-let
+LL | | println!("irrefutable pattern");
+LL | | });
+ | |_______- in this macro invocation
-error: aborting due to 3 previous errors
+warning: irrefutable while-let pattern
+ --> $DIR/while-let.rs:24:5
+ |
+LL | / while let a = 1 { //~ WARN irrefutable while-let
+LL | | println!("irrefutable pattern");
+LL | | break;
+LL | | }
+ | |_____^
-For more information about this error, try `rustc --explain E0165`.
-#![feature(const_let)]
-
pub static mut A: u32 = 0;
pub static mut B: () = unsafe { A = 1; };
//~^ ERROR could not evaluate static initializer
error[E0080]: could not evaluate static initializer
- --> $DIR/write-to-static-mut-in-static.rs:4:33
+ --> $DIR/write-to-static-mut-in-static.rs:2:33
|
LL | pub static mut B: () = unsafe { A = 1; };
| ^^^^^ tried to modify a static's initial value from another static's initializer
error[E0391]: cycle detected when const-evaluating `C`
- --> $DIR/write-to-static-mut-in-static.rs:7:34
+ --> $DIR/write-to-static-mut-in-static.rs:5:34
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^
|
note: ...which requires const-evaluating `C`...
- --> $DIR/write-to-static-mut-in-static.rs:7:1
+ --> $DIR/write-to-static-mut-in-static.rs:5:1
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires const-evaluating `C`, completing the cycle
note: cycle used when const-evaluating + checking `C`
- --> $DIR/write-to-static-mut-in-static.rs:7:1
+ --> $DIR/write-to-static-mut-in-static.rs:5:1
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"thumbv7em-none-eabi",
"thumbv7em-none-eabihf",
"thumbv7m-none-eabi",
+ "thumbv8m.main-none-eabi",
"wasm32-unknown-emscripten",
"wasm32-unknown-unknown",
"x86_64-apple-darwin",
manifest_version: String,
date: String,
pkg: BTreeMap<String, Package>,
- renames: BTreeMap<String, Rename>
+ renames: BTreeMap<String, Rename>,
+ profiles: BTreeMap<String, Vec<String>>,
}
#[derive(Serialize)]
rustfmt_release: String,
llvm_tools_release: String,
lldb_release: String,
+ miri_release: String,
input: PathBuf,
output: PathBuf,
rustfmt_version: Option<String>,
llvm_tools_version: Option<String>,
lldb_version: Option<String>,
+ miri_version: Option<String>,
rust_git_commit_hash: Option<String>,
cargo_git_commit_hash: Option<String>,
rustfmt_git_commit_hash: Option<String>,
llvm_tools_git_commit_hash: Option<String>,
lldb_git_commit_hash: Option<String>,
+ miri_git_commit_hash: Option<String>,
should_sign: bool,
}
let output = PathBuf::from(args.next().unwrap());
let date = args.next().unwrap();
let rust_release = args.next().unwrap();
+ let s3_address = args.next().unwrap();
let cargo_release = args.next().unwrap();
let rls_release = args.next().unwrap();
let clippy_release = args.next().unwrap();
+ let miri_release = args.next().unwrap();
let rustfmt_release = args.next().unwrap();
let llvm_tools_release = args.next().unwrap();
let lldb_release = args.next().unwrap();
- let s3_address = args.next().unwrap();
// Do not ask for a passphrase while manually testing
let mut passphrase = String::new();
rustfmt_release,
llvm_tools_release,
lldb_release,
+ miri_release,
input,
output,
rustfmt_version: None,
llvm_tools_version: None,
lldb_version: None,
+ miri_version: None,
rust_git_commit_hash: None,
cargo_git_commit_hash: None,
rustfmt_git_commit_hash: None,
llvm_tools_git_commit_hash: None,
lldb_git_commit_hash: None,
+ miri_git_commit_hash: None,
should_sign,
}.build();
self.llvm_tools_version = self.version("llvm-tools", "x86_64-unknown-linux-gnu");
// lldb is only built for macOS.
self.lldb_version = self.version("lldb", "x86_64-apple-darwin");
+ self.miri_version = self.version("miri", "x86_64-unknown-linux-gnu");
self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu");
self.cargo_git_commit_hash = self.git_commit_hash("cargo", "x86_64-unknown-linux-gnu");
self.llvm_tools_git_commit_hash = self.git_commit_hash("llvm-tools",
"x86_64-unknown-linux-gnu");
self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu");
+ self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu");
self.digest_and_sign();
let manifest = self.build_manifest();
date: self.date.to_string(),
pkg: BTreeMap::new(),
renames: BTreeMap::new(),
+ profiles: BTreeMap::new(),
};
self.package("rustc", &mut manifest.pkg, HOSTS);
self.package("llvm-tools-preview", &mut manifest.pkg, TARGETS);
self.package("lldb-preview", &mut manifest.pkg, TARGETS);
+ self.profile("minimal",
+ &mut manifest.profiles,
+ &["rustc", "cargo", "rust-std", "rust-mingw"]);
+ self.profile("default",
+ &mut manifest.profiles,
+ &["rustc", "cargo", "rust-std", "rust-mingw",
+ "rust-docs", "rustfmt-preview", "clippy-preview"]);
+ self.profile("complete",
+ &mut manifest.profiles,
+ &["rustc", "cargo", "rust-std", "rust-mingw",
+ "rust-docs", "rustfmt-preview", "clippy-preview",
+ "rls-preview", "rust-src", "llvm-tools-preview",
+ "lldb-preview", "rust-analysis"]);
+
manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
manifest.renames.insert("rustfmt".to_owned(), Rename { to: "rustfmt-preview".to_owned() });
manifest.renames.insert("clippy".to_owned(), Rename { to: "clippy-preview".to_owned() });
return manifest;
}
+ fn profile(&mut self,
+ profile_name: &str,
+ dst: &mut BTreeMap<String, Vec<String>>,
+ pkgs: &[&str]) {
+ dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect());
+ }
+
fn package(&mut self,
pkgname: &str,
dst: &mut BTreeMap<String, Package>,
format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target)
} else if component == "lldb" || component == "lldb-preview" {
format!("lldb-{}-{}.tar.gz", self.lldb_release, target)
+ } else if component == "miri" || component == "miri-preview" {
+ format!("miri-{}-{}.tar.gz", self.miri_release, target)
} else {
format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
}
&self.llvm_tools_version
} else if component == "lldb" || component == "lldb-preview" {
&self.lldb_version
+ } else if component == "miri" || component == "miri-preview" {
+ &self.miri_version
} else {
&self.rust_version
}
&self.llvm_tools_git_commit_hash
} else if component == "lldb" || component == "lldb-preview" {
&self.lldb_git_commit_hash
+ } else if component == "miri" || component == "miri-preview" {
+ &self.miri_git_commit_hash
} else {
&self.rust_git_commit_hash
}
-Subproject commit 39bd84494f4a9b40f2e3b38416a91d52d5c4738b
+Subproject commit c63b6349b44019146cc2edcef8141692891b9401
-Subproject commit 2e2a33aab897273a36498d526530f648d6113dc8
+Subproject commit 97f4cff8e904c268569d37922a27835209deff5d
-Subproject commit 6f5e4bba7b1586fca6e0ea7724cadb5683b2f308
+Subproject commit 1a6361bd399a9466deba9b42ff2ff2ae365c5d0e
"errhandlingapi",
"jobapi",
"jobapi2",
+ "knownfolders",
"lmcons",
"memoryapi",
"minschannel",
"minwinbase",
"ntsecapi",
"ntstatus",
+ "objbase",
"profileapi",
"processenv",
"psapi",
"schannel",
"securitybaseapi",
"shellapi",
+ "shlobj",
"sspi",
"synchapi",
"sysinfoapi",
]
[dependencies]
-curl-sys = { version = "0.4.13", optional = true }
+curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
parking_lot = { version = "0.6", features = ['nightly'] }
rand = { version = "0.5.5", features = ["i128_support"] }
serde = { version = "1.0.82", features = ['derive'] }
serde_json = { version = "1.0.31", features = ["raw_value"] }
smallvec = { version = "0.6", features = ['union'] }
+scopeguard = { version = "0.3.3", features = ["use_std", "default"]}
+byteorder = { version = "1.2.7", features = ["i128"]}
+
[target.'cfg(not(windows))'.dependencies]
openssl = { version = "0.10.12", optional = true }
level: Status::Unstable,
since: "None".to_owned(),
has_gate_test: false,
- // Whether there is a common tracking issue
- // for these feature gates remains an open question
- // https://github.com/rust-lang/rust/issues/24111#issuecomment-340283184
- // But we take 24111 otherwise they will be shown as
- // "internal to the compiler" which they are not.
- tracking_issue: Some(24111),
+ // FIXME(#57563): #57563 is now used as a common tracking issue,
+ // although we would like to have specific tracking
+ // issues for each `rustc_const_unstable` in the
+ // future.
+ tracking_issue: Some(57563),
};
mf(Ok((feature_name, feature)), file, i + 1);
continue;