Merge from rust-lang/rust
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 663ace4..9fd8054 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -23,3 +23,5 @@
# test directives migration
6e48b96692d63a79a14563f27fe5185f122434f8
ec2cc761bc7067712ecc7734502f703fe3b024c8
+# format use declarations
+84ac80f1921afc243d71fd0caaa4f2838c294102
diff --git a/.gitignore b/.gitignore
index 87d0256..a36cb51 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,9 @@
*.iml
.vscode
.project
+.vim/
+.helix/
+.zed/
.favorites.json
.settings/
.vs/
@@ -48,6 +51,7 @@
/dist/
/unicode-downloads
/target
+/library/target
/src/bootstrap/target
/src/tools/x/target
# Created by default with `src/ci/docker/run.sh`
diff --git a/.gitmodules b/.gitmodules
index 9ad207a..b5250d4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -33,7 +33,7 @@
[submodule "src/llvm-project"]
path = src/llvm-project
url = https://github.com/rust-lang/llvm-project.git
- branch = rustc/18.1-2024-05-19
+ branch = rustc/19.1-2024-07-30
shallow = true
[submodule "src/doc/embedded-book"]
path = src/doc/embedded-book
diff --git a/Cargo.lock b/Cargo.lock
index f89ecc9..4bd99b7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,26 +12,10 @@
]
[[package]]
-name = "addr2line"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
-dependencies = [
- "compiler_builtins",
- "gimli 0.29.0",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
[[package]]
name = "aes"
@@ -67,16 +51,6 @@
]
[[package]]
-name = "alloc"
-version = "0.0.0"
-dependencies = [
- "compiler_builtins",
- "core",
- "rand",
- "rand_xorshift",
-]
-
-[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -231,11 +205,11 @@
[[package]]
name = "ar_archive_writer"
-version = "0.3.0"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8412a2d690663356cba5a2532f3ed55d1e8090743bc6695b88403b27df67733"
+checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374"
dependencies = [
- "object 0.35.0",
+ "object 0.36.2",
]
[[package]]
@@ -256,7 +230,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
dependencies = [
- "addr2line 0.21.0",
+ "addr2line",
"cc",
"cfg-if",
"libc",
@@ -455,10 +429,6 @@
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
[[package]]
name = "cfg_aliases"
@@ -594,7 +564,7 @@
"termize",
"tokio",
"toml 0.7.8",
- "ui_test 0.24.0",
+ "ui_test 0.25.0",
"walkdir",
]
@@ -602,6 +572,7 @@
name = "clippy_config"
version = "0.1.82"
dependencies = [
+ "itertools",
"rustc-semver",
"serde",
"toml 0.7.8",
@@ -738,16 +709,6 @@
checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
[[package]]
-name = "compiler_builtins"
-version = "0.1.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
-dependencies = [
- "cc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "compiletest"
version = "0.0.0"
dependencies = [
@@ -771,7 +732,7 @@
"tracing-subscriber",
"unified-diff",
"walkdir",
- "windows",
+ "windows 0.52.0",
]
[[package]]
@@ -788,14 +749,6 @@
]
[[package]]
-name = "core"
-version = "0.0.0"
-dependencies = [
- "rand",
- "rand_xorshift",
-]
-
-[[package]]
name = "core-foundation-sys"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1135,19 +1088,6 @@
checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d"
[[package]]
-name = "dlmalloc"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3264b043b8e977326c1ee9e723da2c1f8d09a99df52cacf00b4dbce5ac54414d"
-dependencies = [
- "cfg-if",
- "compiler_builtins",
- "libc",
- "rustc-std-workspace-core",
- "windows-sys 0.52.0",
-]
-
-[[package]]
name = "either"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1349,16 +1289,6 @@
]
[[package]]
-name = "fortanix-sgx-abi"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "fs-err"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1477,8 +1407,11 @@
version = "0.1.0"
dependencies = [
"anyhow",
+ "cargo_metadata 0.18.1",
+ "rinja",
"serde",
"serde_json",
+ "thiserror",
]
[[package]]
@@ -1504,8 +1437,6 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
- "rustc-std-workspace-core",
- "rustc-std-workspace-std",
"unicode-width",
]
@@ -1526,27 +1457,13 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
dependencies = [
- "compiler_builtins",
"fallible-iterator",
"indexmap",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
"stable_deref_trait",
]
[[package]]
name = "gimli"
-version = "0.29.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "gimli"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
@@ -1606,9 +1523,6 @@
dependencies = [
"ahash",
"allocator-api2",
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
"serde",
]
@@ -1631,17 +1545,6 @@
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
-name = "hermit-abi"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1713,7 +1616,7 @@
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
- "windows-core",
+ "windows-core 0.52.0",
]
[[package]]
@@ -2065,9 +1968,6 @@
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
-dependencies = [
- "rustc-std-workspace-core",
-]
[[package]]
name = "libdbus-sys"
@@ -2299,10 +2199,6 @@
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
[[package]]
name = "memmap2"
@@ -2357,9 +2253,6 @@
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
]
[[package]]
@@ -2393,6 +2286,7 @@
"smallvec",
"tempfile",
"ui_test 0.21.2",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -2437,15 +2331,6 @@
]
[[package]]
-name = "ntapi"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
-dependencies = [
- "winapi",
-]
-
-[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2549,7 +2434,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
- "hermit-abi 0.3.9",
+ "hermit-abi",
"libc",
]
@@ -2571,39 +2456,21 @@
"indexmap",
"memchr",
"ruzstd 0.5.0",
- "wasmparser 0.118.2",
]
[[package]]
name = "object"
-version = "0.34.0"
+version = "0.36.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7090bae93f8585aad99e595b7073c5de9ba89fbd6b4e9f0cdd7a10177273ac8"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
dependencies = [
+ "crc32fast",
"flate2",
+ "hashbrown",
+ "indexmap",
"memchr",
- "ruzstd 0.6.0",
-]
-
-[[package]]
-name = "object"
-version = "0.35.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "object"
-version = "0.36.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
-dependencies = [
- "compiler_builtins",
- "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
+ "ruzstd 0.7.0",
+ "wasmparser 0.214.0",
]
[[package]]
@@ -2726,29 +2593,6 @@
]
[[package]]
-name = "panic_abort"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "cfg-if",
- "compiler_builtins",
- "core",
- "libc",
-]
-
-[[package]]
-name = "panic_unwind"
-version = "0.0.0"
-dependencies = [
- "alloc",
- "cfg-if",
- "compiler_builtins",
- "core",
- "libc",
- "unwind",
-]
-
-[[package]]
name = "papergrid"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3003,23 +2847,6 @@
]
[[package]]
-name = "proc_macro"
-version = "0.0.0"
-dependencies = [
- "core",
- "std",
-]
-
-[[package]]
-name = "profiler_builtins"
-version = "0.0.0"
-dependencies = [
- "cc",
- "compiler_builtins",
- "core",
-]
-
-[[package]]
name = "psm"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3097,27 +2924,6 @@
]
[[package]]
-name = "r-efi"
-version = "4.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "r-efi-alloc"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7"
-dependencies = [
- "compiler_builtins",
- "r-efi",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3148,15 +2954,6 @@
]
[[package]]
-name = "rand_xorshift"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "rand_xoshiro"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3297,20 +3094,25 @@
[[package]]
name = "rinja"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2d47a46d7729e891c8accf260e9daa02ae6d570aa2a94fb1fb27eb5364a2323"
+checksum = "6d3762e3740cdbf2fd2be465cc2c26d643ad17353cc2e0223d211c1b096118bd"
dependencies = [
+ "humansize",
+ "itoa",
+ "num-traits",
+ "percent-encoding",
"rinja_derive",
]
[[package]]
name = "rinja_derive"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44dae9afe59d58ed8d988d67d1945f3638125d2fd2104058399382e11bd3ea2a"
+checksum = "fd01fd8e15e7d19c8b8052c1d428325131e02ff1633cdcf695190c2e56ab682c"
dependencies = [
"basic-toml",
+ "memchr",
"mime",
"mime_guess",
"once_map",
@@ -3323,10 +3125,11 @@
[[package]]
name = "rinja_parser"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b1771c78cd5d3b1646ef8d8f2ed100db936e8b291d3cc06e92a339ff346858c"
+checksum = "a2f6bf7cef118c6de21206edf0b3f19f5ede60006be674a58ca21b6e003a1b57"
dependencies = [
+ "memchr",
"nom",
]
@@ -3344,17 +3147,17 @@
"bstr",
"build_helper",
"gimli 0.31.0",
- "object 0.34.0",
+ "object 0.36.2",
"regex",
"similar",
- "wasmparser 0.118.2",
+ "wasmparser 0.214.0",
]
[[package]]
name = "rustc-build-sysroot"
-version = "0.5.2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa3ca63cc537c1cb69e4c2c0afc5fda2ccd36ac84c97d5a4ae05e69b1c834afb"
+checksum = "2471f8f296262437d7e848e527b4210b44a96e53a3b4435b890227ce3e6da106"
dependencies = [
"anyhow",
"rustc_version",
@@ -3367,10 +3170,6 @@
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
[[package]]
name = "rustc-hash"
@@ -3432,27 +3231,6 @@
checksum = "e5c9f15eec8235d7cb775ee6f81891db79b98fd54ba1ad8fae565b88ef1ae4e2"
[[package]]
-name = "rustc-std-workspace-alloc"
-version = "1.99.0"
-dependencies = [
- "alloc",
-]
-
-[[package]]
-name = "rustc-std-workspace-core"
-version = "1.99.0"
-dependencies = [
- "core",
-]
-
-[[package]]
-name = "rustc-std-workspace-std"
-version = "1.99.0"
-dependencies = [
- "std",
-]
-
-[[package]]
name = "rustc_abi"
version = "0.0.0"
dependencies = [
@@ -3653,7 +3431,7 @@
"itertools",
"libc",
"measureme",
- "object 0.32.2",
+ "object 0.36.2",
"rustc-demangle",
"rustc_ast",
"rustc_attr",
@@ -3692,7 +3470,7 @@
"itertools",
"jobserver",
"libc",
- "object 0.32.2",
+ "object 0.36.2",
"pathdiff",
"regex",
"rustc_arena",
@@ -3722,8 +3500,8 @@
"thin-vec",
"thorin-dwp",
"tracing",
- "wasm-encoder 0.200.0",
- "windows",
+ "wasm-encoder 0.210.0",
+ "windows 0.52.0",
]
[[package]]
@@ -3780,7 +3558,7 @@
"tempfile",
"thin-vec",
"tracing",
- "windows",
+ "windows 0.52.0",
]
[[package]]
@@ -3841,7 +3619,7 @@
"shlex",
"time",
"tracing",
- "windows",
+ "windows 0.52.0",
]
[[package]]
@@ -3892,7 +3670,7 @@
"termcolor",
"termize",
"tracing",
- "windows",
+ "windows 0.52.0",
]
[[package]]
@@ -4361,6 +4139,7 @@
"rustc_span",
"rustc_target",
"rustc_trait_selection",
+ "rustc_type_ir",
"smallvec",
"tracing",
]
@@ -4613,7 +4392,7 @@
"smallvec",
"termize",
"tracing",
- "windows",
+ "windows 0.52.0",
]
[[package]]
@@ -4675,7 +4454,7 @@
version = "0.0.0"
dependencies = [
"bitflags 2.5.0",
- "object 0.32.2",
+ "object 0.36.2",
"rustc_abi",
"rustc_data_structures",
"rustc_feature",
@@ -4832,6 +4611,7 @@
"tracing",
"tracing-subscriber",
"tracing-tree",
+ "unicode-segmentation",
]
[[package]]
@@ -4960,12 +4740,11 @@
[[package]]
name = "ruzstd"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
+checksum = "5022b253619b1ba797f243056276bed8ed1a73b0f5a7ce7225d524067644bf8f"
dependencies = [
"byteorder",
- "derive_more",
"twox-hash",
]
@@ -5158,9 +4937,9 @@
[[package]]
name = "spanned"
-version = "0.2.1"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed14ba8b4b82241bd5daba2c49185d4a0581a0058355fe96537338f002b8605d"
+checksum = "86af297923fbcfd107c20a189a6e9c872160df71a7190ae4a7a6c5dce4b2feb6"
dependencies = [
"bstr",
"color-eyre",
@@ -5238,46 +5017,6 @@
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
-name = "std"
-version = "0.0.0"
-dependencies = [
- "addr2line 0.22.0",
- "alloc",
- "cfg-if",
- "compiler_builtins",
- "core",
- "dlmalloc",
- "fortanix-sgx-abi",
- "hashbrown",
- "hermit-abi 0.4.0",
- "libc",
- "miniz_oxide",
- "object 0.36.0",
- "panic_abort",
- "panic_unwind",
- "profiler_builtins",
- "r-efi",
- "r-efi-alloc",
- "rand",
- "rand_xorshift",
- "rustc-demangle",
- "std_detect",
- "unwind",
- "wasi",
-]
-
-[[package]]
-name = "std_detect"
-version = "0.1.5"
-dependencies = [
- "cfg-if",
- "compiler_builtins",
- "libc",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "string_cache"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5371,25 +5110,13 @@
[[package]]
name = "sysinfo"
-version = "0.30.12"
+version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae"
+checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab"
dependencies = [
- "cfg-if",
"core-foundation-sys",
"libc",
- "ntapi",
- "once_cell",
- "windows",
-]
-
-[[package]]
-name = "sysroot"
-version = "0.0.0"
-dependencies = [
- "proc_macro",
- "std",
- "test",
+ "windows 0.57.0",
]
[[package]]
@@ -5477,16 +5204,6 @@
]
[[package]]
-name = "test"
-version = "0.0.0"
-dependencies = [
- "core",
- "getopts",
- "libc",
- "std",
-]
-
-[[package]]
name = "test-float-parse"
version = "0.1.0"
dependencies = [
@@ -5846,9 +5563,9 @@
[[package]]
name = "ui_test"
-version = "0.24.0"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc1c6c78d55482388711c8d417b8e547263046a607512278fed274c54633bbe4"
+checksum = "f7e4f339f62edc873975c47115f9e71c5454ddaa37c1142b42fc0b2672c8dacb"
dependencies = [
"annotate-snippets 0.11.4",
"anyhow",
@@ -5984,11 +5701,6 @@
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
- "rustc-std-workspace-std",
-]
[[package]]
name = "unicode-xid"
@@ -6014,28 +5726,6 @@
]
[[package]]
-name = "unwind"
-version = "0.0.0"
-dependencies = [
- "cfg-if",
- "compiler_builtins",
- "core",
- "libc",
- "unwinding",
-]
-
-[[package]]
-name = "unwinding"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b"
-dependencies = [
- "compiler_builtins",
- "gimli 0.28.1",
- "rustc-std-workspace-core",
-]
-
-[[package]]
name = "url"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6106,11 +5796,6 @@
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
[[package]]
name = "wasm-bindgen"
@@ -6190,15 +5875,6 @@
[[package]]
name = "wasm-encoder"
-version = "0.200.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e3fb0c8fbddd78aa6095b850dfeedbc7506cf5f81e633f69cf8f2333ab84b9"
-dependencies = [
- "leb128",
-]
-
-[[package]]
-name = "wasm-encoder"
version = "0.210.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7e3764d9d6edabd8c9e16195e177be0d20f6ab942ad18af52860f12f82bc59a"
@@ -6233,16 +5909,6 @@
[[package]]
name = "wasmparser"
-version = "0.118.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77f1154f1ab868e2a01d9834a805faca7bf8b50d041b4ca714d005d0dab1c50c"
-dependencies = [
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wasmparser"
version = "0.210.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7bbcd21e7581619d9f6ca00f8c4f08f1cacfe58bf63f83af57cd0476f1026f5"
@@ -6256,6 +5922,16 @@
]
[[package]]
+name = "wasmparser"
+version = "0.214.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5309c1090e3e84dad0d382f42064e9933fdaedb87e468cc239f0eabea73ddcb6"
+dependencies = [
+ "bitflags 2.5.0",
+ "indexmap",
+]
+
+[[package]]
name = "wast"
version = "211.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6314,7 +5990,17 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
- "windows-core",
+ "windows-core 0.52.0",
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "windows"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
+dependencies = [
+ "windows-core 0.57.0",
"windows-targets 0.52.5",
]
@@ -6342,12 +6028,55 @@
]
[[package]]
+name = "windows-core"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-result",
+ "windows-targets 0.52.5",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.67",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.67",
+]
+
+[[package]]
name = "windows-metadata"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e837f3c3012cfe9e7086302a93f441a7999439be1ad4c530d55d2f6d2921809"
[[package]]
+name = "windows-result"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
+dependencies = [
+ "windows-targets 0.52.5",
+]
+
+[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 178a5ab..131feec 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,8 +2,6 @@
resolver = "1"
members = [
"compiler/rustc",
- "library/std",
- "library/sysroot",
"src/etc/test-float-parse",
"src/rustdoc-json-types",
"src/tools/build_helper",
@@ -61,23 +59,8 @@
# not all `Cargo.toml` files are available, so we exclude the `x` binary,
# so it can be invoked before the current checkout is set up.
"src/tools/x",
- # stdarch has its own Cargo workspace
- "library/stdarch",
]
-[profile.release.package.compiler_builtins]
-# For compiler-builtins we always use a high number of codegen units.
-# The goal here is to place every single intrinsic into its own object
-# file to avoid symbol clashes with the system libgcc if possible. Note
-# that this number doesn't actually produce this many object files, we
-# just don't create more than this number of object files.
-#
-# It's a bit of a bummer that we have to pass this here, unfortunately.
-# Ideally this would be specified through an env var to Cargo so Cargo
-# knows how many CGUs are for this specific crate, but for now
-# per-crate configuration isn't specifiable in the environment.
-codegen-units = 10000
-
[profile.release.package.rustc-rayon-core]
# The rustc fork of Rayon has deadlock detection code which intermittently
# causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227)
@@ -85,19 +68,6 @@
# FIXME: This workaround should be removed once #90227 is fixed.
overflow-checks = false
-# These dependencies of the standard library implement symbolication for
-# backtraces on most platforms. Their debuginfo causes both linking to be slower
-# (more data to chew through) and binaries to be larger without really all that
-# much benefit. This section turns them all to down to have no debuginfo which
-# helps to improve link times a little bit.
-[profile.release.package]
-addr2line.debug = 0
-adler.debug = 0
-gimli.debug = 0
-miniz_oxide.debug = 0
-object.debug = 0
-rustc-demangle.debug = 0
-
# These are very thin wrappers around executing lld with the right binary name.
# Basically nothing within them can go wrong without having been explicitly logged anyway.
# We ship these in every rustc tarball and even after compression they add up
@@ -120,10 +90,3 @@
# FIXME: LTO cannot be enabled for binaries in a workspace
# <https://github.com/rust-lang/cargo/issues/9330>
# lto = true
-
-[patch.crates-io]
-# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
-# here
-rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' }
-rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' }
-rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' }
diff --git a/REUSE.toml b/REUSE.toml
index 1a30d80..efd7055 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -163,7 +163,7 @@
path = "src/llvm-project/**"
precedence = "override"
SPDX-FileCopyrightText = [
- "2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)",
+ "2003-2019 by the contributors listed in CREDITS.TXT (https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)",
"2010 Apple Inc",
"2003-2019 University of Illinois at Urbana-Champaign.",
]
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index 29766fc..e9a7397 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -1,3 +1,6 @@
+// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
+#![feature(rustc_private)]
+
// A note about jemalloc: rustc uses jemalloc when built for CI and
// distribution. The obvious way to do this is with the `#[global_allocator]`
// mechanism. However, for complicated reasons (see
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 197dd7f..5160b4e 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -1,9 +1,7 @@
use std::borrow::{Borrow, Cow};
-use std::cmp;
use std::fmt::{self, Write};
-use std::iter;
-use std::ops::Bound;
-use std::ops::Deref;
+use std::ops::{Bound, Deref};
+use std::{cmp, iter};
use rustc_index::Idx;
use tracing::debug;
@@ -982,7 +980,8 @@ fn univariant<
if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
#[cfg(feature = "randomize")]
{
- use rand::{seq::SliceRandom, SeedableRng};
+ use rand::seq::SliceRandom;
+ use rand::SeedableRng;
// `ReprOptions.field_shuffle_seed` is a deterministic seed we can use to randomize field
// ordering.
let mut rng =
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 52ec41f..3dc548c 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -6,21 +6,20 @@
// tidy-alphabetical-end
use std::fmt;
+#[cfg(feature = "nightly")]
+use std::iter::Step;
use std::num::{NonZeroUsize, ParseIntError};
use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
use std::str::FromStr;
use bitflags::bitflags;
-use rustc_index::{Idx, IndexSlice, IndexVec};
-
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::StableOrd;
+use rustc_index::{Idx, IndexSlice, IndexVec};
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_Generic;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_Generic, Encodable_Generic};
-#[cfg(feature = "nightly")]
-use std::iter::Step;
mod layout;
#[cfg(test)]
@@ -517,7 +516,7 @@ pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: &C) -> Option<Size> {
/// Truncates `value` to `self` bits and then sign-extends it to 128 bits
/// (i.e., if it is negative, fill with 1's on the left).
#[inline]
- pub fn sign_extend(self, value: u128) -> u128 {
+ pub fn sign_extend(self, value: u128) -> i128 {
let size = self.bits();
if size == 0 {
// Truncated until nothing is left.
@@ -527,7 +526,7 @@ pub fn sign_extend(self, value: u128) -> u128 {
let shift = 128 - size;
// Shift the unsigned value to the left, then shift back to the right as signed
// (essentially fills with sign bit on the left).
- (((value << shift) as i128) >> shift) as u128
+ ((value << shift) as i128) >> shift
}
/// Truncates `value` to `self` bits.
@@ -545,7 +544,7 @@ pub fn truncate(self, value: u128) -> u128 {
#[inline]
pub fn signed_int_min(&self) -> i128 {
- self.sign_extend(1_u128 << (self.bits() - 1)) as i128
+ self.sign_extend(1_u128 << (self.bits() - 1))
}
#[inline]
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 810cb7a..f5f0134 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -27,15 +27,14 @@
#![feature(strict_provenance)]
// tidy-alphabetical-end
-use smallvec::SmallVec;
-
use std::alloc::Layout;
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;
use std::mem::{self, MaybeUninit};
use std::ptr::{self, NonNull};
-use std::slice;
-use std::{cmp, intrinsics};
+use std::{cmp, intrinsics, slice};
+
+use smallvec::SmallVec;
/// This calls the passed function while ensuring it won't be inlined into the caller.
#[inline(never)]
diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs
index 49a070ba..9eaa292 100644
--- a/compiler/rustc_arena/src/tests.rs
+++ b/compiler/rustc_arena/src/tests.rs
@@ -1,8 +1,10 @@
extern crate test;
-use super::TypedArena;
use std::cell::Cell;
+
use test::Bencher;
+use super::TypedArena;
+
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq)]
struct Point {
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 628badd..a44ed82 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -18,15 +18,9 @@
//! - [`Attribute`]: Metadata associated with item.
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
-pub use crate::format::*;
-pub use crate::util::parser::ExprPrecedence;
-pub use rustc_span::AttrId;
-pub use GenericArgs::*;
-pub use UnsafeSource::*;
+use std::borrow::Cow;
+use std::{cmp, fmt, mem};
-use crate::ptr::P;
-use crate::token::{self, CommentKind, Delimiter};
-use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
pub use rustc_ast_ir::{Movability, Mutability};
use rustc_data_structures::packed::Pu128;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -35,12 +29,17 @@
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
+pub use rustc_span::AttrId;
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
-use std::borrow::Cow;
-use std::cmp;
-use std::fmt;
-use std::mem;
use thin_vec::{thin_vec, ThinVec};
+pub use GenericArgs::*;
+pub use UnsafeSource::*;
+
+pub use crate::format::*;
+use crate::ptr::P;
+use crate::token::{self, CommentKind, Delimiter};
+use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
+pub use crate::util::parser::ExprPrecedence;
/// A "Label" is an identifier of some point in sources,
/// e.g. in the following code:
@@ -586,7 +585,9 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
}
// A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array,
// when `P` can be reparsed as a type `T`.
- PatKind::Slice(pats) if pats.len() == 1 => pats[0].to_ty().map(TyKind::Slice)?,
+ PatKind::Slice(pats) if let [pat] = pats.as_slice() => {
+ pat.to_ty().map(TyKind::Slice)?
+ }
// A tuple pattern `(P0, .., Pn)` can be reparsed as `(T0, .., Tn)`
// assuming `T0` to `Tn` are all syntactically valid as types.
PatKind::Tuple(pats) => {
@@ -1188,8 +1189,8 @@ impl Expr {
/// Does not ensure that the path resolves to a const param, the caller should check this.
pub fn is_potential_trivial_const_arg(&self) -> bool {
let this = if let ExprKind::Block(block, None) = &self.kind
- && block.stmts.len() == 1
- && let StmtKind::Expr(expr) = &block.stmts[0].kind
+ && let [stmt] = block.stmts.as_slice()
+ && let StmtKind::Expr(expr) = &stmt.kind
{
expr
} else {
@@ -1249,7 +1250,9 @@ pub fn to_ty(&self) -> Option<P<Ty>> {
expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?
}
- ExprKind::Array(exprs) if exprs.len() == 1 => exprs[0].to_ty().map(TyKind::Slice)?,
+ ExprKind::Array(exprs) if let [expr] = exprs.as_slice() => {
+ expr.to_ty().map(TyKind::Slice)?
+ }
ExprKind::Tup(exprs) => {
let tys = exprs.iter().map(|expr| expr.to_ty()).collect::<Option<ThinVec<_>>>()?;
@@ -3491,8 +3494,9 @@ fn try_from(item_kind: ItemKind) -> Result<ForeignItemKind, ItemKind> {
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(AssocItem, 88);
static_assert_size!(AssocItemKind, 16);
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 7754ca0..6b95fb7 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -2,16 +2,17 @@
//! typically those used in AST fragments during macro expansion.
//! The traits are not implemented exhaustively, only when actually necessary.
+use std::fmt;
+use std::marker::PhantomData;
+
use crate::ptr::P;
use crate::token::Nonterminal;
use crate::tokenstream::LazyAttrTokenStream;
-use crate::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant};
-use crate::{AssocItem, Expr, ForeignItem, Item, NodeId};
-use crate::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
-use crate::{AttrVec, Attribute, Stmt, StmtKind};
-
-use std::fmt;
-use std::marker::PhantomData;
+use crate::{
+ Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
+ FieldDef, ForeignItem, GenericParam, Item, NodeId, Param, Pat, PatField, Path, Stmt, StmtKind,
+ Ty, Variant, Visibility,
+};
/// A utility trait to reduce boilerplate.
/// Standard `Deref(Mut)` cannot be reused due to coherence.
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index d2c7b1c..94a00ab 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -1,25 +1,25 @@
//! Functions dealing with attributes and meta items.
-use crate::ast::{
- AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, Safety,
-};
-use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
-use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
-use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
-use crate::ptr::P;
-use crate::token::{self, CommentKind, Delimiter, Token};
-use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
-use crate::tokenstream::{LazyAttrTokenStream, TokenStream};
-use crate::util::comments;
-use crate::util::literal::escape_string_symbol;
+use std::iter;
+use std::sync::atomic::{AtomicU32, Ordering};
+
use rustc_index::bit_set::GrowableBitSet;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
-use std::iter;
-use std::sync::atomic::{AtomicU32, Ordering};
use thin_vec::{thin_vec, ThinVec};
+use crate::ast::{
+ AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DelimArgs,
+ Expr, ExprKind, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NormalAttr, Path,
+ PathSegment, Safety, DUMMY_NODE_ID,
+};
+use crate::ptr::P;
+use crate::token::{self, CommentKind, Delimiter, Token};
+use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenTree};
+use crate::util::comments;
+use crate::util::literal::escape_string_symbol;
+
pub struct MarkedAttrs(GrowableBitSet<AttrId>);
impl MarkedAttrs {
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index dd231e2..60a1261 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -1,7 +1,8 @@
-use crate::{attr, Attribute};
use rustc_span::symbol::sym;
use rustc_span::Symbol;
+use crate::{attr, Attribute};
+
#[derive(Debug)]
pub enum EntryPointType {
/// This function is not an entrypoint.
diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs
index 37caadd..1341328 100644
--- a/compiler/rustc_ast/src/expand/mod.rs
+++ b/compiler/rustc_ast/src/expand/mod.rs
@@ -1,7 +1,8 @@
//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`.
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::{def_id::DefId, symbol::Ident};
+use rustc_span::def_id::DefId;
+use rustc_span::symbol::Ident;
use crate::MetaItem;
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs
index 49910e2..e72d32d 100644
--- a/compiler/rustc_ast/src/format.rs
+++ b/compiler/rustc_ast/src/format.rs
@@ -1,10 +1,11 @@
-use crate::ptr::P;
-use crate::Expr;
use rustc_data_structures::fx::FxHashMap;
use rustc_macros::{Decodable, Encodable};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
+use crate::ptr::P;
+use crate::Expr;
+
// Definitions:
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 846a108..27e9f3d 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -43,11 +43,11 @@ pub mod util {
pub mod tokenstream;
pub mod visit;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+
pub use self::ast::*;
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in `rustc_middle`.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 8387e44..8a66894 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -7,11 +7,8 @@
//! a `MutVisitor` renaming item names in a module will miss all of those
//! that are created by the expansion of a macro.
-use crate::ast::*;
-use crate::ptr::P;
-use crate::token::{self, Token};
-use crate::tokenstream::*;
-use crate::visit::{AssocCtxt, BoundKind};
+use std::ops::DerefMut;
+use std::panic;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -20,10 +17,14 @@
use rustc_span::symbol::Ident;
use rustc_span::Span;
use smallvec::{smallvec, Array, SmallVec};
-use std::ops::DerefMut;
-use std::panic;
use thin_vec::ThinVec;
+use crate::ast::*;
+use crate::ptr::P;
+use crate::token::{self, Token};
+use crate::tokenstream::*;
+use crate::visit::{AssocCtxt, BoundKind};
+
pub trait ExpectOne<A: Array> {
fn expect_one(self, err: &'static str) -> A::Item;
}
diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs
index 1cd2449..adca184 100644
--- a/compiler/rustc_ast/src/node_id.rs
+++ b/compiler/rustc_ast/src/node_id.rs
@@ -1,6 +1,7 @@
-use rustc_span::LocalExpnId;
use std::fmt;
+use rustc_span::LocalExpnId;
+
rustc_index::newtype_index! {
/// Identifies an AST node.
///
diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
index 34c539e..97c714d 100644
--- a/compiler/rustc_ast/src/ptr.rs
+++ b/compiler/rustc_ast/src/ptr.rs
@@ -21,9 +21,8 @@
use std::ops::{Deref, DerefMut};
use std::{slice, vec};
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
/// An owned smart pointer.
///
/// See the [module level documentation][crate::ptr] for details.
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 9478da2..43d87b9 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -1,3 +1,15 @@
+use std::borrow::Cow;
+use std::fmt;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::sync::Lrc;
+use rustc_macros::{Decodable, Encodable, HashStable_Generic};
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{kw, sym};
+#[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint.
+#[allow(hidden_glob_reexports)]
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
pub use BinOpToken::*;
pub use LitKind::*;
pub use Nonterminal::*;
@@ -9,17 +21,6 @@
use crate::ptr::P;
use crate::util::case::Case;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::Lrc;
-use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::symbol::{kw, sym};
-#[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint.
-#[allow(hidden_glob_reexports)]
-use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{edition::Edition, ErrorGuaranteed, Span, DUMMY_SP};
-use std::borrow::Cow;
-use std::fmt;
-
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CommentKind {
Line,
@@ -1062,8 +1063,9 @@ fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(Lit, 12);
static_assert_size!(LitKind, 2);
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index a92ef57..057b445 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -13,10 +13,8 @@
//! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
//! ownership of the original.
-use crate::ast::{AttrStyle, StmtKind};
-use crate::ast_traits::{HasAttrs, HasTokens};
-use crate::token::{self, Delimiter, Nonterminal, Token, TokenKind};
-use crate::{AttrVec, Attribute};
+use std::borrow::Cow;
+use std::{cmp, fmt, iter};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{self, Lrc};
@@ -24,8 +22,10 @@
use rustc_serialize::{Decodable, Encodable};
use rustc_span::{sym, Span, SpanDecoder, SpanEncoder, Symbol, DUMMY_SP};
-use std::borrow::Cow;
-use std::{cmp, fmt, iter};
+use crate::ast::{AttrStyle, StmtKind};
+use crate::ast_traits::{HasAttrs, HasTokens};
+use crate::token::{self, Delimiter, Nonterminal, Token, TokenKind};
+use crate::{AttrVec, Attribute};
/// Part of a `TokenStream`.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
@@ -767,8 +767,9 @@ pub fn new(open: Spacing, close: Spacing) -> DelimSpacing {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(AttrTokenStream, 8);
static_assert_size!(AttrTokenTree, 32);
diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs
index cbc1afc..f39142f 100644
--- a/compiler/rustc_ast/src/util/comments.rs
+++ b/compiler/rustc_ast/src/util/comments.rs
@@ -1,6 +1,7 @@
-use crate::token::CommentKind;
use rustc_span::{BytePos, Symbol};
+use crate::token::CommentKind;
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs
index 11d5060..61bb246 100644
--- a/compiler/rustc_ast/src/util/comments/tests.rs
+++ b/compiler/rustc_ast/src/util/comments/tests.rs
@@ -1,6 +1,7 @@
-use super::*;
use rustc_span::create_default_session_globals_then;
+use super::*;
+
#[test]
fn test_block_doc_comment_1() {
create_default_session_globals_then(|| {
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index cb73b79..3bd2a80 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -1,15 +1,17 @@
//! Code related to parsing literals.
-use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
-use crate::token::{self, Token};
+use std::{ascii, fmt, str};
+
use rustc_lexer::unescape::{
byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode,
};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use std::{ascii, fmt, str};
use tracing::debug;
+use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
+use crate::token::{self, Token};
+
// Escapes a string, represented as a symbol. Reuses the original symbol,
// avoiding interning, if no changes are required.
pub fn escape_string_symbol(symbol: Symbol) -> Symbol {
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index ad92bf2..8436c76 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -1,6 +1,7 @@
+use rustc_span::symbol::kw;
+
use crate::ast::{self, BinOpKind};
use crate::token::{self, BinOpToken, Token};
-use rustc_span::symbol::kw;
/// Associative operator with precedence.
///
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index f692905..fe07ec4 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -13,14 +13,13 @@
//! instance, a walker looking for item names in a module will miss all of
//! those that are created by the expansion of a macro.
-use crate::ast::*;
-use crate::ptr::P;
-
+pub use rustc_ast_ir::visit::VisitorResult;
+pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
use rustc_span::symbol::Ident;
use rustc_span::Span;
-pub use rustc_ast_ir::visit::VisitorResult;
-pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
+use crate::ast::*;
+use crate::ptr::P;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AssocCtxt {
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 9ed93d4..0a7f750 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -167,11 +167,23 @@
ast_lowering_this_not_async = this is not `async`
+ast_lowering_underscore_array_length_unstable =
+ using `_` for array lengths is unstable
+
ast_lowering_underscore_expr_lhs_assign =
in expressions, `_` can only be used on the left-hand side of an assignment
.label = `_` not allowed here
+ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture
+ast_lowering_unstable_inline_assembly_const_operands =
+ const operands for inline assembly are unstable
+ast_lowering_unstable_inline_assembly_label_operands =
+ label operands for inline assembly are unstable
+ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable
+
ast_lowering_use_angle_brackets = use angle brackets instead
+
+ast_lowering_yield = yield syntax is experimental
ast_lowering_yield_in_closure =
`yield` can only be used in `#[coroutine]` closures, or `gen` blocks
.suggestion = use `#[coroutine]` to make this closure a coroutine
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index de0874a..8acca78 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -1,13 +1,5 @@
-use crate::{ImplTraitContext, ImplTraitPosition, ParamMode, ResolverAstLoweringExt};
-
-use super::errors::{
- AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
- InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
- InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
- InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
- InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict,
-};
-use super::LoweringContext;
+use std::collections::hash_map::Entry;
+use std::fmt::Write;
use rustc_ast::ptr::P;
use rustc_ast::*;
@@ -18,11 +10,21 @@
use rustc_span::symbol::kw;
use rustc_span::{sym, Span};
use rustc_target::asm;
-use std::collections::hash_map::Entry;
-use std::fmt::Write;
+
+use super::errors::{
+ AbiSpecifiedMultipleTimes, AttSyntaxOnlyX86, ClobberAbiNotSupported,
+ InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
+ InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
+ InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
+ InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict,
+};
+use super::LoweringContext;
+use crate::{
+ fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode,
+ ResolverAstLoweringExt,
+};
impl<'a, 'hir> LoweringContext<'a, 'hir> {
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
pub(crate) fn lower_inline_asm(
&mut self,
sp: Span,
@@ -52,7 +54,7 @@ pub(crate) fn lower_inline_asm(
&self.tcx.sess,
sym::asm_experimental_arch,
sp,
- "inline assembly is not stable yet on this architecture",
+ fluent::ast_lowering_unstable_inline_assembly,
)
.emit();
}
@@ -64,8 +66,13 @@ pub(crate) fn lower_inline_asm(
self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp });
}
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
- feature_err(&self.tcx.sess, sym::asm_unwind, sp, "the `may_unwind` option is unstable")
- .emit();
+ feature_err(
+ &self.tcx.sess,
+ sym::asm_unwind,
+ sp,
+ fluent::ast_lowering_unstable_may_unwind,
+ )
+ .emit();
}
let mut clobber_abis = FxIndexMap::default();
@@ -182,7 +189,7 @@ pub(crate) fn lower_inline_asm(
sess,
sym::asm_const,
*op_sp,
- "const operands for inline assembly are unstable",
+ fluent::ast_lowering_unstable_inline_assembly_const_operands,
)
.emit();
}
@@ -246,7 +253,7 @@ pub(crate) fn lower_inline_asm(
sess,
sym::asm_goto,
*op_sp,
- "label operands for inline assembly are unstable",
+ fluent::ast_lowering_unstable_inline_assembly_label_operands,
)
.emit();
}
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index e821a08..9d2b569 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -1,9 +1,9 @@
-use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
use rustc_hir as hir;
-
use smallvec::SmallVec;
+use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
+
impl<'a, 'hir> LoweringContext<'a, 'hir> {
pub(super) fn lower_block(
&mut self,
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index 6df2c15..300bfa1 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -33,26 +33,26 @@
//! HIR ty lowering.
//!
//! Similarly generics, predicates and header are set to the "default" values.
-//! In case of discrepancy with callee function the `NotSupportedDelegation` error will
+//! In case of discrepancy with callee function the `UnsupportedDelegation` error will
//! also be emitted during HIR ty lowering.
-use crate::{ImplTraitPosition, ResolverAstLoweringExt};
-
-use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
+use std::iter;
use ast::visit::Visitor;
use hir::def::{DefKind, PartialRes, Res};
use hir::{BodyId, HirId};
-use rustc_ast as ast;
use rustc_ast::*;
use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
-use rustc_span::{symbol::Ident, Span};
+use rustc_span::symbol::Ident;
+use rustc_span::Span;
use rustc_target::spec::abi;
-use std::iter;
+use {rustc_ast as ast, rustc_hir as hir};
+
+use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
+use crate::{ImplTraitPosition, ResolverAstLoweringExt};
pub(crate) struct DelegationResults<'hir> {
pub body_id: hir::BodyId,
@@ -275,8 +275,8 @@ fn lower_delegation_body(
// FIXME(fn_delegation): Alternatives for target expression lowering:
// https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600.
fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> {
- if block.stmts.len() == 1
- && let StmtKind::Expr(expr) = &block.stmts[0].kind
+ if let [stmt] = block.stmts.as_slice()
+ && let StmtKind::Expr(expr) = &stmt.kind
{
return self.lower_expr_mut(expr);
}
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 4c77892..7a6c9d8 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,8 +1,8 @@
-use rustc_errors::{
- codes::*, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic,
-};
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_span::{symbol::Ident, Span, Symbol};
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index d870f9f..b5d8a54 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,15 +1,5 @@
use std::assert_matches::assert_matches;
-use super::errors::{
- AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
- ClosureCannotBeStatic, CoroutineTooManyParameters,
- FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
- NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign,
-};
-use super::ResolverAstLoweringExt;
-use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
-use crate::errors::YieldInClosure;
-use crate::{FnDeclKind, ImplTraitPosition};
use rustc_ast::ptr::P as AstP;
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -20,10 +10,21 @@
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::DUMMY_SP;
-use rustc_span::{DesugaringKind, Span};
+use rustc_span::{DesugaringKind, Span, DUMMY_SP};
use thin_vec::{thin_vec, ThinVec};
+use super::errors::{
+ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
+ ClosureCannotBeStatic, CoroutineTooManyParameters,
+ FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
+ NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign,
+};
+use super::{
+ ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs, ResolverAstLoweringExt,
+};
+use crate::errors::YieldInClosure;
+use crate::{fluent_generated, FnDeclKind, ImplTraitPosition};
+
impl<'hir> LoweringContext<'_, 'hir> {
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
@@ -1539,7 +1540,6 @@ fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
}
}
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
let yielded =
opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span));
@@ -1574,7 +1574,7 @@ fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::Expr
&self.tcx.sess,
sym::coroutines,
span,
- "yield syntax is experimental",
+ fluent_generated::ast_lowering_yield,
)
.emit();
}
@@ -1586,7 +1586,7 @@ fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::Expr
&self.tcx.sess,
sym::coroutines,
span,
- "yield syntax is experimental",
+ fluent_generated::ast_lowering_yield,
)
.emit();
}
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index ca4604c..bf40c9b 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -1,16 +1,14 @@
-use super::LoweringContext;
use core::ops::ControlFlow;
-use rustc_ast as ast;
+use std::borrow::Cow;
+
use rustc_ast::visit::Visitor;
use rustc_ast::*;
use rustc_data_structures::fx::FxIndexMap;
-use rustc_hir as hir;
-use rustc_span::{
- sym,
- symbol::{kw, Ident},
- Span, Symbol,
-};
-use std::borrow::Cow;
+use rustc_span::symbol::{kw, Ident};
+use rustc_span::{sym, Span, Symbol};
+use {rustc_ast as ast, rustc_hir as hir};
+
+use super::LoweringContext;
impl<'hir> LoweringContext<'_, 'hir> {
pub(crate) fn lower_format_args(&mut self, sp: Span, fmt: &FormatArgs) -> hir::ExprKind<'hir> {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 6e6aac1..7af3945 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1,8 +1,3 @@
-use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
-use super::ResolverAstLoweringExt;
-use super::{AstOwner, ImplTraitContext, ImplTraitPosition};
-use super::{FnDeclKind, LoweringContext, ParamMode};
-
use rustc_ast::ptr::P;
use rustc_ast::visit::AssocCtxt;
use rustc_ast::*;
@@ -22,6 +17,12 @@
use thin_vec::ThinVec;
use tracing::instrument;
+use super::errors::{InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
+use super::{
+ AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
+ ResolverAstLoweringExt,
+};
+
pub(super) struct ItemLowerer<'a, 'hir> {
pub(super) tcx: TyCtxt<'hir>,
pub(super) resolver: &'a mut ResolverAstLowering,
@@ -1667,7 +1668,6 @@ fn lower_generics<T>(
}),
)),
)),
- // FIXME(effects) we might not need a default.
default: Some(default_ct),
is_host_effect: true,
synthetic: true,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d44f953..81d17a9 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -39,7 +39,8 @@
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
-use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
+use std::collections::hash_map::Entry;
+
use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, *};
@@ -53,9 +54,9 @@
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::{self as hir};
use rustc_hir::{
- ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName, TraitCandidate,
+ self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, MissingLifetimeKind, ParamName,
+ TraitCandidate,
};
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_macros::extension;
@@ -65,10 +66,11 @@
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-use std::collections::hash_map::Entry;
use thin_vec::ThinVec;
use tracing::{debug, instrument, trace};
+use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
+
macro_rules! arena_vec {
($this:expr; $($x:expr),*) => (
$this.arena.alloc_from_iter([$($x),*])
@@ -2324,7 +2326,6 @@ fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
self.expr_block(block)
}
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> {
match c.value.kind {
ExprKind::Underscore => {
@@ -2338,7 +2339,7 @@ fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> {
&self.tcx.sess,
sym::generic_arg_infer,
c.value.span,
- "using `_` for array lengths is unstable",
+ fluent_generated::ast_lowering_underscore_array_length_unstable,
)
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c))
diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
index 5456abd..77cc2a3 100644
--- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs
+++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
@@ -1,4 +1,3 @@
-use super::ResolverAstLoweringExt;
use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
use rustc_ast::{GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind};
use rustc_data_structures::fx::FxIndexSet;
@@ -8,6 +7,8 @@
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
+use super::ResolverAstLoweringExt;
+
struct LifetimeCollectVisitor<'ast> {
resolver: &'ast ResolverAstLowering,
current_binders: Vec<NodeId>,
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 32de07a..d82bdd5 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -1,17 +1,17 @@
-use super::errors::{
- ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
-};
-use super::ResolverAstLoweringExt;
-use super::{ImplTraitContext, LoweringContext, ParamMode};
-use crate::ImplTraitPosition;
-
use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::Res;
+use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
-use rustc_span::{source_map::Spanned, Span};
+use rustc_span::Span;
+
+use super::errors::{
+ ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
+};
+use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
+use crate::ImplTraitPosition;
impl<'a, 'hir> LoweringContext<'a, 'hir> {
pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index ac36b07..077b06a 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -1,13 +1,3 @@
-use crate::ImplTraitPosition;
-
-use super::errors::{
- AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, BadReturnTypeNotation,
- GenericTypeWithParentheses, UseAngleBrackets,
-};
-use super::ResolverAstLoweringExt;
-use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs};
-use super::{ImplTraitContext, LoweringContext, ParamMode};
-
use rustc_ast::{self as ast, *};
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
@@ -17,10 +7,19 @@
use rustc_middle::span_bug;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
-
use smallvec::{smallvec, SmallVec};
use tracing::{debug, instrument};
+use super::errors::{
+ AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, BadReturnTypeNotation,
+ GenericTypeWithParentheses, UseAngleBrackets,
+};
+use super::{
+ GenericArgsCtor, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode,
+ ParenthesizedGenericArgs, ResolverAstLoweringExt,
+};
+use crate::ImplTraitPosition;
+
impl<'a, 'hir> LoweringContext<'a, 'hir> {
#[instrument(level = "trace", skip(self))]
pub(crate) fn lower_qpath(
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 9b063a3..a353c79 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -16,6 +16,9 @@
//! constructions produced by proc macros. This pass is only intended for simple checks that do not
//! require name resolution or type checking, or other kinds of complex analysis.
+use std::mem;
+use std::ops::{Deref, DerefMut};
+
use itertools::{Either, Itertools};
use rustc_ast::ptr::P;
use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
@@ -34,8 +37,6 @@
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use rustc_target::spec::abi;
-use std::mem;
-use std::ops::{Deref, DerefMut};
use thin_vec::thin_vec;
use crate::errors::{self, TildeConstReason};
@@ -452,11 +453,6 @@ fn check_item_safety(&self, span: Span, safety: Safety) {
item_span: span,
block: Some(self.current_extern_span().shrink_to_lo()),
});
- } else if !self.features.unsafe_extern_blocks {
- self.dcx().emit_err(errors::InvalidSafetyOnExtern {
- item_span: span,
- block: None,
- });
}
}
}
@@ -1053,32 +1049,19 @@ fn visit_item(&mut self, item: &'a Item) {
errors::VisibilityNotPermittedNote::IndividualForeignItems,
);
- if this.features.unsafe_extern_blocks {
- if &Safety::Default == safety {
- if item.span.at_least_rust_2024() {
- this.dcx()
- .emit_err(errors::MissingUnsafeOnExtern { span: item.span });
- } else {
- this.lint_buffer.buffer_lint(
- MISSING_UNSAFE_ON_EXTERN,
- item.id,
- item.span,
- BuiltinLintDiag::MissingUnsafeOnExtern {
- suggestion: item.span.shrink_to_lo(),
- },
- );
- }
+ if &Safety::Default == safety {
+ if item.span.at_least_rust_2024() {
+ this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
+ } else {
+ this.lint_buffer.buffer_lint(
+ MISSING_UNSAFE_ON_EXTERN,
+ item.id,
+ item.span,
+ BuiltinLintDiag::MissingUnsafeOnExtern {
+ suggestion: item.span.shrink_to_lo(),
+ },
+ );
}
- } else if let &Safety::Unsafe(span) = safety {
- let mut diag = this
- .dcx()
- .create_err(errors::UnsafeItem { span, kind: "extern block" });
- rustc_session::parse::add_feature_diagnostics(
- &mut diag,
- self.session,
- sym::unsafe_extern_blocks,
- );
- diag.emit();
}
if abi.is_none() {
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 9151c4a..9e40368 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,11 +1,11 @@
//! Errors emitted by ast_passes.
use rustc_ast::ParamKindOrd;
-use rustc_errors::{
- codes::*, Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic,
-};
+use rustc_errors::codes::*;
+use rustc_errors::{Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_span::{symbol::Ident, Span, Symbol};
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
use crate::fluent_generated as fluent;
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index e91dfb2..3ceb8e0 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,7 +1,6 @@
use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
-use rustc_ast::{attr, NodeId};
-use rustc_ast::{token, PatKind};
+use rustc_ast::{attr, token, NodeId, PatKind};
use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_session::Session;
@@ -561,10 +560,6 @@ macro_rules! gate_all {
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
gate_all!(global_registration, "global registration is experimental");
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
- gate_all!(
- unsafe_extern_blocks,
- "`unsafe extern {}` blocks and `safe` keyword are experimental"
- );
gate_all!(return_type_notation, "return type notation is experimental");
if !visitor.features.never_patterns {
diff --git a/compiler/rustc_ast_pretty/src/helpers.rs b/compiler/rustc_ast_pretty/src/helpers.rs
index c3e0ecc..34641ea 100644
--- a/compiler/rustc_ast_pretty/src/helpers.rs
+++ b/compiler/rustc_ast_pretty/src/helpers.rs
@@ -1,6 +1,7 @@
-use crate::pp::Printer;
use std::borrow::Cow;
+use crate::pp::Printer;
+
impl Printer {
pub fn word_space<W: Into<Cow<'static, str>>>(&mut self, w: W) {
self.word(w);
diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs
index 96f5eff..e4fd7e9 100644
--- a/compiler/rustc_ast_pretty/src/pp.rs
+++ b/compiler/rustc_ast_pretty/src/pp.rs
@@ -135,11 +135,11 @@
mod convenience;
mod ring;
-use ring::RingBuffer;
use std::borrow::Cow;
-use std::cmp;
use std::collections::VecDeque;
-use std::iter;
+use std::{cmp, iter};
+
+use ring::RingBuffer;
/// How to break. Described in more detail in the module docs.
#[derive(Clone, Copy, PartialEq)]
diff --git a/compiler/rustc_ast_pretty/src/pp/convenience.rs b/compiler/rustc_ast_pretty/src/pp/convenience.rs
index c4c4fdc..6d46c26 100644
--- a/compiler/rustc_ast_pretty/src/pp/convenience.rs
+++ b/compiler/rustc_ast_pretty/src/pp/convenience.rs
@@ -1,6 +1,7 @@
-use crate::pp::{BeginToken, BreakToken, Breaks, IndentStyle, Printer, Token, SIZE_INFINITY};
use std::borrow::Cow;
+use crate::pp::{BeginToken, BreakToken, Breaks, IndentStyle, Printer, Token, SIZE_INFINITY};
+
impl Printer {
/// "raw box"
pub fn rbox(&mut self, indent: isize, breaks: Breaks) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index 83b7e13..cfcc28b 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -2,13 +2,12 @@
mod tests;
pub mod state;
-pub use state::{print_crate, AnnNode, Comments, PpAnn, PrintState, State};
+use std::borrow::Cow;
use rustc_ast as ast;
use rustc_ast::token::{Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
-
-use std::borrow::Cow;
+pub use state::{print_crate, AnnNode, Comments, PpAnn, PrintState, State};
pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
State::new().nonterminal_to_string(nt)
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index b463d1f..c7ff39d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -6,9 +6,8 @@
mod fixup;
mod item;
-use crate::pp::Breaks::{Consistent, Inconsistent};
-use crate::pp::{self, Breaks};
-use crate::pprust::state::fixup::FixupContext;
+use std::borrow::Cow;
+
use ast::TraitBoundModifiers;
use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::ptr::P;
@@ -16,18 +15,21 @@
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
use rustc_ast::util::classify;
use rustc_ast::util::comments::{Comment, CommentStyle};
-use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind, Safety};
-use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
-use rustc_ast::{GenericArg, GenericBound, SelfKind};
-use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
-use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_ast::{
+ self as ast, attr, AttrArgs, AttrArgsEq, BindingMode, BlockCheckMode, ByRef, DelimArgs,
+ GenericArg, GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass,
+ InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, Safety, SelfKind, Term,
+};
use rustc_span::edition::Edition;
use rustc_span::source_map::{SourceMap, Spanned};
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
use rustc_span::{BytePos, CharPos, FileName, Pos, Span, DUMMY_SP};
-use std::borrow::Cow;
use thin_vec::ThinVec;
+use crate::pp::Breaks::{Consistent, Inconsistent};
+use crate::pp::{self, Breaks};
+use crate::pprust::state::fixup::FixupContext;
+
pub enum MacHeader<'a> {
Path(&'a ast::Path),
Keyword(&'static str),
@@ -290,8 +292,7 @@ pub fn print_crate<'a>(
fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
use token::*;
use Delimiter::*;
- use TokenTree::Delimited as Del;
- use TokenTree::Token as Tok;
+ use TokenTree::{Delimited as Del, Token as Tok};
fn is_punct(tt: &TokenTree) -> bool {
matches!(tt, TokenTree::Token(tok, _) if tok.is_punct())
@@ -501,8 +502,8 @@ fn print_comment(&mut self, cmnt: Comment) {
if !self.is_beginning_of_line() {
self.word(" ");
}
- if cmnt.lines.len() == 1 {
- self.word(cmnt.lines[0].clone());
+ if let [line] = cmnt.lines.as_slice() {
+ self.word(line.clone());
self.hardbreak()
} else {
self.visual_align();
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 5b13858..b13c89c 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -1,19 +1,19 @@
-use crate::pp::Breaks::Inconsistent;
-use crate::pprust::state::fixup::FixupContext;
-use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
+use std::fmt::Write;
+
use ast::{ForLoopKind, MatchKind};
use itertools::{Itertools, Position};
use rustc_ast::ptr::P;
-use rustc_ast::token;
use rustc_ast::util::classify;
use rustc_ast::util::literal::escape_byte_str_symbol;
use rustc_ast::util::parser::{self, AssocOp, Fixity};
-use rustc_ast::{self as ast, BlockCheckMode};
use rustc_ast::{
- FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign,
- FormatTrait,
+ self as ast, token, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece,
+ FormatCount, FormatDebugHex, FormatSign, FormatTrait,
};
-use std::fmt::Write;
+
+use crate::pp::Breaks::Inconsistent;
+use crate::pprust::state::fixup::FixupContext;
+use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
impl<'a> State<'a> {
fn print_else(&mut self, els: Option<&ast::Expr>) {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index d838205..85a0b3b 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -1,7 +1,3 @@
-use crate::pp::Breaks::Inconsistent;
-use crate::pprust::state::fixup::FixupContext;
-use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
-
use ast::StaticItem;
use itertools::{Itertools, Position};
use rustc_ast as ast;
@@ -9,6 +5,10 @@
use rustc_ast::ModKind;
use rustc_span::symbol::Ident;
+use crate::pp::Breaks::Inconsistent;
+use crate::pprust::state::fixup::FixupContext;
+use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
+
enum DelegationKind<'a> {
Single,
List(&'a [(Ident, Option<Ident>)]),
@@ -783,8 +783,8 @@ fn print_use_tree(&mut self, tree: &ast::UseTree) {
}
if items.is_empty() {
self.word("{}");
- } else if items.len() == 1 {
- self.print_use_tree(&items[0].0);
+ } else if let [(item, _)] = items.as_slice() {
+ self.print_use_tree(item);
} else {
self.cbox(INDENT_UNIT);
self.word("{");
diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs
index 5b5ffbc..3fefc52 100644
--- a/compiler/rustc_ast_pretty/src/pprust/tests.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs
@@ -1,11 +1,10 @@
-use super::*;
-
use rustc_ast as ast;
-use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::Ident;
-use rustc_span::DUMMY_SP;
+use rustc_span::{create_default_session_globals_then, DUMMY_SP};
use thin_vec::ThinVec;
+use super::*;
+
fn fun_to_string(
decl: &ast::FnDecl,
header: ast::FnHeader,
diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl
index eb51e56..5d9ac23 100644
--- a/compiler/rustc_attr/messages.ftl
+++ b/compiler/rustc_attr/messages.ftl
@@ -104,6 +104,9 @@
attr_unknown_version_literal =
unknown version literal format, assuming it refers to a future version
+attr_unstable_cfg_target_compact =
+ compact `cfg(target(..))` is experimental and subject to change
+
attr_unsupported_literal_cfg_string =
literal in `cfg` predicate value must be a string
attr_unsupported_literal_deprecated_kv_pair =
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 34c24a2..d057dcf 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -1,8 +1,12 @@
//! Parsing and validation of builtin attributes
+use std::num::NonZero;
+
use rustc_abi::Align;
-use rustc_ast::{self as ast, attr};
-use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId};
+use rustc_ast::{
+ self as ast, attr, Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem,
+ NodeId,
+};
use rustc_ast_pretty::pprust;
use rustc_errors::ErrorGuaranteed;
use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg};
@@ -13,9 +17,10 @@
use rustc_session::parse::feature_err;
use rustc_session::{RustcVersion, Session};
use rustc_span::hygiene::Transparency;
-use rustc_span::{symbol::sym, symbol::Symbol, Span};
-use std::num::NonZero;
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::Span;
+use crate::fluent_generated;
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
/// The version placeholder that recently stabilized features contain inside the
@@ -517,7 +522,6 @@ pub struct Condition {
}
/// Tests if a cfg-pattern matches the cfg set
-#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
pub fn cfg_matches(
cfg: &ast::MetaItem,
sess: &Session,
@@ -574,7 +578,7 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Fea
/// Parse a rustc version number written inside string literal in an attribute,
/// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are
/// not accepted in this position, unlike when parsing CFG_RELEASE.
-fn parse_version(s: Symbol) -> Option<RustcVersion> {
+pub fn parse_version(s: Symbol) -> Option<RustcVersion> {
let mut components = s.as_str().split('-');
let d = components.next()?;
if components.next().is_some() {
@@ -589,7 +593,6 @@ fn parse_version(s: Symbol) -> Option<RustcVersion> {
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
/// evaluate individual items.
-#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
pub fn eval_condition(
cfg: &ast::MetaItem,
sess: &Session,
@@ -661,12 +664,12 @@ pub fn eval_condition(
res & eval_condition(mi.meta_item().unwrap(), sess, features, eval)
}),
sym::not => {
- if mis.len() != 1 {
+ let [mi] = mis.as_slice() else {
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
return false;
- }
+ };
- !eval_condition(mis[0].meta_item().unwrap(), sess, features, eval)
+ !eval_condition(mi.meta_item().unwrap(), sess, features, eval)
}
sym::target => {
if let Some(features) = features
@@ -676,7 +679,7 @@ pub fn eval_condition(
sess,
sym::cfg_target_compact,
cfg.span,
- "compact `cfg(target(..))` is experimental and subject to change",
+ fluent_generated::attr_unstable_cfg_target_compact,
)
.emit();
}
@@ -1047,10 +1050,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
MetaItemKind::List(nested_items) => {
if meta_item.has_name(sym::align) {
recognised = true;
- if nested_items.len() == 1 {
+ if let [nested_item] = nested_items.as_slice() {
sess.dcx().emit_err(
session_diagnostics::IncorrectReprFormatExpectInteger {
- span: nested_items[0].span(),
+ span: nested_item.span(),
},
);
} else {
@@ -1062,10 +1065,10 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
}
} else if meta_item.has_name(sym::packed) {
recognised = true;
- if nested_items.len() == 1 {
+ if let [nested_item] = nested_items.as_slice() {
sess.dcx().emit_err(
session_diagnostics::IncorrectReprFormatPackedExpectInteger {
- span: nested_items[0].span(),
+ span: nested_item.span(),
},
);
} else {
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index 9cc53ad..1ecfc42 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -15,12 +15,10 @@
mod session_diagnostics;
pub use builtin::*;
+pub use rustc_ast::attr::*;
+pub(crate) use rustc_session::HashStableContext;
pub use IntType::*;
pub use ReprAttr::*;
pub use StabilityLevel::*;
-pub use rustc_ast::attr::*;
-
-pub(crate) use rustc_session::HashStableContext;
-
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 0cffeed..92a3a38 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -1,13 +1,12 @@
use std::num::IntErrorKind;
use rustc_ast as ast;
-use rustc_errors::DiagCtxtHandle;
-use rustc_errors::{codes::*, Applicability, Diag, Diagnostic, EmissionGuarantee, Level};
+use rustc_errors::codes::*;
+use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
-use crate::fluent_generated as fluent;
-use crate::UnsupportedLiteralReason;
+use crate::{fluent_generated as fluent, UnsupportedLiteralReason};
#[derive(Diagnostic)]
#[diag(attr_expected_one_cfg_pattern, code = E0536)]
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index c14a617..edb25e12 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -62,6 +62,9 @@
borrowck_could_not_prove =
could not prove `{$predicate}`
+borrowck_dereference_suggestion =
+ dereference the return value
+
borrowck_func_take_self_moved_place =
`{$func}` takes ownership of the receiver `self`, which moves {$place_name}
@@ -74,9 +77,24 @@
borrowck_higher_ranked_subtype_error =
higher-ranked subtype error
+borrowck_implicit_static =
+ this has an implicit `'static` lifetime requirement
+
+borrowck_implicit_static_introduced =
+ calling this method introduces the `impl`'s `'static` requirement
+
+borrowck_implicit_static_relax =
+ consider relaxing the implicit `'static` requirement
+
borrowck_lifetime_constraints_error =
lifetime may not live long enough
+borrowck_limitations_implies_static =
+ due to current limitations in the borrow checker, this implies a `'static` lifetime
+
+borrowck_move_closure_suggestion =
+ consider adding 'move' keyword before the nested closure
+
borrowck_move_out_place_here =
{$place} is moved here
@@ -163,6 +181,9 @@
*[false] moved
} due to use in coroutine
+borrowck_restrict_to_static =
+ consider restricting the type parameter to the `'static` lifetime
+
borrowck_returned_async_block_escaped =
returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 0bae1bd..51b420c 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -1,16 +1,17 @@
-use crate::path_utils::allow_two_phase_borrow;
-use crate::place_ext::PlaceExt;
-use crate::BorrowIndex;
+use std::fmt;
+use std::ops::Index;
+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{self, Body, Local, Location};
+use rustc_middle::mir::{self, traversal, Body, Local, Location};
use rustc_middle::span_bug;
use rustc_middle::ty::{RegionVid, TyCtxt};
use rustc_mir_dataflow::move_paths::MoveData;
-use std::fmt;
-use std::ops::Index;
+
+use crate::path_utils::allow_two_phase_borrow;
+use crate::place_ext::PlaceExt;
+use crate::BorrowIndex;
pub struct BorrowSet<'tcx> {
/// The fundamental map relating bitvector indexes to the borrows
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 80deea1..76e39fe 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,8 +1,8 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-use rustc_errors::Applicability;
-use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, Diag, DiagCtxtHandle};
use rustc_hir as hir;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs
index 540b466..0ae8378 100644
--- a/compiler/rustc_borrowck/src/constraints/graph.rs
+++ b/compiler/rustc_borrowck/src/constraints/graph.rs
@@ -4,11 +4,8 @@
use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
use rustc_span::DUMMY_SP;
-use crate::{
- constraints::OutlivesConstraintIndex,
- constraints::{OutlivesConstraint, OutlivesConstraintSet},
- type_check::Locations,
-};
+use crate::constraints::{OutlivesConstraint, OutlivesConstraintIndex, OutlivesConstraintSet};
+use crate::type_check::Locations;
/// The construct graph organizes the constraints by their end-points.
/// It can be used to view a `R1: R2` constraint as either an edge `R1
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index bb2fc3b..7062632 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -1,12 +1,14 @@
-use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker};
-use crate::type_check::Locations;
-use crate::universal_regions::UniversalRegions;
+use std::fmt;
+use std::ops::Index;
+
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{RegionVid, TyCtxt, VarianceDiagInfo};
use rustc_span::Span;
-use std::fmt;
-use std::ops::Index;
+
+use crate::region_infer::{ConstraintSccs, RegionDefinition, RegionTracker};
+use crate::type_check::Locations;
+use crate::universal_regions::UniversalRegions;
pub(crate) mod graph;
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index b9fa46e..8f56063 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -1,24 +1,22 @@
//! This file provides API for compiler consumers.
+use std::rc::Rc;
+
use rustc_hir::def_id::LocalDefId;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::{Body, Promoted};
use rustc_middle::ty::TyCtxt;
-use std::rc::Rc;
+pub use super::constraints::OutlivesConstraint;
+pub use super::dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows};
+pub use super::facts::{AllFacts as PoloniusInput, RustcFacts};
+pub use super::location::{LocationTable, RichLocation};
+pub use super::nll::PoloniusOutput;
+pub use super::place_ext::PlaceExt;
+pub use super::places_conflict::{places_conflict, PlaceConflictBias};
+pub use super::region_infer::RegionInferenceContext;
use crate::borrow_set::BorrowSet;
-pub use super::{
- constraints::OutlivesConstraint,
- dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows},
- facts::{AllFacts as PoloniusInput, RustcFacts},
- location::{LocationTable, RichLocation},
- nll::PoloniusOutput,
- place_ext::PlaceExt,
- places_conflict::{places_conflict, PlaceConflictBias},
- region_infer::RegionInferenceContext,
-};
-
/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
///
/// If executing under `-Z polonius` the choice here has no effect, and everything as if
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 59b3c69..77794a8 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -1,16 +1,15 @@
+use std::fmt;
+
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::graph;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::{
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
};
-use rustc_middle::ty::RegionVid;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
-use rustc_mir_dataflow::ResultsVisitable;
-use rustc_mir_dataflow::{fmt::DebugWithContext, GenKill};
-use rustc_mir_dataflow::{Analysis, AnalysisDomain, Results};
-use std::fmt;
+use rustc_mir_dataflow::{Analysis, AnalysisDomain, GenKill, Results, ResultsVisitable};
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index cbee01f..52eda721 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -1,17 +1,18 @@
+use std::fmt;
+use std::rc::Rc;
+
use rustc_errors::Diag;
use rustc_hir::def_id::LocalDefId;
use rustc_infer::infer::canonical::Canonical;
-use rustc_infer::infer::region_constraints::Constraint;
-use rustc_infer::infer::region_constraints::RegionConstraintData;
-use rustc_infer::infer::RegionVariableOrigin;
-use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
+use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
+use rustc_infer::infer::{
+ InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _,
+};
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::RePlaceholder;
-use rustc_middle::ty::Region;
-use rustc_middle::ty::RegionVid;
-use rustc_middle::ty::UniverseIndex;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{
+ self, RePlaceholder, Region, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex,
+};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -19,13 +20,10 @@
use rustc_trait_selection::traits::ObligationCtxt;
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
-use std::fmt;
-use std::rc::Rc;
-
use crate::region_infer::values::RegionElement;
-use crate::session_diagnostics::HigherRankedErrorCause;
-use crate::session_diagnostics::HigherRankedLifetimeError;
-use crate::session_diagnostics::HigherRankedSubtypeError;
+use crate::session_diagnostics::{
+ HigherRankedErrorCause, HigherRankedLifetimeError, HigherRankedSubtypeError,
+};
use crate::MirBorrowckCtxt;
#[derive(Clone)]
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6fe50ad..a58c7c4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -3,25 +3,27 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
+use std::iter;
+use std::ops::ControlFlow;
+
use either::Either;
use hir::{ClosureKind, Path};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_block, walk_expr, Map, Visitor};
-use rustc_hir::{CoroutineDesugaring, PatField};
-use rustc_hir::{CoroutineKind, CoroutineSource, LangItem};
+use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
-use rustc_middle::mir::VarDebugInfoContents;
use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
- TerminatorKind, VarBindingForm,
+ TerminatorKind, VarBindingForm, VarDebugInfoContents,
};
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
@@ -30,8 +32,7 @@
};
use rustc_middle::util::CallKind;
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
-use rustc_span::def_id::DefId;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, Symbol};
@@ -39,22 +40,14 @@
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
-use std::iter;
-use std::ops::ControlFlow;
-use crate::borrow_set::TwoPhaseActivation;
-use crate::borrowck_errors;
+use super::explain_borrow::{BorrowExplanation, LaterUseKind};
+use super::{DescribePlaceOpt, RegionName, RegionNameSource, UseSpans};
+use crate::borrow_set::{BorrowData, TwoPhaseActivation};
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
-use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
-use crate::{
- borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
- InitializationRequiringAction, MirBorrowckCtxt, WriteKind,
-};
-
-use super::{
- explain_borrow::{BorrowExplanation, LaterUseKind},
- DescribePlaceOpt, RegionName, RegionNameSource, UseSpans,
-};
+use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt, Instance};
+use crate::prefixes::IsPrefixOf;
+use crate::{borrowck_errors, InitializationRequiringAction, MirBorrowckCtxt, WriteKind};
#[derive(Debug)]
struct MoveSite {
@@ -570,11 +563,11 @@ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
} = move_spans
&& can_suggest_clone
{
- self.suggest_cloning(err, ty, expr, None, Some(move_spans));
+ self.suggest_cloning(err, ty, expr, Some(move_spans));
} else if self.suggest_hoisting_call_outside_loop(err, expr) && can_suggest_clone {
// The place where the type moves would be misleading to suggest clone.
// #121466
- self.suggest_cloning(err, ty, expr, None, Some(move_spans));
+ self.suggest_cloning(err, ty, expr, Some(move_spans));
}
}
@@ -1131,8 +1124,8 @@ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) -> Self::Result {
err.multipart_suggestion(
"consider moving the expression out of the loop so it is only moved once",
vec![
- (parent.span, "value".to_string()),
(span.shrink_to_lo(), format!("let mut value = {value};{indent}")),
+ (parent.span, "value".to_string()),
],
Applicability::MaybeIncorrect,
);
@@ -1236,8 +1229,7 @@ pub(crate) fn suggest_cloning(
&self,
err: &mut Diag<'_>,
ty: Ty<'tcx>,
- mut expr: &'tcx hir::Expr<'tcx>,
- mut other_expr: Option<&'tcx hir::Expr<'tcx>>,
+ expr: &'tcx hir::Expr<'tcx>,
use_spans: Option<UseSpans<'tcx>>,
) {
if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
@@ -1249,66 +1241,6 @@ pub(crate) fn suggest_cloning(
return;
}
- if let Some(some_other_expr) = other_expr
- && let Some(parent_binop) =
- self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
- if let (hir_id, hir::Node::Expr(e)) = n
- && let hir::ExprKind::AssignOp(_binop, target, _arg) = e.kind
- && target.hir_id == expr.hir_id
- {
- Some(hir_id)
- } else {
- None
- }
- })
- && let Some(other_parent_binop) =
- self.infcx.tcx.hir().parent_iter(some_other_expr.hir_id).find_map(|n| {
- if let (hir_id, hir::Node::Expr(expr)) = n
- && let hir::ExprKind::AssignOp(..) = expr.kind
- {
- Some(hir_id)
- } else {
- None
- }
- })
- && parent_binop == other_parent_binop
- {
- // Explicitly look for `expr += other_expr;` and avoid suggesting
- // `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
- other_expr = Some(expr);
- expr = some_other_expr;
- }
- 'outer: {
- if let ty::Ref(..) = ty.kind() {
- // We check for either `let binding = foo(expr, other_expr);` or
- // `foo(expr, other_expr);` and if so we don't suggest an incorrect
- // `foo(expr, other_expr).clone()`
- if let Some(other_expr) = other_expr
- && let Some(parent_let) =
- self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
- if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
- Some(hir_id)
- } else {
- None
- }
- })
- && let Some(other_parent_let) =
- self.infcx.tcx.hir().parent_iter(other_expr.hir_id).find_map(|n| {
- if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
- Some(hir_id)
- } else {
- None
- }
- })
- && parent_let == other_parent_let
- {
- // Explicitly check that we don't have `foo(&*expr, other_expr)`, as cloning the
- // result of `foo(...)` won't help.
- break 'outer;
- }
- }
- }
- let ty = ty.peel_refs();
if self.implements_clone(ty) {
self.suggest_cloning_inner(err, ty, expr);
} else if let ty::Adt(def, args) = ty.kind()
@@ -1580,10 +1512,27 @@ pub(crate) fn report_move_out_while_borrowed(
);
self.suggest_copy_for_type_in_cloned_ref(&mut err, place);
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
- if let Some(expr) = self.find_expr(borrow_span)
- && let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
- {
- self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
+ if let Some(expr) = self.find_expr(borrow_span) {
+ // This is a borrow span, so we want to suggest cloning the referent.
+ if let hir::ExprKind::AddrOf(_, _, borrowed_expr) = expr.kind
+ && let Some(ty) = typeck_results.expr_ty_opt(borrowed_expr)
+ {
+ self.suggest_cloning(&mut err, ty, borrowed_expr, Some(move_spans));
+ } else if typeck_results.expr_adjustments(expr).first().is_some_and(|adj| {
+ matches!(
+ adj.kind,
+ ty::adjustment::Adjust::Borrow(ty::adjustment::AutoBorrow::Ref(
+ _,
+ ty::adjustment::AutoBorrowMutability::Not
+ | ty::adjustment::AutoBorrowMutability::Mut {
+ allow_two_phase_borrow: ty::adjustment::AllowTwoPhase::No
+ }
+ ))
+ )
+ }) && let Some(ty) = typeck_results.expr_ty_opt(expr)
+ {
+ self.suggest_cloning(&mut err, ty, expr, Some(move_spans));
+ }
}
self.buffer_error(err);
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index ffe52f9..d85959c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -3,6 +3,8 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
+use std::assert_matches::assert_matches;
+
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
@@ -19,13 +21,11 @@
use rustc_span::{sym, DesugaringKind, Span};
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
-use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
-use crate::{
- borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
- WriteKind,
-};
-
use super::{find_use, RegionName, UseSpans};
+use crate::borrow_set::BorrowData;
+use crate::nll::ConstraintDescription;
+use crate::region_infer::{BlameConstraint, Cause, ExtraConstraintInfo};
+use crate::{MirBorrowckCtxt, WriteKind};
#[derive(Debug)]
pub(crate) enum BorrowExplanation<'tcx> {
@@ -118,7 +118,7 @@ pub(crate) fn add_explanation_to_diagnostic(
// path_span must be `Some` as otherwise the if condition is true
let path_span = path_span.unwrap();
// path_span is only present in the case of closure capture
- assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture));
+ assert_matches!(later_use_kind, LaterUseKind::ClosureCapture);
if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) {
let path_label = "used here by closure";
let capture_kind_label = message;
@@ -149,7 +149,7 @@ pub(crate) fn add_explanation_to_diagnostic(
// path_span must be `Some` as otherwise the if condition is true
let path_span = path_span.unwrap();
// path_span is only present in the case of closure capture
- assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture));
+ assert_matches!(later_use_kind, LaterUseKind::ClosureCapture);
if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) {
let path_label = "used here by closure";
let capture_kind_label = message;
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index 94b17e0..bea8d3b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -1,15 +1,14 @@
use std::collections::VecDeque;
use std::rc::Rc;
-use crate::{
- def_use::{self, DefUse},
- region_infer::{Cause, RegionInferenceContext},
-};
use rustc_data_structures::fx::FxIndexSet;
use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc_middle::mir::{self, Body, Local, Location};
use rustc_middle::ty::{RegionVid, TyCtxt};
+use crate::def_use::{self, DefUse};
+use crate::region_infer::{Cause, RegionInferenceContext};
+
pub(crate) fn find<'tcx>(
body: &Body<'tcx>,
regioncx: &Rc<RegionInferenceContext<'tcx>>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index d505d9c..a2e5c7b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1,14 +1,8 @@
//! Borrow checker diagnostics.
-use crate::session_diagnostics::{
- CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
- CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
-};
-use rustc_errors::MultiSpan;
-use rustc_errors::{Applicability, Diag};
+use rustc_errors::{Applicability, Diag, MultiSpan};
use rustc_hir::def::{CtorKind, Namespace};
-use rustc_hir::CoroutineKind;
-use rustc_hir::{self as hir, LangItem};
+use rustc_hir::{self as hir, CoroutineKind, LangItem};
use rustc_index::IndexSlice;
use rustc_infer::infer::BoundRegionConversionTime;
use rustc_infer::traits::SelectionError;
@@ -25,7 +19,8 @@
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::def_id::LocalDefId;
use rustc_span::source_map::Spanned;
-use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
+use rustc_span::symbol::sym;
+use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtExt;
@@ -33,10 +28,13 @@
type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
};
-use crate::fluent_generated as fluent;
-
use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
+use crate::fluent_generated as fluent;
+use crate::session_diagnostics::{
+ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
+ CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
+};
mod find_all_local_uses;
mod find_use;
@@ -599,8 +597,9 @@ pub(super) fn var_path_only_subdiag(
err: &mut Diag<'_>,
action: crate::InitializationRequiringAction,
) {
- use crate::InitializationRequiringAction::*;
use CaptureVarPathUseCause::*;
+
+ use crate::InitializationRequiringAction::*;
if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self {
match closure_kind {
hir::ClosureKind::Coroutine(_) => {
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index fcf23aa..792f154 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -11,8 +11,7 @@
use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
-use crate::diagnostics::CapturedMessageOpt;
-use crate::diagnostics::{DescribePlaceOpt, UseSpans};
+use crate::diagnostics::{CapturedMessageOpt, DescribePlaceOpt, UseSpans};
use crate::prefixes::PrefixSet;
use crate::MirBorrowckCtxt;
@@ -565,9 +564,7 @@ fn report_cannot_move_from_borrowed_content(
fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) {
match error {
- GroupedMoveError::MovesFromPlace {
- mut binds_to, move_from, span: other_span, ..
- } => {
+ GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
self.add_borrow_suggestions(err, span);
if binds_to.is_empty() {
let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
@@ -577,7 +574,7 @@ fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span
};
if let Some(expr) = self.find_expr(span) {
- self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span), None);
+ self.suggest_cloning(err, place_ty, expr, None);
}
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
@@ -609,13 +606,7 @@ fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span
};
if let Some(expr) = self.find_expr(use_span) {
- self.suggest_cloning(
- err,
- place_ty,
- expr,
- self.find_expr(span),
- Some(use_spans),
- );
+ self.suggest_cloning(err, place_ty, expr, Some(use_spans));
}
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
@@ -740,7 +731,7 @@ fn add_move_error_details(&self, err: &mut Diag<'_>, binds_to: &[Local]) {
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
if let Some(expr) = self.find_expr(binding_span) {
- self.suggest_cloning(err, bind_to.ty, expr, None, None);
+ self.suggest_cloning(err, bind_to.ty, expr, None);
}
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index a7bf6d6..0303b80 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -2,17 +2,18 @@
#![allow(rustc::untranslatable_diagnostic)]
use core::ops::ControlFlow;
+
use hir::{ExprKind, Param};
use rustc_errors::{Applicability, Diag};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, BindingMode, ByRef, Node};
use rustc_middle::bug;
-use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
-use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Upcast};
-use rustc_middle::{
- hir::place::PlaceBase,
- mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
+use rustc_middle::hir::place::PlaceBase;
+use rustc_middle::mir::{
+ self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location, Mutability, Place,
+ PlaceRef, ProjectionElem,
};
+use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Upcast};
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, BytePos, DesugaringKind, Span};
use rustc_target::abi::FieldIdx;
@@ -847,10 +848,8 @@ fn show_mutating_upvar(
// Attempt to search similar mutable associated items for suggestion.
// In the future, attempt in all path but initially for RHS of for_loop
fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diag<'_>, span: Span) {
- use hir::{
- BorrowKind, Expr,
- ExprKind::{AddrOf, Block, Call, MethodCall},
- };
+ use hir::ExprKind::{AddrOf, Block, Call, MethodCall};
+ use hir::{BorrowKind, Expr};
let hir_map = self.infcx.tcx.hir();
struct Finder {
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index 082111a..de0df34 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -4,15 +4,15 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
+use std::collections::BTreeMap;
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diag;
use rustc_middle::ty::RegionVid;
use smallvec::SmallVec;
-use std::collections::BTreeMap;
-
-use crate::MirBorrowckCtxt;
use super::{ErrorConstraintInfo, RegionName, RegionNameSource};
+use crate::MirBorrowckCtxt;
/// The different things we could suggest.
enum SuggestedConstraint {
@@ -206,8 +206,8 @@ pub(crate) fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_, '_, '_>)
// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
// list of diagnostics.
- let mut diag = if suggested.len() == 1 {
- mbcx.dcx().struct_help(match suggested.last().unwrap() {
+ let mut diag = if let [constraint] = suggested.as_slice() {
+ mbcx.dcx().struct_help(match constraint {
SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
format!("add bound `{a}: {}`", bs.join(" + "))
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 6b7bd7dc..451e8bc 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -14,10 +14,7 @@
use rustc_middle::bug;
use rustc_middle::hir::place::PlaceBase;
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::TypeVisitor;
-use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_middle::ty::{Region, TyCtxt};
+use rustc_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor};
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::infer::nice_region_error::{
@@ -29,20 +26,16 @@
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
-use crate::borrowck_errors;
+use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
+use crate::nll::ConstraintDescription;
+use crate::region_infer::values::RegionElement;
+use crate::region_infer::{BlameConstraint, ExtraConstraintInfo, TypeTest};
use crate::session_diagnostics::{
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
};
-
-use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
-use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
-use crate::{
- nll::ConstraintDescription,
- region_infer::{values::RegionElement, TypeTest},
- universal_regions::DefiningTy,
- MirBorrowckCtxt,
-};
+use crate::universal_regions::DefiningTy;
+use crate::{borrowck_errors, fluent_generated as fluent, MirBorrowckCtxt};
impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
fn description(&self) -> &'static str {
@@ -205,7 +198,6 @@ fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
// from higher-ranked trait bounds (HRTB). Try to locate span of the trait
// and the span which bounded to the trait for adding 'static lifetime suggestion
#[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn suggest_static_lifetime_for_gat_from_hrtb(
&self,
diag: &mut Diag<'_>,
@@ -258,23 +250,28 @@ fn suggest_static_lifetime_for_gat_from_hrtb(
debug!(?hrtb_bounds);
hrtb_bounds.iter().for_each(|bound| {
- let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else { return; };
- diag.span_note(
- *trait_span,
- "due to current limitations in the borrow checker, this implies a `'static` lifetime"
- );
- let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local()) else { return; };
- let Def(_, trait_res_defid) = trait_ref.path.res else { return; };
+ let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else {
+ return;
+ };
+ diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static);
+ let Some(generics_fn) = hir.get_generics(self.body.source.def_id().expect_local())
+ else {
+ return;
+ };
+ let Def(_, trait_res_defid) = trait_ref.path.res else {
+ return;
+ };
debug!(?generics_fn);
generics_fn.predicates.iter().for_each(|predicate| {
- let BoundPredicate(
- WhereBoundPredicate {
- span: bounded_span,
- bounded_ty,
- bounds,
- ..
- }
- ) = predicate else { return; };
+ let BoundPredicate(WhereBoundPredicate {
+ span: bounded_span,
+ bounded_ty,
+ bounds,
+ ..
+ }) = predicate
+ else {
+ return;
+ };
bounds.iter().for_each(|bd| {
if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }, _) = bd
&& let Def(_, res_defid) = tr_ref.path.res
@@ -284,16 +281,17 @@ fn suggest_static_lifetime_for_gat_from_hrtb(
&& generics_fn.params
.iter()
.rfind(|param| param.def_id.to_def_id() == defid)
- .is_some() {
- suggestions.push((bounded_span.shrink_to_hi(), " + 'static".to_string()));
- }
+ .is_some()
+ {
+ suggestions.push((bounded_span.shrink_to_hi(), " + 'static".to_string()));
+ }
});
});
});
if suggestions.len() > 0 {
suggestions.dedup();
diag.multipart_suggestion_verbose(
- "consider restricting the type parameter to the `'static` lifetime",
+ fluent::borrowck_restrict_to_static,
suggestions,
Applicability::MaybeIncorrect,
);
@@ -983,7 +981,6 @@ fn maybe_suggest_constrain_dyn_trait_impl(
}
#[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
#[instrument(skip(self, err), level = "debug")]
fn suggest_constrain_dyn_trait_in_impl(
&self,
@@ -1001,16 +998,12 @@ fn suggest_constrain_dyn_trait_in_impl(
debug!("trait spans found: {:?}", traits);
for span in &traits {
let mut multi_span: MultiSpan = vec![*span].into();
- multi_span
- .push_span_label(*span, "this has an implicit `'static` lifetime requirement");
- multi_span.push_span_label(
- ident.span,
- "calling this method introduces the `impl`'s `'static` requirement",
- );
+ multi_span.push_span_label(*span, fluent::borrowck_implicit_static);
+ multi_span.push_span_label(ident.span, fluent::borrowck_implicit_static_introduced);
err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
err.span_suggestion_verbose(
span.shrink_to_hi(),
- "consider relaxing the implicit `'static` requirement",
+ fluent::borrowck_implicit_static_relax,
" + '_",
Applicability::MaybeIncorrect,
);
@@ -1052,7 +1045,6 @@ fn suggest_adding_lifetime_params(&self, diag: &mut Diag<'_>, sub: RegionVid, su
}
#[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
/// When encountering a lifetime error caused by the return type of a closure, check the
/// corresponding trait bound and see if dereferencing the closure return value would satisfy
/// them. If so, we produce a structured suggestion.
@@ -1173,7 +1165,7 @@ fn suggest_deref_closure_return(&self, diag: &mut Diag<'_>) {
if ocx.select_all_or_error().is_empty() && count > 0 {
diag.span_suggestion_verbose(
tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
- "dereference the return value",
+ fluent::borrowck_dereference_suggestion,
"*".repeat(count),
Applicability::MachineApplicable,
);
@@ -1181,7 +1173,6 @@ fn suggest_deref_closure_return(&self, diag: &mut Diag<'_>) {
}
#[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
let map = self.infcx.tcx.hir();
let body = map.body_owned_by(self.mir_def_id());
@@ -1220,7 +1211,7 @@ fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
if let Some(closure_span) = closure_span {
diag.span_suggestion_verbose(
closure_span,
- "consider adding 'move' keyword before the nested closure",
+ fluent::borrowck_move_closure_suggestion,
"move ",
Applicability::MaybeIncorrect,
);
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 6443c5e..12aedf6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -9,14 +9,14 @@
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::print::RegionHighlightMode;
-use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
+use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, RegionVid, Ty};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
-use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
+use crate::universal_regions::DefiningTy;
+use crate::MirBorrowckCtxt;
/// A name for a particular region used in emitting diagnostics. This name could be a generated
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 0479cd8..3e9f975 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -1,10 +1,11 @@
-use crate::region_infer::RegionInferenceContext;
use rustc_index::IndexSlice;
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{self, RegionVid, TyCtxt};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use crate::region_infer::RegionInferenceContext;
+
impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn get_var_name_and_span_for_region(
&self,
diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index af96f11..94b5044 100644
--- a/compiler/rustc_borrowck/src/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -1,17 +1,18 @@
-use crate::location::{LocationIndex, LocationTable};
-use crate::BorrowIndex;
-use polonius_engine::AllFacts as PoloniusFacts;
-use polonius_engine::Atom;
-use rustc_macros::extension;
-use rustc_middle::mir::Local;
-use rustc_middle::ty::{RegionVid, TyCtxt};
-use rustc_mir_dataflow::move_paths::MovePathIndex;
use std::error::Error;
use std::fmt::Debug;
use std::fs::{self, File};
use std::io::{BufWriter, Write};
use std::path::Path;
+use polonius_engine::{AllFacts as PoloniusFacts, Atom};
+use rustc_macros::extension;
+use rustc_middle::mir::Local;
+use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_mir_dataflow::move_paths::MovePathIndex;
+
+use crate::location::{LocationIndex, LocationTable};
+use crate::BorrowIndex;
+
#[derive(Copy, Clone, Debug)]
pub struct RustcFacts;
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 9ad941d..9c2a003 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -17,6 +17,13 @@
#[macro_use]
extern crate tracing;
+use std::cell::RefCell;
+use std::collections::BTreeMap;
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::rc::Rc;
+
+use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_errors::Diag;
@@ -24,40 +31,31 @@
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
use rustc_index::{IndexSlice, IndexVec};
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
+use rustc_infer::infer::{
+ InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
+};
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt};
use rustc_middle::{bug, span_bug};
-use rustc_session::lint::builtin::UNUSED_MUT;
-use rustc_span::{Span, Symbol};
-use rustc_target::abi::FieldIdx;
-
-use smallvec::SmallVec;
-use std::cell::RefCell;
-use std::collections::BTreeMap;
-use std::marker::PhantomData;
-use std::ops::Deref;
-use std::rc::Rc;
-
use rustc_mir_dataflow::impls::{
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
};
-use rustc_mir_dataflow::move_paths::{InitIndex, MoveOutIndex, MovePathIndex};
-use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData};
+use rustc_mir_dataflow::move_paths::{
+ InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
+};
use rustc_mir_dataflow::Analysis;
-use rustc_mir_dataflow::MoveDataParamEnv;
-
-use crate::session_diagnostics::VarNeedNotMut;
+use rustc_session::lint::builtin::UNUSED_MUT;
+use rustc_span::{Span, Symbol};
+use rustc_target::abi::FieldIdx;
+use smallvec::SmallVec;
use self::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName};
use self::location::LocationTable;
-use self::prefixes::PrefixSet;
-use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
-
use self::path_utils::*;
+use self::prefixes::PrefixSet;
+use crate::session_diagnostics::VarNeedNotMut;
pub mod borrow_set;
mod borrowck_errors;
@@ -196,9 +194,7 @@ fn do_mir_borrowck<'tcx>(
.iter_enumerated()
.map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, param_env, |_| true)));
- let mdpe = MoveDataParamEnv { move_data, param_env };
-
- let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe)
+ let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint()
@@ -206,7 +202,7 @@ fn do_mir_borrowck<'tcx>(
let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure();
let borrow_set =
- Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
+ Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data));
// Compute non-lexical lifetimes.
let nll::NllOutput {
@@ -224,7 +220,7 @@ fn do_mir_borrowck<'tcx>(
&location_table,
param_env,
&mut flow_inits,
- &mdpe.move_data,
+ &move_data,
&borrow_set,
tcx.closure_captures(def),
consumer_options,
@@ -256,11 +252,11 @@ fn do_mir_borrowck<'tcx>(
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint();
- let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe)
+ let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data)
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint();
- let flow_ever_inits = EverInitializedPlaces::new(body, &mdpe)
+ let flow_ever_inits = EverInitializedPlaces::new(body, &move_data)
.into_engine(tcx, body)
.pass_name("borrowck")
.iterate_to_fixpoint();
@@ -326,7 +322,7 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
infcx: &infcx,
param_env,
body,
- move_data: &mdpe.move_data,
+ move_data: &move_data,
location_table: &location_table,
movable_coroutine,
locals_are_invalidated_at_exit,
diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs
index 5129b32..499c323 100644
--- a/compiler/rustc_borrowck/src/member_constraints.rs
+++ b/compiler/rustc_borrowck/src/member_constraints.rs
@@ -1,11 +1,12 @@
+use std::hash::Hash;
+use std::ops::Index;
+
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexMap;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::infer::MemberConstraint;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
-use std::hash::Hash;
-use std::ops::Index;
/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
/// indexed by the region `R0`.
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 2ffa9ba..af37c02 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -1,11 +1,18 @@
//! The entry point of the NLL borrow checker.
+use std::path::PathBuf;
+use std::rc::Rc;
+use std::str::FromStr;
+use std::{env, io};
+
use polonius_engine::{Algorithm, Output};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::LocalDefId;
use rustc_index::IndexSlice;
-use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
-use rustc_middle::mir::{Body, ClosureOutlivesSubject, ClosureRegionRequirements, Promoted};
+use rustc_middle::mir::{
+ create_dump_file, dump_enabled, dump_mir, Body, ClosureOutlivesSubject,
+ ClosureRegionRequirements, PassWhere, Promoted,
+};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
@@ -13,25 +20,16 @@
use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_mir_dataflow::ResultsCursor;
use rustc_span::symbol::sym;
-use std::env;
-use std::io;
-use std::path::PathBuf;
-use std::rc::Rc;
-use std::str::FromStr;
-use crate::{
- borrow_set::BorrowSet,
- consumers::ConsumerOptions,
- diagnostics::RegionErrors,
- facts::{AllFacts, AllFactsExt, RustcFacts},
- location::LocationTable,
- polonius,
- region_infer::RegionInferenceContext,
- renumber,
- type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
- universal_regions::UniversalRegions,
- BorrowckInferCtxt,
-};
+use crate::borrow_set::BorrowSet;
+use crate::consumers::ConsumerOptions;
+use crate::diagnostics::RegionErrors;
+use crate::facts::{AllFacts, AllFactsExt, RustcFacts};
+use crate::location::LocationTable;
+use crate::region_infer::RegionInferenceContext;
+use crate::type_check::{self, MirTypeckRegionConstraints, MirTypeckResults};
+use crate::universal_regions::UniversalRegions;
+use crate::{polonius, renumber, BorrowckInferCtxt};
pub type PoloniusOutput = Output<RustcFacts>;
diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs
index 88b20bb..4afb41b 100644
--- a/compiler/rustc_borrowck/src/path_utils.rs
+++ b/compiler/rustc_borrowck/src/path_utils.rs
@@ -1,13 +1,11 @@
-use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
-use crate::places_conflict;
-use crate::AccessDepth;
-use crate::BorrowIndex;
use rustc_data_structures::graph::dominators::Dominators;
-use rustc_middle::mir::BorrowKind;
-use rustc_middle::mir::{BasicBlock, Body, Location, Place, PlaceRef, ProjectionElem};
+use rustc_middle::mir::{BasicBlock, Body, BorrowKind, Location, Place, PlaceRef, ProjectionElem};
use rustc_middle::ty::TyCtxt;
use rustc_target::abi::FieldIdx;
+use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
+use crate::{places_conflict, AccessDepth, BorrowIndex};
+
/// Returns `true` if the borrow represented by `kind` is
/// allowed to be split into separate Reservation and
/// Activation phases.
diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index 0f806df..ce63d51 100644
--- a/compiler/rustc_borrowck/src/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -1,10 +1,10 @@
-use crate::borrow_set::LocalsStateAtExit;
use rustc_hir as hir;
use rustc_macros::extension;
-use rustc_middle::mir::ProjectionElem;
-use rustc_middle::mir::{Body, Mutability, Place};
+use rustc_middle::mir::{Body, Mutability, Place, ProjectionElem};
use rustc_middle::ty::{self, TyCtxt};
+use crate::borrow_set::LocalsStateAtExit;
+
#[extension(pub trait PlaceExt<'tcx>)]
impl<'tcx> Place<'tcx> {
/// Returns `true` if we can safely ignore borrows of this place.
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index ad3c3e6..42d0c20 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -50,17 +50,17 @@
//! and either equal or disjoint.
//! - If we did run out of access, the borrow can access a part of it.
-use crate::ArtificialField;
-use crate::Overlap;
-use crate::{AccessDepth, Deep, Shallow};
+use std::cmp::max;
+use std::iter;
+
use rustc_hir as hir;
use rustc_middle::bug;
use rustc_middle::mir::{
Body, BorrowKind, FakeBorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
};
use rustc_middle::ty::{self, TyCtxt};
-use std::cmp::max;
-use std::iter;
+
+use crate::{AccessDepth, ArtificialField, Deep, Overlap, Shallow};
/// When checking if a place conflicts with another place, this enum is used to influence decisions
/// where a place might be equal or disjoint with another place, such as if `a[i] == a[j]`.
diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
index 30dfc4c..f090da0 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs
@@ -2,17 +2,19 @@
use rustc_middle::bug;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
- self, BasicBlock, Body, FakeBorrowKind, Location, NonDivergingIntrinsic, Place, Rvalue,
+ self, BasicBlock, Body, BorrowKind, FakeBorrowKind, InlineAsmOperand, Location, Mutability,
+ NonDivergingIntrinsic, Operand, Place, Rvalue, Statement, StatementKind, Terminator,
+ TerminatorKind,
};
-use rustc_middle::mir::{BorrowKind, Mutability, Operand};
-use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
-use rustc_middle::mir::{Statement, StatementKind};
use rustc_middle::ty::TyCtxt;
+use crate::borrow_set::BorrowSet;
+use crate::facts::AllFacts;
+use crate::location::LocationTable;
+use crate::path_utils::*;
use crate::{
- borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, path_utils::*, AccessDepth,
- Activation, ArtificialField, BorrowIndex, Deep, LocalMutationIsAllowed, Read, ReadKind,
- ReadOrWrite, Reservation, Shallow, Write, WriteKind,
+ AccessDepth, Activation, ArtificialField, BorrowIndex, Deep, LocalMutationIsAllowed, Read,
+ ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteKind,
};
/// Emit `loan_invalidated_at` facts.
diff --git a/compiler/rustc_borrowck/src/polonius/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/loan_kills.rs
index 53adad5..d85c217 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_kills.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_kills.rs
@@ -5,7 +5,10 @@
};
use rustc_middle::ty::TyCtxt;
-use crate::{borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict};
+use crate::borrow_set::BorrowSet;
+use crate::facts::AllFacts;
+use crate::location::LocationTable;
+use crate::places_conflict;
/// Emit `loan_killed_at` and `cfg_edge` facts at the same time.
pub(super) fn emit_loan_kills<'tcx>(
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index 5d3ac1c..d3bfd1c 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -4,10 +4,10 @@
//! is borrowed. But: writing `a` is legal if `*a` is borrowed,
//! whether or not `a` is a shared or mutable reference. [...] "
-use super::MirBorrowckCtxt;
-
use rustc_middle::mir::{PlaceRef, ProjectionElem};
+use super::MirBorrowckCtxt;
+
pub trait IsPrefixOf<'tcx> {
fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool;
}
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index 53541b3..6b8dd1a 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -3,11 +3,13 @@
//! state of region inference. This code handles emitting the region
//! context internal state.
-use super::{OutlivesConstraint, RegionInferenceContext};
-use crate::type_check::Locations;
+use std::io::{self, Write};
+
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::ty::TyCtxt;
-use std::io::{self, Write};
+
+use super::{OutlivesConstraint, RegionInferenceContext};
+use crate::type_check::Locations;
// Room for "'_#NNNNr" before things get misaligned.
// Easy enough to fix if this ever doesn't seem like
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index f145d30..743864d 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -5,11 +5,12 @@
use std::borrow::Cow;
use std::io::{self, Write};
-use super::*;
use itertools::Itertools;
use rustc_graphviz as dot;
use rustc_middle::ty::UniverseIndex;
+use super::*;
+
fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
match constraint.locations {
Locations::All(_) => "All(...)".to_string(),
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 44a84fb..c8dc012d 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -17,27 +17,25 @@
ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
TerminatorKind,
};
-use rustc_middle::traits::ObligationCause;
-use rustc_middle::traits::ObligationCauseCode;
+use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex};
use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_span::Span;
use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph};
+use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet};
use crate::dataflow::BorrowIndex;
-use crate::{
- constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet},
- diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo},
- member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
- nll::PoloniusOutput,
- region_infer::reverse_sccs::ReverseSccGraph,
- region_infer::values::{
- LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
- },
- type_check::{free_region_relations::UniversalRegionRelations, Locations},
- universal_regions::UniversalRegions,
- BorrowckInferCtxt,
+use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo};
+use crate::member_constraints::{MemberConstraintSet, NllMemberConstraintIndex};
+use crate::nll::PoloniusOutput;
+use crate::region_infer::reverse_sccs::ReverseSccGraph;
+use crate::region_infer::values::{
+ LivenessValues, PlaceholderIndices, RegionElement, RegionValues, ToElementIndex,
};
+use crate::type_check::free_region_relations::UniversalRegionRelations;
+use crate::type_check::Locations;
+use crate::universal_regions::UniversalRegions;
+use crate::BorrowckInferCtxt;
mod dump_mir;
mod graphviz;
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index cf28ba2..1073ea4 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -3,22 +3,20 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
-use rustc_infer::infer::TyCtxtInferExt as _;
-use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
+use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _};
use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_macros::extension;
use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
-use rustc_middle::ty::{GenericArgKind, GenericArgs};
+use rustc_middle::ty::{
+ self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
+};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::ObligationCtxt;
-use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
-use crate::session_diagnostics::NonGenericOpaqueTypeParam;
-use crate::universal_regions::RegionClassification;
-
use super::RegionInferenceContext;
+use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam};
+use crate::universal_regions::RegionClassification;
impl<'tcx> RegionInferenceContext<'tcx> {
/// Resolve any opaque types that were encountered while borrow checking
@@ -227,21 +225,26 @@ pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
// Find something that we can name
let upper_bound = self.approx_universal_upper_bound(vid);
- let upper_bound = &self.definitions[upper_bound];
- match upper_bound.external_name {
- Some(reg) => reg,
- None => {
- // Nothing exact found, so we pick the first one that we find.
- let scc = self.constraint_sccs.scc(vid);
- for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
- match self.definitions[vid].external_name {
- None => {}
- Some(region) if region.is_static() => {}
- Some(region) => return region,
- }
- }
- region
- }
+ if let Some(universal_region) = self.definitions[upper_bound].external_name {
+ return universal_region;
+ }
+
+ // Nothing exact found, so we pick a named upper bound, if there's only one.
+ // If there's >1 universal region, then we probably are dealing w/ an intersection
+ // region which cannot be mapped back to a universal.
+ // FIXME: We could probably compute the LUB if there is one.
+ let scc = self.constraint_sccs.scc(vid);
+ let upper_bounds: Vec<_> = self
+ .rev_scc_graph
+ .as_ref()
+ .unwrap()
+ .upper_bounds(scc)
+ .filter_map(|vid| self.definitions[vid].external_name)
+ .filter(|r| !r.is_static())
+ .collect();
+ match &upper_bounds[..] {
+ [universal_region] => *universal_region,
+ _ => region,
}
}
_ => region,
diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index 97ddc45..3cc5fa4 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -1,10 +1,12 @@
-use crate::constraints::ConstraintSccIndex;
-use crate::RegionInferenceContext;
+use std::ops::Range;
+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph;
use rustc_data_structures::graph::vec_graph::VecGraph;
use rustc_middle::ty::RegionVid;
-use std::ops::Range;
+
+use crate::constraints::ConstraintSccIndex;
+use crate::RegionInferenceContext;
pub(crate) struct ReverseSccGraph {
graph: VecGraph<ConstraintSccIndex>,
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index b1caaa6..1e91130 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -1,14 +1,13 @@
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::fx::FxIndexSet;
+use std::fmt::Debug;
+use std::rc::Rc;
+
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_index::bit_set::SparseBitMatrix;
-use rustc_index::interval::IntervalSet;
-use rustc_index::interval::SparseIntervalMatrix;
+use rustc_index::interval::{IntervalSet, SparseIntervalMatrix};
use rustc_index::Idx;
use rustc_middle::mir::{BasicBlock, Location};
use rustc_middle::ty::{self, RegionVid};
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
-use std::fmt::Debug;
-use std::rc::Rc;
use crate::BorrowIndex;
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 2858a40..2a3b515 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -1,12 +1,12 @@
-use crate::BorrowckInferCtxt;
use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::visit::{MutVisitor, TyContext};
use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable};
use rustc_span::Symbol;
+use crate::BorrowckInferCtxt;
+
/// Replaces all free regions appearing in the MIR with fresh
/// inference variables, returning the number of variables created.
#[instrument(skip(infcx, body, promoted), level = "debug")]
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 40c2ef1..4a50b0f 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -1,4 +1,5 @@
-use rustc_errors::{codes::*, MultiSpan};
+use rustc_errors::codes::*;
+use rustc_errors::MultiSpan;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{GenericArg, Ty};
use rustc_span::Span;
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 2dc2568..b58691f 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -7,12 +7,12 @@
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
use rustc_span::def_id::DefId;
use rustc_span::Span;
+use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use rustc_trait_selection::traits::ObligationCause;
-use crate::diagnostics::ToUniverseInfo;
-
use super::{Locations, NormalizeLocation, TypeChecker};
+use crate::diagnostics::ToUniverseInfo;
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// Given some operation `op` that manipulates types, proves
@@ -167,6 +167,52 @@ pub(super) fn normalize_with_category<T>(
}
#[instrument(skip(self), level = "debug")]
+ pub(super) fn struct_tail(
+ &mut self,
+ ty: Ty<'tcx>,
+ location: impl NormalizeLocation,
+ ) -> Ty<'tcx> {
+ let tcx = self.tcx();
+ if self.infcx.next_trait_solver() {
+ let body = self.body;
+ let param_env = self.param_env;
+ self.fully_perform_op(
+ location.to_locations(),
+ ConstraintCategory::Boring,
+ CustomTypeOp::new(
+ |ocx| {
+ let structurally_normalize = |ty| {
+ ocx.structurally_normalize(
+ &ObligationCause::misc(
+ location.to_locations().span(body),
+ body.source.def_id().expect_local(),
+ ),
+ param_env,
+ ty,
+ )
+ .unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR"))
+ };
+
+ let tail = tcx.struct_tail_raw(
+ ty,
+ structurally_normalize,
+ || {},
+ );
+
+ Ok(tail)
+ },
+ "normalizing struct tail",
+ ),
+ )
+ .unwrap_or_else(|guar| Ty::new_error(tcx, guar))
+ } else {
+ let mut normalize = |ty| self.normalize(ty, location);
+ let tail = tcx.struct_tail_raw(ty, &mut normalize, || {});
+ normalize(tail)
+ }
+ }
+
+ #[instrument(skip(self), level = "debug")]
pub(super) fn ascribe_user_type(
&mut self,
mir_ty: Ty<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 0cb4b15..9876f44 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -14,12 +14,10 @@
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
use rustc_trait_selection::traits::ScrubbedTraitError;
-use crate::{
- constraints::OutlivesConstraint,
- region_infer::TypeTest,
- type_check::{Locations, MirTypeckRegionConstraints},
- universal_regions::UniversalRegions,
-};
+use crate::constraints::OutlivesConstraint;
+use crate::region_infer::TypeTest;
+use crate::type_check::{Locations, MirTypeckRegionConstraints};
+use crate::universal_regions::UniversalRegions;
pub(crate) struct ConstraintConversion<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index e4c2e0f..b7fb996 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -1,11 +1,12 @@
+use std::rc::Rc;
+
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
use rustc_hir::def::DefKind;
use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::infer::outlives;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::region_constraints::GenericKind;
-use rustc_infer::infer::InferCtxt;
+use rustc_infer::infer::{outlives, InferCtxt};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::traits::ObligationCause;
@@ -14,14 +15,10 @@
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::solve::deeply_normalize;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
-use std::rc::Rc;
use type_op::TypeOpOutput;
-use crate::{
- type_check::constraint_conversion,
- type_check::{Locations, MirTypeckRegionConstraints},
- universal_regions::UniversalRegions,
-};
+use crate::type_check::{constraint_conversion, Locations, MirTypeckRegionConstraints};
+use crate::universal_regions::UniversalRegions;
#[derive(Debug)]
pub(crate) struct UniversalRegionRelations<'tcx> {
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 741ec05..ba6030b 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -16,11 +16,10 @@
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
+use super::{Locations, TypeChecker};
use crate::renumber::RegionCtxt;
use crate::universal_regions::{DefiningTy, UniversalRegions};
-use super::{Locations, TypeChecker};
-
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// Check explicit closure signature annotation,
/// e.g., `|x: FxIndexMap<_, &'static u32>| ...`.
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 6d6425b..a320add 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -1,3 +1,5 @@
+use std::rc::Rc;
+
use itertools::{Either, Itertools};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::visit::{TyContext, Visitor};
@@ -9,14 +11,11 @@
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_mir_dataflow::ResultsCursor;
-use std::rc::Rc;
-
-use crate::{
- constraints::OutlivesConstraintSet, region_infer::values::LivenessValues,
- universal_regions::UniversalRegions,
-};
use super::TypeChecker;
+use crate::constraints::OutlivesConstraintSet;
+use crate::region_infer::values::LivenessValues;
+use crate::universal_regions::UniversalRegions;
mod local_use_map;
mod polonius;
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index a009e28a..8c13b16 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -1,11 +1,11 @@
-use crate::def_use::{self, DefUse};
-use crate::location::{LocationIndex, LocationTable};
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Place};
use rustc_middle::ty::GenericArg;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
use super::TypeChecker;
+use crate::def_use::{self, DefUse};
+use crate::location::{LocationIndex, LocationTable};
type VarPointRelation = Vec<(Local, LocationIndex)>;
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index eb86c8d..f0c521c 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -1,3 +1,5 @@
+use std::rc::Rc;
+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_index::bit_set::BitSet;
use rustc_index::interval::IntervalSet;
@@ -6,24 +8,19 @@
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc_middle::traits::query::DropckOutlivesResult;
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
+use rustc_mir_dataflow::ResultsCursor;
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
-use std::rc::Rc;
-
-use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
-use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
-use rustc_mir_dataflow::ResultsCursor;
use crate::location::RichLocation;
-use crate::{
- region_infer::values::{self, LiveLoans},
- type_check::liveness::local_use_map::LocalUseMap,
- type_check::liveness::polonius,
- type_check::NormalizeLocation,
- type_check::TypeChecker,
-};
+use crate::region_infer::values::{self, LiveLoans};
+use crate::type_check::liveness::local_use_map::LocalUseMap;
+use crate::type_check::liveness::polonius;
+use crate::type_check::{NormalizeLocation, TypeChecker};
/// This is the heart of the liveness computation. For each variable X
/// that requires a liveness computation, it walks over all the uses
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index db4b520..6bab0f3 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -4,7 +4,6 @@
use std::{fmt, iter, mem};
use either::Either;
-
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
@@ -28,44 +27,38 @@
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
- Dynamic, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType,
- UserTypeAnnotationIndex,
+ Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs,
+ UserType, UserTypeAnnotationIndex,
};
-use rustc_middle::ty::{GenericArgsRef, UserArgs};
use rustc_middle::{bug, span_bug};
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::points::DenseLocationMap;
+use rustc_mir_dataflow::ResultsCursor;
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
-use rustc_span::Span;
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
-use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
-use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
+use rustc_trait_selection::traits::query::type_op::custom::{
+ scrape_region_constraints, CustomTypeOp,
+};
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
-
use rustc_trait_selection::traits::PredicateObligation;
-use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
-use rustc_mir_dataflow::move_paths::MoveData;
-use rustc_mir_dataflow::ResultsCursor;
-
+use crate::borrow_set::BorrowSet;
+use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
+use crate::diagnostics::UniverseInfo;
+use crate::facts::AllFacts;
+use crate::location::LocationTable;
+use crate::member_constraints::MemberConstraintSet;
+use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
+use crate::region_infer::TypeTest;
use crate::renumber::RegionCtxt;
use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
-use crate::{
- borrow_set::BorrowSet,
- constraints::{OutlivesConstraint, OutlivesConstraintSet},
- diagnostics::UniverseInfo,
- facts::AllFacts,
- location::LocationTable,
- member_constraints::MemberConstraintSet,
- path_utils,
- region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices},
- region_infer::TypeTest,
- type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
- universal_regions::{DefiningTy, UniversalRegions},
- BorrowckInferCtxt,
-};
+use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
+use crate::universal_regions::{DefiningTy, UniversalRegions};
+use crate::{path_utils, BorrowckInferCtxt};
macro_rules! span_mirbug {
($context:expr, $elem:expr, $($message:tt)*) => ({
@@ -2336,11 +2329,8 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
- let mut normalize = |t| self.normalize(t, location);
- let src_tail =
- tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ());
- let dst_tail =
- tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ());
+ let src_tail = self.struct_tail(src.ty, location);
+ let dst_tail = self.struct_tail(dst.ty, location);
// This checks (lifetime part of) vtable validity for pointer casts,
// which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 9f5fb59..1ad80cb 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -15,6 +15,9 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
+use std::cell::Cell;
+use std::iter;
+
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Diag;
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -25,13 +28,12 @@
use rustc_macros::extension;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::ty::{
+ self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt,
+};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{kw, sym};
use rustc_span::{ErrorGuaranteed, Symbol};
-use std::cell::Cell;
-use std::iter;
use crate::renumber::RegionCtxt;
use crate::BorrowckInferCtxt;
diff --git a/compiler/rustc_borrowck/src/util/collect_writes.rs b/compiler/rustc_borrowck/src/util/collect_writes.rs
index 8d92bb3..93c7810 100644
--- a/compiler/rustc_borrowck/src/util/collect_writes.rs
+++ b/compiler/rustc_borrowck/src/util/collect_writes.rs
@@ -1,5 +1,4 @@
-use rustc_middle::mir::visit::PlaceContext;
-use rustc_middle::mir::visit::Visitor;
+use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location};
pub trait FindAssignments {
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index a30ab23..9695df9 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -115,9 +115,6 @@
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
.suggestion = remove the value
-builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)`
- .suggestion = remove the `unsafe(...)`
-
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
.custom = use `std::env::var({$var_expr})` to read the variable at run time
@@ -199,6 +196,9 @@
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
+builtin_macros_global_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `global_asm!`
+ .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it
+
builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
.label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
.suggestion = remove this option
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 4721e74..1df2812 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -1,14 +1,15 @@
-use crate::errors;
-use crate::util::check_builtin_macro_attribute;
-
use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, FnHeader, FnSig, Generics, StmtKind};
-use rustc_ast::{Fn, ItemKind, Safety, Stmt, TyKind};
+use rustc_ast::{
+ self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
+};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::errors;
+use crate::util::check_builtin_macro_attribute;
+
pub(crate) fn expand(
ecx: &mut ExtCtxt<'_>,
_span: Span,
@@ -79,7 +80,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)];
let decl = cx.fn_decl(params, never);
let header = FnHeader { safety: Safety::Unsafe(span), ..FnHeader::default() };
- let sig = FnSig { decl, header, span: span };
+ let sig = FnSig { decl, header, span };
let body = Some(cx.block_expr(call));
let kind = ItemKind::Fn(Box::new(Fn {
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 62e59f1..ed54c0c 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -1,8 +1,5 @@
-use crate::errors;
-use crate::util::expr_to_spanned_string;
use ast::token::IdentIsRaw;
use lint::BuiltinLintDiag;
-use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter};
use rustc_ast::tokenstream::TokenStream;
@@ -11,13 +8,15 @@
use rustc_expand::base::*;
use rustc_index::bit_set::GrowableBitSet;
use rustc_parse::parser::Parser;
-use rustc_parse_format as parse;
use rustc_session::lint;
-use rustc_span::symbol::Ident;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ErrorGuaranteed, InnerSpan, Span};
use rustc_target::asm::InlineAsmArch;
use smallvec::smallvec;
+use {rustc_ast as ast, rustc_parse_format as parse};
+
+use crate::errors;
+use crate::util::expr_to_spanned_string;
pub struct AsmArgs {
pub templates: Vec<P<ast::Expr>>,
@@ -29,6 +28,29 @@ pub struct AsmArgs {
pub options_spans: Vec<Span>,
}
+/// Used for better error messages when operand types are used that are not
+/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
+///
+/// returns
+///
+/// - `Ok(true)` if the current token matches the keyword, and was expected
+/// - `Ok(false)` if the current token does not match the keyword
+/// - `Err(_)` if the current token matches the keyword, but was not expected
+fn eat_operand_keyword<'a>(p: &mut Parser<'a>, symbol: Symbol, expect: bool) -> PResult<'a, bool> {
+ if expect {
+ Ok(p.eat_keyword(symbol))
+ } else {
+ let span = p.token.span;
+ if p.eat_keyword_noexpect(symbol) {
+ // in gets printed as `r#in` otherwise
+ let symbol = if symbol == kw::In { "in" } else { symbol.as_str() };
+ Err(p.dcx().create_err(errors::GlobalAsmUnsupportedOperand { span, symbol }))
+ } else {
+ Ok(false)
+ }
+ }
+}
+
fn parse_args<'a>(
ecx: &ExtCtxt<'a>,
sp: Span,
@@ -106,7 +128,7 @@ pub fn parse_asm_args<'a>(
};
let mut explicit_reg = false;
- let op = if !is_global_asm && p.eat_keyword(kw::In) {
+ let op = if eat_operand_keyword(p, kw::In, !is_global_asm)? {
let reg = parse_reg(p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
@@ -114,15 +136,15 @@ pub fn parse_asm_args<'a>(
}
let expr = p.parse_expr()?;
ast::InlineAsmOperand::In { reg, expr }
- } else if !is_global_asm && p.eat_keyword(sym::out) {
+ } else if eat_operand_keyword(p, sym::out, !is_global_asm)? {
let reg = parse_reg(p, &mut explicit_reg)?;
let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) };
ast::InlineAsmOperand::Out { reg, expr, late: false }
- } else if !is_global_asm && p.eat_keyword(sym::lateout) {
+ } else if eat_operand_keyword(p, sym::lateout, !is_global_asm)? {
let reg = parse_reg(p, &mut explicit_reg)?;
let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) };
ast::InlineAsmOperand::Out { reg, expr, late: true }
- } else if !is_global_asm && p.eat_keyword(sym::inout) {
+ } else if eat_operand_keyword(p, sym::inout, !is_global_asm)? {
let reg = parse_reg(p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
@@ -136,7 +158,7 @@ pub fn parse_asm_args<'a>(
} else {
ast::InlineAsmOperand::InOut { reg, expr, late: false }
}
- } else if !is_global_asm && p.eat_keyword(sym::inlateout) {
+ } else if eat_operand_keyword(p, sym::inlateout, !is_global_asm)? {
let reg = parse_reg(p, &mut explicit_reg)?;
if p.eat_keyword(kw::Underscore) {
let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
@@ -150,6 +172,9 @@ pub fn parse_asm_args<'a>(
} else {
ast::InlineAsmOperand::InOut { reg, expr, late: true }
}
+ } else if eat_operand_keyword(p, sym::label, !is_global_asm)? {
+ let block = p.parse_block()?;
+ ast::InlineAsmOperand::Label { block }
} else if p.eat_keyword(kw::Const) {
let anon_const = p.parse_expr_anon_const()?;
ast::InlineAsmOperand::Const { anon_const }
@@ -165,9 +190,6 @@ pub fn parse_asm_args<'a>(
path: path.clone(),
};
ast::InlineAsmOperand::Sym { sym }
- } else if !is_global_asm && p.eat_keyword(sym::label) {
- let block = p.parse_block()?;
- ast::InlineAsmOperand::Label { block }
} else if allow_templates {
let template = p.parse_expr()?;
// If it can't possibly expand to a string, provide diagnostics here to include other
@@ -723,10 +745,9 @@ fn expand_preparsed_asm(
unused_operands.push((args.operands[idx].1, msg));
}
}
- match unused_operands.len() {
- 0 => {}
- 1 => {
- let (sp, msg) = unused_operands.into_iter().next().unwrap();
+ match unused_operands[..] {
+ [] => {}
+ [(sp, msg)] => {
ecx.dcx()
.struct_span_err(sp, msg)
.with_span_label(sp, msg)
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index c75050f..99f433c 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -1,12 +1,9 @@
mod context;
-use crate::edition_panic::use_panic_2021;
-use crate::errors;
use rustc_ast::ptr::P;
-use rustc_ast::token;
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
-use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp};
+use rustc_ast::{token, DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
@@ -15,6 +12,9 @@
use rustc_span::{Span, DUMMY_SP};
use thin_vec::thin_vec;
+use crate::edition_panic::use_panic_2021;
+use crate::errors;
+
pub(crate) fn expand_assert<'cx>(
cx: &'cx mut ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index c664891..2cd5b9d 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -1,17 +1,15 @@
+use rustc_ast::ptr::P;
+use rustc_ast::token::{self, Delimiter, IdentIsRaw};
+use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
use rustc_ast::{
- ptr::P,
- token::{self, Delimiter, IdentIsRaw},
- tokenstream::{DelimSpan, TokenStream, TokenTree},
BinOpKind, BorrowKind, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MethodCall, Mutability,
Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::ExtCtxt;
-use rustc_span::{
- symbol::{sym, Ident, Symbol},
- Span,
-};
+use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
pub(super) struct Context<'cx, 'a> {
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 827719d..de19811 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -2,14 +2,15 @@
//! a literal `true` or `false` based on whether the given cfg matches the
//! current compilation environment.
-use crate::errors;
-use rustc_ast as ast;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
-use rustc_attr as attr;
use rustc_errors::PResult;
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
+use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_span::Span;
+use {rustc_ast as ast, rustc_attr as attr};
+
+use crate::errors;
pub(crate) fn expand_cfg(
cx: &mut ExtCtxt<'_>,
@@ -42,7 +43,7 @@ fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a,
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
}
- let cfg = p.parse_meta_item()?;
+ let cfg = p.parse_meta_item(AllowLeadingUnsafe::Yes)?;
let _ = p.eat(&token::Comma);
diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
index 98c0ca3..006b6aa 100644
--- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
@@ -1,6 +1,5 @@
//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
-use crate::errors;
use rustc_ast as ast;
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
@@ -8,6 +7,8 @@
use rustc_span::symbol::sym;
use rustc_span::Span;
+use crate::errors;
+
pub(crate) struct Expander;
fn validate_input<'a>(ecx: &ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
@@ -46,11 +47,13 @@ fn expand(
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let template = AttributeTemplate { list: Some("path"), ..Default::default() };
validate_attr::check_builtin_meta_item(
+ &ecx.ecfg.features,
&ecx.sess.psess,
meta_item,
ast::AttrStyle::Outer,
sym::cfg_accessible,
template,
+ true,
);
let Some(path) = validate_input(ecx, meta_item) else {
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index b3d252e..4b05c14 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -1,13 +1,10 @@
-use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
-
use core::ops::ControlFlow;
+
use rustc_ast as ast;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::ptr::P;
use rustc_ast::visit::{AssocCtxt, Visitor};
-use rustc_ast::NodeId;
-use rustc_ast::{mut_visit, visit};
-use rustc_ast::{Attribute, HasAttrs, HasTokens};
+use rustc_ast::{mut_visit, visit, Attribute, HasAttrs, HasTokens, NodeId};
use rustc_errors::PResult;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured;
@@ -20,6 +17,8 @@
use smallvec::SmallVec;
use tracing::instrument;
+use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
+
pub(crate) fn expand(
ecx: &mut ExtCtxt<'_>,
_span: Span,
@@ -203,7 +202,7 @@ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Anno
}
// Now that we have our re-parsed `AttrTokenStream`, recursively configuring
- // our attribute target will correctly the tokens as well.
+ // our attribute target will correctly configure the tokens as well.
flat_map_annotatable(self, annotatable)
}
}
diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
index bffd567..66fa74d 100644
--- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
+++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs
@@ -1,14 +1,14 @@
//! Attributes injected into the crate root from command line using `-Z crate-attr`.
-use crate::errors;
use rustc_ast::attr::mk_attr;
-use rustc_ast::token;
-use rustc_ast::{self as ast, AttrItem, AttrStyle};
+use rustc_ast::{self as ast, token, AttrItem, AttrStyle};
use rustc_parse::parser::ForceCollect;
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_session::parse::ParseSess;
use rustc_span::FileName;
+use crate::errors;
+
pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
for raw_attr in attrs {
let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str(
diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs
index a08e8b2..7fc4b43 100644
--- a/compiler/rustc_builtin_macros/src/compile_error.rs
+++ b/compiler/rustc_builtin_macros/src/compile_error.rs
@@ -1,10 +1,11 @@
// The compiler code necessary to support the compile_error! extension.
-use crate::util::get_single_str_from_tts;
use rustc_ast::tokenstream::TokenStream;
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_span::Span;
+use crate::util::get_single_str_from_tts;
+
pub(crate) fn expand_compile_error<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index 15af79e..a28801f 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -1,11 +1,12 @@
-use crate::errors;
-use crate::util::get_exprs_from_tts;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{ExprKind, LitKind, UnOp};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_session::errors::report_lit_error;
use rustc_span::symbol::Symbol;
+use crate::errors;
+use crate::util::get_exprs_from_tts;
+
pub(crate) fn expand_concat(
cx: &mut ExtCtxt<'_>,
sp: rustc_span::Span,
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 3130870..196bf90 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -1,10 +1,13 @@
-use crate::errors;
-use crate::util::get_exprs_from_tts;
-use rustc_ast::{ptr::P, token, tokenstream::TokenStream, ExprKind, LitIntType, LitKind, UintTy};
+use rustc_ast::ptr::P;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, ExprKind, LitIntType, LitKind, UintTy};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_session::errors::report_lit_error;
use rustc_span::{ErrorGuaranteed, Span};
+use crate::errors;
+use crate::util::get_exprs_from_tts;
+
/// Emits errors for literal expressions that are invalid inside and outside of an array.
fn invalid_type_err(
cx: &ExtCtxt<'_>,
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index b5cbfdf..57bddf0 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -1,8 +1,5 @@
-use crate::cfg_eval::cfg_eval;
-use crate::errors;
-
use rustc_ast as ast;
-use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, Safety, StmtKind};
+use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_expand::base::{
Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier,
};
@@ -12,6 +9,9 @@
use rustc_span::symbol::{sym, Ident};
use rustc_span::{ErrorGuaranteed, Span};
+use crate::cfg_eval::cfg_eval;
+use crate::errors;
+
pub(crate) struct Expander {
pub is_const: bool,
}
@@ -38,11 +38,13 @@ fn expand(
let template =
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
validate_attr::check_builtin_meta_item(
+ features,
&sess.psess,
meta_item,
ast::AttrStyle::Outer,
sym::derive,
template,
+ true,
);
let mut resolutions = match &meta_item.kind {
@@ -60,7 +62,6 @@ fn expand(
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
// paths.
report_path_args(sess, meta);
- report_unsafe_args(sess, meta);
meta.path.clone()
})
.map(|path| DeriveResolution {
@@ -160,13 +161,3 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
}
}
}
-
-fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) {
- match meta.unsafety {
- Safety::Unsafe(span) => {
- sess.dcx().emit_err(errors::DeriveUnsafePath { span });
- }
- Safety::Default => {}
- Safety::Safe(_) => unreachable!(),
- }
-}
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index f6b5433..a98e9c6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -1,10 +1,10 @@
-use crate::deriving::generic::*;
-use crate::deriving::path_std;
-
use rustc_ast::MetaItem;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::Span;
+use crate::deriving::generic::*;
+use crate::deriving::path_std;
+
pub(crate) fn expand_deriving_copy(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index abcb402..22beca4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -1,6 +1,3 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::path_std;
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -8,6 +5,10 @@
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::path_std;
+
pub(crate) fn expand_deriving_clone(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index 53a1513..a5e1217 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -1,7 +1,3 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::path_std;
-
use rustc_ast::{self as ast, MetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -9,6 +5,10 @@
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::path_std;
+
pub(crate) fn expand_deriving_eq(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 8470d46..705c411 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -1,12 +1,13 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::path_std;
use rustc_ast::MetaItem;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use thin_vec::thin_vec;
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::path_std;
+
pub(crate) fn expand_deriving_ord(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index a6457f4..f629958 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -1,6 +1,3 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::{path_local, path_std};
use rustc_ast::ptr::P;
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -8,6 +5,10 @@
use rustc_span::Span;
use thin_vec::thin_vec;
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::{path_local, path_std};
+
pub(crate) fn expand_deriving_partial_eq(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 006e5a3..a51f98f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -1,12 +1,13 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::{path_std, pathvec_std};
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use thin_vec::thin_vec;
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::{path_std, pathvec_std};
+
pub(crate) fn expand_deriving_partial_ord(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 57ec043..755e6ee 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -1,13 +1,13 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::path_std;
-
use rustc_ast::{self as ast, EnumDef, MetaItem};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::path_std;
+
pub(crate) fn expand_deriving_debug(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index e9851c8..89300a3 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -1,8 +1,5 @@
//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more.
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::pathvec_std;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Expr, MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
@@ -10,6 +7,10 @@
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::pathvec_std;
+
pub(crate) fn expand_deriving_rustc_decodable(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 7a65ed9..afc55dd 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -1,17 +1,18 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::errors;
use core::ops::ControlFlow;
+
use rustc_ast as ast;
use rustc_ast::visit::visit_opt;
use rustc_ast::{attr, EnumDef, VariantData};
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
-use rustc_span::symbol::Ident;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{ErrorGuaranteed, Span};
use smallvec::SmallVec;
use thin_vec::{thin_vec, ThinVec};
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::errors;
+
pub(crate) fn expand_deriving_default(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index 3bd74d8..9c26d05 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -85,15 +85,16 @@
//! }
//! ```
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::pathvec_std;
use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::pathvec_std;
+
pub(crate) fn expand_deriving_rustc_encodable(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index ba289f9..c90a916 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -174,26 +174,25 @@
//! )
//! ```
+use std::cell::RefCell;
+use std::ops::Not;
+use std::{iter, vec};
+
+use rustc_ast::ptr::P;
+use rustc_ast::{
+ self as ast, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
+ Mutability, PatKind, VariantData,
+};
+use rustc_attr as attr;
+use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{Span, DUMMY_SP};
+use thin_vec::{thin_vec, ThinVec};
+use ty::{Bounds, Path, Ref, Self_, Ty};
pub(crate) use StaticFields::*;
pub(crate) use SubstructureFields::*;
use crate::{deriving, errors};
-use rustc_ast::ptr::P;
-use rustc_ast::{
- self as ast, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
- Mutability, PatKind, TyKind, VariantData,
-};
-use rustc_attr as attr;
-use rustc_expand::base::{Annotatable, ExtCtxt};
-use rustc_session::lint::builtin::BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE;
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
-use std::cell::RefCell;
-use std::iter;
-use std::ops::Not;
-use std::vec;
-use thin_vec::{thin_vec, ThinVec};
-use ty::{Bounds, Path, Ref, Self_, Ty};
pub(crate) mod ty;
@@ -379,8 +378,8 @@ fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> P<Expr> {
None => cx.expr_block(cx.block(span, ThinVec::new())),
Some(expr) => expr,
}
- } else if self.0.len() == 1
- && let ast::StmtKind::Expr(expr) = &self.0[0].kind
+ } else if let [stmt] = self.0.as_slice()
+ && let ast::StmtKind::Expr(expr) = &stmt.kind
&& self.1.is_none()
{
// There's only a single statement expression. Pull it out.
@@ -1274,7 +1273,7 @@ fn expand_enum_method_body<'b>(
}
FieldlessVariantsStrategy::Default => (),
}
- } else if variants.len() == 1 {
+ } else if let [variant] = variants.as_slice() {
// If there is a single variant, we don't need an operation on
// the discriminant(s). Just use the most degenerate result.
return self.call_substructure_method(
@@ -1282,7 +1281,7 @@ fn expand_enum_method_body<'b>(
trait_,
type_ident,
nonselflike_args,
- &EnumMatching(0, &variants[0], Vec::new()),
+ &EnumMatching(0, variant, Vec::new()),
);
}
}
@@ -1599,52 +1598,11 @@ fn create_struct_field_access_fields(
),
);
if is_packed {
- // In general, fields in packed structs are copied via a
- // block, e.g. `&{self.0}`. The two exceptions are `[u8]`
- // and `str` fields, which cannot be copied and also never
- // cause unaligned references. These exceptions are allowed
- // to handle the `FlexZeroSlice` type in the `zerovec`
- // crate within `icu4x-0.9.0`.
- //
- // Once use of `icu4x-0.9.0` has dropped sufficiently, this
- // exception should be removed.
- let is_simple_path = |ty: &P<ast::Ty>, sym| {
- if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind
- && let [seg] = segments.as_slice()
- && seg.ident.name == sym
- && seg.args.is_none()
- {
- true
- } else {
- false
- }
- };
-
- let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind
- && is_simple_path(ty, sym::u8)
- {
- Some("byte")
- } else if is_simple_path(&struct_field.ty, sym::str) {
- Some("string")
- } else {
- None
- };
-
- if let Some(ty) = exception {
- cx.sess.psess.buffer_lint(
- BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
- sp,
- ast::CRATE_NODE_ID,
- rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive {
- ty: ty.to_string(),
- },
- );
- } else {
- // Wrap the expression in `{...}`, causing a copy.
- field_expr = cx.expr_block(
- cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]),
- );
- }
+ // Fields in packed structs are wrapped in a block, e.g. `&{self.0}`,
+ // causing a copy instead of a (potentially misaligned) reference.
+ field_expr = cx.expr_block(
+ cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]),
+ );
}
cx.expr_addr_of(sp, field_expr)
})
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index f01d586..747da2e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -1,8 +1,6 @@
//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use
//! when specifying impls to be derived.
-pub(crate) use Ty::*;
-
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
use rustc_expand::base::ExtCtxt;
@@ -10,6 +8,7 @@
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use thin_vec::ThinVec;
+pub(crate) use Ty::*;
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
/// for type parameters.
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index dcd9281..4fa6686 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -1,12 +1,13 @@
-use crate::deriving::generic::ty::*;
-use crate::deriving::generic::*;
-use crate::deriving::{path_std, pathvec_std};
use rustc_ast::{MetaItem, Mutability};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use thin_vec::thin_vec;
+use crate::deriving::generic::ty::*;
+use crate::deriving::generic::*;
+use crate::deriving::{path_std, pathvec_std};
+
pub(crate) fn expand_deriving_hash(
cx: &ExtCtxt<'_>,
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
index bbc7cd3..7eb1f17 100644
--- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
@@ -1,14 +1,16 @@
-use std::mem::swap;
-
+use ast::ptr::P;
use ast::HasAttrs;
+use rustc_ast::mut_visit::MutVisitor;
+use rustc_ast::visit::BoundKind;
use rustc_ast::{
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
- TraitBoundModifiers, VariantData,
+ TraitBoundModifiers, VariantData, WherePredicate,
};
use rustc_attr as attr;
+use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{sym, Ident};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use smallvec::{smallvec, SmallVec};
use thin_vec::{thin_vec, ThinVec};
@@ -141,33 +143,237 @@ pub fn expand_deriving_smart_ptr(
alt_self_params[pointee_param_idx] = GenericArg::Type(s_ty.clone());
let alt_self_type = cx.ty_path(cx.path_all(span, false, vec![name_ident], alt_self_params));
+ // # Add `Unsize<__S>` bound to `#[pointee]` at the generic parameter location
+ //
// Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
let mut impl_generics = generics.clone();
+ let pointee_ty_ident = generics.params[pointee_param_idx].ident;
+ let mut self_bounds;
{
- let p = &mut impl_generics.params[pointee_param_idx];
+ let pointee = &mut impl_generics.params[pointee_param_idx];
+ self_bounds = pointee.bounds.clone();
+ if !contains_maybe_sized_bound(&self_bounds)
+ && !contains_maybe_sized_bound_on_pointee(
+ &generics.where_clause.predicates,
+ pointee_ty_ident.name,
+ )
+ {
+ cx.dcx()
+ .struct_span_err(
+ pointee_ty_ident.span,
+ format!(
+ "`derive(SmartPointer)` requires {} to be marked `?Sized`",
+ pointee_ty_ident.name
+ ),
+ )
+ .emit();
+ return;
+ }
let arg = GenericArg::Type(s_ty.clone());
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
- p.bounds.push(cx.trait_bound(unsize, false));
- let mut attrs = thin_vec![];
- swap(&mut p.attrs, &mut attrs);
- p.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
+ pointee.bounds.push(cx.trait_bound(unsize, false));
+ // Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)`
+ pointee.attrs.retain(|attr| !attr.has_name(sym::pointee));
}
- // Add the `__S: ?Sized` extra parameter to the impl block.
- let sized = cx.path_global(span, path!(span, core::marker::Sized));
- let bound = GenericBound::Trait(
- cx.poly_trait_ref(span, sized),
- TraitBoundModifiers {
- polarity: ast::BoundPolarity::Maybe(span),
- constness: ast::BoundConstness::Never,
- asyncness: ast::BoundAsyncness::Normal,
- },
- );
- let extra_param = cx.typaram(span, Ident::new(sym::__S, span), vec![bound], None);
- impl_generics.params.push(extra_param);
+ // # Rewrite generic parameter bounds
+ // For each bound `U: ..` in `struct<U: ..>`, make a new bound with `__S` in place of `#[pointee]`
+ // Example:
+ // ```
+ // struct<
+ // U: Trait<T>,
+ // #[pointee] T: Trait<T> + ?Sized,
+ // V: Trait<T>> ...
+ // ```
+ // ... generates this `impl` generic parameters
+ // ```
+ // impl<
+ // U: Trait<T> + Trait<__S>,
+ // T: Trait<T> + ?Sized + Unsize<__S>, // (**)
+ // __S: Trait<__S> + ?Sized, // (*)
+ // V: Trait<T> + Trait<__S>> ...
+ // ```
+ // The new bound marked with (*) has to be done separately.
+ // See next section
+ for (idx, (params, orig_params)) in
+ impl_generics.params.iter_mut().zip(&generics.params).enumerate()
+ {
+ // Default type parameters are rejected for `impl` block.
+ // We should drop them now.
+ match &mut params.kind {
+ ast::GenericParamKind::Const { default, .. } => *default = None,
+ ast::GenericParamKind::Type { default } => *default = None,
+ ast::GenericParamKind::Lifetime => {}
+ }
+ // We CANNOT rewrite `#[pointee]` type parameter bounds.
+ // This has been set in stone. (**)
+ // So we skip over it.
+ // Otherwise, we push extra bounds involving `__S`.
+ if idx != pointee_param_idx {
+ for bound in &orig_params.bounds {
+ let mut bound = bound.clone();
+ let mut substitution = TypeSubstitution {
+ from_name: pointee_ty_ident.name,
+ to_ty: &s_ty,
+ rewritten: false,
+ };
+ substitution.visit_param_bound(&mut bound, BoundKind::Bound);
+ if substitution.rewritten {
+ // We found use of `#[pointee]` somewhere,
+ // so we make a new bound using `__S` in place of `#[pointee]`
+ params.bounds.push(bound);
+ }
+ }
+ }
+ }
+
+ // # Insert `__S` type parameter
+ //
+ // We now insert `__S` with the missing bounds marked with (*) above.
+ // We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`.
+ {
+ let mut substitution =
+ TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false };
+ for bound in &mut self_bounds {
+ substitution.visit_param_bound(bound, BoundKind::Bound);
+ }
+ }
+
+ // # Rewrite `where` clauses
+ //
+ // Move on to `where` clauses.
+ // Example:
+ // ```
+ // struct MyPointer<#[pointee] T, ..>
+ // where
+ // U: Trait<V> + Trait<T>,
+ // Companion<T>: Trait<T>,
+ // T: Trait<T> + ?Sized,
+ // { .. }
+ // ```
+ // ... will have a impl prelude like so
+ // ```
+ // impl<..> ..
+ // where
+ // U: Trait<V> + Trait<T>,
+ // U: Trait<__S>,
+ // Companion<T>: Trait<T>,
+ // Companion<__S>: Trait<__S>,
+ // T: Trait<T> + ?Sized,
+ // __S: Trait<__S> + ?Sized,
+ // ```
+ //
+ // We should also write a few new `where` bounds from `#[pointee] T` to `__S`
+ // as well as any bound that indirectly involves the `#[pointee] T` type.
+ for bound in &generics.where_clause.predicates {
+ if let ast::WherePredicate::BoundPredicate(bound) = bound {
+ let mut substitution = TypeSubstitution {
+ from_name: pointee_ty_ident.name,
+ to_ty: &s_ty,
+ rewritten: false,
+ };
+ let mut predicate = ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
+ span: bound.span,
+ bound_generic_params: bound.bound_generic_params.clone(),
+ bounded_ty: bound.bounded_ty.clone(),
+ bounds: bound.bounds.clone(),
+ });
+ substitution.visit_where_predicate(&mut predicate);
+ if substitution.rewritten {
+ impl_generics.where_clause.predicates.push(predicate);
+ }
+ }
+ }
+
+ let extra_param = cx.typaram(span, Ident::new(sym::__S, span), self_bounds, None);
+ impl_generics.params.insert(pointee_param_idx + 1, extra_param);
// Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
let gen_args = vec![GenericArg::Type(alt_self_type.clone())];
add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args.clone());
}
+
+fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: Symbol) -> bool {
+ for bound in predicates {
+ if let ast::WherePredicate::BoundPredicate(bound) = bound
+ && bound.bounded_ty.kind.is_simple_path().is_some_and(|name| name == pointee)
+ {
+ for bound in &bound.bounds {
+ if is_maybe_sized_bound(bound) {
+ return true;
+ }
+ }
+ }
+ }
+ false
+}
+
+fn is_maybe_sized_bound(bound: &GenericBound) -> bool {
+ if let GenericBound::Trait(
+ trait_ref,
+ TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. },
+ ) = bound
+ {
+ is_sized_marker(&trait_ref.trait_ref.path)
+ } else {
+ false
+ }
+}
+
+fn contains_maybe_sized_bound(bounds: &[GenericBound]) -> bool {
+ bounds.iter().any(is_maybe_sized_bound)
+}
+
+fn path_segment_is_exact_match(path_segments: &[ast::PathSegment], syms: &[Symbol]) -> bool {
+ path_segments.iter().zip(syms).all(|(segment, &symbol)| segment.ident.name == symbol)
+}
+
+fn is_sized_marker(path: &ast::Path) -> bool {
+ const CORE_UNSIZE: [Symbol; 3] = [sym::core, sym::marker, sym::Sized];
+ const STD_UNSIZE: [Symbol; 3] = [sym::std, sym::marker, sym::Sized];
+ if path.segments.len() == 4 && path.is_global() {
+ path_segment_is_exact_match(&path.segments[1..], &CORE_UNSIZE)
+ || path_segment_is_exact_match(&path.segments[1..], &STD_UNSIZE)
+ } else if path.segments.len() == 3 {
+ path_segment_is_exact_match(&path.segments, &CORE_UNSIZE)
+ || path_segment_is_exact_match(&path.segments, &STD_UNSIZE)
+ } else {
+ *path == sym::Sized
+ }
+}
+
+struct TypeSubstitution<'a> {
+ from_name: Symbol,
+ to_ty: &'a ast::Ty,
+ rewritten: bool,
+}
+
+impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> {
+ fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
+ if let Some(name) = ty.kind.is_simple_path()
+ && name == self.from_name
+ {
+ **ty = self.to_ty.clone();
+ self.rewritten = true;
+ } else {
+ ast::mut_visit::walk_ty(self, ty);
+ }
+ }
+
+ fn visit_where_predicate(&mut self, where_predicate: &mut ast::WherePredicate) {
+ match where_predicate {
+ rustc_ast::WherePredicate::BoundPredicate(bound) => {
+ bound
+ .bound_generic_params
+ .flat_map_in_place(|param| self.flat_map_generic_param(param));
+ self.visit_ty(&mut bound.bounded_ty);
+ for bound in &mut bound.bounds {
+ self.visit_param_bound(bound, BoundKind::Bound)
+ }
+ }
+ rustc_ast::WherePredicate::RegionPredicate(_)
+ | rustc_ast::WherePredicate::EqPredicate(_) => {}
+ }
+ }
+}
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index b03e14c..1a4fc65 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -3,18 +3,20 @@
// interface.
//
-use crate::errors;
-use crate::util::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts};
+use std::env;
+use std::env::VarError;
+
use rustc_ast::token::{self, LitKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use std::env;
-use std::env::VarError;
use thin_vec::thin_vec;
+use crate::errors;
+use crate::util::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts};
+
fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Result<Symbol, VarError> {
let var = var.as_str();
if let Some(value) = cx.sess.opts.logical_env.get(var) {
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index f178194..6ca4344 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1,9 +1,11 @@
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
- SingleLabelManySpans, SubdiagMessageOp, Subdiagnostic,
+ Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans,
+ SubdiagMessageOp, Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_span::{symbol::Ident, Span, Symbol};
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
#[diag(builtin_macros_requires_cfg_pattern)]
@@ -296,13 +298,6 @@ pub(crate) struct DerivePathArgsValue {
}
#[derive(Diagnostic)]
-#[diag(builtin_macros_derive_unsafe_path)]
-pub(crate) struct DeriveUnsafePath {
- #[primary_span]
- pub(crate) span: Span,
-}
-
-#[derive(Diagnostic)]
#[diag(builtin_macros_no_default_variant)]
#[help]
pub(crate) struct NoDefaultVariant {
@@ -857,6 +852,15 @@ pub(crate) struct GlobalAsmUnsupportedOption {
}
#[derive(Diagnostic)]
+#[diag(builtin_macros_global_asm_unsupported_operand)]
+pub(crate) struct GlobalAsmUnsupportedOperand<'a> {
+ #[primary_span]
+ #[label]
+ pub(crate) span: Span,
+ pub(crate) symbol: &'a str,
+}
+
+#[derive(Diagnostic)]
#[diag(builtin_macros_test_runner_invalid)]
pub(crate) struct TestRunnerInvalid {
#[primary_span]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 5cb0407..f99530c 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,13 +1,10 @@
-use crate::errors;
-use crate::util::expr_to_spanned_string;
use parse::Position::ArgumentNamed;
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{token, StmtKind};
use rustc_ast::{
- Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
+ token, Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
- FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait, Recovered,
+ FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait, Recovered, StmtKind,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans};
@@ -18,6 +15,9 @@
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span};
+use crate::errors;
+use crate::util::expr_to_spanned_string;
+
// The format_args!() macro is expanded in three steps:
// 1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax,
// but doesn't parse the template (the literal) itself.
@@ -180,8 +180,8 @@ fn make_format_args(
Ok((mut err, suggested)) => {
if !suggested {
if let ExprKind::Block(block, None) = &efmt.kind
- && block.stmts.len() == 1
- && let StmtKind::Expr(expr) = &block.stmts[0].kind
+ && let [stmt] = block.stmts.as_slice()
+ && let StmtKind::Expr(expr) = &stmt.kind
&& let ExprKind::Path(None, path) = &expr.kind
&& path.is_potential_trivial_const_arg()
{
@@ -196,8 +196,8 @@ fn make_format_args(
} else {
let sugg_fmt = match args.explicit_args().len() {
0 => "{}".to_string(),
- _ => {
- format!("{}{{}}", "{} ".repeat(args.explicit_args().len()))
+ count => {
+ format!("{}{{}}", "{} ".repeat(count))
}
};
err.span_suggestion(
@@ -555,7 +555,7 @@ enum ArgRef<'a> {
};
let arg_name = args.explicit_args()[index].kind.ident().unwrap();
ecx.buffered_early_lint.push(BufferedEarlyLint {
- span: arg_name.span.into(),
+ span: Some(arg_name.span.into()),
node_id: rustc_ast::CRATE_NODE_ID,
lint_id: LintId::of(NAMED_ARGUMENTS_USED_POSITIONALLY),
diagnostic: BuiltinLintDiag::NamedArgumentUsedPositionally {
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index bc2c6de..b52f606 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -1,7 +1,8 @@
pub(crate) mod printf {
- use super::strcursor::StrCursor as Cur;
use rustc_span::InnerSpan;
+ use super::strcursor::StrCursor as Cur;
+
/// Represents a single `printf`-style substitution.
#[derive(Clone, PartialEq, Debug)]
pub enum Substitution<'a> {
@@ -615,9 +616,10 @@ fn is_flag(c: &char) -> bool {
}
pub mod shell {
- use super::strcursor::StrCursor as Cur;
use rustc_span::InnerSpan;
+ use super::strcursor::StrCursor as Cur;
+
#[derive(Clone, PartialEq, Debug)]
pub enum Substitution<'a> {
Ordinal(u8, (usize, usize)),
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index b44ff97..734da31 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -1,17 +1,19 @@
-use crate::util::check_builtin_macro_attribute;
-
-use crate::errors;
use rustc_ast::expand::allocator::{
global_fn_name, AllocatorMethod, AllocatorMethodInput, AllocatorTy, ALLOCATOR_METHODS,
};
use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
-use rustc_ast::{Fn, ItemKind, Mutability, Safety, Stmt, Ty, TyKind};
+use rustc_ast::{
+ self as ast, AttrVec, Expr, Fn, FnHeader, FnSig, Generics, ItemKind, Mutability, Param, Safety,
+ Stmt, StmtKind, Ty, TyKind,
+};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use thin_vec::{thin_vec, ThinVec};
+use crate::errors;
+use crate::util::check_builtin_macro_attribute;
+
pub(crate) fn expand(
ecx: &mut ExtCtxt<'_>,
_span: Span,
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index c77ff9e..a9ba733 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -5,7 +5,6 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
@@ -21,11 +20,12 @@
extern crate proc_macro;
-use crate::deriving::*;
use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro;
use rustc_span::symbol::sym;
+use crate::deriving::*;
+
mod alloc_error_handler;
mod assert;
mod cfg;
diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs
index 31f5656d..869d203 100644
--- a/compiler/rustc_builtin_macros/src/pattern_type.rs
+++ b/compiler/rustc_builtin_macros/src/pattern_type.rs
@@ -1,4 +1,6 @@
-use rustc_ast::{ast, ptr::P, tokenstream::TokenStream, Pat, Ty};
+use rustc_ast::ptr::P;
+use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{ast, Pat, Ty};
use rustc_errors::PResult;
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_span::{sym, Span};
@@ -22,7 +24,7 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P
let mut parser = cx.new_parser_from_tts(stream);
let ty = parser.parse_ty()?;
- parser.eat_keyword(sym::is);
+ parser.expect_keyword(sym::is)?;
let pat = parser.parse_pat_no_top_alt(None, None)?;
Ok((ty, pat))
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index a8a595e..6b2b2b9 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -1,4 +1,5 @@
-use crate::errors;
+use std::mem;
+
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{self as ast, attr, NodeId};
@@ -13,9 +14,10 @@
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use smallvec::smallvec;
-use std::mem;
use thin_vec::{thin_vec, ThinVec};
+use crate::errors;
+
struct ProcMacroDerive {
id: NodeId,
trait_name: Symbol,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 44db12c..9554d97 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -1,7 +1,6 @@
-use crate::errors;
-use crate::util::{
- check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
-};
+use std::path::{Path, PathBuf};
+use std::rc::Rc;
+
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token;
@@ -20,8 +19,11 @@
use rustc_span::symbol::Symbol;
use rustc_span::{Pos, Span};
use smallvec::SmallVec;
-use std::path::{Path, PathBuf};
-use std::rc::Rc;
+
+use crate::errors;
+use crate::util::{
+ check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr,
+};
// These macros all relate to the file system; they either return
// the column/row/filename of the expression, or they include
@@ -71,7 +73,8 @@ pub(crate) fn expand_file(
let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.source_map().lookup_char_pos(topmost.lo());
- use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+ use rustc_session::config::RemapPathScopeComponents;
+ use rustc_session::RemapFileNameExt;
ExpandResult::Ready(MacEager::expr(cx.expr_str(
topmost,
Symbol::intern(
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index bb00c8d..1b76a5f 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -1,8 +1,9 @@
//! The expansion from a test function to the appropriate test struct for libtest
//! Ideally, this code would be in libtest but for efficiency and error messages it lives here.
-use crate::errors;
-use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
+use std::assert_matches::assert_matches;
+use std::iter;
+
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, attr, GenericParamKind};
use rustc_ast_pretty::pprust;
@@ -10,11 +11,12 @@
use rustc_expand::base::*;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Span};
-use std::assert_matches::assert_matches;
-use std::iter;
use thin_vec::{thin_vec, ThinVec};
use tracing::debug;
+use crate::errors;
+use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
+
/// #[test_case] is used by custom test authors to mark tests
/// When building for test, it needs to make the item public and gensym the name
/// Otherwise, we'll omit the item. This behavior means that any item annotated
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index bbafb0a..a9e4434 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -1,5 +1,7 @@
// Code that generates a test runner to run all the tests in a crate
+use std::{iter, mem};
+
use rustc_ast as ast;
use rustc_ast::entry::EntryPointType;
use rustc_ast::mut_visit::*;
@@ -21,8 +23,6 @@
use thin_vec::{thin_vec, ThinVec};
use tracing::debug;
-use std::{iter, mem};
-
use crate::errors;
#[derive(Clone)]
diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs
index 4833ec3..bd9ebc3 100644
--- a/compiler/rustc_builtin_macros/src/trace_macros.rs
+++ b/compiler/rustc_builtin_macros/src/trace_macros.rs
@@ -1,9 +1,10 @@
-use crate::errors;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_span::symbol::kw;
use rustc_span::Span;
+use crate::errors;
+
pub(crate) fn expand_trace_macros(
cx: &mut ExtCtxt<'_>,
sp: Span,
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index fabcb6a..73cc8ff 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -1,24 +1,29 @@
-use crate::errors;
+use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{self as ast, attr, ptr::P, token, AttrStyle, Attribute, MetaItem};
+use rustc_ast::{self as ast, attr, token, AttrStyle, Attribute, MetaItem};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt};
use rustc_expand::expand::AstFragment;
use rustc_feature::AttributeTemplate;
-use rustc_lint_defs::{builtin::DUPLICATE_MACRO_ATTRIBUTES, BuiltinLintDiag};
+use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
+use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::{parser, validate_attr};
use rustc_session::errors::report_lit_error;
use rustc_span::{BytePos, Span, Symbol};
+use crate::errors;
+
pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) {
// All the built-in macro attributes are "words" at the moment.
let template = AttributeTemplate { word: true, ..Default::default() };
validate_attr::check_builtin_meta_item(
+ &ecx.ecfg.features,
&ecx.sess.psess,
meta_item,
AttrStyle::Outer,
name,
template,
+ true,
);
}
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
index 1ed6f8f..30dc5cb 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
@@ -2,13 +2,14 @@
on:
- push
+ - pull_request
permissions: {}
jobs:
abi_cafe:
runs-on: ${{ matrix.os }}
- timeout-minutes: 60
+ timeout-minutes: 30
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.os }}-${{ matrix.env.TARGET_TRIPLE }}
cancel-in-progress: true
@@ -27,12 +28,16 @@
- os: macos-latest
env:
TARGET_TRIPLE: x86_64-apple-darwin
+ - os: macos-latest
+ env:
+ TARGET_TRIPLE: aarch64-apple-darwin
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-msvc
- - os: windows-latest
- env:
- TARGET_TRIPLE: x86_64-pc-windows-gnu
+ # FIXME Currently hangs. Re-enable once this is fixed or abi-cafe adds a timeout.
+ #- os: windows-latest
+ # env:
+ # TARGET_TRIPLE: x86_64-pc-windows-gnu
steps:
- uses: actions/checkout@v4
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml b/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
index b4f8ce0..27c9557 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
@@ -13,7 +13,6 @@
- uses: actions/checkout@v4
- run: |
sed -i 's/components.*/components = []/' rust-toolchain
- echo 'profile = "minimal"' >> rust-toolchain
- uses: rustsec/audit-check@v1.4.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index a2ae3d6..896a5c3 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -29,7 +29,6 @@
- name: Avoid installing rustc-dev
run: |
sed -i 's/components.*/components = ["rustfmt"]/' rust-toolchain
- echo 'profile = "minimal"' >> rust-toolchain
rustfmt -v
- name: Rustfmt
diff --git a/compiler/rustc_codegen_cranelift/.zed/settings.json b/compiler/rustc_codegen_cranelift/.zed/settings.json
new file mode 100644
index 0000000..e93bed3
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/.zed/settings.json
@@ -0,0 +1,68 @@
+{
+ "format_on_save": "on",
+ "lsp": {
+ "rust-analyzer": {
+ "initialization_options": {
+ "diagnostics": {
+ // in case rustc.source is disabled for performance reasons; disable the errors about this
+ "disabled": ["unresolved-extern-crate", "unresolved-macro-call"]
+ },
+ "rustc": {
+ "source": "discover"
+ },
+ "imports": {
+ "granularity": {
+ "enforce": true,
+ "group": "module"
+ },
+ "prefix": "crate"
+ },
+ "cargo": {
+ "features": ["unstable-features"]
+ },
+ "linkedProjects": [
+ "./Cargo.toml",
+ "./build_system/Cargo.toml",
+ {
+ "crates": [
+ {
+ "root_module": "./example/mini_core.rs",
+ "edition": "2018",
+ "deps": [],
+ "cfg": []
+ },
+ {
+ "root_module": "./example/mini_core_hello_world.rs",
+ "edition": "2018",
+ "deps": [
+ {
+ "crate": 0,
+ "name": "mini_core"
+ }
+ ],
+ "cfg": []
+ },
+ {
+ "root_module": "./example/mod_bench.rs",
+ "edition": "2018",
+ "deps": [],
+ "cfg": []
+ }
+ ]
+ },
+ {
+ "sysroot_src": "./build/stdlib/library",
+ "crates": [
+ {
+ "root_module": "./example/std_example.rs",
+ "edition": "2015",
+ "deps": [],
+ "cfg": []
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index efec5db..02d4d98 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -46,21 +46,28 @@
[[package]]
name = "cranelift-bforest"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b6b33d7e757a887989eb18b35712b2a67d96171ec3149d1bfb657b29b7b367c"
+checksum = "effa84ab2023f7138045ece6b326588c17447ca22e66db71ec15cb0a6c0c4ad2"
dependencies = [
"cranelift-entity",
]
[[package]]
-name = "cranelift-codegen"
-version = "0.109.0"
+name = "cranelift-bitset"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9acf15cb22be42d07c3b57d7856329cb228b7315d385346149df2566ad5e4aa"
+checksum = "38a1dfc50dca188a15d938867c4400589530bcb0138f7022aae6d059d1d8c309"
+
+[[package]]
+name = "cranelift-codegen"
+version = "0.110.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "821c20c639350158ecca928dc2a244d0d1c9cef2377a378fc62a445a286eb1ca"
dependencies = [
"bumpalo",
"cranelift-bforest",
+ "cranelift-bitset",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-control",
@@ -77,39 +84,42 @@
[[package]]
name = "cranelift-codegen-meta"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e934d301392b73b3f8b0540391fb82465a0f179a3cee7c726482ac4727efcc97"
+checksum = "064473f2fd59b44fa2c9aaa60de1f9c44db5e13521e28bc85d2b92ee535ef625"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb2a2566b3d54b854dfb288b3b187f6d3d17d6f762c92898207eba302931da"
+checksum = "d0f39b9ebfd2febdc2acfb9a0fca110665bcd5a6839502576307735ed07b2177"
[[package]]
name = "cranelift-control"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0100f33b704cdacd01ad66ff41f8c5030d57cbff078e2a4e49ab1822591299fa"
+checksum = "94e125c189c3a1ca8dfe209fc6f46edba058a6d24e0b92aff69459a15f4711e7"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8cfdc315e5d18997093e040a8d234bea1ac1e118a716d3e30f40d449e78207b"
+checksum = "ea62eb109baec2247e1a6fa7b74c0f584b1e76e289cfd7017385b4b031fc8450"
+dependencies = [
+ "cranelift-bitset",
+]
[[package]]
name = "cranelift-frontend"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f74b84f16af2e982b0c0c72233503d9d55cbfe3865dbe807ca28dc6642a28b5"
+checksum = "722b089357aacb6c7528b2e59a5fe00917d61ce63448b25a3e477a5b7819fac8"
dependencies = [
"cranelift-codegen",
"log",
@@ -119,15 +129,15 @@
[[package]]
name = "cranelift-isle"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adf306d3dde705fb94bd48082f01d38c4ededc74293a4c007805f610bf08bc6e"
+checksum = "c4b5005a48288e7fc2a2991a377831c534e26929b063c379c018060727785a9b"
[[package]]
name = "cranelift-jit"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5c5cfb8bbd3339cd25cca30e7516ff8fe5cb1feeddde6980cc4d5ef34df97bb"
+checksum = "f843932baf8d1025c5f114b929eda172d74b7163d058e0de2597c308b567c7e9"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -145,9 +155,9 @@
[[package]]
name = "cranelift-module"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c9b0d4269b36fd858e6d8f20cd4938941186fb831488c361888cb2d6b33a9a6"
+checksum = "449819ef1c4af139cf1b9717916fcaea0e23248853d3e95135139773a842d3eb"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -156,9 +166,9 @@
[[package]]
name = "cranelift-native"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ea0ebdef7aff4a79bcbc8b6495f31315f16b3bf311152f472eaa8d679352581"
+checksum = "3ae2d48f38081a9e679ad795bd36bb29bedeb5552fc1c195185bf9885fa1b16e"
dependencies = [
"cranelift-codegen",
"libc",
@@ -167,9 +177,9 @@
[[package]]
name = "cranelift-object"
-version = "0.109.0"
+version = "0.110.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e33439ec20db058bc7cc3410f9748ab1ad90a35cef713d625c736f43e3820d"
+checksum = "3a39ee2cfd0ec485eca76f6b4dc17701a280fa406bc05137bb43f1635ed12c9f"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -279,9 +289,9 @@
[[package]]
name = "object"
-version = "0.36.1"
+version = "0.36.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
dependencies = [
"crc32fast",
"hashbrown 0.14.5",
@@ -411,9 +421,9 @@
[[package]]
name = "wasmtime-jit-icache-coherence"
-version = "22.0.0"
+version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5afe2f0499542f9a4bcfa1b55bfdda803b6ade4e7c93c6b99e0f39dba44b0a91"
+checksum = "7fddf3e2980fb1d123d1fcac55189e417fdd3dba4f62139b5a0a1f9efe5669d5"
dependencies = [
"anyhow",
"cfg-if",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index 2969a6c..a0df502 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { version = "0.109.0", default-features = false, features = ["std", "unwind", "all-arch"] }
-cranelift-frontend = { version = "0.109.0" }
-cranelift-module = { version = "0.109.0" }
-cranelift-native = { version = "0.109.0" }
-cranelift-jit = { version = "0.109.0", optional = true }
-cranelift-object = { version = "0.109.0" }
+cranelift-codegen = { version = "0.110.1", default-features = false, features = ["std", "unwind", "all-arch"] }
+cranelift-frontend = { version = "0.110.1" }
+cranelift-module = { version = "0.110.1" }
+cranelift-native = { version = "0.110.1" }
+cranelift-jit = { version = "0.110.1", optional = true }
+cranelift-object = { version = "0.110.1" }
target-lexicon = "0.12.0"
gimli = { version = "0.28", default-features = false, features = ["write"]}
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index 3b3c86a..6766e2f 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -16,7 +16,6 @@
Once it is installed, you can enable it with one of the following approaches:
- `CARGO_PROFILE_DEV_CODEGEN_BACKEND=cranelift cargo +nightly build -Zcodegen-backend`
-- `RUSTFLAGS="-Zcodegen-backend=cranelift" cargo +nightly build`
- Add the following to `.cargo/config.toml`:
```toml
[unstable]
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
index ecf303c..e3f1162 100644
--- a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -1,14 +1,13 @@
-use crate::build_sysroot;
-use crate::path::Dirs;
+use crate::path::{Dirs, RelPath};
use crate::prepare::GitRepo;
use crate::utils::{spawn_and_wait, CargoProject, Compiler};
-use crate::{CodegenBackend, SysrootKind};
+use crate::{build_sysroot, CodegenBackend, SysrootKind};
static ABI_CAFE_REPO: GitRepo = GitRepo::github(
"Gankra",
"abi-cafe",
- "4c6dc8c9c687e2b3a760ff2176ce236872b37212",
- "588df6d66abbe105",
+ "f1220cfd13b57f5c0082c26529163865ee25e115",
+ "fe93a9acd461425d",
"abi-cafe",
);
@@ -22,6 +21,7 @@ pub(crate) fn run(
rustup_toolchain_name: Option<&str>,
bootstrap_host_compiler: &Compiler,
) {
+ RelPath::DOWNLOAD.ensure_exists(dirs);
ABI_CAFE_REPO.fetch(dirs);
ABI_CAFE_REPO.patch(dirs);
@@ -39,17 +39,23 @@ pub(crate) fn run(
eprintln!("Running abi-cafe");
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
-
- let mut cmd = ABI_CAFE.run(bootstrap_host_compiler, dirs);
- cmd.arg("--");
- cmd.arg("--pairs");
- cmd.args(
+ let pairs =
if cfg!(not(any(target_os = "macos", all(target_os = "windows", target_env = "msvc")))) {
&pairs[..]
} else {
&pairs[..2]
- },
- );
+ };
+
+ let mut cmd = ABI_CAFE.run(bootstrap_host_compiler, dirs);
+ cmd.arg("--");
+
+ // stdcall, vectorcall and such don't work yet
+ cmd.arg("--conventions").arg("c").arg("--conventions").arg("rust");
+
+ for pair in pairs {
+ cmd.arg("--pairs").arg(pair);
+ }
+
cmd.arg("--add-rustc-codegen-backend");
match cg_clif_dylib {
CodegenBackend::Local(path) => {
@@ -59,6 +65,7 @@ pub(crate) fn run(
cmd.arg(format!("cgclif:{name}"));
}
}
+
cmd.current_dir(ABI_CAFE.source_dir(dirs));
spawn_and_wait(cmd);
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index dfbe0f5..e41f6c5 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -1,7 +1,6 @@
-use std::env;
-use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
+use std::{env, fs};
use crate::path::{Dirs, RelPath};
use crate::rustc_info::get_file_name;
@@ -272,7 +271,7 @@ fn build_clif_sysroot_for_triple(
if channel == "release" {
build_cmd.arg("--release");
}
- build_cmd.arg("--features").arg("backtrace panic-unwind");
+ build_cmd.arg("--features").arg("backtrace panic-unwind compiler-builtins-no-f16-f128");
build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
if compiler.triple.contains("apple") {
@@ -313,7 +312,6 @@ fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
let obj = RTSTARTUP_SYSROOT.to_path(dirs).join(format!("{file}.o"));
let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
build_rtstartup_cmd
- .arg("-Ainternal_features") // Missing #[allow(internal_features)]
.arg("--target")
.arg(&compiler.triple)
.arg("--emit=obj")
diff --git a/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs
index c31784e..ef540cf 100644
--- a/compiler/rustc_codegen_cranelift/build_system/config.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/config.rs
@@ -1,5 +1,4 @@
-use std::fs;
-use std::process;
+use std::{fs, process};
fn load_config_file() -> Vec<(String, Option<String>)> {
fs::read_to_string("config.txt")
diff --git a/compiler/rustc_codegen_cranelift/build_system/main.rs b/compiler/rustc_codegen_cranelift/build_system/main.rs
index 7dbf608..9ddeda5 100644
--- a/compiler/rustc_codegen_cranelift/build_system/main.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/main.rs
@@ -2,9 +2,8 @@
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]
-use std::env;
use std::path::PathBuf;
-use std::process;
+use std::{env, process};
use self::utils::Compiler;
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index 5525a5f..be0bed0 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -22,36 +22,6 @@ pub(crate) fn prepare_stdlib(dirs: &Dirs, rustc: &Path) {
assert!(sysroot_src_orig.exists());
apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs));
-
- std::fs::write(
- STDLIB_SRC.to_path(dirs).join("Cargo.toml"),
- r#"
-[workspace]
-resolver = "1"
-members = ["./library/sysroot"]
-
-[patch.crates-io]
-rustc-std-workspace-core = { path = "./library/rustc-std-workspace-core" }
-rustc-std-workspace-alloc = { path = "./library/rustc-std-workspace-alloc" }
-rustc-std-workspace-std = { path = "./library/rustc-std-workspace-std" }
-
-# Mandatory for correctly compiling compiler-builtins
-[profile.dev.package.compiler_builtins]
-debug-assertions = false
-overflow-checks = false
-codegen-units = 10000
-
-[profile.release.package.compiler_builtins]
-debug-assertions = false
-overflow-checks = false
-codegen-units = 10000
-"#,
- )
- .unwrap();
-
- let source_lockfile = RelPath::PATCHES.to_path(dirs).join("stdlib-lock.toml");
- let target_lockfile = STDLIB_SRC.to_path(dirs).join("Cargo.lock");
- fs::copy(source_lockfile, target_lockfile).unwrap();
}
pub(crate) struct GitRepo {
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index 790d9cb..38c3786 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -3,14 +3,12 @@
use std::path::PathBuf;
use std::process::Command;
-use crate::build_sysroot;
-use crate::config;
use crate::path::{Dirs, RelPath};
use crate::prepare::{apply_patches, GitRepo};
use crate::rustc_info::get_default_sysroot;
use crate::shared_utils::rustflags_from_env;
use crate::utils::{spawn_and_wait, CargoProject, Compiler, LogGroup};
-use crate::{CodegenBackend, SysrootKind};
+use crate::{build_sysroot, config, CodegenBackend, SysrootKind};
static BUILD_EXAMPLE_OUT_DIR: RelPath = RelPath::BUILD.join("example");
@@ -108,6 +106,7 @@ const fn jit_bin(config: &'static str, source: &'static str, args: &'static str)
]);
runner.run_out_command("gen_block_iterate", &[]);
}),
+ TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]),
];
pub(crate) static RAND_REPO: GitRepo = GitRepo::github(
@@ -439,7 +438,7 @@ fn rustc_command<I, S>(&self, args: I) -> Command
cmd.arg("-L");
cmd.arg(format!("crate={}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
cmd.arg("--out-dir");
- cmd.arg(format!("{}", BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs).display()));
+ cmd.arg(BUILD_EXAMPLE_OUT_DIR.to_path(&self.dirs));
cmd.arg("-Cdebuginfo=2");
cmd.arg("--target");
cmd.arg(&self.target_compiler.triple);
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index 9f95122..3c4b45e 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -1,9 +1,7 @@
-use std::env;
-use std::fs;
-use std::io;
use std::path::{Path, PathBuf};
use std::process::{self, Command};
use std::sync::atomic::{AtomicBool, Ordering};
+use std::{env, fs, io};
use crate::path::{Dirs, RelPath};
use crate::shared_utils::rustflags_to_cmd_env;
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index 0b7cac1..527ec53 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -45,6 +45,7 @@
aot.polymorphize_coroutine
aot.neon
aot.gen_block_iterate
+aot.raw-dylib
testsuite.extended_sysroot
test.rust-random/rand
diff --git a/compiler/rustc_codegen_cranelift/example/alloc_system.rs b/compiler/rustc_codegen_cranelift/example/alloc_system.rs
index 441f3cd..2884c9c 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_system.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_system.rs
@@ -8,8 +8,7 @@
#[cfg(any(windows, unix, target_os = "redox"))]
mod realloc_fallback {
use core::alloc::{GlobalAlloc, Layout};
- use core::cmp;
- use core::ptr;
+ use core::{cmp, ptr};
impl super::System {
pub(crate) unsafe fn realloc_fallback(
&self,
@@ -34,6 +33,7 @@ mod platform {
use core::alloc::{GlobalAlloc, Layout};
use core::ffi::c_void;
use core::ptr;
+
use System;
extern "C" {
fn posix_memalign(memptr: *mut *mut c_void, align: usize, size: usize) -> i32;
@@ -71,6 +71,7 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
#[allow(nonstandard_style)]
mod platform {
use core::alloc::{GlobalAlloc, Layout};
+
use System;
type LPVOID = *mut u8;
type HANDLE = LPVOID;
diff --git a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs
index f7edfa9..5479b0c 100644
--- a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs
+++ b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs
@@ -2,10 +2,8 @@
#![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)]
-use std::{
- marker::Unsize,
- ops::{CoerceUnsized, Deref, DispatchFromDyn},
-};
+use std::marker::Unsize;
+use std::ops::{CoerceUnsized, Deref, DispatchFromDyn};
struct Ptr<T: ?Sized>(Box<T>);
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index 7d361a9..e603ac5 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -585,6 +585,7 @@ pub enum E2<X> {
V4,
}
+#[allow(unreachable_patterns)]
fn check_niche_behavior() {
if let E1::V2 { .. } = (E1::V1 { f: true }) {
intrinsics::abort();
diff --git a/compiler/rustc_codegen_cranelift/example/raw-dylib.rs b/compiler/rustc_codegen_cranelift/example/raw-dylib.rs
new file mode 100644
index 0000000..4711884
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/example/raw-dylib.rs
@@ -0,0 +1,31 @@
+// Tests the raw-dylib feature for Windows.
+// https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute
+
+fn main() {
+ #[cfg(windows)]
+ {
+ #[link(name = "kernel32", kind = "raw-dylib")]
+ extern "C" {
+ fn GetModuleFileNameA(
+ module: *mut std::ffi::c_void,
+ filename: *mut u8,
+ size: u32,
+ ) -> u32;
+ }
+
+ // Get the filename of the current executable....
+ let mut buffer = [0u8; 1024];
+ let size = unsafe {
+ GetModuleFileNameA(core::ptr::null_mut(), buffer.as_mut_ptr(), buffer.len() as u32)
+ };
+ if size == 0 {
+ eprintln!("failed to get module file name: {}", std::io::Error::last_os_error());
+ return;
+ } else {
+ // ...and make sure that it matches the test name.
+ let filename =
+ std::ffi::CStr::from_bytes_with_nul(&buffer[..size as usize + 1]).unwrap();
+ assert!(filename.to_str().unwrap().ends_with("raw-dylib.exe"));
+ }
+ }
+}
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
deleted file mode 100644
index 77716c5..0000000
--- a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 2b15fee2bb5fd14e34c7e17e44d99cb34f4c555d Mon Sep 17 00:00:00 2001
-From: Afonso Bordado <afonsobordado@az8.co>
-Date: Tue, 27 Sep 2022 07:55:17 +0100
-Subject: [PATCH] Disable some test on x86_64-pc-windows-gnu
-
----
- src/report.rs | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/src/report.rs b/src/report.rs
-index eeec614..f582867 100644
---- a/src/report.rs
-+++ b/src/report.rs
-@@ -48,6 +48,15 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
- //
- // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
-
-+ // x86_64-pc-windows-gnu has some broken i128 tests that aren't disabled by default
-+ if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" {
-+ result.run = Link;
-+ result.check = Pass(Link);
-+ } else if test.test_name == "ui128" {
-+ result.run == Check;
-+ result.check = Pass(Check);
-+ }
-+
- // END OF VENDOR RESERVED AREA
- //
- //
---
-2.30.1.windows.1
-
diff --git a/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch b/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch
new file mode 100644
index 0000000..8a2565f
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0002-abi-cafe-Disable-broken-tests.patch
@@ -0,0 +1,75 @@
+From 236df390f3bc4ed69c26f4d51d584bea246da886 Mon Sep 17 00:00:00 2001
+From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
+Date: Tue, 9 Jul 2024 11:25:14 +0000
+Subject: [PATCH] Disable broken tests
+
+---
+ src/report.rs | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/src/report.rs b/src/report.rs
+index 958ab43..dcf1044 100644
+--- a/src/report.rs
++++ b/src/report.rs
+@@ -48,6 +48,58 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn Toolchain, callee: &dyn Toolc
+ //
+ // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
+
++ if cfg!(all(target_arch = "aarch64", target_os = "linux")) {
++ if test.test == "F32Array" && test.options.convention == CallingConvention::C {
++ result.check = Busted(Check);
++ }
++
++ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C {
++ result.check = Busted(Check);
++ }
++ }
++
++ if cfg!(all(target_arch = "aarch64", target_os = "macos")) {
++ if test.test == "SingleVariantUnion" && test.options.convention == CallingConvention::C && test.options.repr == LangRepr::C {
++ result.check = Busted(Check);
++ }
++
++ if test.test == "OptionU128" && test.caller == "rustc" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C {
++ result.check = Busted(Run);
++ }
++
++ if test.test == "OptionU128" && test.caller == "cgclif" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C {
++ result.check = Busted(Check);
++ }
++ }
++
++ if cfg!(all(target_arch = "x86_64", unix)) {
++ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::Rust {
++ result.check = Busted(Run);
++ }
++ }
++
++ if cfg!(all(target_arch = "x86_64", windows)) {
++ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust {
++ result.check = Busted(Check);
++ }
++
++ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && (test.caller == "rustc" || test.options.repr == LangRepr::Rust) {
++ result.check = Busted(Run);
++ }
++
++ if test.test == "simple" && test.options.convention == CallingConvention::Rust {
++ result.check = Busted(Check);
++ }
++
++ if test.test == "simple" && test.options.convention == CallingConvention::Rust && test.caller == "rustc" {
++ result.check = Busted(Run);
++ }
++ }
++
++ if test.test == "f16" || test.test == "f128" {
++ result.run = Skip;
++ }
++
+ // END OF VENDOR RESERVED AREA
+ //
+ //
+--
+2.34.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
index 7cf7f86..8c40495 100644
--- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch
@@ -37,8 +37,8 @@
+++ b/lib.rs
@@ -1,3 +1,4 @@
+#![cfg(test)]
- #![feature(alloc_layout_extra)]
- #![feature(array_chunks)]
- #![feature(array_ptr_get)]
+ // tidy-alphabetical-start
+ #![cfg_attr(bootstrap, feature(offset_of_nested))]
+ #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
--
2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
index 271ca12..d579c95 100644
--- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
@@ -11,17 +11,17 @@
4 files changed, 4 insertions(+), 50 deletions(-)
diff --git a/lib.rs b/lib.rs
-index 897a5e9..331f66f 100644
+index 1e336bf..35e6f54 100644
--- a/lib.rs
+++ b/lib.rs
-@@ -93,7 +93,6 @@
- #![feature(const_option)]
- #![feature(const_option_ext)]
- #![feature(const_result)]
+@@ -1,7 +1,6 @@
+ #![cfg(test)]
+ // tidy-alphabetical-start
+ #![cfg_attr(bootstrap, feature(offset_of_nested))]
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
#![cfg_attr(test, feature(cfg_match))]
- #![feature(int_roundings)]
- #![feature(split_array)]
+ #![feature(alloc_layout_extra)]
+ #![feature(array_chunks)]
diff --git a/atomic.rs b/atomic.rs
index b735957..ea728b6 100644
--- a/atomic.rs
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
new file mode 100644
index 0000000..ada3514
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
@@ -0,0 +1,25 @@
+From 175d52c5e1779764b66777db1e6f172c2dc365ff Mon Sep 17 00:00:00 2001
+From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
+Date: Fri, 9 Aug 2024 15:44:51 +0000
+Subject: [PATCH] Disable f16 and f128 in compiler-builtins
+
+---
+ library/sysroot/Cargo.toml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
+index 7165c3e48af..968552ad435 100644
+--- a/library/sysroot/Cargo.toml
++++ b/library/sysroot/Cargo.toml
+@@ -11,7 +11,7 @@ test = { path = "../test" }
+
+ # Forward features to the `std` crate as necessary
+ [features]
+-default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
++default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind", "compiler-builtins-no-f16-f128"]
+ backtrace = ["std/backtrace"]
+ compiler-builtins-c = ["std/compiler-builtins-c"]
+ compiler-builtins-mem = ["std/compiler-builtins-mem"]
+--
+2.34.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-rawdylib-processprng.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-rawdylib-processprng.patch
deleted file mode 100644
index 584dbdb..0000000
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-rawdylib-processprng.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 9f65e742ba3e41474e6126c6c4469c48eaa6ca7e Mon Sep 17 00:00:00 2001
-From: Chris Denton <chris@chrisdenton.dev>
-Date: Tue, 20 Feb 2024 16:01:40 -0300
-Subject: [PATCH] Don't use raw-dylib in std
-
----
- library/std/src/sys/pal/windows/c.rs | 2 +-
- library/std/src/sys/pal/windows/rand.rs | 3 +--
- 2 files changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
-index ad8e01bfa9b..9ca8e4c16ce 100644
---- a/library/std/src/sys/pal/windows/c.rs
-+++ b/library/std/src/sys/pal/windows/c.rs
-@@ -312,7 +312,7 @@ pub unsafe fn NtWriteFile(
-
- // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library.
- cfg_if::cfg_if! {
--if #[cfg(not(target_vendor = "win7"))] {
-+if #[cfg(any())] {
- #[cfg(target_arch = "x86")]
- #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")]
- extern "system" {
-diff --git a/library/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs
-index e427546222a..f2fe42a4d51 100644
---- a/library/std/src/sys/pal/windows/rand.rs
-+++ b/library/std/src/sys/pal/windows/rand.rs
-@@ -2,7 +2,7 @@
-
- use crate::sys::c;
-
--#[cfg(not(target_vendor = "win7"))]
-+#[cfg(any())]
- #[inline]
- pub fn hashmap_random_keys() -> (u64, u64) {
- let mut v = (0, 0);
-@@ -13,7 +13,6 @@ pub fn hashmap_random_keys() -> (u64, u64) {
- v
- }
-
--#[cfg(target_vendor = "win7")]
- pub fn hashmap_random_keys() -> (u64, u64) {
- use crate::ffi::c_void;
- use crate::io;
---
-2.42.0.windows.2
-
diff --git a/compiler/rustc_codegen_cranelift/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch b/compiler/rustc_codegen_cranelift/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch
deleted file mode 100644
index 21f5ee9..0000000
--- a/compiler/rustc_codegen_cranelift/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 0d741cf82c3c908616abd39dc84ebf7d8702e0c3 Mon Sep 17 00:00:00 2001
-From: Chris Denton <chris@chrisdenton.dev>
-Date: Tue, 16 Apr 2024 15:51:34 +0000
-Subject: [PATCH] Revert use raw-dylib for Windows futex APIs
-
----
- library/std/src/sys/pal/windows/c.rs | 14 +-------------
- 1 file changed, 1 insertion(+), 13 deletions(-)
-
-diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
-index 9d58ce05f01..1c828bac4b6 100644
---- a/library/std/src/sys/pal/windows/c.rs
-+++ b/library/std/src/sys/pal/windows/c.rs
-@@ -357,19 +357,7 @@ pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 {
- }
-
- #[cfg(not(target_vendor = "win7"))]
--// Use raw-dylib to import synchronization functions to workaround issues with the older mingw import library.
--#[cfg_attr(
-- target_arch = "x86",
-- link(
-- name = "api-ms-win-core-synch-l1-2-0",
-- kind = "raw-dylib",
-- import_name_type = "undecorated"
-- )
--)]
--#[cfg_attr(
-- not(target_arch = "x86"),
-- link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib")
--)]
-+#[link(name = "synchronization")]
- extern "system" {
- pub fn WaitOnAddress(
- address: *const c_void,
---
-2.42.0.windows.2
-
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index db9b551..96c467e 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,4 @@
[toolchain]
-channel = "nightly-2024-07-13"
+channel = "nightly-2024-08-09"
components = ["rust-src", "rustc-dev", "llvm-tools"]
+profile = "minimal"
diff --git a/compiler/rustc_codegen_cranelift/rustfmt.toml b/compiler/rustc_codegen_cranelift/rustfmt.toml
index 6f4d441..d9e6ac3 100644
--- a/compiler/rustc_codegen_cranelift/rustfmt.toml
+++ b/compiler/rustc_codegen_cranelift/rustfmt.toml
@@ -6,3 +6,5 @@
version = "Two"
use_small_heuristics = "Max"
merge_derives = false
+group_imports = "StdExternalCrate"
+imports_granularity = "Module"
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index f0550c2..bb5af91 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -39,6 +39,7 @@
# exotic linkages
rm tests/incremental/hashes/function_interfaces.rs
rm tests/incremental/hashes/statics.rs
+rm -r tests/run-make/naked-symbol-visibility
# variadic arguments
rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
@@ -118,6 +119,7 @@
rm tests/ui/mir/mir_raw_fat_ptr.rs # same
rm tests/ui/consts/issue-33537.rs # same
rm tests/ui/consts/const-mut-refs-crate.rs # same
+rm tests/ui/abi/large-byval-align.rs # exceeds implementation limit of Cranelift
# doesn't work due to the way the rustc test suite is invoked.
# should work when using ./x.py test the way it is intended
@@ -134,6 +136,8 @@
# bugs in the test suite
# ======================
rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
+rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annotation
+rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
@@ -157,8 +161,8 @@
RUSTDOC := \$(RUSTDOC) -Clinker='\$(RUSTC_LINKER)'
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index 9607ff02f96..b7d97caf9a2 100644
---- a/src/tools/run-make-support/src/rustdoc.rs
-+++ b/src/tools/run-make-support/src/rustdoc.rs
+--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
++++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
@@ -34,8 +34,6 @@ pub fn bare() -> Self {
#[track_caller]
pub fn new() -> Self {
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index 1935005..5eedab4 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -1,8 +1,13 @@
-use std::path::{Path, PathBuf};
+use std::borrow::Borrow;
+use std::fs;
+use std::path::Path;
+use ar_archive_writer::{COFFShortExport, MachineTypes};
use rustc_codegen_ssa::back::archive::{
- ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
+ create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
+ DEFAULT_OBJECT_READER,
};
+use rustc_codegen_ssa::common::is_mingw_gnu_toolchain;
use rustc_session::Session;
pub(crate) struct ArArchiveBuilderBuilder;
@@ -15,11 +20,74 @@ fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder +
fn create_dll_import_lib(
&self,
sess: &Session,
- _lib_name: &str,
- _dll_imports: &[rustc_session::cstore::DllImport],
- _tmpdir: &Path,
- _is_direct_dependency: bool,
- ) -> PathBuf {
- sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
+ lib_name: &str,
+ import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+ output_path: &Path,
+ ) {
+ if is_mingw_gnu_toolchain(&sess.target) {
+ // The binutils linker used on -windows-gnu targets cannot read the import
+ // libraries generated by LLVM: in our attempts, the linker produced an .EXE
+ // that loaded but crashed with an AV upon calling one of the imported
+ // functions. Therefore, use binutils to create the import library instead,
+ // by writing a .DEF file to the temp dir and calling binutils's dlltool.
+ create_mingw_dll_import_lib(
+ sess,
+ lib_name,
+ import_name_and_ordinal_vector,
+ output_path,
+ );
+ } else {
+ let mut file =
+ match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) {
+ Ok(file) => file,
+ Err(error) => {
+ sess.dcx().fatal(format!(
+ "failed to create import library file `{path}`: {error}",
+ path = output_path.display(),
+ ));
+ }
+ };
+
+ let machine = match sess.target.arch.borrow() {
+ "x86" => MachineTypes::I386,
+ "x86_64" => MachineTypes::AMD64,
+ "arm" => MachineTypes::ARMNT,
+ "aarch64" => MachineTypes::ARM64,
+ _ => {
+ sess.dcx().fatal(format!(
+ "unsupported target architecture `{arch}`",
+ arch = sess.target.arch,
+ ));
+ }
+ };
+
+ let exports = import_name_and_ordinal_vector
+ .iter()
+ .map(|(name, ordinal)| COFFShortExport {
+ name: name.to_string(),
+ ext_name: None,
+ symbol_name: None,
+ alias_target: None,
+ ordinal: ordinal.unwrap_or(0),
+ noname: ordinal.is_some(),
+ data: false,
+ private: false,
+ constant: false,
+ })
+ .collect::<Vec<_>>();
+
+ if let Err(error) = ar_archive_writer::write_import_library(
+ &mut file,
+ lib_name,
+ &exports,
+ machine,
+ !sess.target.is_like_msvc,
+ ) {
+ sess.dcx().fatal(format!(
+ "failed to create import library `{path}`: `{error}`",
+ path = output_path.display(),
+ ));
+ }
+ }
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
index e16b776..b6a4769 100644
--- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
+++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
@@ -23,19 +23,7 @@ pub(crate) fn maybe_codegen<'tcx>(
match bin_op {
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None,
BinOp::Add | BinOp::AddUnchecked | BinOp::Sub | BinOp::SubUnchecked => None,
- BinOp::Mul | BinOp::MulUnchecked => {
- let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
- let ret_val = fx.lib_call(
- "__multi3",
- vec![AbiParam::new(types::I128), AbiParam::new(types::I128)],
- vec![AbiParam::new(types::I128)],
- &args,
- )[0];
- Some(CValue::by_val(
- ret_val,
- fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }),
- ))
- }
+ BinOp::Mul | BinOp::MulUnchecked => None,
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
BinOp::Div | BinOp::Rem => {
let name = match (bin_op, is_signed) {
@@ -92,6 +80,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
match bin_op {
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(),
+ BinOp::Add | BinOp::Sub => None,
BinOp::Mul if is_signed => {
let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
@@ -112,7 +101,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
let oflow = fx.bcx.ins().ireduce(types::I8, oflow);
Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty)))
}
- BinOp::Add | BinOp::Sub | BinOp::Mul => {
+ BinOp::Mul => {
let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
let param_types = vec![
@@ -121,15 +110,7 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
AbiParam::new(types::I128),
];
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
- let name = match (bin_op, is_signed) {
- (BinOp::Add, false) => "__rust_u128_addo",
- (BinOp::Add, true) => "__rust_i128_addo",
- (BinOp::Sub, false) => "__rust_u128_subo",
- (BinOp::Sub, true) => "__rust_i128_subo",
- (BinOp::Mul, false) => "__rust_u128_mulo",
- _ => unreachable!(),
- };
- fx.lib_call(name, param_types, vec![], &args);
+ fx.lib_call("__rust_u128_mulo", param_types, vec![], &args);
Some(out_place.to_cvalue(fx))
}
BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 0931713..a1b29a4 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -107,7 +107,7 @@ pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
return false;
}
- let tail = tcx.struct_tail_erasing_lifetimes(ty, ParamEnv::reveal_all());
+ let tail = tcx.struct_tail_for_codegen(ty, ParamEnv::reveal_all());
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
index f3b9632..4154a62 100644
--- a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
+++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
@@ -38,18 +38,12 @@ pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) {
register_functions_for_jit;
// integers
- fn __multi3(a: i128, b: i128) -> i128;
fn __muloti4(n: i128, d: i128, oflow: &mut i32) -> i128;
fn __udivti3(n: u128, d: u128) -> u128;
fn __divti3(n: i128, d: i128) -> i128;
fn __umodti3(n: u128, d: u128) -> u128;
fn __modti3(n: i128, d: i128) -> i128;
- fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool);
- fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool);
- fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool);
- fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool);
fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool);
- fn __rust_i128_mulo(a: i128, b: i128) -> (i128, bool);
// floats
fn __floattisf(i: i128) -> f32;
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
index eebd181..ac7dd0b 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs
@@ -1,7 +1,8 @@
//! Unwind info generation (`.eh_frame`)
use cranelift_codegen::ir::Endianness;
-use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa};
+use cranelift_codegen::isa::unwind::UnwindInfo;
+use cranelift_codegen::isa::TargetIsa;
use cranelift_object::ObjectProduct;
use gimli::write::{CieId, EhFrame, FrameTable, Section};
use gimli::RunTimeEndian;
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 763d9a4..b6fee1b 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -11,8 +11,9 @@
use rustc_codegen_ssa::back::link::ensure_removed;
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
use rustc_codegen_ssa::base::determine_cgu_reuse;
-use rustc_codegen_ssa::errors as ssa_errors;
-use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
+use rustc_codegen_ssa::{
+ errors as ssa_errors, CodegenResults, CompiledModule, CrateInfo, ModuleKind,
+};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{par_map, IntoDynSyncSend};
@@ -26,8 +27,9 @@
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
use crate::debuginfo::TypeDebugContext;
use crate::global_asm::GlobalAsmConfig;
+use crate::prelude::*;
use crate::unwind_module::UnwindModule;
-use crate::{prelude::*, BackendConfig};
+use crate::BackendConfig;
struct ModuleCodegenResult {
module_regular: CompiledModule,
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index dfee8e7..12e860f 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -14,9 +14,9 @@
use rustc_span::Symbol;
use crate::debuginfo::TypeDebugContext;
+use crate::prelude::*;
use crate::unwind_module::UnwindModule;
-use crate::{prelude::*, BackendConfig};
-use crate::{CodegenCx, CodegenMode};
+use crate::{BackendConfig, CodegenCx, CodegenMode};
struct JitState {
jit_module: UnwindModule<JITModule>,
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index a20faa2..cb00303 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -169,39 +169,6 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
}
}
- "llvm.x86.sse.add.ss" => {
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_add_ss&ig_expand=171
- intrinsic_args!(fx, args => (a, b); intrinsic);
-
- assert_eq!(a.layout(), b.layout());
- assert_eq!(a.layout(), ret.layout());
- let layout = a.layout();
-
- let (_, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
- assert!(lane_ty.is_floating_point());
- let ret_lane_layout = fx.layout_of(lane_ty);
-
- ret.write_cvalue(fx, a);
-
- let a_lane = a.value_lane(fx, 0).load_scalar(fx);
- let b_lane = b.value_lane(fx, 0).load_scalar(fx);
-
- let res = fx.bcx.ins().fadd(a_lane, b_lane);
-
- let res_lane = CValue::by_val(res, ret_lane_layout);
- ret.place_lane(fx, 0).write_cvalue(fx, res_lane);
- }
-
- "llvm.x86.sse.sqrt.ps" => {
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sqrt_ps&ig_expand=6245
- intrinsic_args!(fx, args => (a); intrinsic);
-
- // FIXME use vector instructions when possible
- simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
- fx.bcx.ins().sqrt(lane)
- });
- }
-
"llvm.x86.sse.max.ps" => {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_max_ps&ig_expand=4357
intrinsic_args!(fx, args => (a, b); intrinsic);
@@ -744,117 +711,6 @@ fn select4(
pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Avx);
}
- "llvm.x86.fma.vfmaddsub.ps"
- | "llvm.x86.fma.vfmaddsub.pd"
- | "llvm.x86.fma.vfmaddsub.ps.256"
- | "llvm.x86.fma.vfmaddsub.pd.256" => {
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmaddsub_ps&ig_expand=3205
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmaddsub_pd&ig_expand=3181
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmaddsub_ps&ig_expand=3209
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmaddsub_pd&ig_expand=3185
- intrinsic_args!(fx, args => (a, b, c); intrinsic);
-
- assert_eq!(a.layout(), b.layout());
- assert_eq!(a.layout(), c.layout());
- let layout = a.layout();
-
- let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
- let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
- assert!(lane_ty.is_floating_point());
- assert!(ret_lane_ty.is_floating_point());
- assert_eq!(lane_count, ret_lane_count);
- let ret_lane_layout = fx.layout_of(ret_lane_ty);
-
- for idx in 0..lane_count {
- let a_lane = a.value_lane(fx, idx).load_scalar(fx);
- let b_lane = b.value_lane(fx, idx).load_scalar(fx);
- let c_lane = c.value_lane(fx, idx).load_scalar(fx);
-
- let mul = fx.bcx.ins().fmul(a_lane, b_lane);
- let res = if idx & 1 == 0 {
- fx.bcx.ins().fsub(mul, c_lane)
- } else {
- fx.bcx.ins().fadd(mul, c_lane)
- };
-
- let res_lane = CValue::by_val(res, ret_lane_layout);
- ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
- }
- }
-
- "llvm.x86.fma.vfmsubadd.ps"
- | "llvm.x86.fma.vfmsubadd.pd"
- | "llvm.x86.fma.vfmsubadd.ps.256"
- | "llvm.x86.fma.vfmsubadd.pd.256" => {
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmsubadd_ps&ig_expand=3325
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fmsubadd_pd&ig_expand=3301
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmsubadd_ps&ig_expand=3329
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fmsubadd_pd&ig_expand=3305
- intrinsic_args!(fx, args => (a, b, c); intrinsic);
-
- assert_eq!(a.layout(), b.layout());
- assert_eq!(a.layout(), c.layout());
- let layout = a.layout();
-
- let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
- let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
- assert!(lane_ty.is_floating_point());
- assert!(ret_lane_ty.is_floating_point());
- assert_eq!(lane_count, ret_lane_count);
- let ret_lane_layout = fx.layout_of(ret_lane_ty);
-
- for idx in 0..lane_count {
- let a_lane = a.value_lane(fx, idx).load_scalar(fx);
- let b_lane = b.value_lane(fx, idx).load_scalar(fx);
- let c_lane = c.value_lane(fx, idx).load_scalar(fx);
-
- let mul = fx.bcx.ins().fmul(a_lane, b_lane);
- let res = if idx & 1 == 0 {
- fx.bcx.ins().fadd(mul, c_lane)
- } else {
- fx.bcx.ins().fsub(mul, c_lane)
- };
-
- let res_lane = CValue::by_val(res, ret_lane_layout);
- ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
- }
- }
-
- "llvm.x86.fma.vfnmadd.ps"
- | "llvm.x86.fma.vfnmadd.pd"
- | "llvm.x86.fma.vfnmadd.ps.256"
- | "llvm.x86.fma.vfnmadd.pd.256" => {
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fnmadd_ps&ig_expand=3391
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_fnmadd_pd&ig_expand=3367
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fnmadd_ps&ig_expand=3395
- // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_fnmadd_pd&ig_expand=3371
- intrinsic_args!(fx, args => (a, b, c); intrinsic);
-
- assert_eq!(a.layout(), b.layout());
- assert_eq!(a.layout(), c.layout());
- let layout = a.layout();
-
- let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
- let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
- assert!(lane_ty.is_floating_point());
- assert!(ret_lane_ty.is_floating_point());
- assert_eq!(lane_count, ret_lane_count);
- let ret_lane_layout = fx.layout_of(ret_lane_ty);
-
- for idx in 0..lane_count {
- let a_lane = a.value_lane(fx, idx).load_scalar(fx);
- let b_lane = b.value_lane(fx, idx).load_scalar(fx);
- let c_lane = c.value_lane(fx, idx).load_scalar(fx);
-
- let mul = fx.bcx.ins().fmul(a_lane, b_lane);
- let neg_mul = fx.bcx.ins().fneg(mul);
- let res = fx.bcx.ins().fadd(neg_mul, c_lane);
-
- let res_lane = CValue::by_val(res, ret_lane_layout);
- ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
- }
- }
-
"llvm.x86.sse42.crc32.32.8"
| "llvm.x86.sse42.crc32.32.16"
| "llvm.x86.sse42.crc32.32.32"
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index b21c559..29deac6 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -725,7 +725,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
// Cranelift treats stores as volatile by default
// FIXME correctly handle unaligned_volatile_store
- // FIXME actually do nontemporal stores if requested
+ // FIXME actually do nontemporal stores if requested (but do not just emit MOVNT on x86;
+ // see the LLVM backend for details)
let dest = CPlace::for_ptr(Pointer::new(ptr), val.layout());
dest.write_cvalue(fx, val);
}
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 8d3d5ac..21930fa 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -12,6 +12,7 @@
#![warn(unused_lifetimes)]
// tidy-alphabetical-end
+extern crate ar_archive_writer;
extern crate jobserver;
#[macro_use]
extern crate rustc_middle;
@@ -85,10 +86,9 @@
mod prelude {
pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
pub(crate) use cranelift_codegen::ir::function::Function;
- pub(crate) use cranelift_codegen::ir::types;
pub(crate) use cranelift_codegen::ir::{
- AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot,
- StackSlotData, StackSlotKind, TrapCode, Type, Value,
+ types, AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
+ StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
};
pub(crate) use cranelift_codegen::Context;
pub(crate) use cranelift_module::{self, DataDescription, FuncId, Linkage, Module};
@@ -191,9 +191,20 @@ fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_sp
if sess.target.arch == "x86_64" && sess.target.os != "none" {
// x86_64 mandates SSE2 support
vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")]
- } else if sess.target.arch == "aarch64" && sess.target.os != "none" {
- // AArch64 mandates Neon support
- vec![sym::neon]
+ } else if sess.target.arch == "aarch64" {
+ match &*sess.target.os {
+ "none" => vec![],
+ // On macOS the aes, sha2 and sha3 features are enabled by default and ring
+ // fails to compile on macOS when they are not present.
+ "macos" => vec![
+ sym::neon,
+ Symbol::intern("aes"),
+ Symbol::intern("sha2"),
+ Symbol::intern("sha3"),
+ ],
+ // AArch64 mandates Neon support
+ _ => vec![sym::neon],
+ }
} else {
vec![]
}
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index fe0a155..ba20a75 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -1,7 +1,6 @@
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
use rustc_hir::LangItem;
-use rustc_middle::ty::AssocKind;
-use rustc_middle::ty::GenericArg;
+use rustc_middle::ty::{AssocKind, GenericArg};
use rustc_session::config::{sigpipe, EntryFnType};
use rustc_span::symbol::Ident;
use rustc_span::DUMMY_SP;
diff --git a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
index 26327dc..c93fe93 100644
--- a/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
+++ b/compiler/rustc_codegen_cranelift/src/optimize/peephole.rs
@@ -1,6 +1,7 @@
//! Peephole optimizations that can be performed while creating clif ir.
-use cranelift_codegen::ir::{condcodes::IntCC, InstructionData, Opcode, Value, ValueDef};
+use cranelift_codegen::ir::condcodes::IntCC;
+use cranelift_codegen::ir::{InstructionData, Opcode, Value, ValueDef};
use cranelift_frontend::FunctionBuilder;
/// If the given value was produced by the lowering of `Rvalue::Not` return the input and true,
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index 967aa53..e09cd16 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -22,7 +22,7 @@ pub(crate) fn unsized_info<'tcx>(
old_info: Option<Value>,
) -> Value {
let (source, target) =
- fx.tcx.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all());
+ fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all());
match (&source.kind(), &target.kind()) {
(&ty::Array(_, len), &ty::Slice(_)) => fx
.bcx
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 1aa28da..8eb2095 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -677,8 +677,10 @@ fn transmute_scalar<'tcx>(
let to_addr = to_ptr.get_addr(fx);
let src_layout = from.1;
let size = dst_layout.size.bytes();
- let src_align = src_layout.align.abi.bytes() as u8;
- let dst_align = dst_layout.align.abi.bytes() as u8;
+ // `emit_small_memory_copy` uses `u8` for alignments, just use the maximum
+ // alignment that fits in a `u8` if the actual alignment is larger.
+ let src_align = src_layout.align.abi.bytes().try_into().unwrap_or(128);
+ let dst_align = dst_layout.align.abi.bytes().try_into().unwrap_or(128);
fx.bcx.emit_small_memory_copy(
fx.target_config,
to_addr,
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock
index d6ec1f8..771f2f1 100644
--- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.lock
@@ -50,7 +50,7 @@
[[package]]
name = "compiler_builtins"
-version = "0.1.109"
+version = "0.1.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
dependencies = [
diff --git a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
index e466992..0550312 100644
--- a/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/build_system/build_sysroot/Cargo.toml
@@ -6,9 +6,7 @@
[dependencies]
core = { path = "./sysroot_src/library/core" }
-# TODO: after the sync, revert to using version 0.1.
-# compiler_builtins = "0.1"
-compiler_builtins = "=0.1.109"
+compiler_builtins = "0.1"
alloc = { path = "./sysroot_src/library/alloc" }
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
test = { path = "./sysroot_src/library/test" }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs
index d465ab7..8d95186 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/build.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs
@@ -1,12 +1,13 @@
-use crate::config::{Channel, ConfigInfo};
-use crate::utils::{
- copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
-};
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs;
use std::path::Path;
+use crate::config::{Channel, ConfigInfo};
+use crate::utils::{
+ copy_file, create_dir, get_sysroot_dir, run_command, run_command_with_output_and_env, walk_dir,
+};
+
#[derive(Default)]
struct BuildArg {
flags: Vec<String>,
@@ -141,7 +142,14 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu
rustflags.push_str(" -Csymbol-mangling-version=v0");
}
- let mut args: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"build", &"--target", &config.target];
+ let mut args: Vec<&dyn AsRef<OsStr>> = vec![
+ &"cargo",
+ &"build",
+ &"--target",
+ &config.target,
+ &"--features",
+ &"compiler-builtins-no-f16-f128",
+ ];
if config.no_default_features {
rustflags.push_str(" -Csymbol-mangling-version=v0");
diff --git a/compiler/rustc_codegen_gcc/build_system/src/clean.rs b/compiler/rustc_codegen_gcc/build_system/src/clean.rs
index 55f55ac..768a78e 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/clean.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/clean.rs
@@ -1,8 +1,8 @@
-use crate::utils::{get_sysroot_dir, remove_file, run_command};
-
use std::fs::remove_dir_all;
use std::path::Path;
+use crate::utils::{get_sysroot_dir, remove_file, run_command};
+
#[derive(Default)]
enum CleanArg {
/// `clean all`
diff --git a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
index cbf590c..e28ee87 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
@@ -1,8 +1,8 @@
+use std::path::{Path, PathBuf};
+
use crate::config::ConfigInfo;
use crate::utils::{git_clone, run_command_with_output};
-use std::path::{Path, PathBuf};
-
fn show_usage() {
println!(
r#"
diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs
index bbb711c..15ba161 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/config.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs
@@ -1,14 +1,15 @@
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::path::{Path, PathBuf};
+use std::{env as std_env, fs};
+
+use boml::types::TomlValue;
+use boml::Toml;
+
use crate::utils::{
create_dir, create_symlink, get_os_name, get_sysroot_dir, run_command_with_output,
rustc_version_info, split_args,
};
-use std::collections::HashMap;
-use std::env as std_env;
-use std::ffi::OsStr;
-use std::fs;
-use std::path::{Path, PathBuf};
-
-use boml::{types::TomlValue, Toml};
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
pub enum Channel {
diff --git a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
index 43644ba..de310a6 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
@@ -1,7 +1,8 @@
-use crate::utils::run_command_with_output;
use std::ffi::OsStr;
use std::path::Path;
+use crate::utils::run_command_with_output;
+
fn show_usage() {
println!(
r#"
diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs
index d678fd7..3a860e2 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/main.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs
@@ -1,5 +1,4 @@
-use std::env;
-use std::process;
+use std::{env, process};
mod build;
mod clean;
diff --git a/compiler/rustc_codegen_gcc/build_system/src/prepare.rs b/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
index 00aa632..d14639a 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
@@ -1,12 +1,12 @@
+use std::fs;
+use std::path::{Path, PathBuf};
+
use crate::rustc_info::get_rustc_path;
use crate::utils::{
cargo_install, create_dir, get_sysroot_dir, git_clone_root_dir, remove_file, run_command,
run_command_with_output, walk_dir,
};
-use std::fs;
-use std::path::{Path, PathBuf};
-
fn prepare_libcore(
sysroot_path: &Path,
libgccjit12_patches: bool,
diff --git a/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs b/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs
index 242fa7e..105f5ee 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs
@@ -1,13 +1,13 @@
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::path::PathBuf;
+
use crate::config::ConfigInfo;
use crate::utils::{
get_toolchain, run_command_with_output_and_env_no_err, rustc_toolchain_version_info,
rustc_version_info,
};
-use std::collections::HashMap;
-use std::ffi::OsStr;
-use std::path::PathBuf;
-
fn args(command: &str) -> Result<Option<Vec<String>>, String> {
// We skip the binary and the "cargo"/"rustc" option.
if let Some("--help") = std::env::args().skip(2).next().as_deref() {
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 06f28d1..83fa805 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -1,3 +1,10 @@
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::fs::{remove_dir_all, File};
+use std::io::{BufRead, BufReader};
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+
use crate::build;
use crate::config::{Channel, ConfigInfo};
use crate::utils::{
@@ -6,13 +13,6 @@
split_args, walk_dir,
};
-use std::collections::HashMap;
-use std::ffi::OsStr;
-use std::fs::{remove_dir_all, File};
-use std::io::{BufRead, BufReader};
-use std::path::{Path, PathBuf};
-use std::str::FromStr;
-
type Env = HashMap<String, String>;
type Runner = fn(&Env, &TestArg) -> Result<(), String>;
type Runners = HashMap<&'static str, (&'static str, Runner)>;
@@ -552,7 +552,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> {
&"--stage",
&"0",
&"tests/assembly/asm",
- &"--rustc-args",
+ &"--compiletest-rustc-args",
&rustc_args,
],
Some(&rust_dir),
@@ -1020,7 +1020,7 @@ fn file_handling(file_path: &Path) -> Result<(), String> {
&"--stage",
&"0",
&format!("tests/{}", test_type),
- &"--rustc-args",
+ &"--compiletest-rustc-args",
&rustc_args,
],
Some(&rust_path),
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index 5a7ddc4..9f096e9 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -430,6 +430,7 @@ pub enum E2<X> {
V4,
}
+#[allow(unreachable_patterns)]
fn check_niche_behavior () {
if let E1::V2 { .. } = (E1::V1 { f: true }) {
intrinsics::abort();
diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs
index 21676f5..0cee05f 100644
--- a/compiler/rustc_codegen_gcc/src/archive.rs
+++ b/compiler/rustc_codegen_gcc/src/archive.rs
@@ -1,12 +1,10 @@
-use std::path::{Path, PathBuf};
+use std::path::Path;
use rustc_codegen_ssa::back::archive::{
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
};
use rustc_session::Session;
-use rustc_session::cstore::DllImport;
-
pub(crate) struct ArArchiveBuilderBuilder;
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
@@ -18,10 +16,9 @@ fn create_dll_import_lib(
&self,
_sess: &Session,
_lib_name: &str,
- _dll_imports: &[DllImport],
- _tmpdir: &Path,
- _is_direct_dependency: bool,
- ) -> PathBuf {
+ _import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+ _output_path: &Path,
+ ) {
unimplemented!("creating dll imports is not yet supported");
}
}
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 1da6912..7c13528 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::mir::operand::OperandValue;
@@ -6,13 +8,11 @@
AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef,
InlineAsmOperandRef,
};
-
-use rustc_middle::{bug, ty::Instance};
+use rustc_middle::bug;
+use rustc_middle::ty::Instance;
use rustc_span::Span;
use rustc_target::asm::*;
-use std::borrow::Cow;
-
use crate::builder::Builder;
use crate::callee::get_fn;
use crate::context::CodegenCx;
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index 27f2110..5fdf268 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -9,8 +9,9 @@
use rustc_middle::ty;
use rustc_span::symbol::sym;
+use crate::context::CodegenCx;
+use crate::errors::TiedTargetFeatures;
use crate::gcc_util::{check_tied_features, to_gcc_features};
-use crate::{context::CodegenCx, errors::TiedTargetFeatures};
/// Get GCC attribute for the provided inline heuristic.
#[cfg(feature = "master")]
@@ -74,7 +75,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
let function_features = codegen_fn_attrs
.target_features
.iter()
- .map(|features| features.as_str())
+ .map(|features| features.name.as_str())
.collect::<Vec<&str>>();
if let Some(features) = check_tied_features(
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index be149ff..4940a7f 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -19,8 +19,7 @@
use crate::builder::Builder;
use crate::context::CodegenCx;
-use crate::{gcc_util, new_context, LockedTargetInfo};
-use crate::{GccContext, SyncContext};
+use crate::{gcc_util, new_context, GccContext, LockedTargetInfo, SyncContext};
#[cfg(feature = "master")]
pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index b9e4bd7..47b378c 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -28,9 +28,8 @@
use rustc_middle::ty::{Instance, ParamEnv, Ty, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::Span;
-use rustc_target::abi::{
- self, call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout, WrappingRange,
-};
+use rustc_target::abi::call::FnAbi;
+use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout, WrappingRange};
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi};
use crate::common::{type_is_pointer, SignType, TypeReflection};
@@ -1128,6 +1127,8 @@ fn store_with_flags(
self.llbb().add_assignment(self.location, aligned_destination, val);
// TODO(antoyo): handle align and flags.
// NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
+ // When adding support for NONTEMPORAL, make sure to not just emit MOVNT on x86; see the
+ // LLVM backend for details.
self.cx.context.new_rvalue_zero(self.type_i32())
}
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 70f0dc3..dca6b64 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,5 +1,4 @@
-use gccjit::LValue;
-use gccjit::{RValue, ToRValue, Type};
+use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods, StaticMethods};
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
use rustc_middle::mir::Mutability;
@@ -161,6 +160,11 @@ fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> {
self.context.new_struct_constructor(None, struct_type.as_type(), None, values)
}
+ fn const_vector(&self, values: &[RValue<'gcc>]) -> RValue<'gcc> {
+ let typ = self.type_vector(values[0].get_type(), values.len() as u64);
+ self.context.new_rvalue_from_vector(None, typ, values)
+ }
+
fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option<u64> {
// TODO(antoyo)
None
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index ba7e08e..e5673cd 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -3,14 +3,13 @@
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, StaticMethods};
use rustc_hir::def::DefKind;
-use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::interpret::{
self, read_target_uint, ConstAllocation, ErrorHandled, Scalar as InterpScalar,
};
-use rustc_middle::span_bug;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance};
+use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 86a5000..e330102 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -6,8 +6,7 @@
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, MiscMethods};
-use rustc_data_structures::base_n::ToBaseN;
-use rustc_data_structures::base_n::ALPHANUMERIC_ONLY;
+use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::span_bug;
@@ -17,10 +16,10 @@
};
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_session::Session;
-use rustc_span::{source_map::respan, Span, DUMMY_SP};
-use rustc_target::abi::{
- call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
-};
+use rustc_span::source_map::respan;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi::call::FnAbi;
+use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi};
use crate::callee::get_fn;
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index 3d9ea27..d770da5 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -1,3 +1,5 @@
+use std::ops::Range;
+
use gccjit::{Location, RValue};
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
@@ -10,7 +12,6 @@
use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::Size;
-use std::ops::Range;
use crate::builder::Builder;
use crate::context::CodegenCx;
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 53877e8..5308ccd 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -1,11 +1,10 @@
#[cfg(feature = "master")]
use gccjit::Context;
-use smallvec::{smallvec, SmallVec};
-
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::bug;
use rustc_session::Session;
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
+use smallvec::{smallvec, SmallVec};
use crate::errors::{
PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
@@ -66,8 +65,8 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
let feature = backend_feature_name(s)?;
// Warn against use of GCC specific feature names on the CLI.
- if diagnostics && !supported_features.iter().any(|&(v, _)| v == feature) {
- let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
+ if diagnostics && !supported_features.iter().any(|&(v, _, _)| v == feature) {
+ let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| {
let gcc_features = to_gcc_features(sess, rust_feature);
if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
Some(rust_feature)
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index e4c5eb9..92d5c1c 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -6,18 +6,13 @@
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
use rustc_middle::ty::{ParamEnv, Ty};
-use rustc_target::abi::{
- call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode},
- Endian,
-};
+use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
+use rustc_target::abi::Endian;
use rustc_target::spec;
-use crate::builder::ToGccComp;
-use crate::{
- builder::Builder,
- common::{SignType, TypeReflection},
- context::CodegenCx,
-};
+use crate::builder::{Builder, ToGccComp};
+use crate::common::{SignType, TypeReflection};
+use crate::context::CodegenCx;
impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
pub fn gcc_urem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -266,7 +261,9 @@ pub fn gcc_checked_binop(
lhs: <Self as BackendTypes>::Value,
rhs: <Self as BackendTypes>::Value,
) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) {
- use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
+ use rustc_middle::ty::IntTy::*;
+ use rustc_middle::ty::UintTy::*;
+ use rustc_middle::ty::{Int, Uint};
let new_kind = match *typ.kind() {
Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index a127048..554e572 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -3,7 +3,8 @@
use gccjit::{Function, FunctionPtrType, RValue, ToRValue, UnaryOp};
use rustc_codegen_ssa::traits::BuilderMethods;
-use crate::{builder::Builder, context::CodegenCx};
+use crate::builder::Builder;
+use crate::context::CodegenCx;
pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
builder: &Builder<'a, 'gcc, 'tcx>,
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index ba214a9..8da1df3 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -1,10 +1,8 @@
use std::iter::FromIterator;
-use gccjit::ToRValue;
-use gccjit::{BinaryOp, RValue, Type};
+use gccjit::{BinaryOp, RValue, ToRValue, Type};
#[cfg(feature = "master")]
use gccjit::{ComparisonOp, UnaryOp};
-
use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
#[cfg(feature = "master")]
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 1132b0c..94f0162 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -79,14 +79,11 @@
use std::sync::atomic::AtomicBool;
#[cfg(not(feature = "master"))]
use std::sync::atomic::Ordering;
-use std::sync::Arc;
-use std::sync::Mutex;
+use std::sync::{Arc, Mutex};
-use back::lto::ThinBuffer;
-use back::lto::ThinData;
+use back::lto::{ThinBuffer, ThinData};
use errors::LTONotSupported;
-use gccjit::CType;
-use gccjit::{Context, OptimizationLevel};
+use gccjit::{CType, Context, OptimizationLevel};
#[cfg(feature = "master")]
use gccjit::{TargetInfo, Version};
use rustc_ast::expand::allocator::AllocatorKind;
@@ -489,7 +486,7 @@ pub fn target_features(
sess.target
.supported_target_features()
.iter()
- .filter_map(|&(feature, gate)| {
+ .filter_map(|&(feature, gate, _)| {
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
Some(feature)
} else {
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index 44657ad..e6b22d5 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -9,10 +9,9 @@
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
-use crate::attributes;
-use crate::base;
use crate::context::CodegenCx;
use crate::type_of::LayoutGccExt;
+use crate::{attributes, base};
impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
#[cfg_attr(not(feature = "master"), allow(unused_variables))]
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index bb5045e..dad4722 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -12,7 +12,7 @@
itertools = "0.12"
libc = "0.2"
measureme = "11"
-object = { version = "0.32.0", default-features = false, features = ["std", "read"] }
+object = { version = "0.36.2", default-features = false, features = ["std", "read"] }
rustc-demangle = "0.1.21"
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index 1c126e7..267da93 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -1,23 +1,13 @@
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
-codegen_llvm_dlltool_fail_import_library =
- Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
- {$stdout}
- {$stderr}
-
codegen_llvm_dynamic_linking_with_lto =
cannot prefer dynamic linking when performing LTO
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
-codegen_llvm_error_calling_dlltool =
- Error calling dlltool '{$dlltool_path}': {$error}
codegen_llvm_error_creating_import_library =
Error creating import library for {$lib_name}: {$error}
-codegen_llvm_error_writing_def_file =
- Error writing .DEF file: {$error}
-
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
codegen_llvm_from_llvm_diag = {$message}
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index d034f9b..5ff580e 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -1,30 +1,29 @@
-use crate::attributes;
-use crate::builder::Builder;
-use crate::context::CodegenCx;
-use crate::llvm::{self, Attribute, AttributePlace};
-use crate::llvm_util;
-use crate::type_::Type;
-use crate::type_of::LayoutLlvmExt;
-use crate::value::Value;
+use std::cmp;
+use libc::c_uint;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
-use rustc_middle::bug;
use rustc_middle::ty::layout::LayoutOf;
pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
use rustc_middle::ty::Ty;
+use rustc_middle::{bug, ty};
use rustc_session::config;
pub use rustc_target::abi::call::*;
use rustc_target::abi::{self, HasDataLayout, Int, Size};
pub use rustc_target::spec::abi::Abi;
use rustc_target::spec::SanitizerSet;
-
-use libc::c_uint;
use smallvec::SmallVec;
-use std::cmp;
+use crate::attributes::llfn_attrs_from_instance;
+use crate::builder::Builder;
+use crate::context::CodegenCx;
+use crate::llvm::{self, Attribute, AttributePlace};
+use crate::type_::Type;
+use crate::type_of::LayoutLlvmExt;
+use crate::value::Value;
+use crate::{attributes, llvm_util};
pub trait ArgAttributesExt {
fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value);
@@ -121,8 +120,10 @@ fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
match self.kind {
RegKind::Integer => cx.type_ix(self.size.bits()),
RegKind::Float => match self.size.bits() {
+ 16 => cx.type_f16(),
32 => cx.type_f32(),
64 => cx.type_f64(),
+ 128 => cx.type_f128(),
_ => bug!("unsupported float: {:?}", self),
},
RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()),
@@ -310,7 +311,16 @@ pub trait FnAbiLlvmExt<'ll, 'tcx> {
fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
fn llvm_cconv(&self) -> llvm::CallConv;
- fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value);
+
+ /// Apply attributes to a function declaration/definition.
+ fn apply_attrs_llfn(
+ &self,
+ cx: &CodegenCx<'ll, 'tcx>,
+ llfn: &'ll Value,
+ instance: Option<ty::Instance<'tcx>>,
+ );
+
+ /// Apply attributes to a function call.
fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value);
}
@@ -396,7 +406,12 @@ fn llvm_cconv(&self) -> llvm::CallConv {
self.conv.into()
}
- fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
+ fn apply_attrs_llfn(
+ &self,
+ cx: &CodegenCx<'ll, 'tcx>,
+ llfn: &'ll Value,
+ instance: Option<ty::Instance<'tcx>>,
+ ) {
let mut func_attrs = SmallVec::<[_; 3]>::new();
if self.ret.layout.abi.is_uninhabited() {
func_attrs.push(llvm::AttributeKind::NoReturn.create_attr(cx.llcx));
@@ -415,9 +430,32 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
i += 1;
i - 1
};
+
+ let apply_range_attr = |idx: AttributePlace, scalar: rustc_target::abi::Scalar| {
+ if cx.sess().opts.optimize != config::OptLevel::No
+ && llvm_util::get_version() >= (19, 0, 0)
+ && matches!(scalar.primitive(), Int(..))
+ // If the value is a boolean, the range is 0..2 and that ultimately
+ // become 0..0 when the type becomes i1, which would be rejected
+ // by the LLVM verifier.
+ && !scalar.is_bool()
+ // LLVM also rejects full range.
+ && !scalar.is_always_valid(cx)
+ {
+ attributes::apply_to_llfn(
+ llfn,
+ idx,
+ &[llvm::CreateRangeAttr(cx.llcx, scalar.size(cx), scalar.valid_range(cx))],
+ );
+ }
+ };
+
match &self.ret.mode {
PassMode::Direct(attrs) => {
attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
+ if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
+ apply_range_attr(llvm::AttributePlace::ReturnValue, scalar);
+ }
}
PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
assert!(!on_stack);
@@ -456,8 +494,13 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
);
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]);
}
- PassMode::Direct(attrs)
- | PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
+ PassMode::Direct(attrs) => {
+ let i = apply(attrs);
+ if let abi::Abi::Scalar(scalar) = arg.layout.abi {
+ apply_range_attr(llvm::AttributePlace::Argument(i), scalar);
+ }
+ }
+ PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
apply(attrs);
}
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
@@ -466,8 +509,12 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
apply(meta_attrs);
}
PassMode::Pair(a, b) => {
- apply(a);
- apply(b);
+ let i = apply(a);
+ let ii = apply(b);
+ if let abi::Abi::ScalarPair(scalar_a, scalar_b) = arg.layout.abi {
+ apply_range_attr(llvm::AttributePlace::Argument(i), scalar_a);
+ apply_range_attr(llvm::AttributePlace::Argument(ii), scalar_b);
+ }
}
PassMode::Cast { cast, pad_i32 } => {
if *pad_i32 {
@@ -477,6 +524,11 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
}
}
}
+
+ // If the declaration has an associated instance, compute extra attributes based on that.
+ if let Some(instance) = instance {
+ llfn_attrs_from_instance(cx, llfn, instance);
+ }
}
fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) {
@@ -517,15 +569,18 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll V
}
_ => {}
}
- if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
- // If the value is a boolean, the range is 0..2 and that ultimately
- // become 0..0 when the type becomes i1, which would be rejected
- // by the LLVM verifier.
- if let Int(..) = scalar.primitive() {
- if !scalar.is_bool() && !scalar.is_always_valid(bx) {
- bx.range_metadata(callsite, scalar.valid_range(bx));
- }
- }
+ if bx.cx.sess().opts.optimize != config::OptLevel::No
+ && llvm_util::get_version() < (19, 0, 0)
+ && let abi::Abi::Scalar(scalar) = self.ret.layout.abi
+ && matches!(scalar.primitive(), Int(..))
+ // If the value is a boolean, the range is 0..2 and that ultimately
+ // become 0..0 when the type becomes i1, which would be rejected
+ // by the LLVM verifier.
+ && !scalar.is_bool()
+ // LLVM also rejects full range.
+ && !scalar.is_always_valid(bx)
+ {
+ bx.range_metadata(callsite, scalar.valid_range(bx));
}
for arg in self.args.iter() {
match &arg.mode {
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 5969d9b..8fb3108 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -1,4 +1,3 @@
-use crate::attributes;
use libc::c_uint;
use rustc_ast::expand::allocator::{
alloc_error_handler_name, default_fn_name, global_fn_name, AllocatorKind, AllocatorTy,
@@ -8,9 +7,8 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{DebugInfo, OomStrategy};
-use crate::debuginfo;
use crate::llvm::{self, Context, False, Module, True, Type};
-use crate::ModuleLlvm;
+use crate::{attributes, debuginfo, ModuleLlvm};
pub(crate) unsafe fn codegen(
tcx: TyCtxt<'_>,
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 597ebd9..f931698 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -1,25 +1,26 @@
-use crate::attributes;
-use crate::builder::Builder;
-use crate::common::Funclet;
-use crate::context::CodegenCx;
-use crate::llvm;
-use crate::type_::Type;
-use crate::type_of::LayoutLlvmExt;
-use crate::value::Value;
+use std::assert_matches::assert_matches;
+use libc::{c_char, c_uint};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::mir::operand::OperandValue;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::layout::TyAndLayout;
-use rustc_middle::{bug, span_bug, ty::Instance};
+use rustc_middle::ty::Instance;
+use rustc_middle::{bug, span_bug};
use rustc_span::{sym, Pos, Span, Symbol};
use rustc_target::abi::*;
use rustc_target::asm::*;
+use smallvec::SmallVec;
use tracing::debug;
-use libc::{c_char, c_uint};
-use smallvec::SmallVec;
+use crate::builder::Builder;
+use crate::common::Funclet;
+use crate::context::CodegenCx;
+use crate::type_::Type;
+use crate::type_of::LayoutLlvmExt;
+use crate::value::Value;
+use crate::{attributes, llvm};
impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
fn codegen_inline_asm(
@@ -90,7 +91,7 @@ fn codegen_inline_asm(
// if the target feature needed by the register class is
// disabled. This is necessary otherwise LLVM will try
// to actually allocate a register for the dummy output.
- assert!(matches!(reg, InlineAsmRegOrRegClass::Reg(_)));
+ assert_matches!(reg, InlineAsmRegOrRegClass::Reg(_));
clobbers.push(format!("~{}", reg_to_llvm(reg, None)));
continue;
} else {
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 3877460..fde9510 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -1,23 +1,21 @@
//! Set and unset common attributes on LLVM values.
+pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_codegen_ssa::traits::*;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::config::{FunctionReturn, OptLevel};
+use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet};
use rustc_span::symbol::sym;
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
use smallvec::SmallVec;
-use crate::attributes;
+use crate::context::CodegenCx;
use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable};
use crate::llvm::AttributePlace::Function;
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
-use crate::llvm_util;
-pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
-
-use crate::context::CodegenCx;
use crate::value::Value;
+use crate::{attributes, llvm_util};
pub fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) {
if !attrs.is_empty() {
@@ -326,9 +324,10 @@ fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute {
llvm::CreateAttrStringValue(llcx, "alloc-family", "__rust_alloc")
}
+/// Helper for `FnAbi::apply_attrs_llfn`:
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
/// attributes.
-pub fn from_fn_attrs<'ll, 'tcx>(
+pub fn llfn_attrs_from_instance<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
llfn: &'ll Value,
instance: ty::Instance<'tcx>,
@@ -407,8 +406,33 @@ pub fn from_fn_attrs<'ll, 'tcx>(
// And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules.
// Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768
to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
- // Need this for AArch64.
- to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
+ if llvm_util::get_version() < (19, 0, 0) {
+ // Prior to LLVM 19, branch-target-enforcement was disabled by setting the attribute to
+ // the string "false". Now it is disabled by absence of the attribute.
+ to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false"));
+ }
+ } else if llvm_util::get_version() >= (19, 0, 0) {
+ // For non-naked functions, set branch protection attributes on aarch64.
+ if let Some(BranchProtection { bti, pac_ret }) =
+ cx.sess().opts.unstable_opts.branch_protection
+ {
+ assert!(cx.sess().target.arch == "aarch64");
+ if bti {
+ to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
+ }
+ if let Some(PacRet { leaf, key }) = pac_ret {
+ to_add.push(llvm::CreateAttrStringValue(
+ cx.llcx,
+ "sign-return-address",
+ if leaf { "all" } else { "non-leaf" },
+ ));
+ to_add.push(llvm::CreateAttrStringValue(
+ cx.llcx,
+ "sign-return-address-key",
+ if key == PAuthKey::A { "a_key" } else { "b_key" },
+ ));
+ }
+ }
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR)
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED)
@@ -473,7 +497,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
to_add.extend(tune_cpu_attr(cx));
let function_features =
- codegen_fn_attrs.target_features.iter().map(|f| f.as_str()).collect::<Vec<&str>>();
+ codegen_fn_attrs.target_features.iter().map(|f| f.name.as_str()).collect::<Vec<&str>>();
if let Some(f) = llvm_util::check_tied_features(
cx.tcx.sess,
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index f46c6b1..a2ab19a 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -1,27 +1,21 @@
//! A helper class for dealing with static archives
-use std::env;
-use std::ffi::{c_char, c_void, CStr, CString, OsString};
-use std::io;
-use std::mem;
+use std::ffi::{c_char, c_void, CStr, CString};
use std::path::{Path, PathBuf};
-use std::ptr;
-use std::str;
+use std::{io, mem, ptr, str};
-use crate::common;
-use crate::errors::{
- DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
-};
-use crate::llvm::archive_ro::{ArchiveRO, Child};
-use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::{
- try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
- ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
+ create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder,
+ ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind,
+ DEFAULT_OBJECT_READER,
};
+use rustc_codegen_ssa::common;
+use rustc_session::Session;
use tracing::trace;
-use rustc_session::cstore::DllImport;
-use rustc_session::Session;
+use crate::errors::ErrorCreatingImportLibrary;
+use crate::llvm::archive_ro::{ArchiveRO, Child};
+use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
/// Helper for adding many files to an archive.
#[must_use = "must call build() to finish building the archive"]
@@ -101,7 +95,9 @@ fn add_file(&mut self, file: &Path) {
fn build(mut self: Box<Self>, output: &Path) -> bool {
match self.build_with_llvm(output) {
Ok(any_members) => any_members,
- Err(e) => self.sess.dcx().emit_fatal(ArchiveBuildFailure { error: e }),
+ Err(error) => {
+ self.sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error })
+ }
}
}
}
@@ -123,116 +119,21 @@ fn create_dll_import_lib(
&self,
sess: &Session,
lib_name: &str,
- dll_imports: &[DllImport],
- tmpdir: &Path,
- is_direct_dependency: bool,
- ) -> PathBuf {
- let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
- let output_path = tmpdir.join(format!("{lib_name}{name_suffix}.lib"));
-
- let target = &sess.target;
- let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target);
-
- let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
- .iter()
- .map(|import: &DllImport| {
- if sess.target.arch == "x86" {
- (
- common::i686_decorated_name(import, mingw_gnu_toolchain, false),
- import.ordinal(),
- )
- } else {
- (import.name.to_string(), import.ordinal())
- }
- })
- .collect();
-
- if mingw_gnu_toolchain {
+ import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+ output_path: &Path,
+ ) {
+ if common::is_mingw_gnu_toolchain(&sess.target) {
// The binutils linker used on -windows-gnu targets cannot read the import
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
// that loaded but crashed with an AV upon calling one of the imported
// functions. Therefore, use binutils to create the import library instead,
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
- let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def"));
-
- let def_file_content = format!(
- "EXPORTS\n{}",
- import_name_and_ordinal_vector
- .into_iter()
- .map(|(name, ordinal)| {
- match ordinal {
- Some(n) => format!("{name} @{n} NONAME"),
- None => name,
- }
- })
- .collect::<Vec<String>>()
- .join("\n")
+ create_mingw_dll_import_lib(
+ sess,
+ lib_name,
+ import_name_and_ordinal_vector,
+ output_path,
);
-
- match std::fs::write(&def_file_path, def_file_content) {
- Ok(_) => {}
- Err(e) => {
- sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
- }
- };
-
- // --no-leading-underscore: For the `import_name_type` feature to work, we need to be
- // able to control the *exact* spelling of each of the symbols that are being imported:
- // hence we don't want `dlltool` adding leading underscores automatically.
- let dlltool = find_binutils_dlltool(sess);
- let temp_prefix = {
- let mut path = PathBuf::from(&output_path);
- path.pop();
- path.push(lib_name);
- path
- };
- // dlltool target architecture args from:
- // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
- let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
- "x86_64" => ("i386:x86-64", "--64"),
- "x86" => ("i386", "--32"),
- "aarch64" => ("arm64", "--64"),
- "arm" => ("arm", "--32"),
- _ => panic!("unsupported arch {}", sess.target.arch),
- };
- let mut dlltool_cmd = std::process::Command::new(&dlltool);
- dlltool_cmd
- .arg("-d")
- .arg(def_file_path)
- .arg("-D")
- .arg(lib_name)
- .arg("-l")
- .arg(&output_path)
- .arg("-m")
- .arg(dlltool_target_arch)
- .arg("-f")
- .arg(dlltool_target_bitness)
- .arg("--no-leading-underscore")
- .arg("--temp-prefix")
- .arg(temp_prefix);
-
- match dlltool_cmd.output() {
- Err(e) => {
- sess.dcx().emit_fatal(ErrorCallingDllTool {
- dlltool_path: dlltool.to_string_lossy(),
- error: e,
- });
- }
- // dlltool returns '0' on failure, so check for error output instead.
- Ok(output) if !output.stderr.is_empty() => {
- sess.dcx().emit_fatal(DlltoolFailImportLibrary {
- dlltool_path: dlltool.to_string_lossy(),
- dlltool_args: dlltool_cmd
- .get_args()
- .map(|arg| arg.to_string_lossy())
- .collect::<Vec<_>>()
- .join(" "),
- stdout: String::from_utf8_lossy(&output.stdout),
- stderr: String::from_utf8_lossy(&output.stderr),
- })
- }
- _ => {}
- }
} else {
// we've checked for \0 characters in the library name already
let dll_name_z = CString::new(lib_name).unwrap();
@@ -244,9 +145,9 @@ fn create_dll_import_lib(
trace!(" output_path {}", output_path.display());
trace!(
" import names: {}",
- dll_imports
+ import_name_and_ordinal_vector
.iter()
- .map(|import| import.name.to_string())
+ .map(|(name, _ordinal)| name.clone())
.collect::<Vec<_>>()
.join(", "),
);
@@ -283,9 +184,7 @@ fn create_dll_import_lib(
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
});
}
- };
-
- output_path
+ }
}
}
@@ -459,39 +358,3 @@ fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
fn string_to_io_error(s: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}"))
}
-
-fn find_binutils_dlltool(sess: &Session) -> OsString {
- assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
- if let Some(dlltool_path) = &sess.opts.cg.dlltool {
- return dlltool_path.clone().into_os_string();
- }
-
- let tool_name: OsString = if sess.host.options.is_like_windows {
- // If we're compiling on Windows, always use "dlltool.exe".
- "dlltool.exe"
- } else {
- // On other platforms, use the architecture-specific name.
- match sess.target.arch.as_ref() {
- "x86_64" => "x86_64-w64-mingw32-dlltool",
- "x86" => "i686-w64-mingw32-dlltool",
- "aarch64" => "aarch64-w64-mingw32-dlltool",
-
- // For non-standard architectures (e.g., aarch32) fallback to "dlltool".
- _ => "dlltool",
- }
- }
- .into();
-
- // NOTE: it's not clear how useful it is to explicitly search PATH.
- for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
- let full_path = dir.join(&tool_name);
- if full_path.is_file() {
- return full_path.into_os_string();
- }
- }
-
- // The user didn't specify the location of the dlltool binary, and we weren't able
- // to find the appropriate one on the PATH. Just return the name of the tool
- // and let the invocation fail with a hopefully useful error message.
- tool_name
-}
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index aef6726..f68155f 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -1,11 +1,11 @@
-use crate::back::write::{
- self, bitcode_section_name, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers,
-};
-use crate::errors::{
- DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro,
-};
-use crate::llvm::{self, build_string};
-use crate::{LlvmCodegenBackend, ModuleLlvm};
+use std::collections::BTreeMap;
+use std::ffi::{CStr, CString};
+use std::fs::File;
+use std::mem::ManuallyDrop;
+use std::path::Path;
+use std::sync::Arc;
+use std::{io, iter, slice};
+
use object::read::archive::ArchiveFile;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::symbol_export;
@@ -22,15 +22,14 @@
use rustc_session::config::{self, CrateType, Lto};
use tracing::{debug, info};
-use std::collections::BTreeMap;
-use std::ffi::{CStr, CString};
-use std::fs::File;
-use std::io;
-use std::iter;
-use std::mem::ManuallyDrop;
-use std::path::Path;
-use std::slice;
-use std::sync::Arc;
+use crate::back::write::{
+ self, bitcode_section_name, save_temp_bitcode, CodegenDiagnosticsStage, DiagnosticHandlers,
+};
+use crate::errors::{
+ DynamicLinkingWithLTO, LlvmError, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib, LtoProcMacro,
+};
+use crate::llvm::{self, build_string};
+use crate::{LlvmCodegenBackend, ModuleLlvm};
/// We keep track of the computed LTO cache keys from the previous
/// session to determine which CGUs we can reuse.
diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
index b72636a..681ac75 100644
--- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
+++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
@@ -1,13 +1,12 @@
-use std::{
- ffi::{c_char, CStr},
- marker::PhantomData,
- ops::Deref,
- ptr::NonNull,
-};
+use std::ffi::{c_char, CStr};
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::ptr::NonNull;
use rustc_data_structures::small_c_str::SmallCStr;
-use crate::{errors::LlvmError, llvm};
+use crate::errors::LlvmError;
+use crate::llvm;
/// Responsible for safely creating and disposing llvm::TargetMachine via ffi functions.
/// Not cloneable as there is no clone function for llvm::TargetMachine.
diff --git a/compiler/rustc_codegen_llvm/src/back/profiling.rs b/compiler/rustc_codegen_llvm/src/back/profiling.rs
index 2eee9f8..26fb4a9 100644
--- a/compiler/rustc_codegen_llvm/src/back/profiling.rs
+++ b/compiler/rustc_codegen_llvm/src/back/profiling.rs
@@ -1,9 +1,11 @@
-use measureme::{event_id::SEPARATOR_BYTE, EventId, StringComponent, StringId};
-use rustc_data_structures::profiling::{SelfProfiler, TimingGuard};
use std::ffi::{c_void, CStr};
use std::os::raw::c_char;
use std::sync::Arc;
+use measureme::event_id::SEPARATOR_BYTE;
+use measureme::{EventId, StringComponent, StringId};
+use rustc_data_structures::profiling::{SelfProfiler, TimingGuard};
+
fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &str) -> EventId {
let pass_name = profiler.get_or_alloc_cached_string(pass_name);
let mut components = vec![StringComponent::Ref(pass_name)];
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index ddd52e8..a1f2433 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -1,19 +1,10 @@
-use crate::back::lto::ThinBuffer;
-use crate::back::owned_target_machine::OwnedTargetMachine;
-use crate::back::profiling::{
- selfprofile_after_pass_callback, selfprofile_before_pass_callback, LlvmSelfProfiler,
-};
-use crate::base;
-use crate::common;
-use crate::errors::{
- CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, UnknownCompression,
- WithLlvmError, WriteBytecode,
-};
-use crate::llvm::{self, DiagnosticInfo, PassManager};
-use crate::llvm_util;
-use crate::type_::Type;
-use crate::LlvmCodegenBackend;
-use crate::ModuleLlvm;
+use std::ffi::CString;
+use std::io::{self, Write};
+use std::path::{Path, PathBuf};
+use std::sync::Arc;
+use std::{fs, slice, str};
+
+use libc::{c_char, c_int, c_void, size_t};
use llvm::{
LLVMRustLLVMHasZlibCompressionForDebugSymbols, LLVMRustLLVMHasZstdCompressionForDebugSymbols,
};
@@ -29,23 +20,28 @@
use rustc_errors::{DiagCtxtHandle, FatalError, Level};
use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{self, Lto, OutputType, Passes};
-use rustc_session::config::{RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath};
+use rustc_session::config::{
+ self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
+};
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::InnerSpan;
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel};
use tracing::debug;
+use crate::back::lto::ThinBuffer;
+use crate::back::owned_target_machine::OwnedTargetMachine;
+use crate::back::profiling::{
+ selfprofile_after_pass_callback, selfprofile_before_pass_callback, LlvmSelfProfiler,
+};
+use crate::errors::{
+ CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, UnknownCompression,
+ WithLlvmError, WriteBytecode,
+};
use crate::llvm::diagnostic::OptimizationDiagnosticKind;
-use libc::{c_char, c_int, c_void, size_t};
-use std::ffi::CString;
-use std::fs;
-use std::io::{self, Write};
-use std::path::{Path, PathBuf};
-use std::slice;
-use std::str;
-use std::sync::Arc;
+use crate::llvm::{self, DiagnosticInfo, PassManager};
+use crate::type_::Type;
+use crate::{base, common, llvm_util, LlvmCodegenBackend, ModuleLlvm};
pub fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError {
match llvm::last_error() {
@@ -99,11 +95,14 @@ pub fn write_output_file<'ll>(
}
}
-pub fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine {
+pub fn create_informational_target_machine(
+ sess: &Session,
+ only_base_features: bool,
+) -> OwnedTargetMachine {
let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None };
// Can't use query system here quite yet because this function is invoked before the query
// system/tcx is set up.
- let features = llvm_util::global_llvm_features(sess, false);
+ let features = llvm_util::global_llvm_features(sess, false, only_base_features);
target_machine_factory(sess, config::OptLevel::No, &features)(config)
.unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
}
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 5dc271c..e8236b4 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -11,13 +11,7 @@
//! [`Ty`]: rustc_middle::ty::Ty
//! [`val_ty`]: crate::common::val_ty
-use super::ModuleLlvm;
-
-use crate::attributes;
-use crate::builder::Builder;
-use crate::context::CodegenCx;
-use crate::llvm;
-use crate::value::Value;
+use std::time::Instant;
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
@@ -32,7 +26,11 @@
use rustc_span::symbol::Symbol;
use rustc_target::spec::SanitizerSet;
-use std::time::Instant;
+use super::ModuleLlvm;
+use crate::builder::Builder;
+use crate::context::CodegenCx;
+use crate::value::Value;
+use crate::{attributes, llvm};
pub struct ValueIter<'ll> {
cur: Option<&'ll Value>,
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 72ff9ea..cc081f2 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1,12 +1,7 @@
-use crate::abi::FnAbiLlvmExt;
-use crate::attributes;
-use crate::common::Funclet;
-use crate::context::CodegenCx;
-use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
-use crate::llvm_util;
-use crate::type_::Type;
-use crate::type_of::LayoutLlvmExt;
-use crate::value::Value;
+use std::borrow::Cow;
+use std::ops::Deref;
+use std::{iter, ptr};
+
use libc::{c_char, c_uint};
use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
@@ -17,21 +12,28 @@
use rustc_hir::def_id::DefId;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
- FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
+ TyAndLayout,
};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_sanitizers::{cfi, kcfi};
use rustc_session::config::OptLevel;
use rustc_span::Span;
-use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
+use rustc_target::abi::call::FnAbi;
+use rustc_target::abi::{self, Align, Size, WrappingRange};
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
use smallvec::SmallVec;
-use std::borrow::Cow;
-use std::iter;
-use std::ops::Deref;
-use std::ptr;
use tracing::{debug, instrument};
+use crate::abi::FnAbiLlvmExt;
+use crate::common::Funclet;
+use crate::context::CodegenCx;
+use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
+use crate::type_::Type;
+use crate::type_of::LayoutLlvmExt;
+use crate::value::Value;
+use crate::{attributes, llvm_util};
+
// All Builders must have an llfn associated with them
#[must_use]
pub struct Builder<'a, 'll, 'tcx> {
@@ -390,8 +392,9 @@ fn checked_binop(
lhs: Self::Value,
rhs: Self::Value,
) -> (Self::Value, Self::Value) {
+ use rustc_middle::ty::IntTy::*;
+ use rustc_middle::ty::UintTy::*;
use rustc_middle::ty::{Int, Uint};
- use rustc_middle::ty::{IntTy::*, UintTy::*};
let new_kind = match ty.kind() {
Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
@@ -529,7 +532,7 @@ fn atomic_load(
#[instrument(level = "trace", skip(self))]
fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx, &'ll Value> {
if place.layout.is_unsized() {
- let tail = self.tcx.struct_tail_with_normalize(place.layout.ty, |ty| ty, || {});
+ let tail = self.tcx.struct_tail_for_codegen(place.layout.ty, self.param_env());
if matches!(tail.kind(), ty::Foreign(..)) {
// Unsized locals and, at least conceptually, even unsized arguments must be copied
// around, which requires dynamically determining their size. Therefore, we cannot
@@ -725,13 +728,32 @@ fn store_with_flags(
llvm::LLVMSetVolatile(store, llvm::True);
}
if flags.contains(MemFlags::NONTEMPORAL) {
- // According to LLVM [1] building a nontemporal store must
- // *always* point to a metadata value of the integer 1.
- //
- // [1]: https://llvm.org/docs/LangRef.html#store-instruction
- let one = self.cx.const_i32(1);
- let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
- llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
+ // Make sure that the current target architectures supports "sane" non-temporal
+ // stores, i.e., non-temporal stores that are equivalent to regular stores except
+ // for performance. LLVM doesn't seem to care about this, and will happily treat
+ // `!nontemporal` stores as-if they were normal stores (for reordering optimizations
+ // etc) even on x86, despite later lowering them to MOVNT which do *not* behave like
+ // regular stores but require special fences.
+ // So we keep a list of architectures where `!nontemporal` is known to be truly just
+ // a hint, and use regular stores everywhere else.
+ // (In the future, we could alternatively ensure that an sfence gets emitted after a sequence of movnt
+ // before any kind of synchronizing operation. But it's not clear how to do that with LLVM.)
+ // For more context, see <https://github.com/rust-lang/rust/issues/114582> and
+ // <https://github.com/llvm/llvm-project/issues/64521>.
+ const WELL_BEHAVED_NONTEMPORAL_ARCHS: &[&str] =
+ &["aarch64", "arm", "riscv32", "riscv64"];
+
+ let use_nontemporal =
+ WELL_BEHAVED_NONTEMPORAL_ARCHS.contains(&&*self.cx.tcx.sess.target.arch);
+ if use_nontemporal {
+ // According to LLVM [1] building a nontemporal store must
+ // *always* point to a metadata value of the integer 1.
+ //
+ // [1]: https://llvm.org/docs/LangRef.html#store-instruction
+ let one = self.cx.const_i32(1);
+ let node = llvm::LLVMMDNodeInContext(self.cx.llcx, &one, 1);
+ llvm::LLVMSetMetadata(store, llvm::MD_nontemporal as c_uint, node);
+ }
}
store
}
@@ -1353,6 +1375,16 @@ fn noundef_metadata(&mut self, load: &'ll Value) {
}
}
+ pub fn set_unpredictable(&mut self, inst: &'ll Value) {
+ unsafe {
+ llvm::LLVMSetMetadata(
+ inst,
+ llvm::MD_unpredictable as c_uint,
+ llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
+ );
+ }
+ }
+
pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
}
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index 659c6ae..663c5be 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -4,16 +4,15 @@
//! and methods are represented as just a fn ptr and not a full
//! closure.
-use crate::attributes;
-use crate::common;
-use crate::context::CodegenCx;
-use crate::llvm;
-use crate::value::Value;
-
+use rustc_codegen_ssa::common;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use tracing::debug;
+use crate::context::CodegenCx;
+use crate::llvm;
+use crate::value::Value;
+
/// Codegens a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
///
@@ -48,7 +47,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
} else {
let instance_def_id = instance.def_id();
let llfn = if tcx.sess.target.arch == "x86"
- && let Some(dllimport) = common::get_dllimport(tcx, instance_def_id, sym)
+ && let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
{
// Fix for https://github.com/rust-lang/rust/issues/104453
// On x86 Windows, LLVM uses 'L' as the prefix for any private
@@ -79,8 +78,6 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
};
debug!("get_fn: not casting pointer!");
- attributes::from_fn_attrs(cx, llfn, instance);
-
// Apply an appropriate linkage/visibility value to our item that we
// just declared.
//
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index fe64649..a399790 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -1,11 +1,6 @@
//! Code that is useful in various codegen modules.
-use crate::consts::const_alloc_to_llvm;
-pub use crate::context::CodegenCx;
-use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True};
-use crate::type_::Type;
-use crate::value::Value;
-
+use libc::{c_char, c_uint};
use rustc_ast::Mutability;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
@@ -13,14 +8,16 @@
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
use rustc_middle::ty::TyCtxt;
-use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
+use rustc_session::cstore::DllImport;
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
-use rustc_target::spec::Target;
-
-use libc::{c_char, c_uint};
-use std::fmt::Write;
use tracing::debug;
+use crate::consts::const_alloc_to_llvm;
+pub use crate::context::CodegenCx;
+use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, OperandBundleDef, True};
+use crate::type_::Type;
+use crate::value::Value;
+
/*
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
*
@@ -100,11 +97,6 @@ pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) }
}
- pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
- let len = c_uint::try_from(elts.len()).expect("LLVMConstVector elements len overflow");
- unsafe { llvm::LLVMConstVector(elts.as_ptr(), len) }
- }
-
pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
bytes_in_context(self.llcx, bytes)
}
@@ -224,6 +216,11 @@ fn const_struct(&self, elts: &[&'ll Value], packed: bool) -> &'ll Value {
struct_in_context(self.llcx, elts, packed)
}
+ fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
+ let len = c_uint::try_from(elts.len()).expect("LLVMConstVector elements len overflow");
+ unsafe { llvm::LLVMConstVector(elts.as_ptr(), len) }
+ }
+
fn const_to_opt_uint(&self, v: &'ll Value) -> Option<u64> {
try_as_const_integral(v).and_then(|v| unsafe {
let mut i = 0u64;
@@ -379,64 +376,3 @@ pub(crate) fn get_dllimport<'tcx>(
tcx.native_library(id)
.and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
}
-
-pub(crate) fn is_mingw_gnu_toolchain(target: &Target) -> bool {
- target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
-}
-
-pub(crate) fn i686_decorated_name(
- dll_import: &DllImport,
- mingw: bool,
- disable_name_mangling: bool,
-) -> String {
- let name = dll_import.name.as_str();
-
- let (add_prefix, add_suffix) = match dll_import.import_name_type {
- Some(PeImportNameType::NoPrefix) => (false, true),
- Some(PeImportNameType::Undecorated) => (false, false),
- _ => (true, true),
- };
-
- // Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
- let mut decorated_name = String::with_capacity(name.len() + 6);
-
- if disable_name_mangling {
- // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
- decorated_name.push('\x01');
- }
-
- let prefix = if add_prefix && dll_import.is_fn {
- match dll_import.calling_convention {
- DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
- DllCallingConvention::Stdcall(_) => (!mingw
- || dll_import.import_name_type == Some(PeImportNameType::Decorated))
- .then_some('_'),
- DllCallingConvention::Fastcall(_) => Some('@'),
- }
- } else if !dll_import.is_fn && !mingw {
- // For static variables, prefix with '_' on MSVC.
- Some('_')
- } else {
- None
- };
- if let Some(prefix) = prefix {
- decorated_name.push(prefix);
- }
-
- decorated_name.push_str(name);
-
- if add_suffix && dll_import.is_fn {
- match dll_import.calling_convention {
- DllCallingConvention::C => {}
- DllCallingConvention::Stdcall(arg_list_size)
- | DllCallingConvention::Fastcall(arg_list_size) => {
- write!(&mut decorated_name, "@{arg_list_size}").unwrap();
- }
- DllCallingConvention::Vectorcall(arg_list_size) => {
- write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
- }
- }
- }
-
- decorated_name
-}
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 80aa201..75b298f 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -1,13 +1,6 @@
-use crate::base;
-use crate::common::{self, CodegenCx};
-use crate::debuginfo;
-use crate::errors::{
- InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
-};
-use crate::llvm::{self, True};
-use crate::type_::Type;
-use crate::type_of::LayoutLlvmExt;
-use crate::value::Value;
+use std::ops::Range;
+
+use rustc_codegen_ssa::common;
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@@ -24,9 +17,18 @@
use rustc_target::abi::{
Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
};
-use std::ops::Range;
use tracing::{debug, instrument, trace};
+use crate::common::CodegenCx;
+use crate::errors::{
+ InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
+};
+use crate::llvm::{self, True};
+use crate::type_::Type;
+use crate::type_of::LayoutLlvmExt;
+use crate::value::Value;
+use crate::{base, debuginfo};
+
pub fn const_alloc_to_llvm<'ll>(
cx: &CodegenCx<'ll, '_>,
alloc: ConstAllocation<'_>,
@@ -194,7 +196,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
g2
}
} else if cx.tcx.sess.target.arch == "x86"
- && let Some(dllimport) = common::get_dllimport(cx.tcx, def_id, sym)
+ && let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
{
cx.declare_global(
&common::i686_decorated_name(
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 49677dc..dd3f39e 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -1,19 +1,13 @@
-use crate::attributes;
-use crate::back::write::to_llvm_code_model;
-use crate::callee::get_fn;
-use crate::coverageinfo;
-use crate::debuginfo;
-use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
-use crate::llvm;
-use crate::llvm_util;
-use crate::type_::Type;
-use crate::value::Value;
+use std::borrow::Borrow;
+use std::cell::{Cell, RefCell};
+use std::ffi::CStr;
+use std::str;
+use libc::c_uint;
use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::base_n::ToBaseN;
-use rustc_data_structures::base_n::ALPHANUMERIC_ONLY;
+use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::def_id::DefId;
@@ -24,20 +18,23 @@
};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
-use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
-use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
+use rustc_session::config::{
+ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, PAuthKey, PacRet,
+};
use rustc_session::Session;
use rustc_span::source_map::Spanned;
use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::{call::FnAbi, HasDataLayout, TargetDataLayout, VariantIdx};
+use rustc_target::abi::call::FnAbi;
+use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx};
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
use smallvec::SmallVec;
-use libc::c_uint;
-use std::borrow::Borrow;
-use std::cell::{Cell, RefCell};
-use std::ffi::CStr;
-use std::str;
+use crate::back::write::to_llvm_code_model;
+use crate::callee::get_fn;
+use crate::debuginfo::metadata::apply_vcall_visibility_metadata;
+use crate::type_::Type;
+use crate::value::Value;
+use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util};
/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
/// `llvm::Context` so that several compilation units may be optimized in parallel.
@@ -152,7 +149,7 @@ pub unsafe fn create_module<'ll>(
// Ensure the data-layout values hardcoded remain the defaults.
{
- let tm = crate::back::write::create_informational_target_machine(tcx.sess);
+ let tm = crate::back::write::create_informational_target_machine(tcx.sess, false);
unsafe {
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
}
@@ -778,10 +775,10 @@ macro_rules! mk_struct {
ifn!("llvm.debugtrap", fn() -> void);
ifn!("llvm.frameaddress", fn(t_i32) -> ptr);
- ifn!("llvm.powi.f16", fn(t_f16, t_i32) -> t_f16);
- ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
- ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
- ifn!("llvm.powi.f128", fn(t_f128, t_i32) -> t_f128);
+ ifn!("llvm.powi.f16.i32", fn(t_f16, t_i32) -> t_f16);
+ ifn!("llvm.powi.f32.i32", fn(t_f32, t_i32) -> t_f32);
+ ifn!("llvm.powi.f64.i32", fn(t_f64, t_i32) -> t_f64);
+ ifn!("llvm.powi.f128.i32", fn(t_f128, t_i32) -> t_f128);
ifn!("llvm.pow.f16", fn(t_f16, t_f16) -> t_f16);
ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32);
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
index 14a9446..9433385 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs
@@ -1,5 +1,3 @@
-use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind};
-
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_index::bit_set::BitSet;
@@ -11,6 +9,8 @@
use rustc_span::Symbol;
use tracing::{debug, instrument};
+use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind};
+
/// Holds all of the coverage mapping data associated with a function instance,
/// collected during traversal of `Coverage` statements in the function's MIR.
#[derive(Debug)]
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index d2c0f20..f8929a2 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,21 +1,19 @@
-use crate::common::CodegenCx;
-use crate::coverageinfo;
-use crate::coverageinfo::ffi::CounterMappingRegion;
-use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
-use crate::llvm;
-
use itertools::Itertools as _;
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::IndexVec;
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::{bug, mir};
use rustc_span::def_id::DefIdSet;
use rustc_span::Symbol;
use tracing::debug;
+use crate::common::CodegenCx;
+use crate::coverageinfo::ffi::CounterMappingRegion;
+use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
+use crate::{coverageinfo, llvm};
+
/// Generates and exports the Coverage Map.
///
/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 7b7f8c8..20a713b 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -1,9 +1,4 @@
-use crate::llvm;
-
-use crate::builder::Builder;
-use crate::common::CodegenCx;
-use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
-use crate::coverageinfo::map_data::FunctionCoverageCollector;
+use std::cell::RefCell;
use libc::c_uint;
use rustc_codegen_ssa::traits::{
@@ -19,7 +14,11 @@
use rustc_target::abi::{Align, Size};
use tracing::{debug, instrument};
-use std::cell::RefCell;
+use crate::builder::Builder;
+use crate::common::CodegenCx;
+use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
+use crate::coverageinfo::map_data::FunctionCoverageCollector;
+use crate::llvm;
pub(crate) mod ffi;
pub(crate) mod map_data;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index 6a63eda..efe6168 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -1,18 +1,17 @@
-use super::metadata::file_metadata;
-use super::utils::DIB;
use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
use rustc_codegen_ssa::traits::*;
-
-use crate::common::CodegenCx;
-use crate::llvm;
-use crate::llvm::debuginfo::{DILocation, DIScope};
+use rustc_index::bit_set::BitSet;
+use rustc_index::Idx;
use rustc_middle::mir::{Body, SourceScope};
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::{self, Instance};
use rustc_session::config::DebugInfo;
-use rustc_index::bit_set::BitSet;
-use rustc_index::Idx;
+use super::metadata::file_metadata;
+use super::utils::DIB;
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::llvm::debuginfo::{DILocation, DIScope};
/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index d82b1e1..5a08f2f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -1,18 +1,19 @@
// .debug_gdb_scripts binary section.
-use crate::llvm;
-
-use crate::builder::Builder;
-use crate::common::CodegenCx;
-use crate::value::Value;
use rustc_ast::attr;
use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
use rustc_codegen_ssa::traits::*;
use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::{bug, middle::debugger_visualizer::DebuggerVisualizerType};
+use rustc_middle::bug;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerType;
use rustc_session::config::{CrateType, DebugInfo};
use rustc_span::symbol::sym;
+use crate::builder::Builder;
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::value::Value;
+
/// Inserts a side-effect free instruction sequence that makes sure that the
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 364c35f..ad63858 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1,32 +1,14 @@
-use self::type_map::DINodeCreationResult;
-use self::type_map::Stub;
-use self::type_map::UniqueTypeId;
+use std::borrow::Cow;
+use std::fmt::{self, Write};
+use std::hash::{Hash, Hasher};
+use std::path::{Path, PathBuf};
+use std::{iter, ptr};
-use super::namespace::mangled_name_of_instance;
-use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
-use super::utils::{
- create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
-};
-use super::CodegenUnitDebugContext;
-
-use crate::abi;
-use crate::common::CodegenCx;
-use crate::debuginfo::metadata::type_map::build_type_with_children;
-use crate::debuginfo::utils::fat_pointer_kind;
-use crate::debuginfo::utils::FatPtrKind;
-use crate::llvm;
-use crate::llvm::debuginfo::{
- DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
- DebugNameTableKind,
-};
-use crate::value::Value;
-
-use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
-use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
+use libc::{c_char, c_longlong, c_uint};
+use rustc_codegen_ssa::debuginfo::type_names::{cpp_like_debuginfo, VTableNameKind};
use rustc_codegen_ssa::traits::*;
use rustc_fs_util::path_to_c_string;
-use rustc_hir::def::CtorKind;
-use rustc_hir::def::DefKind;
+use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
@@ -36,21 +18,29 @@
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::symbol::Symbol;
-use rustc_span::{hygiene, FileName, DUMMY_SP};
-use rustc_span::{FileNameDisplayPreference, SourceFile};
+use rustc_span::{hygiene, FileName, FileNameDisplayPreference, SourceFile, DUMMY_SP};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::abi::{Align, Size};
use rustc_target::spec::DebuginfoKind;
use smallvec::smallvec;
use tracing::{debug, instrument};
-use libc::{c_char, c_longlong, c_uint};
-use std::borrow::Cow;
-use std::fmt::{self, Write};
-use std::hash::{Hash, Hasher};
-use std::iter;
-use std::path::{Path, PathBuf};
-use std::ptr;
+use self::type_map::{DINodeCreationResult, Stub, UniqueTypeId};
+use super::namespace::mangled_name_of_instance;
+use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
+use super::utils::{
+ create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
+};
+use super::CodegenUnitDebugContext;
+use crate::common::CodegenCx;
+use crate::debuginfo::metadata::type_map::build_type_with_children;
+use crate::debuginfo::utils::{fat_pointer_kind, FatPtrKind};
+use crate::llvm::debuginfo::{
+ DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
+ DebugNameTableKind,
+};
+use crate::value::Value;
+use crate::{abi, llvm};
impl PartialEq for llvm::Metadata {
fn eq(&self, other: &Self) -> bool {
@@ -874,7 +864,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
codegen_unit_name: &str,
debug_context: &CodegenUnitDebugContext<'ll, 'tcx>,
) -> &'ll DIDescriptor {
- use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+ use rustc_session::config::RemapPathScopeComponents;
+ use rustc_session::RemapFileNameExt;
let mut name_in_debuginfo = tcx
.sess
.local_crate_source_file()
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index cf7dddc..1300663 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -1,41 +1,27 @@
use std::borrow::Cow;
use libc::c_uint;
-use rustc_codegen_ssa::{
- debuginfo::{type_names::compute_debuginfo_type_name, wants_c_like_enum_debuginfo},
- traits::ConstMethods,
-};
-
+use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
+use rustc_codegen_ssa::debuginfo::wants_c_like_enum_debuginfo;
+use rustc_codegen_ssa::traits::ConstMethods;
use rustc_index::IndexVec;
-use rustc_middle::{
- bug,
- ty::{
- self,
- layout::{LayoutOf, TyAndLayout},
- AdtDef, CoroutineArgs, CoroutineArgsExt, Ty,
- },
-};
+use rustc_middle::bug;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
use rustc_target::abi::{Align, Endian, Size, TagEncoding, VariantIdx, Variants};
use smallvec::smallvec;
-use crate::{
- common::CodegenCx,
- debuginfo::{
- metadata::{
- build_field_di_node,
- enums::{tag_base_type, DiscrResult},
- file_metadata, size_and_align_of, type_di_node,
- type_map::{self, Stub, UniqueTypeId},
- unknown_file_metadata, visibility_di_flags, DINodeCreationResult, SmallVec,
- NO_GENERICS, NO_SCOPE_METADATA, UNKNOWN_LINE_NUMBER,
- },
- utils::DIB,
- },
- llvm::{
- self,
- debuginfo::{DIFile, DIFlags, DIType},
- },
+use crate::common::CodegenCx;
+use crate::debuginfo::metadata::enums::{tag_base_type, DiscrResult};
+use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
+use crate::debuginfo::metadata::{
+ build_field_di_node, file_metadata, size_and_align_of, type_di_node, unknown_file_metadata,
+ visibility_di_flags, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
+ UNKNOWN_LINE_NUMBER,
};
+use crate::debuginfo::utils::DIB;
+use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
+use crate::llvm::{self};
// The names of the associated constants in each variant wrapper struct.
// These have to match up with the names being used in `intrinsic.natvis`.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 96be190..fc3adaf 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -1,45 +1,29 @@
-use rustc_codegen_ssa::debuginfo::{
- type_names::{compute_debuginfo_type_name, cpp_like_debuginfo},
- wants_c_like_enum_debuginfo,
-};
+use std::borrow::Cow;
+
+use rustc_codegen_ssa::debuginfo::type_names::{compute_debuginfo_type_name, cpp_like_debuginfo};
+use rustc_codegen_ssa::debuginfo::wants_c_like_enum_debuginfo;
use rustc_hir::def::CtorKind;
use rustc_index::IndexSlice;
-use rustc_middle::{
- bug,
- mir::CoroutineLayout,
- ty::{
- self,
- layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
- AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef,
- },
-};
+use rustc_middle::bug;
+use rustc_middle::mir::CoroutineLayout;
+use rustc_middle::ty::layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty, VariantDef};
use rustc_span::Symbol;
use rustc_target::abi::{
FieldIdx, HasDataLayout, Integer, Primitive, TagEncoding, VariantIdx, Variants,
};
-use std::borrow::Cow;
-use crate::{
- common::CodegenCx,
- debuginfo::{
- metadata::{
- build_field_di_node, build_generic_type_param_di_nodes, type_di_node,
- type_map::{self, Stub},
- unknown_file_metadata, UNKNOWN_LINE_NUMBER,
- },
- utils::{create_DIArray, get_namespace_for_item, DIB},
- },
- llvm::{
- self,
- debuginfo::{DIFlags, DIType},
- },
+use super::type_map::{DINodeCreationResult, UniqueTypeId};
+use super::{size_and_align_of, SmallVec};
+use crate::common::CodegenCx;
+use crate::debuginfo::metadata::type_map::{self, Stub};
+use crate::debuginfo::metadata::{
+ build_field_di_node, build_generic_type_param_di_nodes, type_di_node, unknown_file_metadata,
+ UNKNOWN_LINE_NUMBER,
};
-
-use super::{
- size_and_align_of,
- type_map::{DINodeCreationResult, UniqueTypeId},
- SmallVec,
-};
+use crate::debuginfo::utils::{create_DIArray, get_namespace_for_item, DIB};
+use crate::llvm::debuginfo::{DIFlags, DIType};
+use crate::llvm::{self};
mod cpp_like;
mod native;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 63a9ce2..d7e3b47 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -1,37 +1,26 @@
use std::borrow::Cow;
-use crate::{
- common::CodegenCx,
- debuginfo::{
- metadata::{
- enums::tag_base_type,
- file_metadata, size_and_align_of, type_di_node,
- type_map::{self, Stub, StubInfo, UniqueTypeId},
- unknown_file_metadata, visibility_di_flags, DINodeCreationResult, SmallVec,
- NO_GENERICS, UNKNOWN_LINE_NUMBER,
- },
- utils::{create_DIArray, get_namespace_for_item, DIB},
- },
- llvm::{
- self,
- debuginfo::{DIFile, DIFlags, DIType},
- },
-};
use libc::c_uint;
-use rustc_codegen_ssa::{
- debuginfo::{type_names::compute_debuginfo_type_name, wants_c_like_enum_debuginfo},
- traits::ConstMethods,
-};
-use rustc_middle::{
- bug,
- ty::{
- self,
- layout::{LayoutOf, TyAndLayout},
- },
-};
+use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
+use rustc_codegen_ssa::debuginfo::wants_c_like_enum_debuginfo;
+use rustc_codegen_ssa::traits::ConstMethods;
+use rustc_middle::bug;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self};
use rustc_target::abi::{Size, TagEncoding, VariantIdx, Variants};
use smallvec::smallvec;
+use crate::common::CodegenCx;
+use crate::debuginfo::metadata::enums::tag_base_type;
+use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId};
+use crate::debuginfo::metadata::{
+ file_metadata, size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags,
+ DINodeCreationResult, SmallVec, NO_GENERICS, UNKNOWN_LINE_NUMBER,
+};
+use crate::debuginfo::utils::{create_DIArray, get_namespace_for_item, DIB};
+use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
+use crate::llvm::{self};
+
/// Build the debuginfo node for an enum type. The listing below shows how such a
/// type looks like at the LLVM IR/DWARF level. It is a `DW_TAG_structure_type`
/// with a single `DW_TAG_variant_part` that in turn contains a `DW_TAG_variant`
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
index 1793191..25b2df9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs
@@ -1,27 +1,18 @@
use std::cell::RefCell;
-use rustc_data_structures::{
- fingerprint::Fingerprint,
- fx::FxHashMap,
- stable_hasher::{HashStable, StableHasher},
-};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable;
-use rustc_middle::{
- bug,
- ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt},
-};
+use rustc_middle::bug;
+use rustc_middle::ty::{ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_target::abi::{Align, Size, VariantIdx};
-use crate::{
- common::CodegenCx,
- debuginfo::utils::{create_DIArray, debug_context, DIB},
- llvm::{
- self,
- debuginfo::{DIFlags, DIScope, DIType},
- },
-};
-
use super::{unknown_file_metadata, SmallVec, UNKNOWN_LINE_NUMBER};
+use crate::common::CodegenCx;
+use crate::debuginfo::utils::{create_DIArray, debug_context, DIB};
+use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
+use crate::llvm::{self};
mod private {
use rustc_macros::HashStable;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 3486ce4..b23e051 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -1,13 +1,34 @@
#![doc = include_str!("doc.md")]
-use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
-use rustc_data_structures::unord::UnordMap;
+use std::cell::{OnceCell, RefCell};
+use std::iter;
+use std::ops::Range;
-use self::metadata::{file_metadata, type_di_node};
-use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use libc::c_uint;
+use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
+use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
+use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::unord::UnordMap;
+use rustc_hir::def_id::{DefId, DefIdMap};
+use rustc_index::IndexVec;
+use rustc_middle::mir;
+use rustc_middle::ty::layout::LayoutOf;
+use rustc_middle::ty::{self, GenericArgsRef, Instance, ParamEnv, Ty, TypeVisitableExt};
+use rustc_session::config::{self, DebugInfo};
+use rustc_session::Session;
+use rustc_span::symbol::Symbol;
+use rustc_span::{
+ BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId,
+};
+use rustc_target::abi::Size;
+use smallvec::SmallVec;
+use tracing::debug;
+
+use self::metadata::{file_metadata, type_di_node, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
use self::namespace::mangled_name_of_instance;
use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
-
use crate::abi::FnAbi;
use crate::builder::Builder;
use crate::common::CodegenCx;
@@ -18,32 +39,6 @@
};
use crate::value::Value;
-use rustc_codegen_ssa::debuginfo::type_names;
-use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
-use rustc_codegen_ssa::traits::*;
-use rustc_data_structures::sync::Lrc;
-use rustc_hir::def_id::{DefId, DefIdMap};
-use rustc_index::IndexVec;
-use rustc_middle::mir;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt};
-use rustc_session::config::{self, DebugInfo};
-use rustc_session::Session;
-use rustc_span::symbol::Symbol;
-use rustc_span::{
- BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span, StableSourceFileId,
-};
-use rustc_target::abi::Size;
-
-use libc::c_uint;
-use smallvec::SmallVec;
-use std::cell::OnceCell;
-use std::cell::RefCell;
-use std::iter;
-use std::ops::Range;
-use tracing::debug;
-
mod create_scope_map;
pub mod gdb;
pub mod metadata;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index fa61c7d..5c4f8fe 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -1,13 +1,13 @@
// Namespace Handling.
-use super::utils::{debug_context, DIB};
use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, Instance};
+use super::utils::{debug_context, DIB};
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::DIScope;
-use rustc_hir::def_id::DefId;
pub fn mangled_name_of_instance<'a, 'tcx>(
cx: &CodegenCx<'a, 'tcx>,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 9bd2ccc..e542aa9 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -1,13 +1,12 @@
// Utility Functions.
-use super::namespace::item_namespace;
-use super::CodegenUnitDebugContext;
-
use rustc_hir::def_id::DefId;
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::ty::{self, Ty};
use tracing::trace;
+use super::namespace::item_namespace;
+use super::CodegenUnitDebugContext;
use crate::common::CodegenCx;
use crate::llvm;
use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope};
@@ -63,7 +62,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
pointee_ty: Ty<'tcx>,
) -> Option<FatPtrKind> {
- let pointee_tail_ty = cx.tcx.struct_tail_erasing_lifetimes(pointee_ty, cx.param_env());
+ let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
let layout = cx.layout_of(pointee_tail_ty);
trace!(
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index bf86d0e..2aa349b 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -11,13 +11,6 @@
//! * Use define_* family of methods when you might be defining the Value.
//! * When in doubt, define.
-use crate::abi::{FnAbi, FnAbiLlvmExt};
-use crate::attributes;
-use crate::context::CodegenCx;
-use crate::llvm;
-use crate::llvm::AttributePlace::Function;
-use crate::type_::Type;
-use crate::value::Value;
use itertools::Itertools;
use rustc_codegen_ssa::traits::TypeMembershipMethods;
use rustc_data_structures::fx::FxIndexSet;
@@ -26,6 +19,13 @@
use smallvec::SmallVec;
use tracing::debug;
+use crate::abi::{FnAbi, FnAbiLlvmExt};
+use crate::context::CodegenCx;
+use crate::llvm::AttributePlace::Function;
+use crate::type_::Type;
+use crate::value::Value;
+use crate::{attributes, llvm};
+
/// Declare a function.
///
/// If there’s a value with the same name already declared, the function will
@@ -137,7 +137,7 @@ pub fn declare_fn(
llvm::Visibility::Default,
fn_abi.llvm_type(self),
);
- fn_abi.apply_attrs_llfn(self, llfn);
+ fn_abi.apply_attrs_llfn(self, llfn, instance);
if self.tcx.sess.is_sanitizer_cfi_enabled() {
if let Some(instance) = instance {
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 40ac2f9..7e53d32 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -1,13 +1,13 @@
-use std::borrow::Cow;
use std::ffi::CString;
use std::path::Path;
-use crate::fluent_generated as fluent;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
+use crate::fluent_generated as fluent;
+
#[derive(Diagnostic)]
#[diag(codegen_llvm_unknown_ctarget_feature_prefix)]
#[note]
@@ -71,28 +71,6 @@ pub(crate) struct InvalidMinimumAlignmentTooLarge {
pub(crate) struct SanitizerMemtagRequiresMte;
#[derive(Diagnostic)]
-#[diag(codegen_llvm_error_writing_def_file)]
-pub(crate) struct ErrorWritingDEFFile {
- pub error: std::io::Error,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_error_calling_dlltool)]
-pub(crate) struct ErrorCallingDllTool<'a> {
- pub dlltool_path: Cow<'a, str>,
- pub error: std::io::Error,
-}
-
-#[derive(Diagnostic)]
-#[diag(codegen_llvm_dlltool_fail_import_library)]
-pub(crate) struct DlltoolFailImportLibrary<'a> {
- pub dlltool_path: Cow<'a, str>,
- pub dlltool_args: String,
- pub stdout: Cow<'a, str>,
- pub stderr: Cow<'a, str>,
-}
-
-#[derive(Diagnostic)]
#[diag(codegen_llvm_dynamic_linking_with_lto)]
#[note]
pub(crate) struct DynamicLinkingWithLTO;
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 68c3d47..f555872 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1,17 +1,11 @@
-use crate::abi::{Abi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode};
-use crate::builder::Builder;
-use crate::context::CodegenCx;
-use crate::llvm;
-use crate::type_::Type;
-use crate::type_of::LayoutLlvmExt;
-use crate::va_arg::emit_va_arg;
-use crate::value::Value;
+use std::assert_matches::assert_matches;
+use std::cmp::Ordering;
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
-use rustc_codegen_ssa::mir::place::PlaceRef;
+use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
use rustc_codegen_ssa::traits::*;
use rustc_hir as hir;
use rustc_middle::mir::BinOp;
@@ -23,7 +17,14 @@
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
use tracing::debug;
-use std::cmp::Ordering;
+use crate::abi::{Abi, FnAbi, FnAbiLlvmExt, LlvmType, PassMode};
+use crate::builder::Builder;
+use crate::context::CodegenCx;
+use crate::llvm;
+use crate::type_::Type;
+use crate::type_of::LayoutLlvmExt;
+use crate::va_arg::emit_va_arg;
+use crate::value::Value;
fn get_simple_intrinsic<'ll>(
cx: &CodegenCx<'ll, '_>,
@@ -35,10 +36,10 @@ fn get_simple_intrinsic<'ll>(
sym::sqrtf64 => "llvm.sqrt.f64",
sym::sqrtf128 => "llvm.sqrt.f128",
- sym::powif16 => "llvm.powi.f16",
- sym::powif32 => "llvm.powi.f32",
- sym::powif64 => "llvm.powi.f64",
- sym::powif128 => "llvm.powi.f128",
+ sym::powif16 => "llvm.powi.f16.i32",
+ sym::powif32 => "llvm.powi.f32.i32",
+ sym::powif64 => "llvm.powi.f64.i32",
+ sym::powif128 => "llvm.powi.f128.i32",
sym::sinf16 => "llvm.sin.f16",
sym::sinf32 => "llvm.sin.f32",
@@ -203,6 +204,35 @@ fn codegen_intrinsic_call(
}
sym::unlikely => self
.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
+ sym::select_unpredictable => {
+ let cond = args[0].immediate();
+ assert_eq!(args[1].layout, args[2].layout);
+ let select = |bx: &mut Self, true_val, false_val| {
+ let result = bx.select(cond, true_val, false_val);
+ bx.set_unpredictable(&result);
+ result
+ };
+ match (args[1].val, args[2].val) {
+ (OperandValue::Ref(true_val), OperandValue::Ref(false_val)) => {
+ assert!(true_val.llextra.is_none());
+ assert!(false_val.llextra.is_none());
+ assert_eq!(true_val.align, false_val.align);
+ let ptr = select(self, true_val.llval, false_val.llval);
+ let selected =
+ OperandValue::Ref(PlaceValue::new_sized(ptr, true_val.align));
+ selected.store(self, result);
+ return Ok(());
+ }
+ (OperandValue::Immediate(_), OperandValue::Immediate(_))
+ | (OperandValue::Pair(_, _), OperandValue::Pair(_, _)) => {
+ let true_val = args[1].immediate_or_packed_pair(self);
+ let false_val = args[2].immediate_or_packed_pair(self);
+ select(self, true_val, false_val)
+ }
+ (OperandValue::ZeroSized, OperandValue::ZeroSized) => return Ok(()),
+ _ => span_bug!(span, "Incompatible OperandValue for select_unpredictable"),
+ }
+ }
sym::catch_unwind => {
catch_unwind_intrinsic(
self,
@@ -1113,7 +1143,7 @@ macro_rules! require_simd {
if cfg!(debug_assertions) {
for (ty, arg) in arg_tys.iter().zip(args) {
if ty.is_simd() {
- assert!(matches!(arg.val, OperandValue::Immediate(_)));
+ assert_matches!(arg.val, OperandValue::Immediate(_));
}
}
}
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index a96993b..4316439 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -8,6 +8,7 @@
#![allow(internal_features)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
+#![feature(assert_matches)]
#![feature(exact_size_is_empty)]
#![feature(extern_types)]
#![feature(hash_raw_entry)]
@@ -17,9 +18,13 @@
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
+use std::any::Any;
+use std::ffi::CStr;
+use std::io::Write;
+use std::mem::ManuallyDrop;
+
use back::owned_target_machine::OwnedTargetMachine;
use back::write::{create_informational_target_machine, create_target_machine};
-
use errors::ParseTargetMachineConfig;
pub use llvm_util::target_features;
use rustc_ast::expand::allocator::AllocatorKind;
@@ -28,8 +33,7 @@
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::traits::*;
-use rustc_codegen_ssa::ModuleCodegen;
-use rustc_codegen_ssa::{CodegenResults, CompiledModule};
+use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
use rustc_metadata::EncodedMetadata;
@@ -40,11 +44,6 @@
use rustc_session::Session;
use rustc_span::symbol::Symbol;
-use std::any::Any;
-use std::ffi::CStr;
-use std::io::Write;
-use std::mem::ManuallyDrop;
-
mod back {
pub mod archive;
pub mod lto;
@@ -271,7 +270,7 @@ fn init(&self, sess: &Session) {
fn provide(&self, providers: &mut Providers) {
providers.global_backend_features =
- |tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
+ |tcx, ()| llvm_util::global_llvm_features(tcx.sess, true, false)
}
fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) {
@@ -394,9 +393,10 @@ fn link(
codegen_results: CodegenResults,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
- use crate::back::archive::LlvmArchiveBuilderBuilder;
use rustc_codegen_ssa::back::link::link_binary;
+ use crate::back::archive::LlvmArchiveBuilderBuilder;
+
// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs)
@@ -435,7 +435,7 @@ fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
ModuleLlvm {
llmod_raw,
llcx,
- tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)),
+ tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, false)),
}
}
}
diff --git a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
index 7d94897..4dabde5 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs
@@ -1,9 +1,9 @@
//! A wrapper around LLVM's archive (.a) code
-use rustc_fs_util::path_to_c_string;
use std::path::Path;
-use std::slice;
-use std::str;
+use std::{slice, str};
+
+use rustc_fs_util::path_to_c_string;
pub struct ArchiveRO {
pub raw: &'static mut super::Archive,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
index 73e1b08..a4cb5a2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
@@ -1,13 +1,12 @@
//! LLVM diagnostic reports.
+use libc::c_uint;
+use rustc_span::InnerSpan;
+
pub use self::Diagnostic::*;
pub use self::OptimizationDiagnosticKind::*;
-
-use crate::value::Value;
-use libc::c_uint;
-
use super::{DiagnosticInfo, SMDiagnostic};
-use rustc_span::InnerSpan;
+use crate::value::Value;
#[derive(Copy, Clone, Debug)]
pub enum OptimizationDiagnosticKind {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 3beda28..faabbcb 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1,18 +1,16 @@
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
+use std::marker::PhantomData;
+
+use libc::{c_char, c_int, c_uint, c_ulonglong, c_void, size_t};
+
use super::debuginfo::{
DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator,
DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace,
DISPFlags, DIScope, DISubprogram, DISubrange, DITemplateTypeParameter, DIType, DIVariable,
DebugEmissionKind, DebugNameTableKind,
};
-
-use libc::{c_char, c_int, c_uint, size_t};
-use libc::{c_ulonglong, c_void};
-
-use std::marker::PhantomData;
-
use super::RustString;
pub type Bool = c_uint;
@@ -428,6 +426,7 @@ pub enum MetadataType {
MD_nontemporal = 9,
MD_mem_parallel_loop_access = 10,
MD_nonnull = 11,
+ MD_unpredictable = 15,
MD_align = 17,
MD_type = 19,
MD_vcall_visibility = 28,
@@ -697,9 +696,10 @@ struct InvariantOpaque<'a> {
pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
pub mod debuginfo {
- use super::{InvariantOpaque, Metadata};
use bitflags::bitflags;
+ use super::{InvariantOpaque, Metadata};
+
#[repr(C)]
pub struct DIBuilder<'a>(InvariantOpaque<'a>);
@@ -1575,6 +1575,12 @@ pub fn LLVMRustGetNamedValue(
pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute;
pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute;
pub fn LLVMRustCreateMemoryEffectsAttr(C: &Context, effects: MemoryEffects) -> &Attribute;
+ pub fn LLVMRustCreateRangeAttribute(
+ C: &Context,
+ num_bits: c_uint,
+ lower_words: *const u64,
+ upper_words: *const u64,
+ ) -> &Attribute;
// Operations on functions
pub fn LLVMRustGetOrInsertFunction<'a>(
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index 6ab1eea..d0db350 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -1,5 +1,15 @@
#![allow(non_snake_case)]
+use std::cell::RefCell;
+use std::ffi::{CStr, CString};
+use std::str::FromStr;
+use std::string::FromUtf8Error;
+
+use libc::c_uint;
+use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_llvm::RustString;
+use rustc_target::abi::{Align, Size, WrappingRange};
+
pub use self::AtomicRmwBinOp::*;
pub use self::CallConv::*;
pub use self::CodeGenOptSize::*;
@@ -8,15 +18,6 @@
pub use self::MetadataType::*;
pub use self::RealPredicate::*;
-use libc::c_uint;
-use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_llvm::RustString;
-use rustc_target::abi::Align;
-use std::cell::RefCell;
-use std::ffi::{CStr, CString};
-use std::str::FromStr;
-use std::string::FromUtf8Error;
-
pub mod archive_ro;
pub mod diagnostic;
mod ffi;
@@ -104,6 +105,21 @@ pub fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribu
unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) }
}
+pub fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
+ let lower = range.start;
+ let upper = range.end.wrapping_add(1);
+ let lower_words = [lower as u64, (lower >> 64) as u64];
+ let upper_words = [upper as u64, (upper >> 64) as u64];
+ unsafe {
+ LLVMRustCreateRangeAttribute(
+ llcx,
+ size.bits().try_into().unwrap(),
+ lower_words.as_ptr(),
+ upper_words.as_ptr(),
+ )
+ }
+}
+
#[derive(Copy, Clone)]
pub enum AttributePlace {
ReturnValue,
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 4d56d1d..9fd8ca4 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -1,13 +1,14 @@
-use crate::back::write::create_informational_target_machine;
-use crate::errors::{
- FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable,
- UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
-};
-use crate::llvm;
+use std::ffi::{c_char, c_void, CStr, CString};
+use std::fmt::Write;
+use std::path::Path;
+use std::sync::Once;
+use std::{ptr, slice, str};
+
use libc::c_int;
use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::small_c_str::SmallCStr;
+use rustc_data_structures::unord::UnordSet;
use rustc_fs_util::path_to_c_string;
use rustc_middle::bug;
use rustc_session::config::{PrintKind, PrintRequest};
@@ -16,13 +17,12 @@
use rustc_target::spec::{MergeFunctions, PanicStrategy};
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
-use std::ffi::{c_char, c_void, CStr, CString};
-use std::fmt::Write;
-use std::path::Path;
-use std::ptr;
-use std::slice;
-use std::str;
-use std::sync::Once;
+use crate::back::write::create_informational_target_machine;
+use crate::errors::{
+ FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable,
+ UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
+};
+use crate::llvm;
static INIT: Once = Once::new();
@@ -240,40 +240,8 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> {
}
// In LLVM neon implicitly enables fp, but we manually enable
// neon when a feature only implicitly enables fp
- ("aarch64", "f32mm") => {
- LLVMFeature::with_dependency("f32mm", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "f64mm") => {
- LLVMFeature::with_dependency("f64mm", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "fhm") => {
- LLVMFeature::with_dependency("fp16fml", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "fp16") => {
- LLVMFeature::with_dependency("fullfp16", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "jsconv") => {
- LLVMFeature::with_dependency("jsconv", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "sve") => {
- LLVMFeature::with_dependency("sve", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "sve2") => {
- LLVMFeature::with_dependency("sve2", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "sve2-aes") => {
- LLVMFeature::with_dependency("sve2-aes", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "sve2-sm4") => {
- LLVMFeature::with_dependency("sve2-sm4", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "sve2-sha3") => {
- LLVMFeature::with_dependency("sve2-sha3", TargetFeatureFoldStrength::EnableOnly("neon"))
- }
- ("aarch64", "sve2-bitperm") => LLVMFeature::with_dependency(
- "sve2-bitperm",
- TargetFeatureFoldStrength::EnableOnly("neon"),
- ),
+ ("aarch64", "fhm") => LLVMFeature::new("fp16fml"),
+ ("aarch64", "fp16") => LLVMFeature::new("fullfp16"),
// In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called
// `fast-unaligned-access`. In LLVM 19, it was split back out.
("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
@@ -309,11 +277,53 @@ pub fn check_tied_features(
/// Used to generate cfg variables and apply features
/// Must express features in the way Rust understands them
pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
- let target_machine = create_informational_target_machine(sess);
+ let mut features = vec![];
+
+ // Add base features for the target
+ let target_machine = create_informational_target_machine(sess, true);
+ features.extend(
+ sess.target
+ .supported_target_features()
+ .iter()
+ .filter(|(feature, _, _)| {
+ // skip checking special features, as LLVM may not understands them
+ if RUSTC_SPECIAL_FEATURES.contains(feature) {
+ return true;
+ }
+ // check that all features in a given smallvec are enabled
+ for llvm_feature in to_llvm_features(sess, feature) {
+ let cstr = SmallCStr::new(llvm_feature);
+ if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
+ return false;
+ }
+ }
+ true
+ })
+ .map(|(feature, _, _)| Symbol::intern(feature)),
+ );
+
+ // Add enabled features
+ for (enabled, feature) in
+ sess.opts.cg.target_feature.split(',').filter_map(|s| match s.chars().next() {
+ Some('+') => Some((true, Symbol::intern(&s[1..]))),
+ Some('-') => Some((false, Symbol::intern(&s[1..]))),
+ _ => None,
+ })
+ {
+ if enabled {
+ features.extend(sess.target.implied_target_features(std::iter::once(feature)));
+ } else {
+ features.retain(|f| {
+ !sess.target.implied_target_features(std::iter::once(*f)).contains(&feature)
+ });
+ }
+ }
+
+ // Filter enabled features based on feature gates
sess.target
.supported_target_features()
.iter()
- .filter_map(|&(feature, gate)| {
+ .filter_map(|&(feature, gate, _)| {
if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
Some(feature)
} else {
@@ -321,18 +331,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
}
})
.filter(|feature| {
- // skip checking special features, as LLVM may not understands them
- if RUSTC_SPECIAL_FEATURES.contains(feature) {
- return true;
- }
- // check that all features in a given smallvec are enabled
- for llvm_feature in to_llvm_features(sess, feature) {
- let cstr = SmallCStr::new(llvm_feature);
- if !unsafe { llvm::LLVMRustHasFeature(&target_machine, cstr.as_ptr()) } {
- return false;
- }
- }
- true
+ RUSTC_SPECIAL_FEATURES.contains(feature) || features.contains(&Symbol::intern(feature))
})
.map(|feature| Symbol::intern(feature))
.collect()
@@ -387,7 +386,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
.target
.supported_target_features()
.iter()
- .map(|(feature, _gate)| {
+ .map(|(feature, _gate, _implied)| {
// LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
let llvm_feature = to_llvm_features(sess, *feature).llvm_feature_name;
let desc =
@@ -441,7 +440,7 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
require_inited();
- let tm = create_informational_target_machine(sess);
+ let tm = create_informational_target_machine(sess, false);
match req.kind {
PrintKind::TargetCPUs => {
// SAFETY generate a C compatible string from a byte slice to pass
@@ -489,7 +488,11 @@ pub fn target_cpu(sess: &Session) -> &str {
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
/// `--target` and similar).
-pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<String> {
+pub(crate) fn global_llvm_features(
+ sess: &Session,
+ diagnostics: bool,
+ only_base_features: bool,
+) -> Vec<String> {
// Features that come earlier are overridden by conflicting features later in the string.
// Typically we'll want more explicit settings to override the implicit ones, so:
//
@@ -549,94 +552,124 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
}
// -Ctarget-features
- let supported_features = sess.target.supported_target_features();
- let (llvm_major, _, _) = get_version();
- let mut featsmap = FxHashMap::default();
- let feats = sess
- .opts
- .cg
- .target_feature
- .split(',')
- .filter_map(|s| {
- let enable_disable = match s.chars().next() {
- None => return None,
- Some(c @ ('+' | '-')) => c,
- Some(_) => {
- if diagnostics {
- sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature: s });
+ if !only_base_features {
+ let supported_features = sess.target.supported_target_features();
+ let (llvm_major, _, _) = get_version();
+ let mut featsmap = FxHashMap::default();
+
+ // insert implied features
+ let mut all_rust_features = vec![];
+ for feature in sess.opts.cg.target_feature.split(',') {
+ match feature.strip_prefix('+') {
+ Some(feature) => all_rust_features.extend(
+ UnordSet::from(
+ sess.target
+ .implied_target_features(std::iter::once(Symbol::intern(feature))),
+ )
+ .to_sorted_stable_ord()
+ .iter()
+ .map(|s| format!("+{}", s.as_str())),
+ ),
+ _ => all_rust_features.push(feature.to_string()),
+ }
+ }
+
+ let feats = all_rust_features
+ .iter()
+ .filter_map(|s| {
+ let enable_disable = match s.chars().next() {
+ None => return None,
+ Some(c @ ('+' | '-')) => c,
+ Some(_) => {
+ if diagnostics {
+ sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature: s });
+ }
+ return None;
}
+ };
+
+ let feature = backend_feature_name(sess, s)?;
+ // Warn against use of LLVM specific feature names and unstable features on the CLI.
+ if diagnostics {
+ let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
+ if feature_state.is_none() {
+ let rust_feature =
+ supported_features.iter().find_map(|&(rust_feature, _, _)| {
+ let llvm_features = to_llvm_features(sess, rust_feature);
+ if llvm_features.contains(feature)
+ && !llvm_features.contains(rust_feature)
+ {
+ Some(rust_feature)
+ } else {
+ None
+ }
+ });
+ let unknown_feature = if let Some(rust_feature) = rust_feature {
+ UnknownCTargetFeature {
+ feature,
+ rust_feature: PossibleFeature::Some { rust_feature },
+ }
+ } else {
+ UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
+ };
+ sess.dcx().emit_warn(unknown_feature);
+ } else if feature_state
+ .is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
+ {
+ // An unstable feature. Warn about using it.
+ sess.dcx().emit_warn(UnstableCTargetFeature { feature });
+ }
+ }
+
+ if diagnostics {
+ // FIXME(nagisa): figure out how to not allocate a full hashset here.
+ featsmap.insert(feature, enable_disable == '+');
+ }
+
+ // rustc-specific features do not get passed down to LLVM…
+ if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
return None;
}
- };
- let feature = backend_feature_name(sess, s)?;
- // Warn against use of LLVM specific feature names and unstable features on the CLI.
- if diagnostics {
- let feature_state = supported_features.iter().find(|&&(v, _)| v == feature);
- if feature_state.is_none() {
- let rust_feature = supported_features.iter().find_map(|&(rust_feature, _)| {
- let llvm_features = to_llvm_features(sess, rust_feature);
- if llvm_features.contains(feature) && !llvm_features.contains(rust_feature)
- {
- Some(rust_feature)
- } else {
- None
- }
- });
- let unknown_feature = if let Some(rust_feature) = rust_feature {
- UnknownCTargetFeature {
- feature,
- rust_feature: PossibleFeature::Some { rust_feature },
- }
- } else {
- UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
- };
- sess.dcx().emit_warn(unknown_feature);
- } else if feature_state
- .is_some_and(|(_name, feature_gate)| !feature_gate.is_stable())
- {
- // An unstable feature. Warn about using it.
- sess.dcx().emit_warn(UnstableCTargetFeature { feature });
+ // if the target-feature is "backchain" and LLVM version is greater than 18
+ // then we also need to add "+backchain" to the target-features attribute.
+ // otherwise, we will only add the naked `backchain` attribute to the attribute-group.
+ if feature == "backchain" && llvm_major < 18 {
+ return None;
}
- }
+ // ... otherwise though we run through `to_llvm_features` when
+ // passing requests down to LLVM. This means that all in-language
+ // features also work on the command line instead of having two
+ // different names when the LLVM name and the Rust name differ.
+ let llvm_feature = to_llvm_features(sess, feature);
- if diagnostics {
- // FIXME(nagisa): figure out how to not allocate a full hashset here.
- featsmap.insert(feature, enable_disable == '+');
- }
-
- // rustc-specific features do not get passed down to LLVM…
- if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
- return None;
- }
-
- // if the target-feature is "backchain" and LLVM version is greater than 18
- // then we also need to add "+backchain" to the target-features attribute.
- // otherwise, we will only add the naked `backchain` attribute to the attribute-group.
- if feature == "backchain" && llvm_major < 18 {
- return None;
- }
- // ... otherwise though we run through `to_llvm_features` when
- // passing requests down to LLVM. This means that all in-language
- // features also work on the command line instead of having two
- // different names when the LLVM name and the Rust name differ.
- let llvm_feature = to_llvm_features(sess, feature);
-
- Some(
- std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
- .chain(llvm_feature.dependency.into_iter().filter_map(move |feat| {
- match (enable_disable, feat) {
+ Some(
+ std::iter::once(format!(
+ "{}{}",
+ enable_disable, llvm_feature.llvm_feature_name
+ ))
+ .chain(llvm_feature.dependency.into_iter().filter_map(
+ move |feat| match (enable_disable, feat) {
('-' | '+', TargetFeatureFoldStrength::Both(f))
| ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
Some(format!("{enable_disable}{f}"))
}
_ => None,
- }
- })),
- )
- })
- .flatten();
- features.extend(feats);
+ },
+ )),
+ )
+ })
+ .flatten();
+ features.extend(feats);
+
+ if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
+ sess.dcx().emit_err(TargetFeatureDisableOrEnable {
+ features: f,
+ span: None,
+ missing_features: None,
+ });
+ }
+ }
// -Zfixed-x18
if sess.opts.unstable_opts.fixed_x18 {
@@ -647,14 +680,6 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
}
}
- if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
- sess.dcx().emit_err(TargetFeatureDisableOrEnable {
- features: f,
- span: None,
- missing_features: None,
- });
- }
-
features
}
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 282a186..f1ef359 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -1,9 +1,3 @@
-use crate::attributes;
-use crate::base;
-use crate::context::CodegenCx;
-use crate::errors::SymbolAlreadyDefined;
-use crate::llvm;
-use crate::type_of::LayoutLlvmExt;
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
@@ -15,6 +9,11 @@
use rustc_target::spec::RelocModel;
use tracing::debug;
+use crate::context::CodegenCx;
+use crate::errors::SymbolAlreadyDefined;
+use crate::type_of::LayoutLlvmExt;
+use crate::{base, llvm};
+
impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
fn predefine_static(
&self,
@@ -88,8 +87,6 @@ fn predefine_fn(
debug!("predefine_fn: instance = {:?}", instance);
- attributes::from_fn_attrs(self, lldecl, instance);
-
unsafe {
if self.should_assume_dso_local(lldecl, false) {
llvm::LLVMRustSetDSOLocal(lldecl, true);
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index f1141c5..7e3ab19 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -1,12 +1,6 @@
-pub use crate::llvm::Type;
+use std::{fmt, ptr};
-use crate::abi::{FnAbiLlvmExt, LlvmType};
-use crate::common;
-use crate::context::CodegenCx;
-use crate::llvm;
-use crate::llvm::{Bool, False, True};
-use crate::type_of::LayoutLlvmExt;
-use crate::value::Value;
+use libc::{c_char, c_uint};
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::small_c_str::SmallCStr;
@@ -16,10 +10,13 @@
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
use rustc_target::abi::{AddressSpace, Align, Integer, Size};
-use std::fmt;
-use std::ptr;
-
-use libc::{c_char, c_uint};
+use crate::abi::{FnAbiLlvmExt, LlvmType};
+use crate::context::CodegenCx;
+pub use crate::llvm::Type;
+use crate::llvm::{Bool, False, True};
+use crate::type_of::LayoutLlvmExt;
+use crate::value::Value;
+use crate::{common, llvm};
impl PartialEq for Type {
fn eq(&self, other: &Self) -> bool {
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 7be941e..4755fa0 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -1,16 +1,15 @@
-use crate::common::*;
-use crate::type_::Type;
+use std::fmt::Write;
+
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt};
-use rustc_target::abi::{Abi, Align, FieldsShape};
-use rustc_target::abi::{Float, Int, Pointer};
-use rustc_target::abi::{Scalar, Size, Variants};
+use rustc_target::abi::{Abi, Align, FieldsShape, Float, Int, Pointer, Scalar, Size, Variants};
use tracing::debug;
-use std::fmt::Write;
+use crate::common::*;
+use crate::type_::Type;
fn uncached_llvm_type<'a, 'tcx>(
cx: &CodegenCx<'a, 'tcx>,
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 220bb77..94e77c5 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -1,15 +1,14 @@
+use rustc_codegen_ssa::common::IntPredicate;
+use rustc_codegen_ssa::mir::operand::OperandRef;
+use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods, ConstMethods};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::Ty;
+use rustc_target::abi::{Align, Endian, HasDataLayout, Size};
+
use crate::builder::Builder;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
-use rustc_codegen_ssa::mir::operand::OperandRef;
-use rustc_codegen_ssa::{
- common::IntPredicate,
- traits::{BaseTypeMethods, BuilderMethods, ConstMethods},
-};
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
-use rustc_middle::ty::Ty;
-use rustc_target::abi::{Align, Endian, HasDataLayout, Size};
fn round_pointer_up_to_alignment<'ll>(
bx: &mut Builder<'_, 'll, '_>,
diff --git a/compiler/rustc_codegen_llvm/src/value.rs b/compiler/rustc_codegen_llvm/src/value.rs
index 1338a22..6295b0d 100644
--- a/compiler/rustc_codegen_llvm/src/value.rs
+++ b/compiler/rustc_codegen_llvm/src/value.rs
@@ -1,10 +1,8 @@
-pub use crate::llvm::Value;
+use std::hash::{Hash, Hasher};
+use std::{fmt, ptr};
use crate::llvm;
-
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::ptr;
+pub use crate::llvm::Value;
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index f7b5b0f..6e1c323 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -5,7 +5,7 @@
[dependencies]
# tidy-alphabetical-start
-ar_archive_writer = "0.3.0"
+ar_archive_writer = "0.3.3"
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
cc = "1.0.90"
@@ -41,7 +41,7 @@
thin-vec = "0.2.12"
thorin-dwp = "0.7"
tracing = "0.1"
-wasm-encoder = "0.200.0"
+wasm-encoder = "0.210.0"
# tidy-alphabetical-end
[target.'cfg(unix)'.dependencies]
@@ -50,7 +50,7 @@
# tidy-alphabetical-end
[dependencies.object]
-version = "0.32.1"
+version = "0.36.2"
default-features = false
features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"]
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 000fe2e..80f25d4 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -4,8 +4,7 @@
codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
-codegen_ssa_archive_build_failure =
- failed to build archive: {$error}
+codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error}
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
@@ -25,8 +24,19 @@
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
+codegen_ssa_dlltool_fail_import_library =
+ Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
+ {$stdout}
+ {$stderr}
+
+codegen_ssa_error_calling_dlltool =
+ Error calling dlltool '{$dlltool_path}': {$error}
+
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
+codegen_ssa_error_writing_def_file =
+ Error writing .DEF file: {$error}
+
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
@@ -198,7 +208,7 @@
codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
-codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib: {$error}
+codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error}
codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index 6e7d736..11bcd72 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -23,10 +23,11 @@
//! allows for doing a more fine-grained check to see if pre- or post-lto data
//! was re-used.
-use crate::errors;
+use std::borrow::Cow;
+use std::fmt;
+
use rustc_ast as ast;
-use rustc_data_structures::unord::UnordMap;
-use rustc_data_structures::unord::UnordSet;
+use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::mir::mono::CodegenUnitNameBuilder;
@@ -34,11 +35,11 @@
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
-use std::borrow::Cow;
-use std::fmt;
use thin_vec::ThinVec;
use tracing::debug;
+use crate::errors;
+
#[allow(missing_docs)]
pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTracker)) {
tcx.dep_graph.with_ignore(|| {
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index ae649cd..ce55d99 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -1,24 +1,24 @@
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_data_structures::memmap::Mmap;
-use rustc_session::cstore::DllImport;
-use rustc_session::Session;
-use rustc_span::symbol::Symbol;
-
-use super::metadata::search_for_section;
+use std::env;
+use std::error::Error;
+use std::ffi::OsString;
+use std::fs::{self, File};
+use std::io::{self, Write};
+use std::path::{Path, PathBuf};
use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER};
use object::read::archive::ArchiveFile;
use object::read::macho::FatArch;
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::memmap::Mmap;
+use rustc_session::Session;
+use rustc_span::symbol::Symbol;
use tempfile::Builder as TempFileBuilder;
-use std::error::Error;
-use std::fs::{self, File};
-use std::io::{self, Write};
-use std::path::{Path, PathBuf};
-
+use super::metadata::search_for_section;
// Re-exporting for rustc_codegen_llvm::back::archive
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
+use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
pub trait ArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
@@ -32,10 +32,9 @@ fn create_dll_import_lib(
&self,
sess: &Session,
lib_name: &str,
- dll_imports: &[DllImport],
- tmpdir: &Path,
- is_direct_dependency: bool,
- ) -> PathBuf;
+ import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+ output_path: &Path,
+ );
fn extract_bundled_libs<'a>(
&'a self,
@@ -74,6 +73,130 @@ fn extract_bundled_libs<'a>(
}
}
+pub fn create_mingw_dll_import_lib(
+ sess: &Session,
+ lib_name: &str,
+ import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+ output_path: &Path,
+) {
+ let def_file_path = output_path.with_extension("def");
+
+ let def_file_content = format!(
+ "EXPORTS\n{}",
+ import_name_and_ordinal_vector
+ .into_iter()
+ .map(|(name, ordinal)| {
+ match ordinal {
+ Some(n) => format!("{name} @{n} NONAME"),
+ None => name,
+ }
+ })
+ .collect::<Vec<String>>()
+ .join("\n")
+ );
+
+ match std::fs::write(&def_file_path, def_file_content) {
+ Ok(_) => {}
+ Err(e) => {
+ sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
+ }
+ };
+
+ // --no-leading-underscore: For the `import_name_type` feature to work, we need to be
+ // able to control the *exact* spelling of each of the symbols that are being imported:
+ // hence we don't want `dlltool` adding leading underscores automatically.
+ let dlltool = find_binutils_dlltool(sess);
+ let temp_prefix = {
+ let mut path = PathBuf::from(&output_path);
+ path.pop();
+ path.push(lib_name);
+ path
+ };
+ // dlltool target architecture args from:
+ // https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
+ let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
+ "x86_64" => ("i386:x86-64", "--64"),
+ "x86" => ("i386", "--32"),
+ "aarch64" => ("arm64", "--64"),
+ "arm" => ("arm", "--32"),
+ _ => panic!("unsupported arch {}", sess.target.arch),
+ };
+ let mut dlltool_cmd = std::process::Command::new(&dlltool);
+ dlltool_cmd
+ .arg("-d")
+ .arg(def_file_path)
+ .arg("-D")
+ .arg(lib_name)
+ .arg("-l")
+ .arg(&output_path)
+ .arg("-m")
+ .arg(dlltool_target_arch)
+ .arg("-f")
+ .arg(dlltool_target_bitness)
+ .arg("--no-leading-underscore")
+ .arg("--temp-prefix")
+ .arg(temp_prefix);
+
+ match dlltool_cmd.output() {
+ Err(e) => {
+ sess.dcx().emit_fatal(ErrorCallingDllTool {
+ dlltool_path: dlltool.to_string_lossy(),
+ error: e,
+ });
+ }
+ // dlltool returns '0' on failure, so check for error output instead.
+ Ok(output) if !output.stderr.is_empty() => {
+ sess.dcx().emit_fatal(DlltoolFailImportLibrary {
+ dlltool_path: dlltool.to_string_lossy(),
+ dlltool_args: dlltool_cmd
+ .get_args()
+ .map(|arg| arg.to_string_lossy())
+ .collect::<Vec<_>>()
+ .join(" "),
+ stdout: String::from_utf8_lossy(&output.stdout),
+ stderr: String::from_utf8_lossy(&output.stderr),
+ })
+ }
+ _ => {}
+ }
+}
+
+fn find_binutils_dlltool(sess: &Session) -> OsString {
+ assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
+ if let Some(dlltool_path) = &sess.opts.cg.dlltool {
+ return dlltool_path.clone().into_os_string();
+ }
+
+ let tool_name: OsString = if sess.host.options.is_like_windows {
+ // If we're compiling on Windows, always use "dlltool.exe".
+ "dlltool.exe"
+ } else {
+ // On other platforms, use the architecture-specific name.
+ match sess.target.arch.as_ref() {
+ "x86_64" => "x86_64-w64-mingw32-dlltool",
+ "x86" => "i686-w64-mingw32-dlltool",
+ "aarch64" => "aarch64-w64-mingw32-dlltool",
+
+ // For non-standard architectures (e.g., aarch32) fallback to "dlltool".
+ _ => "dlltool",
+ }
+ }
+ .into();
+
+ // NOTE: it's not clear how useful it is to explicitly search PATH.
+ for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
+ let full_path = dir.join(&tool_name);
+ if full_path.is_file() {
+ return full_path.into_os_string();
+ }
+ }
+
+ // The user didn't specify the location of the dlltool binary, and we weren't able
+ // to find the appropriate one on the PATH. Just return the name of the tool
+ // and let the invocation fail with a hopefully useful error message.
+ tool_name
+}
+
pub trait ArchiveBuilder {
fn add_file(&mut self, path: &Path);
@@ -110,13 +233,11 @@ pub fn new(sess: &'a Session, object_reader: &'static ObjectReader) -> ArArchive
}
fn try_filter_fat_archs(
- archs: object::read::Result<&[impl FatArch]>,
+ archs: &[impl FatArch],
target_arch: object::Architecture,
archive_path: &Path,
archive_map_data: &[u8],
) -> io::Result<Option<PathBuf>> {
- let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
-
let desired = match archs.iter().find(|a| a.architecture() == target_arch) {
Some(a) => a,
None => return Ok(None),
@@ -146,17 +267,15 @@ pub fn try_extract_macho_fat_archive(
_ => return Ok(None),
};
- match object::macho::FatHeader::parse(&*archive_map) {
- Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
- let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
- try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
- }
- Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
- let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
- try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
- }
+ if let Ok(h) = object::read::macho::MachOFatFile32::parse(&*archive_map) {
+ let archs = h.arches();
+ try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+ } else if let Ok(h) = object::read::macho::MachOFatFile64::parse(&*archive_map) {
+ let archs = h.arches();
+ try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+ } else {
// Not a FatHeader at all, just return None.
- _ => Ok(None),
+ Ok(None)
}
}
@@ -213,7 +332,9 @@ fn build(self: Box<Self>, output: &Path) -> bool {
let sess = self.sess;
match self.build_inner(output) {
Ok(any_members) => any_members,
- Err(e) => sess.dcx().emit_fatal(ArchiveBuildFailure { error: e }),
+ Err(error) => {
+ sess.dcx().emit_fatal(ArchiveBuildFailure { path: output.to_owned(), error })
+ }
}
}
}
@@ -224,11 +345,7 @@ fn build_inner(self, output: &Path) -> io::Result<bool> {
"gnu" => ArchiveKind::Gnu,
"bsd" => ArchiveKind::Bsd,
"darwin" => ArchiveKind::Darwin,
- "coff" => {
- // FIXME: ar_archive_writer doesn't support COFF archives yet.
- // https://github.com/rust-lang/ar_archive_writer/issues/9
- ArchiveKind::Gnu
- }
+ "coff" => ArchiveKind::Coff,
"aix_big" => ArchiveKind::AixBig,
kind => {
self.sess.dcx().emit_fatal(UnknownArchiveKind { kind });
diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs
index 3a89be8..95c4af2 100644
--- a/compiler/rustc_codegen_ssa/src/back/command.rs
+++ b/compiler/rustc_codegen_ssa/src/back/command.rs
@@ -2,10 +2,8 @@
//! read the arguments that are built up.
use std::ffi::{OsStr, OsString};
-use std::fmt;
-use std::io;
-use std::mem;
use std::process::{self, Output};
+use std::{fmt, io, mem};
use rustc_target::spec::LldFlavor;
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 8c582fa..7bad9d3 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,3 +1,15 @@
+use std::collections::BTreeSet;
+use std::ffi::OsString;
+use std::fs::{read, File, OpenOptions};
+use std::io::{BufWriter, Write};
+use std::ops::Deref;
+use std::path::{Path, PathBuf};
+use std::process::{ExitStatus, Output, Stdio};
+use std::{env, fmt, fs, io, mem, str};
+
+use cc::windows_registry;
+use itertools::Itertools;
+use regex::Regex;
use rustc_arena::TypedArena;
use rustc_ast::CRATE_NODE_ID;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -12,9 +24,10 @@
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_session::config::LinkerFeaturesCli;
-use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, OutFileName, Strip};
-use rustc_session::config::{OutputFilenames, OutputType, PrintKind, SplitDwarfKind};
+use rustc_session::config::{
+ self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
+ OutputType, PrintKind, SplitDwarfKind, Strip,
+};
use rustc_session::cstore::DllImport;
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
use rustc_session::search_paths::PathKind;
@@ -24,11 +37,13 @@
use rustc_session::{filesearch, Session};
use rustc_span::symbol::Symbol;
use rustc_target::spec::crt_objects::CrtObjects;
-use rustc_target::spec::LinkSelfContainedDefault;
-use rustc_target::spec::LinkerFlavorCli;
-use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld, PanicStrategy};
-use rustc_target::spec::{LinkSelfContainedComponents, LinkerFeatures};
-use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{
+ Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures,
+ LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
+ SplitDebuginfo,
+};
+use tempfile::Builder as TempFileBuilder;
+use tracing::{debug, info, warn};
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use super::command::Command;
@@ -36,24 +51,10 @@
use super::metadata::{create_wrapper_file, MetadataPosition};
use super::rpath::{self, RPathConfig};
use crate::{
- errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
+ common, errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo,
+ NativeLib,
};
-use cc::windows_registry;
-use regex::Regex;
-use tempfile::Builder as TempFileBuilder;
-
-use itertools::Itertools;
-use std::collections::BTreeSet;
-use std::ffi::OsString;
-use std::fs::{read, File, OpenOptions};
-use std::io::{BufWriter, Write};
-use std::ops::Deref;
-use std::path::{Path, PathBuf};
-use std::process::{ExitStatus, Output, Stdio};
-use std::{env, fmt, fs, io, mem, str};
-use tracing::{debug, info, warn};
-
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
if let Err(e) = fs::remove_file(path) {
if e.kind() != io::ErrorKind::NotFound {
@@ -390,17 +391,13 @@ fn link_rlib<'a>(
}
}
- for (raw_dylib_name, raw_dylib_imports) in
- collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
- {
- let output_path = archive_builder_builder.create_dll_import_lib(
- sess,
- &raw_dylib_name,
- &raw_dylib_imports,
- tmpdir.as_ref(),
- true,
- );
-
+ for output_path in create_dll_import_libs(
+ sess,
+ archive_builder_builder,
+ codegen_results.crate_info.used_libraries.iter(),
+ tmpdir.as_ref(),
+ true,
+ )? {
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
});
@@ -488,6 +485,47 @@ fn collate_raw_dylibs<'a>(
.collect())
}
+fn create_dll_import_libs<'a>(
+ sess: &Session,
+ archive_builder_builder: &dyn ArchiveBuilderBuilder,
+ used_libraries: impl IntoIterator<Item = &'a NativeLib>,
+ tmpdir: &Path,
+ is_direct_dependency: bool,
+) -> Result<Vec<PathBuf>, ErrorGuaranteed> {
+ Ok(collate_raw_dylibs(sess, used_libraries)?
+ .into_iter()
+ .map(|(raw_dylib_name, raw_dylib_imports)| {
+ let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
+ let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
+
+ let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
+
+ let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
+ .iter()
+ .map(|import: &DllImport| {
+ if sess.target.arch == "x86" {
+ (
+ common::i686_decorated_name(import, mingw_gnu_toolchain, false),
+ import.ordinal(),
+ )
+ } else {
+ (import.name.to_string(), import.ordinal())
+ }
+ })
+ .collect();
+
+ archive_builder_builder.create_dll_import_lib(
+ sess,
+ &raw_dylib_name,
+ import_name_and_ordinal_vector,
+ &output_path,
+ );
+
+ output_path
+ })
+ .collect())
+}
+
/// Create a static archive.
///
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
@@ -700,7 +738,7 @@ fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> {
.truncate(true)
.open(dwp_out_filename)?,
);
- let mut output_stream = object::write::StreamingBuffer::new(output_stream);
+ let mut output_stream = thorin::object::write::StreamingBuffer::new(output_stream);
package.finish()?.emit(&mut output_stream)?;
output_stream.result()?;
output_stream.into_inner().flush()?;
@@ -2065,17 +2103,61 @@ fn add_local_crate_metadata_objects(
}
/// Add sysroot and other globally set directories to the directory search list.
-fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
- // The default library location, we need this to find the runtime.
- // The location of crates will be determined as needed.
- let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
- cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
+fn add_library_search_dirs(
+ cmd: &mut dyn Linker,
+ sess: &Session,
+ self_contained_components: LinkSelfContainedComponents,
+ apple_sdk_root: Option<&Path>,
+) {
+ if !sess.opts.unstable_opts.link_native_libraries {
+ return;
+ }
- // Special directory with libraries used only in self-contained linkage mode
- if self_contained {
- let lib_path = sess.target_filesearch(PathKind::All).get_self_contained_lib_path();
+ // Library search paths explicitly supplied by user (`-L` on the command line).
+ for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() {
+ cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir));
+ }
+ for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() {
+ // Contrary to the `-L` docs only framework-specific paths are considered here.
+ if search_path.kind != PathKind::All {
+ cmd.framework_path(&search_path.dir);
+ }
+ }
+
+ // The toolchain ships some native library components and self-contained linking was enabled.
+ // Add the self-contained library directory to search paths.
+ if self_contained_components.intersects(
+ LinkSelfContainedComponents::LIBC
+ | LinkSelfContainedComponents::UNWIND
+ | LinkSelfContainedComponents::MINGW,
+ ) {
+ let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path();
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
}
+
+ // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot
+ // library directory instead of the self-contained directories.
+ // Sanitizer libraries have the same issue and are also linked by name on Apple targets.
+ // The targets here should be in sync with `copy_third_party_objects` in bootstrap.
+ // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind
+ // and sanitizers to self-contained directory, and stop adding this search path.
+ if sess.target.vendor == "fortanix"
+ || sess.target.os == "linux"
+ || sess.target.os == "fuchsia"
+ || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty()
+ {
+ let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path();
+ cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
+ }
+
+ // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
+ // we must have the support library stubs in the library search path (#121430).
+ if let Some(sdk_root) = apple_sdk_root
+ && sess.target.llvm_target.contains("macabi")
+ {
+ cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
+ cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
+ }
}
/// Add options making relocation sections in the produced ELF files read-only
@@ -2261,16 +2343,14 @@ fn linker_with_args(
);
// Link with the import library generated for any raw-dylib functions.
- for (raw_dylib_name, raw_dylib_imports) in
- collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
- {
- cmd.add_object(&archive_builder_builder.create_dll_import_lib(
- sess,
- &raw_dylib_name,
- &raw_dylib_imports,
- tmpdir,
- true,
- ));
+ for output_path in create_dll_import_libs(
+ sess,
+ archive_builder_builder,
+ codegen_results.crate_info.used_libraries.iter(),
+ tmpdir,
+ true,
+ )? {
+ cmd.add_object(&output_path);
}
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
// they are used within inlined functions or instantiated generic functions. We do this *after*
@@ -2295,16 +2375,14 @@ fn linker_with_args(
.flatten()
.collect::<Vec<_>>();
native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
- for (raw_dylib_name, raw_dylib_imports) in
- collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
- {
- cmd.add_object(&archive_builder_builder.create_dll_import_lib(
- sess,
- &raw_dylib_name,
- &raw_dylib_imports,
- tmpdir,
- false,
- ));
+ for output_path in create_dll_import_libs(
+ sess,
+ archive_builder_builder,
+ native_libraries_from_nonstatics,
+ tmpdir,
+ false,
+ )? {
+ cmd.add_object(&output_path);
}
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
@@ -2367,7 +2445,7 @@ fn add_order_independent_options(
// Take care of the flavors and CLI options requesting the `lld` linker.
add_lld_args(cmd, sess, flavor, self_contained_components);
- add_apple_sdk(cmd, sess, flavor);
+ let apple_sdk_root = add_apple_sdk(cmd, sess, flavor);
add_link_script(cmd, sess, tmpdir, crate_type);
@@ -2423,7 +2501,7 @@ fn add_order_independent_options(
cmd.linker_plugin_lto();
- add_library_search_dirs(cmd, sess, self_contained_components.are_any_components_enabled());
+ add_library_search_dirs(cmd, sess, self_contained_components, apple_sdk_root.as_deref());
cmd.output_filename(out_filename);
@@ -2568,16 +2646,7 @@ fn add_native_libs_from_crate(
NativeLibKind::Static { bundle, whole_archive } => {
if link_static {
let bundle = bundle.unwrap_or(true);
- let whole_archive = whole_archive == Some(true)
- // Backward compatibility case: this can be a rlib (so `+whole-archive`
- // cannot be added explicitly if necessary, see the error in `fn link_rlib`)
- // compiled as an executable due to `--test`. Use whole-archive implicitly,
- // like before the introduction of native lib modifiers.
- || (whole_archive == None
- && bundle
- && cnum == LOCAL_CRATE
- && sess.is_test_crate());
-
+ let whole_archive = whole_archive == Some(true);
if bundle && cnum != LOCAL_CRATE {
if let Some(filename) = lib.filename {
// If rlib contains native libs as archives, they are unpacked to tmpdir.
@@ -2637,19 +2706,6 @@ fn add_local_native_libraries(
tmpdir: &Path,
link_output_kind: LinkOutputKind,
) {
- if sess.opts.unstable_opts.link_native_libraries {
- // User-supplied library search paths (-L on the command line). These are the same paths
- // used to find Rust crates, so some of them may have been added already by the previous
- // crate linking code. This only allows them to be found at compile time so it is still
- // entirely up to outside forces to make sure that library can be found at runtime.
- for search_path in sess.target_filesearch(PathKind::All).search_paths() {
- match search_path.kind {
- PathKind::Framework => cmd.framework_path(&search_path.dir),
- _ => cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)),
- }
- }
- }
-
// All static and dynamic native library dependencies are linked to the local crate.
let link_static = true;
let link_dynamic = true;
@@ -2911,7 +2967,8 @@ fn add_static_crate(
false
}),
) {
- sess.dcx().emit_fatal(errors::RlibArchiveBuildFailure { error });
+ sess.dcx()
+ .emit_fatal(errors::RlibArchiveBuildFailure { path: cratepath.clone(), error });
}
if archive.build(&dst) {
link_upstream(&dst);
@@ -2943,7 +3000,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool
}
}
-fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
+fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
let arch = &sess.target.arch;
let os = &sess.target.os;
let llvm_target = &sess.target.llvm_target;
@@ -2951,11 +3008,11 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos")
|| !matches!(flavor, LinkerFlavor::Darwin(..))
{
- return;
+ return None;
}
if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) {
- return;
+ return None;
}
let sdk_name = match (arch.as_ref(), os.as_ref()) {
@@ -2979,14 +3036,14 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
(_, "macos") => "macosx",
_ => {
sess.dcx().emit_err(errors::UnsupportedArch { arch, os });
- return;
+ return None;
}
};
let sdk_root = match get_apple_sdk_root(sdk_name) {
Ok(s) => s,
Err(e) => {
sess.dcx().emit_err(e);
- return;
+ return None;
}
};
@@ -3006,16 +3063,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
_ => unreachable!(),
}
- if llvm_target.contains("macabi") {
- // Mac Catalyst uses the macOS SDK, but to link to iOS-specific
- // frameworks, we must have the support library stubs in the library
- // search path.
-
- // The flags are called `-L` and `-F` both in Clang, ld64 and ldd.
- let sdk_root = Path::new(&sdk_root);
- cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib"));
- cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"));
- }
+ Some(sdk_root.into())
}
fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootError<'_>> {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index dd134eb..febeb70 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1,8 +1,3 @@
-use super::command::Command;
-use super::symbol_export;
-use crate::errors;
-use rustc_span::symbol::sym;
-
use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
use std::io::prelude::*;
@@ -10,6 +5,7 @@
use std::path::{Path, PathBuf};
use std::{env, iter, mem, str};
+use cc::windows_registry;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_metadata::find_native_static_library;
use rustc_middle::bug;
@@ -19,11 +15,14 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
use rustc_session::Session;
+use rustc_span::symbol::sym;
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld};
-
-use cc::windows_registry;
use tracing::{debug, warn};
+use super::command::Command;
+use super::symbol_export;
+use crate::errors;
+
/// Disables non-English messages from localized linkers.
/// Such messages may cause issues with text encoding on Windows (#35785)
/// and prevent inspection of linker output in case of errors, which we occasionally do.
diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs
index 5291cad..8b6f6b5 100644
--- a/compiler/rustc_codegen_ssa/src/back/lto.rs
+++ b/compiler/rustc_codegen_ssa/src/back/lto.rs
@@ -1,12 +1,12 @@
-use super::write::CodegenContext;
-use crate::traits::*;
-use crate::ModuleCodegen;
+use std::ffi::CString;
+use std::sync::Arc;
use rustc_data_structures::memmap::Mmap;
use rustc_errors::FatalError;
-use std::ffi::CString;
-use std::sync::Arc;
+use super::write::CodegenContext;
+use crate::traits::*;
+use crate::ModuleCodegen;
pub struct ThinModule<B: WriteBackendMethods> {
pub shared: Arc<ThinShared<B>>,
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 264a988..9b5a797 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -10,7 +10,6 @@
elf, pe, xcoff, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection,
ObjectSymbol, SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope,
};
-
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
use rustc_metadata::creader::MetadataLoader;
@@ -209,6 +208,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
"powerpc64" => (Architecture::PowerPc64, None),
"riscv32" => (Architecture::Riscv32, None),
"riscv64" => (Architecture::Riscv64, None),
+ "sparc" => (Architecture::Sparc32Plus, None),
"sparc64" => (Architecture::Sparc64, None),
"avr" => (Architecture::Avr, None),
"msp430" => (Architecture::Msp430, None),
@@ -656,7 +656,13 @@ pub fn create_metadata_file_for_wasm(sess: &Session, data: &[u8], section_name:
imports.import(
"env",
"__linear_memory",
- wasm_encoder::MemoryType { minimum: 0, maximum: None, memory64: true, shared: false },
+ wasm_encoder::MemoryType {
+ minimum: 0,
+ maximum: None,
+ memory64: true,
+ shared: false,
+ page_size_log2: None,
+ },
);
}
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs
index 82070d4..42f8c31 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs
@@ -1,8 +1,9 @@
+use std::ffi::OsString;
+use std::path::{Path, PathBuf};
+
use pathdiff::diff_paths;
use rustc_data_structures::fx::FxHashSet;
use rustc_fs_util::try_canonicalize;
-use std::ffi::OsString;
-use std::path::{Path, PathBuf};
use tracing::debug;
pub struct RPathConfig<'a> {
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
index c620e92..0de0b8a 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
@@ -1,8 +1,8 @@
-use super::RPathConfig;
-use super::{get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags};
use std::ffi::OsString;
use std::path::{Path, PathBuf};
+use super::{get_rpath_relative_to_output, minimize_rpaths, rpaths_to_flags, RPathConfig};
+
#[test]
fn test_rpaths_to_flags() {
let flags = rpaths_to_flags(vec!["path1".into(), "path2".into()]);
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index b7ad09b..d2f11d4 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -1,5 +1,3 @@
-use crate::base::allocator_kind_for_codegen;
-
use std::collections::hash_map::Entry::*;
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE};
@@ -12,14 +10,14 @@
metadata_symbol_name, ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
};
use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, SymbolName, TyCtxt};
-use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
+use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, TyCtxt};
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::spec::{SanitizerSet, TlsModel};
use tracing::debug;
+use crate::base::allocator_kind_for_codegen;
+
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
crates_export_threshold(tcx.crate_types())
}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 56e9452..70b45a8 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1,12 +1,11 @@
-use super::link::{self, ensure_removed};
-use super::lto::{self, SerializedModule};
-use super::symbol_export::symbol_name_for_instance_in_crate;
+use std::any::Any;
+use std::assert_matches::assert_matches;
+use std::marker::PhantomData;
+use std::path::{Path, PathBuf};
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::Arc;
+use std::{fs, io, mem, str, thread};
-use crate::errors;
-use crate::traits::*;
-use crate::{
- CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
-};
use jobserver::{Acquired, Client};
use rustc_ast::attr;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@@ -30,27 +29,26 @@
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::exported_symbols::SymbolExportInfo;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{self, CrateType, Lto, OutFileName, OutputFilenames, OutputType};
-use rustc_session::config::{Passes, SwitchWithOptPath};
+use rustc_session::config::{
+ self, CrateType, Lto, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath,
+};
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
use rustc_target::spec::{MergeFunctions, SanitizerSet};
-
-use crate::errors::ErrorCreatingRemarkDir;
-use std::any::Any;
-use std::fs;
-use std::io;
-use std::marker::PhantomData;
-use std::mem;
-use std::path::{Path, PathBuf};
-use std::str;
-use std::sync::mpsc::{channel, Receiver, Sender};
-use std::sync::Arc;
-use std::thread;
use tracing::debug;
+use super::link::{self, ensure_removed};
+use super::lto::{self, SerializedModule};
+use super::symbol_export::symbol_name_for_instance_in_crate;
+use crate::errors::ErrorCreatingRemarkDir;
+use crate::traits::*;
+use crate::{
+ errors, CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen,
+ ModuleKind,
+};
+
const PRE_LTO_BC_EXT: &str = "pre-lto.bc";
/// What kind of object file to emit.
@@ -1966,7 +1964,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
sess.dcx().abort_if_errors();
}
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
- assert!(matches!(level, Level::Error | Level::Warning | Level::Note));
+ assert_matches!(level, Level::Error | Level::Warning | Level::Note);
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
let mut err = Diag::<()>::new(sess.dcx(), level, msg);
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 399ac48..f1e7f87 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -1,19 +1,8 @@
-use crate::assert_module_sources::CguReuse;
-use crate::back::link::are_upstream_rust_objects_already_included;
-use crate::back::metadata::create_compressed_metadata_file;
-use crate::back::write::{
- compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
- submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
-};
-use crate::common::{self, IntPredicate, RealPredicate, TypeKind};
-use crate::errors;
-use crate::meth;
-use crate::mir;
-use crate::mir::operand::OperandValue;
-use crate::mir::place::PlaceRef;
-use crate::traits::*;
-use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind};
+use std::cmp;
+use std::collections::BTreeSet;
+use std::time::{Duration, Instant};
+use itertools::Itertools;
use rustc_ast::expand::allocator::{global_fn_name, AllocatorKind, ALLOCATOR_METHODS};
use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
@@ -26,9 +15,8 @@
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
-use rustc_middle::middle::exported_symbols;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_middle::middle::lang_items;
+use rustc_middle::middle::{exported_symbols, lang_items};
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::mir::BinOp;
use rustc_middle::query::Providers;
@@ -39,14 +27,23 @@
use rustc_span::symbol::sym;
use rustc_span::{Symbol, DUMMY_SP};
use rustc_target::abi::FIRST_VARIANT;
-
-use std::cmp;
-use std::collections::BTreeSet;
-use std::time::{Duration, Instant};
-
-use itertools::Itertools;
use tracing::{debug, info};
+use crate::assert_module_sources::CguReuse;
+use crate::back::link::are_upstream_rust_objects_already_included;
+use crate::back::metadata::create_compressed_metadata_file;
+use crate::back::write::{
+ compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
+ submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
+};
+use crate::common::{self, IntPredicate, RealPredicate, TypeKind};
+use crate::mir::operand::OperandValue;
+use crate::mir::place::PlaceRef;
+use crate::traits::*;
+use crate::{
+ errors, meth, mir, CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
+};
+
pub fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
match op {
BinOp::Eq => IntPredicate::IntEQ,
@@ -146,7 +143,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
) -> Bx::Value {
let cx = bx.cx();
let (source, target) =
- cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, bx.param_env());
+ cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env());
match (source.kind(), target.kind()) {
(&ty::Array(_, len), &ty::Slice(_)) => {
cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index bfa4c68..4ab20c1 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,17 +1,20 @@
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
-use rustc_errors::{codes::*, struct_span_code_err, DiagMessage, SubdiagMessage};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
-use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
+use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
+use rustc_hir::{lang_items, LangItem};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self as ty, TyCtxt};
-use rustc_session::{lint, parse::feature_err};
+use rustc_session::lint;
+use rustc_session::parse::feature_err;
use rustc_span::symbol::Ident;
use rustc_span::{sym, Span};
use rustc_target::spec::{abi, SanitizerSet};
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index ea2fd48..bfb1d21 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -1,15 +1,16 @@
#![allow(non_camel_case_types)]
use rustc_hir::LangItem;
-use rustc_middle::mir;
-use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, layout::TyAndLayout, TyCtxt};
-use rustc_middle::{bug, span_bug};
+use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::{self, Instance, TyCtxt};
+use rustc_middle::{bug, mir, span_bug};
+use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
use rustc_span::Span;
+use rustc_target::spec::Target;
use crate::traits::*;
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub enum IntPredicate {
IntEQ,
IntNE,
@@ -23,7 +24,7 @@ pub enum IntPredicate {
IntSLE,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub enum RealPredicate {
RealPredicateFalse,
RealOEQ,
@@ -43,7 +44,7 @@ pub enum RealPredicate {
RealPredicateTrue,
}
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Debug)]
pub enum AtomicRmwBinOp {
AtomicXchg,
AtomicAdd,
@@ -58,7 +59,7 @@ pub enum AtomicRmwBinOp {
AtomicUMin,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub enum AtomicOrdering {
Unordered,
Relaxed,
@@ -68,7 +69,7 @@ pub enum AtomicOrdering {
SequentiallyConsistent,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub enum SynchronizationScope {
SingleThread,
CrossThread,
@@ -106,9 +107,10 @@ pub enum TypeKind {
// for now we content ourselves with providing a no-op HashStable
// implementation for CGUs.
mod temp_stable_hash_impls {
- use crate::ModuleCodegen;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+ use crate::ModuleCodegen;
+
impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
// do nothing
@@ -176,3 +178,66 @@ pub fn asm_const_to_str<'tcx>(
_ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
}
}
+
+pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
+ target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
+}
+
+pub fn i686_decorated_name(
+ dll_import: &DllImport,
+ mingw: bool,
+ disable_name_mangling: bool,
+) -> String {
+ let name = dll_import.name.as_str();
+
+ let (add_prefix, add_suffix) = match dll_import.import_name_type {
+ Some(PeImportNameType::NoPrefix) => (false, true),
+ Some(PeImportNameType::Undecorated) => (false, false),
+ _ => (true, true),
+ };
+
+ // Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
+ let mut decorated_name = String::with_capacity(name.len() + 6);
+
+ if disable_name_mangling {
+ // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
+ decorated_name.push('\x01');
+ }
+
+ let prefix = if add_prefix && dll_import.is_fn {
+ match dll_import.calling_convention {
+ DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
+ DllCallingConvention::Stdcall(_) => (!mingw
+ || dll_import.import_name_type == Some(PeImportNameType::Decorated))
+ .then_some('_'),
+ DllCallingConvention::Fastcall(_) => Some('@'),
+ }
+ } else if !dll_import.is_fn && !mingw {
+ // For static variables, prefix with '_' on MSVC.
+ Some('_')
+ } else {
+ None
+ };
+ if let Some(prefix) = prefix {
+ decorated_name.push(prefix);
+ }
+
+ decorated_name.push_str(name);
+
+ if add_suffix && dll_import.is_fn {
+ use std::fmt::Write;
+
+ match dll_import.calling_convention {
+ DllCallingConvention::C => {}
+ DllCallingConvention::Stdcall(arg_list_size)
+ | DllCallingConvention::Fastcall(arg_list_size) => {
+ write!(&mut decorated_name, "@{arg_list_size}").unwrap();
+ }
+ DllCallingConvention::Vectorcall(arg_list_size) => {
+ write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
+ }
+ }
+ }
+
+ decorated_name
+}
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
index 60e9b40..1eaf593 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/mod.rs
@@ -1,4 +1,5 @@
-use rustc_middle::ty::{self, layout::TyAndLayout};
+use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::{self};
use rustc_target::abi::Size;
// FIXME(eddyb) find a place for this (or a way to replace it).
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 6a6d47f..2755803 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -11,6 +11,8 @@
// within the brackets).
// * `"` is treated as the start of a string.
+use std::fmt::Write;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::DefId;
@@ -18,14 +20,13 @@
use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability};
use rustc_middle::bug;
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
-use rustc_middle::ty::{self, ExistentialProjection, ParamEnv, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
+use rustc_middle::ty::{
+ self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt,
+};
use rustc_span::DUMMY_SP;
use rustc_target::abi::Integer;
use smallvec::SmallVec;
-use std::fmt::Write;
-
use crate::debuginfo::wants_c_like_enum_debuginfo;
/// Compute the name of the type as it should be stored in debuginfo. Does not do
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index e9d31db..94bf0ab 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1,20 +1,23 @@
//! Errors emitted by codegen_ssa
-use crate::assert_module_sources::CguReuse;
-use crate::back::command::Command;
-use crate::fluent_generated as fluent;
+use std::borrow::Cow;
+use std::io::Error;
+use std::path::{Path, PathBuf};
+use std::process::ExitStatus;
+
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
+ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
};
use rustc_macros::Diagnostic;
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::Ty;
use rustc_span::{Span, Symbol};
use rustc_type_ir::FloatTy;
-use std::borrow::Cow;
-use std::io::Error;
-use std::path::{Path, PathBuf};
-use std::process::ExitStatus;
+
+use crate::assert_module_sources::CguReuse;
+use crate::back::command::Command;
+use crate::fluent_generated as fluent;
#[derive(Diagnostic)]
#[diag(codegen_ssa_incorrect_cgu_reuse_type)]
@@ -497,6 +500,7 @@ pub struct UnableToWriteDebuggerVisualizer {
#[derive(Diagnostic)]
#[diag(codegen_ssa_rlib_archive_build_failure)]
pub struct RlibArchiveBuildFailure {
+ pub path: PathBuf,
pub error: Error,
}
@@ -554,6 +558,7 @@ pub struct ReadFileError {
#[diag(codegen_ssa_archive_build_failure)]
// Public for rustc_codegen_llvm::back::archive
pub struct ArchiveBuildFailure {
+ pub path: PathBuf,
pub error: std::io::Error,
}
@@ -1022,6 +1027,28 @@ pub struct FailedToGetLayout<'tcx> {
}
#[derive(Diagnostic)]
+#[diag(codegen_ssa_dlltool_fail_import_library)]
+pub(crate) struct DlltoolFailImportLibrary<'a> {
+ pub dlltool_path: Cow<'a, str>,
+ pub dlltool_args: String,
+ pub stdout: Cow<'a, str>,
+ pub stderr: Cow<'a, str>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_error_writing_def_file)]
+pub(crate) struct ErrorWritingDEFFile {
+ pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_error_calling_dlltool)]
+pub(crate) struct ErrorCallingDllTool<'a> {
+ pub dlltool_path: Cow<'a, str>,
+ pub error: std::io::Error,
+}
+
+#[derive(Diagnostic)]
#[diag(codegen_ssa_error_creating_remark_dir)]
pub struct ErrorCreatingRemarkDir {
pub error: std::io::Error,
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index e801af4..cb6d9d6 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -4,6 +4,7 @@
#![allow(rustc::untranslatable_diagnostic)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
+#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(let_chains)]
@@ -17,9 +18,12 @@
//! The backend-agnostic functions of this crate use functions defined in various traits that
//! have to be implemented by each backend.
+use std::collections::BTreeSet;
+use std::io;
+use std::path::{Path, PathBuf};
+
use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::UnordMap;
use rustc_hir::def_id::CrateNum;
@@ -36,9 +40,6 @@
use rustc_session::utils::NativeLibKind;
use rustc_session::Session;
use rustc_span::symbol::Symbol;
-use std::collections::BTreeSet;
-use std::io;
-use std::path::{Path, PathBuf};
pub mod assert_module_sources;
pub mod back;
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index febc8ee..c9602d9 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -1,5 +1,3 @@
-use crate::traits::*;
-
use rustc_middle::bug;
use rustc_middle::ty::{self, GenericArgKind, Ty};
use rustc_session::config::Lto;
@@ -7,6 +5,8 @@
use rustc_target::abi::call::FnAbi;
use tracing::{debug, instrument};
+use crate::traits::*;
+
#[derive(Copy, Clone, Debug)]
pub struct VirtualIndex(u64);
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index ac2b6ca..6794365 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -1,18 +1,18 @@
//! An analysis to determine which locals require allocas and
//! which do not.
-use super::FunctionCx;
-use crate::traits::*;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_index::bit_set::BitSet;
use rustc_index::{IndexSlice, IndexVec};
-use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind};
+use rustc_middle::mir::{self, traversal, DefLocation, Location, TerminatorKind};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::{bug, span_bug};
use tracing::debug;
+use super::FunctionCx;
+use crate::traits::*;
+
pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
fx: &FunctionCx<'a, 'tcx, Bx>,
) -> BitSet<mir::Local> {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 9cb8b71..772adf1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1,14 +1,4 @@
-use super::operand::OperandRef;
-use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
-use super::place::{PlaceRef, PlaceValue};
-use super::{CachedLlbb, FunctionCx, LocalRef};
-
-use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization};
-use crate::common::{self, IntPredicate};
-use crate::errors::CompilerBuiltinsCannotCall;
-use crate::meth;
-use crate::traits::*;
-use crate::MemFlags;
+use std::cmp;
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@@ -19,13 +9,22 @@
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
-use rustc_span::{source_map::Spanned, sym, Span};
+use rustc_span::source_map::Spanned;
+use rustc_span::{sym, Span};
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
use rustc_target::abi::{self, HasDataLayout, WrappingRange};
use rustc_target::spec::abi::Abi;
use tracing::{debug, info};
-use std::cmp;
+use super::operand::OperandRef;
+use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
+use super::place::{PlaceRef, PlaceValue};
+use super::{CachedLlbb, FunctionCx, LocalRef};
+use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization};
+use crate::common::{self, IntPredicate};
+use crate::errors::CompilerBuiltinsCannotCall;
+use crate::traits::*;
+use crate::{meth, MemFlags};
// Indicates if we are in the middle of merging a BB's successor into it. This
// can happen when BB jumps directly to its successor and the successor has no
@@ -924,8 +923,12 @@ fn codegen_call_terminator(
// third argument must be constant. This is
// checked by the type-checker.
if i == 2 && intrinsic.name == sym::simd_shuffle {
+ // FIXME: the simd_shuffle argument is actually an array,
+ // not a vector, so we need this special hack to make sure
+ // it is passed as an immediate. We should pass the
+ // shuffle indices as a vector instead to avoid this hack.
if let mir::Operand::Constant(constant) = &arg.node {
- let (llval, ty) = self.simd_shuffle_indices(bx, constant);
+ let (llval, ty) = self.immediate_const_vector(bx, constant);
return OperandRef {
val: Immediate(llval),
layout: bx.layout_of(ty),
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index 35e9a3b..0aa85b8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -1,14 +1,13 @@
-use crate::errors;
-use crate::mir::operand::OperandRef;
-use crate::traits::*;
-use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::HasTyCtxt;
-use rustc_middle::ty::{self, Ty};
-use rustc_middle::{bug, span_bug};
+use rustc_middle::ty::{self, Ty, ValTree};
+use rustc_middle::{bug, mir, span_bug};
use rustc_target::abi::Abi;
use super::FunctionCx;
+use crate::errors;
+use crate::mir::operand::OperandRef;
+use crate::traits::*;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn eval_mir_constant_to_operand(
@@ -29,7 +28,7 @@ pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::Cons
.expect("erroneous constant missed by mono item collection")
}
- /// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
+ /// This is a convenience helper for `immediate_const_vector`. It has the precondition
/// that the given `constant` is an `Const::Unevaluated` and must be convertible to
/// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
///
@@ -60,23 +59,42 @@ pub fn eval_unevaluated_mir_constant_to_valtree(
self.cx.tcx().const_eval_resolve_for_typeck(ty::ParamEnv::reveal_all(), uv, constant.span)
}
- /// process constant containing SIMD shuffle indices
- pub fn simd_shuffle_indices(
+ /// process constant containing SIMD shuffle indices & constant vectors
+ pub fn immediate_const_vector(
&mut self,
bx: &Bx,
constant: &mir::ConstOperand<'tcx>,
) -> (Bx::Value, Ty<'tcx>) {
let ty = self.monomorphize(constant.ty());
+ let ty_is_simd = ty.is_simd();
+ // FIXME: ideally we'd assert that this is a SIMD type, but simd_shuffle
+ // in its current form relies on a regular array being passed as an
+ // immediate argument. This hack can be removed once that is fixed.
+ let field_ty = if ty_is_simd {
+ ty.simd_size_and_type(bx.tcx()).1
+ } else {
+ ty.builtin_index().unwrap()
+ };
+
let val = self
.eval_unevaluated_mir_constant_to_valtree(constant)
.ok()
.map(|x| x.ok())
.flatten()
.map(|val| {
- let field_ty = ty.builtin_index().unwrap();
- let values: Vec<_> = val
- .unwrap_branch()
- .iter()
+ // Depending on whether this is a SIMD type with an array field
+ // or a type with many fields (one for each elements), the valtree
+ // is either a single branch with N children, or a root node
+ // with exactly one child which then in turn has many children.
+ // So we look at the first child to determine whether it is a
+ // leaf or whether we have to go one more layer down.
+ let branch_or_leaf = val.unwrap_branch();
+ let first = branch_or_leaf.get(0).unwrap();
+ let field_iter = match first {
+ ValTree::Branch(_) => first.unwrap_branch().iter(),
+ ValTree::Leaf(_) => branch_or_leaf.iter(),
+ };
+ let values: Vec<_> = field_iter
.map(|field| {
if let Some(prim) = field.try_to_scalar() {
let layout = bx.layout_of(field_ty);
@@ -85,11 +103,11 @@ pub fn simd_shuffle_indices(
};
bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
} else {
- bug!("simd shuffle field {:?}", field)
+ bug!("field is not a scalar {:?}", field)
}
})
.collect();
- bx.const_struct(&values, false)
+ if ty_is_simd { bx.const_vector(&values) } else { bx.const_struct(&values, false) }
})
.unwrap_or_else(|| {
bx.tcx().dcx().emit_err(errors::ShuffleIndicesEvaluation { span: constant.span });
diff --git a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
index 7218727..67f1ef5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/coverageinfo.rs
@@ -1,9 +1,8 @@
-use crate::traits::*;
-
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::SourceScope;
use super::FunctionCx;
+use crate::traits::*;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn codegen_coverage(&self, bx: &mut Bx, kind: &CoverageKind, scope: SourceScope) {
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 82ed561..0e49597 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -1,13 +1,11 @@
-use crate::traits::*;
+use std::ops::Range;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_index::IndexVec;
-use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir;
-use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::Instance;
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{Instance, Ty};
+use rustc_middle::{bug, mir, ty};
use rustc_session::config::DebugInfo;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{hygiene, BytePos, Span};
@@ -16,8 +14,7 @@
use super::operand::{OperandRef, OperandValue};
use super::place::{PlaceRef, PlaceValue};
use super::{FunctionCx, LocalRef};
-
-use std::ops::Range;
+use crate::traits::*;
pub struct FunctionDebugContext<'tcx, S, L> {
/// Maps from source code to the corresponding debug info scope.
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index f88deaa..4acbc04 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -1,21 +1,16 @@
-use super::operand::OperandRef;
-use super::place::PlaceRef;
-use super::FunctionCx;
-use crate::errors;
-use crate::errors::InvalidMonomorphization;
-use crate::meth;
-use crate::size_of_val;
-use crate::traits::*;
-use crate::MemFlags;
-
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
use rustc_span::{sym, Span};
-use rustc_target::abi::{
- call::{FnAbi, PassMode},
- WrappingRange,
-};
+use rustc_target::abi::call::{FnAbi, PassMode};
+use rustc_target::abi::WrappingRange;
+
+use super::operand::OperandRef;
+use super::place::PlaceRef;
+use super::FunctionCx;
+use crate::errors::InvalidMonomorphization;
+use crate::traits::*;
+use crate::{errors, meth, size_of_val, MemFlags};
fn copy_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
diff --git a/compiler/rustc_codegen_ssa/src/mir/locals.rs b/compiler/rustc_codegen_ssa/src/mir/locals.rs
index 5190021..93f0ab3 100644
--- a/compiler/rustc_codegen_ssa/src/mir/locals.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/locals.rs
@@ -2,14 +2,16 @@
//! be careful wrt to subtyping. To deal with this we only allow updates by using
//! `FunctionCx::overwrite_local` which handles it automatically.
-use crate::mir::{FunctionCx, LocalRef};
-use crate::traits::BuilderMethods;
+use std::ops::{Index, IndexMut};
+
use rustc_index::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
-use std::ops::{Index, IndexMut};
use tracing::{debug, warn};
+use crate::mir::{FunctionCx, LocalRef};
+use crate::traits::BuilderMethods;
+
pub(super) struct Locals<'tcx, V> {
values: IndexVec<mir::Local, LocalRef<'tcx, V>>,
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 61f57c9..4ce0726 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -1,18 +1,17 @@
-use crate::base;
-use crate::traits::*;
+use std::iter;
+
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir;
-use rustc_middle::mir::traversal;
-use rustc_middle::mir::UnwindTerminateReason;
+use rustc_middle::mir::{traversal, UnwindTerminateReason};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
-use rustc_middle::{bug, span_bug};
+use rustc_middle::{bug, mir, span_bug};
use rustc_target::abi::call::{FnAbi, PassMode};
use tracing::{debug, instrument};
-use std::iter;
+use crate::base;
+use crate::traits::*;
mod analyze;
mod block;
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index e08d7a3..1891de8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -1,23 +1,21 @@
-use super::place::{PlaceRef, PlaceValue};
-use super::{FunctionCx, LocalRef};
+use std::assert_matches::assert_matches;
+use std::fmt;
-use crate::size_of_val;
-use crate::traits::*;
-use crate::MemFlags;
-
+use arrayvec::ArrayVec;
+use either::Either;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{alloc_range, Pointer, Scalar};
use rustc_middle::mir::{self, ConstValue};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_target::abi::{self, Abi, Align, Size};
-
-use std::fmt;
-
-use arrayvec::ArrayVec;
-use either::Either;
use tracing::debug;
+use super::place::{PlaceRef, PlaceValue};
+use super::{FunctionCx, LocalRef};
+use crate::traits::*;
+use crate::{size_of_val, MemFlags};
+
/// The representation of a Rust value. The enum variant is in fact
/// uniquely determined by the value's type, but is kept as a
/// safety check.
@@ -392,7 +390,7 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
}
// Newtype vector of array, e.g. #[repr(simd)] struct S([i32; 4]);
(OperandValue::Immediate(llval), Abi::Aggregate { sized: true }) => {
- assert!(matches!(self.layout.abi, Abi::Vector { .. }));
+ assert_matches!(self.layout.abi, Abi::Vector { .. });
let llfield_ty = bx.cx().backend_type(field);
@@ -638,7 +636,24 @@ pub fn codegen_operand(
self.codegen_consume(bx, place.as_ref())
}
- mir::Operand::Constant(ref constant) => self.eval_mir_constant_to_operand(bx, constant),
+ mir::Operand::Constant(ref constant) => {
+ let constant_ty = self.monomorphize(constant.ty());
+ // Most SIMD vector constants should be passed as immediates.
+ // (In particular, some intrinsics really rely on this.)
+ if constant_ty.is_simd() {
+ // However, some SIMD types do not actually use the vector ABI
+ // (in particular, packed SIMD types do not). Ensure we exclude those.
+ let layout = bx.layout_of(constant_ty);
+ if let Abi::Vector { .. } = layout.abi {
+ let (llval, ty) = self.immediate_const_vector(bx, constant);
+ return OperandRef {
+ val: OperandValue::Immediate(llval),
+ layout: bx.layout_of(ty),
+ };
+ }
+ }
+ self.eval_mir_constant_to_operand(bx, constant)
+ }
}
}
}
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 4394ffb..0fad4d1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -1,19 +1,18 @@
-use super::operand::OperandValue;
-use super::{FunctionCx, LocalRef};
-
-use crate::common::IntPredicate;
-use crate::size_of_val;
-use crate::traits::*;
-
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Ty};
-use rustc_target::abi::{Align, FieldsShape, Int, Pointer, Size, TagEncoding};
-use rustc_target::abi::{VariantIdx, Variants};
+use rustc_middle::{bug, mir};
+use rustc_target::abi::{
+ Align, FieldsShape, Int, Pointer, Size, TagEncoding, VariantIdx, Variants,
+};
use tracing::{debug, instrument};
+use super::operand::OperandValue;
+use super::{FunctionCx, LocalRef};
+use crate::common::IntPredicate;
+use crate::size_of_val;
+use crate::traits::*;
+
/// The location and extra runtime properties of the place.
///
/// Typically found in a [`PlaceRef`] or an [`OperandValue::Ref`].
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 491b457..3c2c29a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -1,23 +1,22 @@
-use super::operand::{OperandRef, OperandValue};
-use super::place::PlaceRef;
-use super::{FunctionCx, LocalRef};
+use std::assert_matches::assert_matches;
-use crate::base;
-use crate::common::IntPredicate;
-use crate::traits::*;
-use crate::MemFlags;
-
-use rustc_middle::mir;
+use arrayvec::ArrayVec;
+use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt};
-use rustc_middle::{bug, span_bug};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::{bug, mir, span_bug};
use rustc_session::config::OptLevel;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{self, FieldIdx, FIRST_VARIANT};
-
-use arrayvec::ArrayVec;
use tracing::{debug, instrument};
+use super::operand::{OperandRef, OperandValue};
+use super::place::PlaceRef;
+use super::{FunctionCx, LocalRef};
+use crate::common::IntPredicate;
+use crate::traits::*;
+use crate::{base, MemFlags};
+
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
#[instrument(level = "trace", skip(self, bx))]
pub fn codegen_rvalue(
@@ -223,7 +222,7 @@ fn codegen_transmute_operand(
match operand.val {
OperandValue::Ref(source_place_val) => {
assert_eq!(source_place_val.llextra, None);
- assert!(matches!(operand_kind, OperandValueKind::Ref));
+ assert_matches!(operand_kind, OperandValueKind::Ref);
Some(bx.load_operand(source_place_val.with_type(cast)).val)
}
OperandValue::ZeroSized => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 27494f4..2ef860f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -3,8 +3,7 @@
use rustc_session::config::OptLevel;
use tracing::instrument;
-use super::FunctionCx;
-use super::LocalRef;
+use super::{FunctionCx, LocalRef};
use crate::traits::*;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index 559ec40..64fcefd 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -1,16 +1,14 @@
-use crate::base;
-use crate::common;
-use crate::traits::*;
use rustc_hir as hir;
use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::span_bug;
-use rustc_middle::ty;
+use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::Instance;
+use rustc_middle::{span_bug, ty};
use tracing::debug;
+use crate::traits::*;
+use crate::{base, common};
+
pub trait MonoItemExt<'a, 'tcx> {
fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs
index 130fe2e..933904f 100644
--- a/compiler/rustc_codegen_ssa/src/size_of_val.rs
+++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs
@@ -1,9 +1,5 @@
//! Computing the size and alignment of a value.
-use crate::common;
-use crate::common::IntPredicate;
-use crate::meth;
-use crate::traits::*;
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
@@ -11,6 +7,10 @@
use rustc_target::abi::WrappingRange;
use tracing::{debug, trace};
+use crate::common::IntPredicate;
+use crate::traits::*;
+use crate::{common, meth};
+
pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
t: Ty<'tcx>,
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index e7cee52..cf8f7fa 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -1,26 +1,25 @@
-use crate::errors;
use rustc_ast::ast;
use rustc_attr::InstructionSetAttr;
use rustc_data_structures::fx::FxIndexSet;
-use rustc_data_structures::unord::UnordMap;
+use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::Applicability;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_middle::bug;
+use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
-use rustc_span::symbol::sym;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
+use crate::errors;
+
pub fn from_target_feature(
tcx: TyCtxt<'_>,
attr: &ast::Attribute,
supported_target_features: &UnordMap<String, Option<Symbol>>,
- target_features: &mut Vec<Symbol>,
+ target_features: &mut Vec<TargetFeature>,
) {
let Some(list) = attr.meta_item_list() else { return };
let bad_item = |span| {
@@ -32,6 +31,7 @@ pub fn from_target_feature(
.emit();
};
let rust_features = tcx.features();
+ let mut added_target_features = Vec::new();
for item in list {
// Only `enable = ...` is accepted in the meta-item list.
if !item.has_name(sym::enable) {
@@ -46,7 +46,7 @@ pub fn from_target_feature(
};
// We allow comma separation to enable multiple features.
- target_features.extend(value.as_str().split(',').filter_map(|feature| {
+ added_target_features.extend(value.as_str().split(',').filter_map(|feature| {
let Some(feature_gate) = supported_target_features.get(feature) else {
let msg = format!("the feature named `{feature}` is not valid for this target");
let mut err = tcx.dcx().struct_span_err(item.span(), msg);
@@ -80,6 +80,7 @@ pub fn from_target_feature(
Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature,
Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature,
Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature,
+ Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86,
Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics,
Some(sym::xop_target_feature) => rust_features.xop_target_feature,
Some(sym::s390x_target_feature) => rust_features.s390x_target_feature,
@@ -98,6 +99,27 @@ pub fn from_target_feature(
Some(Symbol::intern(feature))
}));
}
+
+ // Add explicit features
+ target_features.extend(
+ added_target_features.iter().copied().map(|name| TargetFeature { name, implied: false }),
+ );
+
+ // Add implied features
+ let mut implied_target_features = UnordSet::new();
+ for feature in added_target_features.iter() {
+ implied_target_features.extend(tcx.implied_target_features(*feature).clone());
+ }
+ for feature in added_target_features.iter() {
+ implied_target_features.remove(feature);
+ }
+ target_features.extend(
+ implied_target_features
+ .into_sorted_stable_ord()
+ .iter()
+ .copied()
+ .map(|name| TargetFeature { name, implied: true }),
+ )
}
/// Computes the set of target features used in a function for the purposes of
@@ -106,7 +128,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
let mut target_features = tcx.sess.unstable_target_features.clone();
if tcx.def_kind(did).has_codegen_attrs() {
let attrs = tcx.codegen_fn_attrs(did);
- target_features.extend(&attrs.target_features);
+ target_features.extend(attrs.target_features.iter().map(|feature| feature.name));
match attrs.instruction_set {
None => {}
Some(InstructionSetAttr::ArmA32) => {
@@ -151,10 +173,14 @@ pub(crate) fn provide(providers: &mut Providers) {
.target
.supported_target_features()
.iter()
- .map(|&(a, b)| (a.to_string(), b.as_feature_name()))
+ .map(|&(a, b, _)| (a.to_string(), b.as_feature_name()))
.collect()
}
},
+ implied_target_features: |tcx, feature| {
+ UnordSet::from(tcx.sess.target.implied_target_features(std::iter::once(feature)))
+ .into_sorted_stable_ord()
+ },
asm_target_features,
..*providers
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs
index 8d67b62..162141a 100644
--- a/compiler/rustc_codegen_ssa/src/traits/asm.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs
@@ -1,12 +1,13 @@
-use super::BackendTypes;
-use crate::mir::operand::OperandRef;
-use crate::mir::place::PlaceRef;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::def_id::DefId;
use rustc_middle::ty::Instance;
use rustc_span::Span;
use rustc_target::asm::InlineAsmRegOrRegClass;
+use super::BackendTypes;
+use crate::mir::operand::OperandRef;
+use crate::mir::place::PlaceRef;
+
#[derive(Debug)]
pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
In {
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 3770bd1..81e9641 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -1,10 +1,5 @@
use std::any::Any;
-use super::write::WriteBackendMethods;
-use super::CodegenObject;
-use crate::back::write::TargetMachineFactoryFn;
-use crate::{CodegenResults, ModuleCodegen};
-
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::{DynSend, DynSync};
@@ -15,13 +10,16 @@
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::util::Providers;
-use rustc_session::{
- config::{self, OutputFilenames, PrintRequest},
- Session,
-};
+use rustc_session::config::{self, OutputFilenames, PrintRequest};
+use rustc_session::Session;
use rustc_span::symbol::Symbol;
use rustc_target::abi::call::FnAbi;
+use super::write::WriteBackendMethods;
+use super::CodegenObject;
+use crate::back::write::TargetMachineFactoryFn;
+use crate::{CodegenResults, ModuleCodegen};
+
pub trait BackendTypes {
type Value: CodegenObject;
type Function: CodegenObject;
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 42980d9..6cf84a0 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -1,19 +1,4 @@
-use super::abi::AbiBuilderMethods;
-use super::asm::AsmBuilderMethods;
-use super::consts::ConstMethods;
-use super::coverageinfo::CoverageInfoBuilderMethods;
-use super::debuginfo::DebugInfoBuilderMethods;
-use super::intrinsic::IntrinsicCallMethods;
-use super::misc::MiscMethods;
-use super::type_::{ArgAbiMethods, BaseTypeMethods, LayoutTypeMethods};
-use super::{HasCodegen, StaticBuilderMethods};
-
-use crate::common::{
- AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
-};
-use crate::mir::operand::{OperandRef, OperandValue};
-use crate::mir::place::{PlaceRef, PlaceValue};
-use crate::MemFlags;
+use std::assert_matches::assert_matches;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
@@ -24,7 +9,23 @@
use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
use rustc_target::spec::HasTargetSpec;
-#[derive(Copy, Clone)]
+use super::abi::AbiBuilderMethods;
+use super::asm::AsmBuilderMethods;
+use super::consts::ConstMethods;
+use super::coverageinfo::CoverageInfoBuilderMethods;
+use super::debuginfo::DebugInfoBuilderMethods;
+use super::intrinsic::IntrinsicCallMethods;
+use super::misc::MiscMethods;
+use super::type_::{ArgAbiMethods, BaseTypeMethods, LayoutTypeMethods};
+use super::{HasCodegen, StaticBuilderMethods};
+use crate::common::{
+ AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
+};
+use crate::mir::operand::{OperandRef, OperandValue};
+use crate::mir::place::{PlaceRef, PlaceValue};
+use crate::MemFlags;
+
+#[derive(Copy, Clone, Debug)]
pub enum OverflowOp {
Add,
Sub,
@@ -255,10 +256,10 @@ fn cast_float_to_int(
} else {
(in_ty, dest_ty)
};
- assert!(matches!(
+ assert_matches!(
self.cx().type_kind(float_ty),
TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128
- ));
+ );
assert_eq!(self.cx().type_kind(int_ty), TypeKind::Integer);
if let Some(false) = self.cx().sess().opts.unstable_opts.saturating_float_casts {
diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs
index 3da7326..c15f1fa 100644
--- a/compiler/rustc_codegen_ssa/src/traits/consts.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs
@@ -1,7 +1,8 @@
-use super::BackendTypes;
use rustc_middle::mir::interpret::{ConstAllocation, Scalar};
use rustc_target::abi;
+use super::BackendTypes;
+
pub trait ConstMethods<'tcx>: BackendTypes {
// Constant constructors
fn const_null(&self, t: Self::Type) -> Self::Value;
@@ -29,6 +30,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
fn const_str(&self, s: &str) -> (Self::Value, Self::Value);
fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;
+ fn const_vector(&self, elts: &[Self::Value]) -> Self::Value;
fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>;
fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>;
diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs
index 906d8b8..0b1645c 100644
--- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs
@@ -1,7 +1,8 @@
-use super::BackendTypes;
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::ty::Instance;
+use super::BackendTypes;
+
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
/// Performs any start-of-function codegen needed for coverage instrumentation.
///
diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
index 4acc0ea..31104e5 100644
--- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
@@ -1,12 +1,13 @@
-use super::BackendTypes;
-use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
+use std::ops::Range;
+
use rustc_middle::mir;
use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
use rustc_span::{SourceFile, Span, Symbol};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::Size;
-use std::ops::Range;
+use super::BackendTypes;
+use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
pub trait DebugInfoMethods<'tcx>: BackendTypes {
fn create_vtable_debuginfo(
diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs
index 655afcd..792d2b0 100644
--- a/compiler/rustc_codegen_ssa/src/traits/declare.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs
@@ -1,8 +1,9 @@
-use super::BackendTypes;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::Instance;
+use super::BackendTypes;
+
pub trait PreDefineMethods<'tcx>: BackendTypes {
fn predefine_static(
&self,
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 502f0b3..172004a 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -1,9 +1,10 @@
-use super::BackendTypes;
-use crate::mir::operand::OperandRef;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_target::abi::call::FnAbi;
+use super::BackendTypes;
+use crate::mir::operand::OperandRef;
+
pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
/// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
/// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs
index 0ace28e..40a49b3 100644
--- a/compiler/rustc_codegen_ssa/src/traits/misc.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs
@@ -1,9 +1,11 @@
-use super::BackendTypes;
+use std::cell::RefCell;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_session::Session;
-use std::cell::RefCell;
+
+use super::BackendTypes;
pub trait MiscMethods<'tcx>: BackendTypes {
fn vtables(
diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs
index 8cb58bd..9ac923b 100644
--- a/compiler/rustc_codegen_ssa/src/traits/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs
@@ -28,6 +28,11 @@
mod type_;
mod write;
+use std::fmt;
+
+use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt};
+use rustc_target::spec::HasTargetSpec;
+
pub use self::abi::AbiBuilderMethods;
pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
@@ -45,11 +50,6 @@
};
pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt};
-use rustc_target::spec::HasTargetSpec;
-
-use std::fmt;
-
pub trait CodegenObject: Copy + PartialEq + fmt::Debug {}
impl<T: Copy + PartialEq + fmt::Debug> CodegenObject for T {}
diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs
index 737d93f..b418199 100644
--- a/compiler/rustc_codegen_ssa/src/traits/statics.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs
@@ -1,7 +1,8 @@
-use super::BackendTypes;
use rustc_hir::def_id::DefId;
use rustc_target::abi::Align;
+use super::BackendTypes;
+
pub trait StaticMethods: BackendTypes {
fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
fn codegen_static(&self, def_id: DefId);
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index b1bad6c..7c042c0 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -1,14 +1,14 @@
-use super::misc::MiscMethods;
-use super::Backend;
-use super::HasCodegen;
-use crate::common::TypeKind;
-use crate::mir::place::PlaceRef;
use rustc_middle::bug;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Ty};
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
use rustc_target::abi::{AddressSpace, Float, Integer};
+use super::misc::MiscMethods;
+use super::{Backend, HasCodegen};
+use crate::common::TypeKind;
+use crate::mir::place::PlaceRef;
+
// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
@@ -91,7 +91,7 @@ fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
return false;
}
- let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env);
+ let tail = self.tcx().struct_tail_for_codegen(ty, param_env);
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index f4b1421..aabe9e3 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -1,10 +1,10 @@
+use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_middle::dep_graph::WorkProduct;
+
use crate::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig};
use crate::{CompiledModule, ModuleCodegen};
-use rustc_errors::{DiagCtxtHandle, FatalError};
-use rustc_middle::dep_graph::WorkProduct;
-
pub trait WriteBackendMethods: 'static + Sized + Clone {
type Module: Send + Sync;
type TargetMachine;
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index cd26981..1442f18 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -41,13 +41,15 @@
*[other] {""}
}
+const_eval_const_stable = const-stable functions can only call other const-stable functions
+
const_eval_copy_nonoverlapping_overlapping =
`copy_nonoverlapping` called on overlapping ranges
const_eval_dangling_int_pointer =
- {$bad_pointer_message}: {$pointer} is a dangling pointer (it has no provenance)
+ {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} which is a dangling pointer (it has no provenance)
const_eval_dangling_null_pointer =
- {$bad_pointer_message}: null pointer is a dangling pointer (it has no provenance)
+ {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got a null pointer
const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind}
const_eval_dead_local =
@@ -87,6 +89,21 @@
const_eval_exact_div_has_remainder =
exact_div: {$a} cannot be divided by {$b} without remainder
+const_eval_expected_inbounds_pointer =
+ expected a pointer to {$inbounds_size_abs ->
+ [0] some allocation
+ *[x] {$inbounds_size_is_neg ->
+ [false] {$inbounds_size_abs ->
+ [1] 1 byte of memory
+ *[x] {$inbounds_size_abs} bytes of memory
+ }
+ *[true] the end of {$inbounds_size_abs ->
+ [1] 1 byte of memory
+ *[x] {$inbounds_size_abs} bytes of memory
+ }
+ }
+ }
+
const_eval_extern_static =
cannot access extern static ({$did})
const_eval_extern_type_field = `extern type` field does not have a known offset
@@ -186,6 +203,9 @@
const_eval_invalid_vtable_trait =
using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected
+const_eval_lazy_lock =
+ consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
+
const_eval_live_drop =
destructor of `{$dropped_ty}` cannot be evaluated at compile-time
.label = the destructor for this type cannot be evaluated in {const_eval_const_context}s
@@ -233,16 +253,17 @@
const_eval_offset_from_different_allocations =
`{$name}` called on pointers into different allocations
-const_eval_offset_from_different_integers =
- `{$name}` called on different pointers without provenance (i.e., without an associated allocation)
const_eval_offset_from_overflow =
`{$name}` called when first pointer is too far ahead of second
const_eval_offset_from_test =
- out-of-bounds `offset_from`
+ out-of-bounds `offset_from` origin
const_eval_offset_from_underflow =
`{$name}` called when first pointer is too far before second
const_eval_offset_from_unsigned_overflow =
- `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
+ `ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr ->
+ [true] address
+ *[false] offset
+ } than second: {$a_offset} < {$b_offset}
const_eval_operator_non_const =
cannot call non-const operator in {const_eval_const_context}s
@@ -261,13 +282,26 @@
const_eval_partial_pointer_overwrite =
unable to overwrite parts of a pointer in memory at {$ptr}
const_eval_pointer_arithmetic_overflow =
- overflowing in-bounds pointer arithmetic
+ overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
const_eval_pointer_out_of_bounds =
- {$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer to {$ptr_size} {$ptr_size ->
- [1] byte
- *[many] bytes
- } starting at offset {$ptr_offset} is out-of-bounds
+ {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
+ [true] which points to before the beginning of the allocation
+ *[false] {$inbounds_size_is_neg ->
+ [true] {$ptr_offset_abs ->
+ [0] which is at the beginning of the allocation
+ *[other] which does not have enough space to the beginning of the allocation
+ }
+ *[false] {$alloc_size_minus_ptr_offset ->
+ [0] which is at or beyond the end of the allocation of size {$alloc_size ->
+ [1] 1 byte
+ *[x] {$alloc_size} bytes
+ }
+ [1] which is only 1 byte from the end of the allocation
+ *[x] which is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
+ }
+ }
+ }
const_eval_pointer_use_after_free =
{$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling
const_eval_ptr_as_bytes_1 =
@@ -287,9 +321,6 @@
const_eval_range_wrapping = less or equal to {$hi}, or greater or equal to {$lo}
const_eval_raw_bytes = the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"}
-const_eval_raw_eq_with_provenance =
- `raw_eq` on bytes with provenance
-
const_eval_raw_ptr_comparison =
pointers cannot be reliably compared during const eval
.note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
@@ -465,5 +496,3 @@
const_eval_write_to_read_only =
writing to {$allocation} which is read-only
-const_eval_zst_pointer_out_of_bounds =
- {$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer at offset {$ptr_offset} is out-of-bounds
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 8700ec4..844f3f3 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -1,5 +1,9 @@
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
+use std::assert_matches::assert_matches;
+use std::mem;
+use std::ops::Deref;
+
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
@@ -9,17 +13,13 @@
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::span_bug;
-use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
-use rustc_middle::ty::{Instance, InstanceKind, TypeVisitableExt};
+use rustc_middle::ty::adjustment::PointerCoercion;
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeVisitableExt};
use rustc_mir_dataflow::Analysis;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitor};
-
-use std::mem;
-use std::ops::Deref;
-
use tracing::{debug, instrument, trace};
use super::ops::{self, NonConstOp, Status};
@@ -591,7 +591,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
if is_int_bool_or_char(lhs_ty) && is_int_bool_or_char(rhs_ty) {
// Int, bool, and char operations are fine.
} else if lhs_ty.is_fn_ptr() || lhs_ty.is_unsafe_ptr() {
- assert!(matches!(
+ assert_matches!(
op,
BinOp::Eq
| BinOp::Ne
@@ -600,7 +600,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
| BinOp::Ge
| BinOp::Gt
| BinOp::Offset
- ));
+ );
self.check_op(ops::RawPtrComparison);
} else if lhs_ty.is_floating_point() || rhs_ty.is_floating_point() {
@@ -635,10 +635,7 @@ fn visit_projection_elem(
trace!(
"visit_projection_elem: place_ref={:?} elem={:?} \
context={:?} location={:?}",
- place_ref,
- elem,
- context,
- location,
+ place_ref, elem, context, location,
);
self.super_projection_elem(place_ref, elem, context, location);
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index ac8f0d8..15ac4ce 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -4,14 +4,12 @@
//! has interior mutability or needs to be dropped, as well as the visitor that emits errors when
//! it finds operations that are invalid in a certain context.
-use rustc_attr as attr;
use rustc_errors::DiagCtxtHandle;
-use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::ty::{self, PolyFnSig, TyCtxt};
+use rustc_middle::{bug, mir};
use rustc_span::Symbol;
+use {rustc_attr as attr, rustc_hir as hir};
pub use self::qualifs::Qualif;
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 55432e6..c636171 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -2,7 +2,8 @@
use hir::def_id::LocalDefId;
use hir::{ConstContext, LangItem};
-use rustc_errors::{codes::*, Diag};
+use rustc_errors::codes::*;
+use rustc_errors::Diag;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
@@ -22,7 +23,7 @@
use tracing::debug;
use super::ConstCx;
-use crate::errors;
+use crate::{errors, fluent_generated};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Status {
@@ -309,7 +310,7 @@ macro_rules! error {
}
if let ConstContext::Static(_) = ccx.const_kind() {
- err.note("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`");
+ err.note(fluent_generated::const_eval_lazy_lock);
}
err
@@ -333,7 +334,7 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
// FIXME: make this translatable
#[allow(rustc::untranslatable_diagnostic)]
if ccx.is_const_stable_const_fn() {
- err.help("const-stable functions can only call other const-stable functions");
+ err.help(fluent_generated::const_eval_const_stable);
} else if ccx.tcx.sess.is_nightly_build() {
if let Some(feature) = feature {
err.help(format!("add `#![feature({feature})]` to the crate attributes to enable"));
@@ -604,8 +605,6 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
span,
format!("referencing statics in {}s is unstable", ccx.const_kind(),),
);
- // FIXME: make this translatable
- #[allow(rustc::untranslatable_diagnostic)]
err
.note("`static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.")
.help("to fix this, the value can be extracted to a `const` and then used.");
diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
index f5e7454..c4f06e5 100644
--- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs
@@ -1,7 +1,8 @@
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_span::{symbol::sym, Span};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
use tracing::trace;
use super::check::Qualifs;
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
index d5d3f77..c0f2d11 100644
--- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -5,11 +5,10 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::mir::*;
use rustc_middle::traits::BuiltinImplSource;
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
+use rustc_middle::{bug, mir};
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
};
diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs
index 0113414..ea3a526 100644
--- a/compiler/rustc_const_eval/src/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs
@@ -2,17 +2,16 @@
//!
//! This contains the dataflow analysis used to track `Qualif`s on complex control-flow graphs.
+use std::fmt;
+use std::marker::PhantomData;
+
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges,
};
use rustc_mir_dataflow::fmt::DebugWithContext;
-use rustc_mir_dataflow::JoinSemiLattice;
-use rustc_mir_dataflow::{Analysis, AnalysisDomain};
-
-use std::fmt;
-use std::marker::PhantomData;
+use rustc_mir_dataflow::{Analysis, AnalysisDomain, JoinSemiLattice};
use super::{qualifs, ConstCx, Qualif};
diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
index 9a98677..aa7449e 100644
--- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
@@ -1,14 +1,14 @@
-use crate::interpret::{
- self, throw_machine_stop, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic,
-};
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult};
use rustc_middle::mir::*;
use rustc_middle::query::TyCtxtAt;
-use rustc_middle::ty;
use rustc_middle::ty::layout::TyAndLayout;
-use rustc_middle::{bug, span_bug};
+use rustc_middle::{bug, span_bug, ty};
use rustc_span::def_id::DefId;
+use crate::interpret::{
+ self, throw_machine_stop, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic,
+};
+
/// Macro for machine-specific `InterpError` without allocation.
/// (These will never be shown to the user, but they help diagnose ICEs.)
pub macro throw_machine_stop_str($($tt:tt)*) {{
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index b17dc7f..00bbd93 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -4,14 +4,15 @@
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
use rustc_middle::mir::AssertKind;
use rustc_middle::query::TyCtxtAt;
-use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::{layout::LayoutError, ConstInt};
+use rustc_middle::ty::layout::LayoutError;
+use rustc_middle::ty::{ConstInt, TyCtxt};
use rustc_span::{Span, Symbol};
use super::CompileTimeMachine;
use crate::errors::{self, FrameNote, ReportErrorExt};
-use crate::interpret::{err_inval, err_machine_stop};
-use crate::interpret::{ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType};
+use crate::interpret::{
+ err_inval, err_machine_stop, ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType,
+};
/// The CTFE machine has some custom error kinds.
#[derive(Clone, Debug)]
@@ -25,8 +26,9 @@ pub enum ConstEvalErrKind {
impl MachineStopType for ConstEvalErrKind {
fn diagnostic_message(&self) -> DiagMessage {
- use crate::fluent_generated::*;
use ConstEvalErrKind::*;
+
+ use crate::fluent_generated::*;
match self {
ConstAccessesMutGlobal => const_eval_const_accesses_mut_global,
ModifiedGlobal => const_eval_modified_global,
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index d8efaa6..96b3ec6 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,8 +1,6 @@
use std::sync::atomic::Ordering::Relaxed;
use either::{Left, Right};
-use tracing::{debug, instrument, trace};
-
use rustc_hir::def::DefKind;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
@@ -16,17 +14,16 @@
use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{self, Abi};
+use tracing::{debug, instrument, trace};
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
use crate::const_eval::CheckAlignment;
-use crate::errors::ConstEvalError;
-use crate::errors::{self, DanglingPtrInFinal};
+use crate::errors::{self, ConstEvalError, DanglingPtrInFinal};
use crate::interpret::{
- create_static_alloc, intern_const_alloc_recursive, CtfeValidationMode, GlobalId, Immediate,
- InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
- StackPopCleanup,
+ create_static_alloc, eval_nullary_intrinsic, intern_const_alloc_recursive, throw_exhaust,
+ CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError,
+ InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup,
};
-use crate::interpret::{eval_nullary_intrinsic, throw_exhaust, InternResult};
use crate::CTRL_C_RECEIVED;
// Returns a pointer to where the result lives
@@ -76,7 +73,9 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
);
- ecx.push_stack_frame(
+ // This can't use `init_stack_frame` since `body` is not a function,
+ // so computing its ABI would fail. It's also not worth it since there are no arguments to pass.
+ ecx.push_stack_frame_raw(
cid.instance,
body,
&ret.clone().into(),
@@ -227,7 +226,7 @@ pub(super) fn op_to_const<'tcx>(
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
debug_assert!(
matches!(
- ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(),
+ ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.param_env).kind(),
ty::Str | ty::Slice(..),
),
"`ConstValue::Slice` is for slice-tailed types only, but got {}",
@@ -399,7 +398,7 @@ fn const_validate_mplace<'tcx>(
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
let mut ref_tracking = RefTracking::new(mplace.clone());
let mut inner = false;
- while let Some((mplace, path)) = ref_tracking.todo.pop() {
+ while let Some((mplace, path)) = ref_tracking.next() {
let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) {
_ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 7acd08e..ca0993f 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -1,10 +1,9 @@
-use rustc_attr as attr;
-use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
+use {rustc_attr as attr, rustc_hir as hir};
/// Whether the `def_id` is an unstable const fn and what feature gate(s) are necessary to enable
/// it.
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 17e1d85..a075bdc 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -4,18 +4,14 @@
use std::ops::ControlFlow;
use rustc_ast::Mutability;
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::fx::IndexEntry;
-use rustc_hir::def_id::DefId;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::LangItem;
-use rustc_hir::{self as hir, CRATE_HIR_ID};
-use rustc_middle::bug;
-use rustc_middle::mir;
+use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, LangItem, CRATE_HIR_ID};
use rustc_middle::mir::AssertMessage;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::{bug, mir};
use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
@@ -23,16 +19,16 @@
use rustc_target::spec::abi::Abi as CallAbi;
use tracing::debug;
+use super::error::*;
use crate::errors::{LongRunning, LongRunningWarn};
use crate::fluent_generated as fluent;
use crate::interpret::{
self, compile_time_machine, err_ub, throw_exhaust, throw_inval, throw_ub_custom, throw_unsup,
- throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal, Frame,
+ throw_unsup_format, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame,
GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar,
+ StackPopCleanup,
};
-use super::error::*;
-
/// When hitting this many interpreted terminators we emit a deny by default lint
/// that notfies the user that their constant takes a long time to evaluate. If that's
/// what they intended, they can just allow the lint.
@@ -201,7 +197,8 @@ fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
- use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+ use rustc_session::config::RemapPathScopeComponents;
+ use rustc_session::RemapFileNameExt;
(
Symbol::intern(
&caller
@@ -299,7 +296,7 @@ fn align_offset(
);
}
- match self.ptr_try_get_alloc_id(ptr) {
+ match self.ptr_try_get_alloc_id(ptr, 0) {
Ok((alloc_id, offset, _extra)) => {
let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id);
@@ -310,17 +307,15 @@ fn align_offset(
let align = ImmTy::from_uint(target_align, args[1].layout).into();
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
- // We replace the entire function call with a "tail call".
- // Note that this happens before the frame of the original function
- // is pushed on the stack.
- self.eval_fn_call(
- FnVal::Instance(instance),
- (CallAbi::Rust, fn_abi),
+ // Push the stack frame with our own adjusted arguments.
+ self.init_stack_frame(
+ instance,
+ self.load_mir(instance.def, None)?,
+ fn_abi,
&[FnArg::Copy(addr), FnArg::Copy(align)],
/* with_caller_location = */ false,
dest,
- ret,
- mir::UnwindAction::Unreachable,
+ StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Unreachable },
)?;
Ok(ControlFlow::Break(()))
} else {
@@ -462,7 +457,7 @@ fn call_intrinsic(
_unwind: mir::UnwindAction,
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
// Shared intrinsics.
- if ecx.emulate_intrinsic(instance, args, dest, target)? {
+ if ecx.eval_intrinsic(instance, args, dest, target)? {
return Ok(None);
}
let intrinsic_name = ecx.tcx.item_name(instance.def_id());
@@ -514,7 +509,7 @@ fn call_intrinsic(
// If an allocation is created in an another const,
// we don't deallocate it.
- let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr, 0)?;
let is_allocated_in_another_const = matches!(
ecx.tcx.try_get_global_alloc(alloc_id),
Some(interpret::GlobalAlloc::Memory(_))
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 3a6dc81..8add23e 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -1,10 +1,9 @@
// Not in interpret to make sure we do not use private implementation details
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::mir::interpret::InterpErrorInfo;
use rustc_middle::query::{Key, TyCtxtAt};
use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::{bug, mir};
use rustc_target::abi::VariantIdx;
use tracing::instrument;
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index 3bc0151..460c979 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -1,9 +1,8 @@
use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
+use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, VariantIdx};
use tracing::{debug, instrument, trace};
@@ -13,10 +12,9 @@
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
use crate::const_eval::CanAccessMutGlobal;
use crate::errors::MaxNumNodesInConstErr;
-use crate::interpret::MPlaceTy;
use crate::interpret::{
- intern_const_alloc_recursive, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy,
- Projectable, Scalar,
+ intern_const_alloc_recursive, ImmTy, Immediate, InternKind, MPlaceTy, MemPlaceMeta, MemoryKind,
+ PlaceTy, Projectable, Scalar,
};
#[instrument(skip(ecx), level = "debug")]
@@ -197,7 +195,7 @@ fn reconstruct_place_meta<'tcx>(
let mut last_valtree = valtree;
// Traverse the type, and update `last_valtree` as we go.
- let tail = tcx.struct_tail_with_normalize(
+ let tail = tcx.struct_tail_raw(
layout.ty,
|ty| ty,
|| {
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 292d6ba..7afb92c 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,20 +1,22 @@
use std::borrow::Cow;
+use std::fmt::Write;
use either::Either;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
+ Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level,
};
use rustc_hir::ConstContext;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::mir::interpret::{
- CheckInAllocMsg, ExpectedKind, InterpError, InvalidMetaKind, InvalidProgramInfo, Misalignment,
- PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
- ValidationErrorInfo,
+ CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpError, InvalidMetaKind,
+ InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
+ UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
};
use rustc_middle::ty::{self, Mutability, Ty};
use rustc_span::Span;
use rustc_target::abi::call::AdjustForForeignAbiError;
-use rustc_target::abi::{Size, WrappingRange};
+use rustc_target::abi::WrappingRange;
use crate::interpret::InternKind;
@@ -468,8 +470,9 @@ fn bad_pointer_message(msg: CheckInAllocMsg, dcx: DiagCtxtHandle<'_>) -> String
impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
fn diagnostic_message(&self) -> DiagMessage {
- use crate::fluent_generated::*;
use UndefinedBehaviorInfo::*;
+
+ use crate::fluent_generated::*;
match self {
Ub(msg) => msg.clone().into(),
Custom(x) => (x.msg)(),
@@ -488,10 +491,9 @@ fn diagnostic_message(&self) -> DiagMessage {
InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
UnterminatedCString(_) => const_eval_unterminated_c_string,
PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free,
- PointerOutOfBounds { ptr_size: Size::ZERO, .. } => const_eval_zst_pointer_out_of_bounds,
PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds,
- DanglingIntPointer(0, _) => const_eval_dangling_null_pointer,
- DanglingIntPointer(_, _) => const_eval_dangling_int_pointer,
+ DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer,
+ DanglingIntPointer { .. } => const_eval_dangling_int_pointer,
AlignmentCheckFailed { .. } => const_eval_alignment_check_failed,
WriteToReadOnly(_) => const_eval_write_to_read_only,
DerefFunctionPointer(_) => const_eval_deref_function_pointer,
@@ -573,18 +575,37 @@ fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
diag.arg("alloc_id", alloc_id)
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
}
- PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => {
- diag.arg("alloc_id", alloc_id)
- .arg("alloc_size", alloc_size.bytes())
- .arg("ptr_offset", ptr_offset)
- .arg("ptr_size", ptr_size.bytes())
- .arg("bad_pointer_message", bad_pointer_message(msg, dcx));
+ PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
+ diag.arg("alloc_size", alloc_size.bytes());
+ diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
+ diag.arg("pointer", {
+ let mut out = format!("{:?}", alloc_id);
+ if ptr_offset > 0 {
+ write!(out, "+{:#x}", ptr_offset).unwrap();
+ } else if ptr_offset < 0 {
+ write!(out, "-{:#x}", ptr_offset.unsigned_abs()).unwrap();
+ }
+ out
+ });
+ diag.arg("inbounds_size_is_neg", inbounds_size < 0);
+ diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
+ diag.arg("ptr_offset_is_neg", ptr_offset < 0);
+ diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs());
+ diag.arg(
+ "alloc_size_minus_ptr_offset",
+ alloc_size.bytes().saturating_sub(ptr_offset as u64),
+ );
}
- DanglingIntPointer(ptr, msg) => {
- if ptr != 0 {
- diag.arg("pointer", format!("{ptr:#x}[noalloc]"));
+ DanglingIntPointer { addr, inbounds_size, msg } => {
+ if addr != 0 {
+ diag.arg(
+ "pointer",
+ Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
+ );
}
+ diag.arg("inbounds_size_is_neg", inbounds_size < 0);
+ diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs());
diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
}
AlignmentCheckFailed(Misalignment { required, has }, msg) => {
@@ -630,8 +651,9 @@ fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
fn diagnostic_message(&self) -> DiagMessage {
- use crate::fluent_generated::*;
use rustc_middle::mir::interpret::ValidationErrorKind::*;
+
+ use crate::fluent_generated::*;
match self.kind {
PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => {
const_eval_validation_box_to_uninhabited
@@ -702,9 +724,10 @@ fn diagnostic_message(&self) -> DiagMessage {
}
fn add_args<G: EmissionGuarantee>(self, err: &mut Diag<'_, G>) {
- use crate::fluent_generated as fluent;
use rustc_middle::mir::interpret::ValidationErrorKind::*;
+ use crate::fluent_generated as fluent;
+
if let PointerAsInt { .. } | PartialPointer = self.kind {
err.help(fluent::const_eval_ptr_as_bytes_1);
err.help(fluent::const_eval_ptr_as_bytes_2);
@@ -835,9 +858,9 @@ fn diagnostic_message(&self) -> DiagMessage {
}
}
fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
- use crate::fluent_generated::*;
-
use UnsupportedOpInfo::*;
+
+ use crate::fluent_generated::*;
if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self {
diag.help(const_eval_ptr_as_bytes_1);
diag.help(const_eval_ptr_as_bytes_2);
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
new file mode 100644
index 0000000..917a2fa
--- /dev/null
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -0,0 +1,976 @@
+//! Manages calling a concrete function (with known MIR body) with argument passing,
+//! and returning the return value to the caller.
+use std::assert_matches::assert_matches;
+use std::borrow::Cow;
+
+use either::{Left, Right};
+use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, AdtDef, Instance, Ty};
+use rustc_middle::{bug, mir, span_bug};
+use rustc_span::sym;
+use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
+use rustc_target::abi::{self, FieldIdx, Integer};
+use rustc_target::spec::abi::Abi;
+use tracing::{info, instrument, trace};
+
+use super::{
+ throw_ub, throw_ub_custom, throw_unsup_format, CtfeProvenance, FnVal, ImmTy, InterpCx,
+ InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Projectable, Provenance, ReturnAction, Scalar,
+ StackPopCleanup, StackPopInfo,
+};
+use crate::fluent_generated as fluent;
+
+/// An argment passed to a function.
+#[derive(Clone, Debug)]
+pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> {
+ /// Pass a copy of the given operand.
+ Copy(OpTy<'tcx, Prov>),
+ /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and
+ /// make the place inaccessible for the duration of the function call.
+ InPlace(MPlaceTy<'tcx, Prov>),
+}
+
+impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
+ pub fn layout(&self) -> &TyAndLayout<'tcx> {
+ match self {
+ FnArg::Copy(op) => &op.layout,
+ FnArg::InPlace(mplace) => &mplace.layout,
+ }
+ }
+}
+
+impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
+ /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
+ /// original memory occurs.
+ pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {
+ match arg {
+ FnArg::Copy(op) => op.clone(),
+ FnArg::InPlace(mplace) => mplace.clone().into(),
+ }
+ }
+
+ /// Make a copy of the given fn_args. Any `InPlace` are degenerated to copies, no protection of the
+ /// original memory occurs.
+ pub fn copy_fn_args(
+ &self,
+ args: &[FnArg<'tcx, M::Provenance>],
+ ) -> Vec<OpTy<'tcx, M::Provenance>> {
+ args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect()
+ }
+
+ /// Helper function for argument untupling.
+ pub(super) fn fn_arg_field(
+ &self,
+ arg: &FnArg<'tcx, M::Provenance>,
+ field: usize,
+ ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
+ Ok(match arg {
+ FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?),
+ FnArg::InPlace(mplace) => FnArg::InPlace(self.project_field(mplace, field)?),
+ })
+ }
+
+ /// Find the wrapped inner type of a transparent wrapper.
+ /// Must not be called on 1-ZST (as they don't have a uniquely defined "wrapped field").
+ ///
+ /// We work with `TyAndLayout` here since that makes it much easier to iterate over all fields.
+ fn unfold_transparent(
+ &self,
+ layout: TyAndLayout<'tcx>,
+ may_unfold: impl Fn(AdtDef<'tcx>) -> bool,
+ ) -> TyAndLayout<'tcx> {
+ match layout.ty.kind() {
+ ty::Adt(adt_def, _) if adt_def.repr().transparent() && may_unfold(*adt_def) => {
+ assert!(!adt_def.is_enum());
+ // Find the non-1-ZST field, and recurse.
+ let (_, field) = layout.non_1zst_field(self).unwrap();
+ self.unfold_transparent(field, may_unfold)
+ }
+ // Not a transparent type, no further unfolding.
+ _ => layout,
+ }
+ }
+
+ /// Unwrap types that are guaranteed a null-pointer-optimization
+ fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+ // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
+ // another type.
+ let ty::Adt(def, args) = layout.ty.kind() else {
+ // Not an ADT, so definitely no NPO.
+ return Ok(layout);
+ };
+ let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
+ // The wrapped type is the only arg.
+ self.layout_of(args[0].as_type().unwrap())?
+ } else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
+ // We want to extract which (if any) of the args is not a 1-ZST.
+ let lhs = self.layout_of(args[0].as_type().unwrap())?;
+ let rhs = self.layout_of(args[1].as_type().unwrap())?;
+ if lhs.is_1zst() {
+ rhs
+ } else if rhs.is_1zst() {
+ lhs
+ } else {
+ return Ok(layout); // no NPO
+ }
+ } else {
+ return Ok(layout); // no NPO
+ };
+
+ // Check if the inner type is one of the NPO-guaranteed ones.
+ // For that we first unpeel transparent *structs* (but not unions).
+ let is_npo = |def: AdtDef<'tcx>| {
+ self.tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed)
+ };
+ let inner = self.unfold_transparent(inner, /* may_unfold */ |def| {
+ // Stop at NPO tpyes so that we don't miss that attribute in the check below!
+ def.is_struct() && !is_npo(def)
+ });
+ Ok(match inner.ty.kind() {
+ ty::Ref(..) | ty::FnPtr(..) => {
+ // Option<&T> behaves like &T, and same for fn()
+ inner
+ }
+ ty::Adt(def, _) if is_npo(*def) => {
+ // Once we found a `nonnull_optimization_guaranteed` type, further strip off
+ // newtype structs from it to find the underlying ABI type.
+ self.unfold_transparent(inner, /* may_unfold */ |def| def.is_struct())
+ }
+ _ => {
+ // Everything else we do not unfold.
+ layout
+ }
+ })
+ }
+
+ /// Check if these two layouts look like they are fn-ABI-compatible.
+ /// (We also compare the `PassMode`, so this doesn't have to check everything. But it turns out
+ /// that only checking the `PassMode` is insufficient.)
+ fn layout_compat(
+ &self,
+ caller: TyAndLayout<'tcx>,
+ callee: TyAndLayout<'tcx>,
+ ) -> InterpResult<'tcx, bool> {
+ // Fast path: equal types are definitely compatible.
+ if caller.ty == callee.ty {
+ return Ok(true);
+ }
+ // 1-ZST are compatible with all 1-ZST (and with nothing else).
+ if caller.is_1zst() || callee.is_1zst() {
+ return Ok(caller.is_1zst() && callee.is_1zst());
+ }
+ // Unfold newtypes and NPO optimizations.
+ let unfold = |layout: TyAndLayout<'tcx>| {
+ self.unfold_npo(self.unfold_transparent(layout, /* may_unfold */ |_def| true))
+ };
+ let caller = unfold(caller)?;
+ let callee = unfold(callee)?;
+ // Now see if these inner types are compatible.
+
+ // Compatible pointer types. For thin pointers, we have to accept even non-`repr(transparent)`
+ // things as compatible due to `DispatchFromDyn`. For instance, `Rc<i32>` and `*mut i32`
+ // must be compatible. So we just accept everything with Pointer ABI as compatible,
+ // even if this will accept some code that is not stably guaranteed to work.
+ // This also handles function pointers.
+ let thin_pointer = |layout: TyAndLayout<'tcx>| match layout.abi {
+ abi::Abi::Scalar(s) => match s.primitive() {
+ abi::Primitive::Pointer(addr_space) => Some(addr_space),
+ _ => None,
+ },
+ _ => None,
+ };
+ if let (Some(caller), Some(callee)) = (thin_pointer(caller), thin_pointer(callee)) {
+ return Ok(caller == callee);
+ }
+ // For wide pointers we have to get the pointee type.
+ let pointee_ty = |ty: Ty<'tcx>| -> InterpResult<'tcx, Option<Ty<'tcx>>> {
+ // We cannot use `builtin_deref` here since we need to reject `Box<T, MyAlloc>`.
+ Ok(Some(match ty.kind() {
+ ty::Ref(_, ty, _) => *ty,
+ ty::RawPtr(ty, _) => *ty,
+ // We only accept `Box` with the default allocator.
+ _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
+ _ => return Ok(None),
+ }))
+ };
+ if let (Some(caller), Some(callee)) = (pointee_ty(caller.ty)?, pointee_ty(callee.ty)?) {
+ // This is okay if they have the same metadata type.
+ let meta_ty = |ty: Ty<'tcx>| {
+ // Even if `ty` is normalized, the search for the unsized tail will project
+ // to fields, which can yield non-normalized types. So we need to provide a
+ // normalization function.
+ let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty);
+ ty.ptr_metadata_ty(*self.tcx, normalize)
+ };
+ return Ok(meta_ty(caller) == meta_ty(callee));
+ }
+
+ // Compatible integer types (in particular, usize vs ptr-sized-u32/u64).
+ // `char` counts as `u32.`
+ let int_ty = |ty: Ty<'tcx>| {
+ Some(match ty.kind() {
+ ty::Int(ity) => (Integer::from_int_ty(&self.tcx, *ity), /* signed */ true),
+ ty::Uint(uty) => (Integer::from_uint_ty(&self.tcx, *uty), /* signed */ false),
+ ty::Char => (Integer::I32, /* signed */ false),
+ _ => return None,
+ })
+ };
+ if let (Some(caller), Some(callee)) = (int_ty(caller.ty), int_ty(callee.ty)) {
+ // This is okay if they are the same integer type.
+ return Ok(caller == callee);
+ }
+
+ // Fall back to exact equality.
+ // FIXME: We are missing the rules for "repr(C) wrapping compatible types".
+ Ok(caller == callee)
+ }
+
+ fn check_argument_compat(
+ &self,
+ caller_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+ callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+ ) -> InterpResult<'tcx, bool> {
+ // We do not want to accept things as ABI-compatible that just "happen to be" compatible on the current target,
+ // so we implement a type-based check that reflects the guaranteed rules for ABI compatibility.
+ if self.layout_compat(caller_abi.layout, callee_abi.layout)? {
+ // Ensure that our checks imply actual ABI compatibility for this concrete call.
+ assert!(caller_abi.eq_abi(callee_abi));
+ return Ok(true);
+ } else {
+ trace!(
+ "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
+ caller_abi, callee_abi
+ );
+ return Ok(false);
+ }
+ }
+
+ /// Initialize a single callee argument, checking the types for compatibility.
+ fn pass_argument<'x, 'y>(
+ &mut self,
+ caller_args: &mut impl Iterator<
+ Item = (&'x FnArg<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>),
+ >,
+ callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+ callee_arg: &mir::Place<'tcx>,
+ callee_ty: Ty<'tcx>,
+ already_live: bool,
+ ) -> InterpResult<'tcx>
+ where
+ 'tcx: 'x,
+ 'tcx: 'y,
+ {
+ assert_eq!(callee_ty, callee_abi.layout.ty);
+ if matches!(callee_abi.mode, PassMode::Ignore) {
+ // This one is skipped. Still must be made live though!
+ if !already_live {
+ self.storage_live(callee_arg.as_local().unwrap())?;
+ }
+ return Ok(());
+ }
+ // Find next caller arg.
+ let Some((caller_arg, caller_abi)) = caller_args.next() else {
+ throw_ub_custom!(fluent::const_eval_not_enough_caller_args);
+ };
+ assert_eq!(caller_arg.layout().layout, caller_abi.layout.layout);
+ // Sadly we cannot assert that `caller_arg.layout().ty` and `caller_abi.layout.ty` are
+ // equal; in closures the types sometimes differ. We just hope that `caller_abi` is the
+ // right type to print to the user.
+
+ // Check compatibility
+ if !self.check_argument_compat(caller_abi, callee_abi)? {
+ throw_ub!(AbiMismatchArgument {
+ caller_ty: caller_abi.layout.ty,
+ callee_ty: callee_abi.layout.ty
+ });
+ }
+ // We work with a copy of the argument for now; if this is in-place argument passing, we
+ // will later protect the source it comes from. This means the callee cannot observe if we
+ // did in-place of by-copy argument passing, except for pointer equality tests.
+ let caller_arg_copy = self.copy_fn_arg(caller_arg);
+ if !already_live {
+ let local = callee_arg.as_local().unwrap();
+ let meta = caller_arg_copy.meta();
+ // `check_argument_compat` ensures that if metadata is needed, both have the same type,
+ // so we know they will use the metadata the same way.
+ assert!(!meta.has_meta() || caller_arg_copy.layout.ty == callee_ty);
+
+ self.storage_live_dyn(local, meta)?;
+ }
+ // Now we can finally actually evaluate the callee place.
+ let callee_arg = self.eval_place(*callee_arg)?;
+ // We allow some transmutes here.
+ // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This
+ // is true for all `copy_op`, but there are a lot of special cases for argument passing
+ // specifically.)
+ self.copy_op_allow_transmute(&caller_arg_copy, &callee_arg)?;
+ // If this was an in-place pass, protect the place it comes from for the duration of the call.
+ if let FnArg::InPlace(mplace) = caller_arg {
+ M::protect_in_place_function_argument(self, mplace)?;
+ }
+ Ok(())
+ }
+
+ fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> {
+ // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
+ let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
+ if !self.tcx.sess.target.is_like_wasm
+ && attrs
+ .target_features
+ .iter()
+ .any(|feature| !self.tcx.sess.target_features.contains(&feature.name))
+ {
+ throw_ub_custom!(
+ fluent::const_eval_unavailable_target_features_for_fn,
+ unavailable_feats = attrs
+ .target_features
+ .iter()
+ .filter(|&feature| !feature.implied
+ && !self.tcx.sess.target_features.contains(&feature.name))
+ .fold(String::new(), |mut s, feature| {
+ if !s.is_empty() {
+ s.push_str(", ");
+ }
+ s.push_str(feature.name.as_str());
+ s
+ }),
+ );
+ }
+ Ok(())
+ }
+
+ /// The main entry point for creating a new stack frame: performs ABI checks and initializes
+ /// arguments.
+ #[instrument(skip(self), level = "trace")]
+ pub fn init_stack_frame(
+ &mut self,
+ instance: Instance<'tcx>,
+ body: &'tcx mir::Body<'tcx>,
+ caller_fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+ args: &[FnArg<'tcx, M::Provenance>],
+ with_caller_location: bool,
+ destination: &MPlaceTy<'tcx, M::Provenance>,
+ mut stack_pop: StackPopCleanup,
+ ) -> InterpResult<'tcx> {
+ // Compute callee information.
+ // FIXME: for variadic support, do we have to somehow determine callee's extra_args?
+ let callee_fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
+
+ if callee_fn_abi.c_variadic || caller_fn_abi.c_variadic {
+ throw_unsup_format!("calling a c-variadic function is not supported");
+ }
+
+ if M::enforce_abi(self) {
+ if caller_fn_abi.conv != callee_fn_abi.conv {
+ throw_ub_custom!(
+ fluent::const_eval_incompatible_calling_conventions,
+ callee_conv = format!("{:?}", callee_fn_abi.conv),
+ caller_conv = format!("{:?}", caller_fn_abi.conv),
+ )
+ }
+ }
+
+ // Check that all target features required by the callee (i.e., from
+ // the attribute `#[target_feature(enable = ...)]`) are enabled at
+ // compile time.
+ self.check_fn_target_features(instance)?;
+
+ if !callee_fn_abi.can_unwind {
+ // The callee cannot unwind, so force the `Unreachable` unwind handling.
+ match &mut stack_pop {
+ StackPopCleanup::Root { .. } => {}
+ StackPopCleanup::Goto { unwind, .. } => {
+ *unwind = mir::UnwindAction::Unreachable;
+ }
+ }
+ }
+
+ self.push_stack_frame_raw(instance, body, destination, stack_pop)?;
+
+ // If an error is raised here, pop the frame again to get an accurate backtrace.
+ // To this end, we wrap it all in a `try` block.
+ let res: InterpResult<'tcx> = try {
+ trace!(
+ "caller ABI: {:#?}, args: {:#?}",
+ caller_fn_abi,
+ args.iter()
+ .map(|arg| (
+ arg.layout().ty,
+ match arg {
+ FnArg::Copy(op) => format!("copy({op:?})"),
+ FnArg::InPlace(mplace) => format!("in-place({mplace:?})"),
+ }
+ ))
+ .collect::<Vec<_>>()
+ );
+ trace!(
+ "spread_arg: {:?}, locals: {:#?}",
+ body.spread_arg,
+ body.args_iter()
+ .map(|local| (
+ local,
+ self.layout_of_local(self.frame(), local, None).unwrap().ty,
+ ))
+ .collect::<Vec<_>>()
+ );
+
+ // In principle, we have two iterators: Where the arguments come from, and where
+ // they go to.
+
+ // The "where they come from" part is easy, we expect the caller to do any special handling
+ // that might be required here (e.g. for untupling).
+ // If `with_caller_location` is set we pretend there is an extra argument (that
+ // we will not pass; our `caller_location` intrinsic implementation walks the stack instead).
+ assert_eq!(
+ args.len() + if with_caller_location { 1 } else { 0 },
+ caller_fn_abi.args.len(),
+ "mismatch between caller ABI and caller arguments",
+ );
+ let mut caller_args = args
+ .iter()
+ .zip(caller_fn_abi.args.iter())
+ .filter(|arg_and_abi| !matches!(arg_and_abi.1.mode, PassMode::Ignore));
+
+ // Now we have to spread them out across the callee's locals,
+ // taking into account the `spread_arg`. If we could write
+ // this is a single iterator (that handles `spread_arg`), then
+ // `pass_argument` would be the loop body. It takes care to
+ // not advance `caller_iter` for ignored arguments.
+ let mut callee_args_abis = callee_fn_abi.args.iter();
+ for local in body.args_iter() {
+ // Construct the destination place for this argument. At this point all
+ // locals are still dead, so we cannot construct a `PlaceTy`.
+ let dest = mir::Place::from(local);
+ // `layout_of_local` does more than just the instantiation we need to get the
+ // type, but the result gets cached so this avoids calling the instantiation
+ // query *again* the next time this local is accessed.
+ let ty = self.layout_of_local(self.frame(), local, None)?.ty;
+ if Some(local) == body.spread_arg {
+ // Make the local live once, then fill in the value field by field.
+ self.storage_live(local)?;
+ // Must be a tuple
+ let ty::Tuple(fields) = ty.kind() else {
+ span_bug!(self.cur_span(), "non-tuple type for `spread_arg`: {ty}")
+ };
+ for (i, field_ty) in fields.iter().enumerate() {
+ let dest = dest.project_deeper(
+ &[mir::ProjectionElem::Field(FieldIdx::from_usize(i), field_ty)],
+ *self.tcx,
+ );
+ let callee_abi = callee_args_abis.next().unwrap();
+ self.pass_argument(
+ &mut caller_args,
+ callee_abi,
+ &dest,
+ field_ty,
+ /* already_live */ true,
+ )?;
+ }
+ } else {
+ // Normal argument. Cannot mark it as live yet, it might be unsized!
+ let callee_abi = callee_args_abis.next().unwrap();
+ self.pass_argument(
+ &mut caller_args,
+ callee_abi,
+ &dest,
+ ty,
+ /* already_live */ false,
+ )?;
+ }
+ }
+ // If the callee needs a caller location, pretend we consume one more argument from the ABI.
+ if instance.def.requires_caller_location(*self.tcx) {
+ callee_args_abis.next().unwrap();
+ }
+ // Now we should have no more caller args or callee arg ABIs
+ assert!(
+ callee_args_abis.next().is_none(),
+ "mismatch between callee ABI and callee body arguments"
+ );
+ if caller_args.next().is_some() {
+ throw_ub_custom!(fluent::const_eval_too_many_caller_args);
+ }
+ // Don't forget to check the return type!
+ if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
+ throw_ub!(AbiMismatchReturn {
+ caller_ty: caller_fn_abi.ret.layout.ty,
+ callee_ty: callee_fn_abi.ret.layout.ty
+ });
+ }
+
+ // Protect return place for in-place return value passing.
+ M::protect_in_place_function_argument(self, &destination)?;
+
+ // Don't forget to mark "initially live" locals as live.
+ self.storage_live_for_always_live_locals()?;
+ };
+ res.inspect_err(|_| {
+ // Don't show the incomplete stack frame in the error stacktrace.
+ self.stack_mut().pop();
+ })
+ }
+
+ /// Initiate a call to this function -- pushing the stack frame and initializing the arguments.
+ ///
+ /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
+ /// However, we also need `caller_abi` to determine if we need to do untupling of arguments.
+ ///
+ /// `with_caller_location` indicates whether the caller passed a caller location. Miri
+ /// implements caller locations without argument passing, but to match `FnAbi` we need to know
+ /// when those arguments are present.
+ pub(super) fn init_fn_call(
+ &mut self,
+ fn_val: FnVal<'tcx, M::ExtraFnVal>,
+ (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
+ args: &[FnArg<'tcx, M::Provenance>],
+ with_caller_location: bool,
+ destination: &MPlaceTy<'tcx, M::Provenance>,
+ target: Option<mir::BasicBlock>,
+ unwind: mir::UnwindAction,
+ ) -> InterpResult<'tcx> {
+ trace!("init_fn_call: {:#?}", fn_val);
+
+ let instance = match fn_val {
+ FnVal::Instance(instance) => instance,
+ FnVal::Other(extra) => {
+ return M::call_extra_fn(
+ self,
+ extra,
+ caller_abi,
+ args,
+ destination,
+ target,
+ unwind,
+ );
+ }
+ };
+
+ match instance.def {
+ ty::InstanceKind::Intrinsic(def_id) => {
+ assert!(self.tcx.intrinsic(def_id).is_some());
+ // FIXME: Should `InPlace` arguments be reset to uninit?
+ if let Some(fallback) = M::call_intrinsic(
+ self,
+ instance,
+ &self.copy_fn_args(args),
+ destination,
+ target,
+ unwind,
+ )? {
+ assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden);
+ assert_matches!(fallback.def, ty::InstanceKind::Item(_));
+ return self.init_fn_call(
+ FnVal::Instance(fallback),
+ (caller_abi, caller_fn_abi),
+ args,
+ with_caller_location,
+ destination,
+ target,
+ unwind,
+ );
+ } else {
+ Ok(())
+ }
+ }
+ ty::InstanceKind::VTableShim(..)
+ | ty::InstanceKind::ReifyShim(..)
+ | ty::InstanceKind::ClosureOnceShim { .. }
+ | ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
+ | ty::InstanceKind::CoroutineKindShim { .. }
+ | ty::InstanceKind::FnPtrShim(..)
+ | ty::InstanceKind::DropGlue(..)
+ | ty::InstanceKind::CloneShim(..)
+ | ty::InstanceKind::FnPtrAddrShim(..)
+ | ty::InstanceKind::ThreadLocalShim(..)
+ | ty::InstanceKind::AsyncDropGlueCtorShim(..)
+ | ty::InstanceKind::Item(_) => {
+ // We need MIR for this fn
+ let Some((body, instance)) = M::find_mir_or_eval_fn(
+ self,
+ instance,
+ caller_abi,
+ args,
+ destination,
+ target,
+ unwind,
+ )?
+ else {
+ return Ok(());
+ };
+
+ // Special handling for the closure ABI: untuple the last argument.
+ let args: Cow<'_, [FnArg<'tcx, M::Provenance>]> =
+ if caller_abi == Abi::RustCall && !args.is_empty() {
+ // Untuple
+ let (untuple_arg, args) = args.split_last().unwrap();
+ trace!("init_fn_call: Will pass last argument by untupling");
+ Cow::from(
+ args.iter()
+ .map(|a| Ok(a.clone()))
+ .chain(
+ (0..untuple_arg.layout().fields.count())
+ .map(|i| self.fn_arg_field(untuple_arg, i)),
+ )
+ .collect::<InterpResult<'_, Vec<_>>>()?,
+ )
+ } else {
+ // Plain arg passing
+ Cow::from(args)
+ };
+
+ self.init_stack_frame(
+ instance,
+ body,
+ caller_fn_abi,
+ &args,
+ with_caller_location,
+ destination,
+ StackPopCleanup::Goto { ret: target, unwind },
+ )
+ }
+ // `InstanceKind::Virtual` does not have callable MIR. Calls to `Virtual` instances must be
+ // codegen'd / interpreted as virtual calls through the vtable.
+ ty::InstanceKind::Virtual(def_id, idx) => {
+ let mut args = args.to_vec();
+ // We have to implement all "object safe receivers". So we have to go search for a
+ // pointer or `dyn Trait` type, but it could be wrapped in newtypes. So recursively
+ // unwrap those newtypes until we are there.
+ // An `InPlace` does nothing here, we keep the original receiver intact. We can't
+ // really pass the argument in-place anyway, and we are constructing a new
+ // `Immediate` receiver.
+ let mut receiver = self.copy_fn_arg(&args[0]);
+ let receiver_place = loop {
+ match receiver.layout.ty.kind() {
+ ty::Ref(..) | ty::RawPtr(..) => {
+ // We do *not* use `deref_pointer` here: we don't want to conceptually
+ // create a place that must be dereferenceable, since the receiver might
+ // be a raw pointer and (for `*const dyn Trait`) we don't need to
+ // actually access memory to resolve this method.
+ // Also see <https://github.com/rust-lang/miri/issues/2786>.
+ let val = self.read_immediate(&receiver)?;
+ break self.ref_to_mplace(&val)?;
+ }
+ ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
+ ty::Dynamic(.., ty::DynStar) => {
+ // Not clear how to handle this, so far we assume the receiver is always a pointer.
+ span_bug!(
+ self.cur_span(),
+ "by-value calls on a `dyn*`... are those a thing?"
+ );
+ }
+ _ => {
+ // Not there yet, search for the only non-ZST field.
+ // (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
+ let (idx, _) = receiver.layout.non_1zst_field(self).expect(
+ "not exactly one non-1-ZST field in a `DispatchFromDyn` type",
+ );
+ receiver = self.project_field(&receiver, idx)?;
+ }
+ }
+ };
+
+ // Obtain the underlying trait we are working on, and the adjusted receiver argument.
+ let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
+ receiver_place.layout.ty.kind()
+ {
+ let recv = self.unpack_dyn_star(&receiver_place, data)?;
+
+ (data.principal(), recv.layout.ty, recv.ptr())
+ } else {
+ // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
+ // (For that reason we also cannot use `unpack_dyn_trait`.)
+ let receiver_tail =
+ self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.param_env);
+ let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
+ span_bug!(
+ self.cur_span(),
+ "dynamic call on non-`dyn` type {}",
+ receiver_tail
+ )
+ };
+ assert!(receiver_place.layout.is_unsized());
+
+ // Get the required information from the vtable.
+ let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
+ let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
+
+ // It might be surprising that we use a pointer as the receiver even if this
+ // is a by-val case; this works because by-val passing of an unsized `dyn
+ // Trait` to a function is actually desugared to a pointer.
+ (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
+ };
+
+ // Now determine the actual method to call. Usually we use the easy way of just
+ // looking up the method at index `idx`.
+ let vtable_entries = self.vtable_entries(trait_, dyn_ty);
+ let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else {
+ // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
+ throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
+ };
+ trace!("Virtual call dispatches to {fn_inst:#?}");
+ // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that
+ // produces the same result.
+ if cfg!(debug_assertions) {
+ let tcx = *self.tcx;
+
+ let trait_def_id = tcx.trait_of_item(def_id).unwrap();
+ let virtual_trait_ref =
+ ty::TraitRef::from_method(tcx, trait_def_id, instance.args);
+ let existential_trait_ref =
+ ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
+ let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
+
+ let concrete_method = Instance::expect_resolve_for_vtable(
+ tcx,
+ self.param_env,
+ def_id,
+ instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
+ self.cur_span(),
+ );
+ assert_eq!(fn_inst, concrete_method);
+ }
+
+ // Adjust receiver argument. Layout can be any (thin) ptr.
+ let receiver_ty = Ty::new_mut_ptr(self.tcx.tcx, dyn_ty);
+ args[0] = FnArg::Copy(
+ ImmTy::from_immediate(
+ Scalar::from_maybe_pointer(adjusted_recv, self).into(),
+ self.layout_of(receiver_ty)?,
+ )
+ .into(),
+ );
+ trace!("Patched receiver operand to {:#?}", args[0]);
+ // Need to also adjust the type in the ABI. Strangely, the layout there is actually
+ // already fine! Just the type is bogus. This is due to what `force_thin_self_ptr`
+ // does in `fn_abi_new_uncached`; supposedly, codegen relies on having the bogus
+ // type, so we just patch this up locally.
+ let mut caller_fn_abi = caller_fn_abi.clone();
+ caller_fn_abi.args[0].layout.ty = receiver_ty;
+
+ // recurse with concrete function
+ self.init_fn_call(
+ FnVal::Instance(fn_inst),
+ (caller_abi, &caller_fn_abi),
+ &args,
+ with_caller_location,
+ destination,
+ target,
+ unwind,
+ )
+ }
+ }
+ }
+
+ /// Initiate a tail call to this function -- popping the current stack frame, pushing the new
+ /// stack frame and initializing the arguments.
+ pub(super) fn init_fn_tail_call(
+ &mut self,
+ fn_val: FnVal<'tcx, M::ExtraFnVal>,
+ (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
+ args: &[FnArg<'tcx, M::Provenance>],
+ with_caller_location: bool,
+ ) -> InterpResult<'tcx> {
+ trace!("init_fn_tail_call: {:#?}", fn_val);
+
+ // This is the "canonical" implementation of tails calls,
+ // a pop of the current stack frame, followed by a normal call
+ // which pushes a new stack frame, with the return address from
+ // the popped stack frame.
+ //
+ // Note that we are using `pop_stack_frame_raw` and not `return_from_current_stack_frame`,
+ // as the latter "executes" the goto to the return block, but we don't want to,
+ // only the tail called function should return to the current return block.
+ M::before_stack_pop(self, self.frame())?;
+
+ let StackPopInfo { return_action, return_to_block, return_place } =
+ self.pop_stack_frame_raw(false)?;
+
+ assert_eq!(return_action, ReturnAction::Normal);
+
+ // Take the "stack pop cleanup" info, and use that to initiate the next call.
+ let StackPopCleanup::Goto { ret, unwind } = return_to_block else {
+ bug!("can't tailcall as root");
+ };
+
+ // FIXME(explicit_tail_calls):
+ // we should check if both caller&callee can/n't unwind,
+ // see <https://github.com/rust-lang/rust/pull/113128#issuecomment-1614979803>
+
+ self.init_fn_call(
+ fn_val,
+ (caller_abi, caller_fn_abi),
+ args,
+ with_caller_location,
+ &return_place,
+ ret,
+ unwind,
+ )
+ }
+
+ pub(super) fn init_drop_in_place_call(
+ &mut self,
+ place: &PlaceTy<'tcx, M::Provenance>,
+ instance: ty::Instance<'tcx>,
+ target: mir::BasicBlock,
+ unwind: mir::UnwindAction,
+ ) -> InterpResult<'tcx> {
+ trace!("init_drop_in_place_call: {:?},\n instance={:?}", place, instance);
+ // We take the address of the object. This may well be unaligned, which is fine
+ // for us here. However, unaligned accesses will probably make the actual drop
+ // implementation fail -- a problem shared by rustc.
+ let place = self.force_allocation(place)?;
+
+ // We behave a bit different from codegen here.
+ // Codegen creates an `InstanceKind::Virtual` with index 0 (the slot of the drop method) and
+ // then dispatches that to the normal call machinery. However, our call machinery currently
+ // only supports calling `VtblEntry::Method`; it would choke on a `MetadataDropInPlace`. So
+ // instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call`
+ // since we can just get a place of the underlying type and use `mplace_to_ref`.
+ let place = match place.layout.ty.kind() {
+ ty::Dynamic(data, _, ty::Dyn) => {
+ // Dropping a trait object. Need to find actual drop fn.
+ self.unpack_dyn_trait(&place, data)?
+ }
+ ty::Dynamic(data, _, ty::DynStar) => {
+ // Dropping a `dyn*`. Need to find actual drop fn.
+ self.unpack_dyn_star(&place, data)?
+ }
+ _ => {
+ debug_assert_eq!(
+ instance,
+ ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
+ );
+ place
+ }
+ };
+ let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
+ let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
+
+ let arg = self.mplace_to_ref(&place)?;
+ let ret = MPlaceTy::fake_alloc_zst(self.layout_of(self.tcx.types.unit)?);
+
+ self.init_fn_call(
+ FnVal::Instance(instance),
+ (Abi::Rust, fn_abi),
+ &[FnArg::Copy(arg.into())],
+ false,
+ &ret.into(),
+ Some(target),
+ unwind,
+ )
+ }
+
+ /// Pops the current frame from the stack, copies the return value to the caller, deallocates
+ /// the memory for allocated locals, and jumps to an appropriate place.
+ ///
+ /// If `unwinding` is `false`, then we are performing a normal return
+ /// from a function. In this case, we jump back into the frame of the caller,
+ /// and continue execution as normal.
+ ///
+ /// If `unwinding` is `true`, then we are in the middle of a panic,
+ /// and need to unwind this frame. In this case, we jump to the
+ /// `cleanup` block for the function, which is responsible for running
+ /// `Drop` impls for any locals that have been initialized at this point.
+ /// The cleanup block ends with a special `Resume` terminator, which will
+ /// cause us to continue unwinding.
+ #[instrument(skip(self), level = "trace")]
+ pub(super) fn return_from_current_stack_frame(
+ &mut self,
+ unwinding: bool,
+ ) -> InterpResult<'tcx> {
+ info!(
+ "popping stack frame ({})",
+ if unwinding { "during unwinding" } else { "returning from function" }
+ );
+
+ // Check `unwinding`.
+ assert_eq!(
+ unwinding,
+ match self.frame().loc {
+ Left(loc) => self.body().basic_blocks[loc.block].is_cleanup,
+ Right(_) => true,
+ }
+ );
+ if unwinding && self.frame_idx() == 0 {
+ throw_ub_custom!(fluent::const_eval_unwind_past_top);
+ }
+
+ M::before_stack_pop(self, self.frame())?;
+
+ // Copy return value. Must of course happen *before* we deallocate the locals.
+ // Must be *after* `before_stack_pop` as otherwise the return place might still be protected.
+ let copy_ret_result = if !unwinding {
+ let op = self
+ .local_to_op(mir::RETURN_PLACE, None)
+ .expect("return place should always be live");
+ let dest = self.frame().return_place.clone();
+ let res = if self.stack().len() == 1 {
+ // The initializer of constants and statics will get validated separately
+ // after the constant has been fully evaluated. While we could fall back to the default
+ // code path, that will cause -Zenforce-validity to cycle on static initializers.
+ // Reading from a static's memory is not allowed during its evaluation, and will always
+ // trigger a cycle error. Validation must read from the memory of the current item.
+ // For Miri this means we do not validate the root frame return value,
+ // but Miri anyway calls `read_target_isize` on that so separate validation
+ // is not needed.
+ self.copy_op_no_dest_validation(&op, &dest)
+ } else {
+ self.copy_op_allow_transmute(&op, &dest)
+ };
+ trace!("return value: {:?}", self.dump_place(&dest.into()));
+ // We delay actually short-circuiting on this error until *after* the stack frame is
+ // popped, since we want this error to be attributed to the caller, whose type defines
+ // this transmute.
+ res
+ } else {
+ Ok(())
+ };
+
+ // All right, now it is time to actually pop the frame.
+ let stack_pop_info = self.pop_stack_frame_raw(unwinding)?;
+
+ // Report error from return value copy, if any.
+ copy_ret_result?;
+
+ match stack_pop_info.return_action {
+ ReturnAction::Normal => {}
+ ReturnAction::NoJump => {
+ // The hook already did everything.
+ return Ok(());
+ }
+ ReturnAction::NoCleanup => {
+ // If we are not doing cleanup, also skip everything else.
+ assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked");
+ assert!(!unwinding, "tried to skip cleanup during unwinding");
+ // Skip machine hook.
+ return Ok(());
+ }
+ }
+
+ // Normal return, figure out where to jump.
+ if unwinding {
+ // Follow the unwind edge.
+ match stack_pop_info.return_to_block {
+ StackPopCleanup::Goto { unwind, .. } => {
+ // This must be the very last thing that happens, since it can in fact push a new stack frame.
+ self.unwind_to_block(unwind)
+ }
+ StackPopCleanup::Root { .. } => {
+ panic!("encountered StackPopCleanup::Root when unwinding!")
+ }
+ }
+ } else {
+ // Follow the normal return edge.
+ match stack_pop_info.return_to_block {
+ StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret),
+ StackPopCleanup::Root { .. } => {
+ assert!(
+ self.stack().is_empty(),
+ "only the bottommost frame can have StackPopCleanup::Root"
+ );
+ Ok(())
+ }
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index bd2a581..37bd6d6 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -12,11 +12,10 @@
use rustc_type_ir::TyKind::*;
use tracing::trace;
+use super::util::ensure_monomorphic_enough;
use super::{
- err_inval, throw_ub, throw_ub_custom, util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate,
- InterpCx, Machine, OpTy, PlaceTy,
+ err_inval, throw_ub, throw_ub_custom, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
};
-
use crate::fluent_generated as fluent;
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
@@ -387,7 +386,7 @@ fn unsize_into_ptr(
) -> InterpResult<'tcx> {
// A<Struct> -> A<Trait> conversion
let (src_pointee_ty, dest_pointee_ty) =
- self.tcx.struct_lockstep_tails_erasing_lifetimes(source_ty, cast_ty, self.param_env);
+ self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.param_env);
match (&src_pointee_ty.kind(), &dest_pointee_ty.kind()) {
(&ty::Array(_, length), &ty::Slice(_)) => {
@@ -401,6 +400,12 @@ fn unsize_into_ptr(
}
(ty::Dynamic(data_a, _, ty::Dyn), ty::Dynamic(data_b, _, ty::Dyn)) => {
let val = self.read_immediate(src)?;
+ // MIR building generates odd NOP casts, prevent them from causing unexpected trouble.
+ // See <https://github.com/rust-lang/rust/issues/128880>.
+ // FIXME: ideally we wouldn't have to do this.
+ if data_a == data_b {
+ return self.write_immediate(*val, dest);
+ }
// Take apart the old pointer, and find the dynamic type.
let (old_data, old_vptr) = val.to_scalar_pair();
let old_data = old_data.to_pointer(self)?;
diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs
index 181c711..0008a15 100644
--- a/compiler/rustc_const_eval/src/interpret/discriminant.rs
+++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs
@@ -1,11 +1,9 @@
//! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
-use rustc_middle::mir;
-use rustc_middle::span_bug;
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt};
use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty};
-use rustc_target::abi::{self, TagEncoding};
-use rustc_target::abi::{VariantIdx, Variants};
+use rustc_middle::{mir, span_bug};
+use rustc_target::abi::{self, TagEncoding, VariantIdx, Variants};
use tracing::{instrument, trace};
use super::{
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 9fddeec..7a6bbdf 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -1,41 +1,29 @@
-use std::cell::Cell;
-use std::{fmt, mem};
-
-use either::{Either, Left, Right};
-use rustc_infer::infer::at::ToTrace;
-use rustc_infer::traits::ObligationCause;
-use rustc_trait_selection::traits::ObligationCtxt;
-use tracing::{debug, info, info_span, instrument, trace};
-
+use either::{Left, Right};
use rustc_errors::DiagCtxtHandle;
-use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
-use rustc_index::IndexVec;
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::mir;
-use rustc_middle::mir::interpret::{
- CtfeProvenance, ErrorHandled, InvalidMetaKind, ReportedErrorInfo,
-};
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{
- self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
- TyAndLayout,
+ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
-use rustc_middle::{bug, span_bug};
-use rustc_mir_dataflow::storage::always_storage_live_locals;
+use rustc_middle::{mir, span_bug};
use rustc_session::Limit;
use rustc_span::Span;
-use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
+use rustc_target::abi::call::FnAbi;
+use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
+use rustc_trait_selection::traits::ObligationCtxt;
+use tracing::{debug, trace};
use super::{
- err_inval, throw_inval, throw_ub, throw_ub_custom, throw_unsup, GlobalId, Immediate,
- InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, MemoryKind,
- OpTy, Operand, Place, PlaceTy, Pointer, PointerArithmetic, Projectable, Provenance,
- ReturnAction, Scalar,
+ err_inval, throw_inval, throw_ub, throw_ub_custom, Frame, FrameInfo, GlobalId, InterpErrorInfo,
+ InterpResult, MPlaceTy, Machine, MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic,
+ Projectable, Provenance,
};
-use crate::errors;
-use crate::util;
-use crate::{fluent_generated as fluent, ReportErrorExt};
+use crate::{fluent_generated as fluent, util, ReportErrorExt};
pub struct InterpCx<'tcx, M: Machine<'tcx>> {
/// Stores the `Machine` instance.
@@ -58,314 +46,6 @@ pub struct InterpCx<'tcx, M: Machine<'tcx>> {
pub recursion_limit: Limit,
}
-// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
-// boundary and dropped in the other thread, it would exit the span in the other thread.
-struct SpanGuard(tracing::Span, std::marker::PhantomData<*const u8>);
-
-impl SpanGuard {
- /// By default a `SpanGuard` does nothing.
- fn new() -> Self {
- Self(tracing::Span::none(), std::marker::PhantomData)
- }
-
- /// If a span is entered, we exit the previous span (if any, normally none) and enter the
- /// new span. This is mainly so we don't have to use `Option` for the `tracing_span` field of
- /// `Frame` by creating a dummy span to being with and then entering it once the frame has
- /// been pushed.
- fn enter(&mut self, span: tracing::Span) {
- // This executes the destructor on the previous instance of `SpanGuard`, ensuring that
- // we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we
- // can't protect the tracing stack, but that'll just lead to weird logging, no actual
- // problems.
- *self = Self(span, std::marker::PhantomData);
- self.0.with_subscriber(|(id, dispatch)| {
- dispatch.enter(id);
- });
- }
-}
-
-impl Drop for SpanGuard {
- fn drop(&mut self) {
- self.0.with_subscriber(|(id, dispatch)| {
- dispatch.exit(id);
- });
- }
-}
-
-/// A stack frame.
-pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
- ////////////////////////////////////////////////////////////////////////////////
- // Function and callsite information
- ////////////////////////////////////////////////////////////////////////////////
- /// The MIR for the function called on this frame.
- pub body: &'tcx mir::Body<'tcx>,
-
- /// The def_id and args of the current function.
- pub instance: ty::Instance<'tcx>,
-
- /// Extra data for the machine.
- pub extra: Extra,
-
- ////////////////////////////////////////////////////////////////////////////////
- // Return place and locals
- ////////////////////////////////////////////////////////////////////////////////
- /// Work to perform when returning from this function.
- pub return_to_block: StackPopCleanup,
-
- /// The location where the result of the current stack frame should be written to,
- /// and its layout in the caller.
- pub return_place: MPlaceTy<'tcx, Prov>,
-
- /// The list of locals for this stack frame, stored in order as
- /// `[return_ptr, arguments..., variables..., temporaries...]`.
- /// The locals are stored as `Option<Value>`s.
- /// `None` represents a local that is currently dead, while a live local
- /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
- ///
- /// Do *not* access this directly; always go through the machine hook!
- pub locals: IndexVec<mir::Local, LocalState<'tcx, Prov>>,
-
- /// The span of the `tracing` crate is stored here.
- /// When the guard is dropped, the span is exited. This gives us
- /// a full stack trace on all tracing statements.
- tracing_span: SpanGuard,
-
- ////////////////////////////////////////////////////////////////////////////////
- // Current position within the function
- ////////////////////////////////////////////////////////////////////////////////
- /// If this is `Right`, we are not currently executing any particular statement in
- /// this frame (can happen e.g. during frame initialization, and during unwinding on
- /// frames without cleanup code).
- ///
- /// Needs to be public because ConstProp does unspeakable things to it.
- pub loc: Either<mir::Location, Span>,
-}
-
-/// What we store about a frame in an interpreter backtrace.
-#[derive(Clone, Debug)]
-pub struct FrameInfo<'tcx> {
- pub instance: ty::Instance<'tcx>,
- pub span: Span,
-}
-
-#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
-pub enum StackPopCleanup {
- /// Jump to the next block in the caller, or cause UB if None (that's a function
- /// that may never return). Also store layout of return place so
- /// we can validate it at that layout.
- /// `ret` stores the block we jump to on a normal return, while `unwind`
- /// stores the block used for cleanup during unwinding.
- Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction },
- /// The root frame of the stack: nowhere else to jump to.
- /// `cleanup` says whether locals are deallocated. Static computation
- /// wants them leaked to intern what they need (and just throw away
- /// the entire `ecx` when it is done).
- Root { cleanup: bool },
-}
-
-/// Return type of [`InterpCx::pop_stack_frame`].
-pub struct StackPopInfo<'tcx, Prov: Provenance> {
- /// Additional information about the action to be performed when returning from the popped
- /// stack frame.
- pub return_action: ReturnAction,
-
- /// [`return_to_block`](Frame::return_to_block) of the popped stack frame.
- pub return_to_block: StackPopCleanup,
-
- /// [`return_place`](Frame::return_place) of the popped stack frame.
- pub return_place: MPlaceTy<'tcx, Prov>,
-}
-
-/// State of a local variable including a memoized layout
-#[derive(Clone)]
-pub struct LocalState<'tcx, Prov: Provenance = CtfeProvenance> {
- value: LocalValue<Prov>,
- /// Don't modify if `Some`, this is only used to prevent computing the layout twice.
- /// Avoids computing the layout of locals that are never actually initialized.
- layout: Cell<Option<TyAndLayout<'tcx>>>,
-}
-
-impl<Prov: Provenance> std::fmt::Debug for LocalState<'_, Prov> {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("LocalState")
- .field("value", &self.value)
- .field("ty", &self.layout.get().map(|l| l.ty))
- .finish()
- }
-}
-
-/// Current value of a local variable
-///
-/// This does not store the type of the local; the type is given by `body.local_decls` and can never
-/// change, so by not storing here we avoid having to maintain that as an invariant.
-#[derive(Copy, Clone, Debug)] // Miri debug-prints these
-pub(super) enum LocalValue<Prov: Provenance = CtfeProvenance> {
- /// This local is not currently alive, and cannot be used at all.
- Dead,
- /// A normal, live local.
- /// Mostly for convenience, we re-use the `Operand` type here.
- /// This is an optimization over just always having a pointer here;
- /// we can thus avoid doing an allocation when the local just stores
- /// immediate values *and* never has its address taken.
- Live(Operand<Prov>),
-}
-
-impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
- pub fn make_live_uninit(&mut self) {
- self.value = LocalValue::Live(Operand::Immediate(Immediate::Uninit));
- }
-
- /// This is a hack because Miri needs a way to visit all the provenance in a `LocalState`
- /// without having a layout or `TyCtxt` available, and we want to keep the `Operand` type
- /// private.
- pub fn as_mplace_or_imm(
- &self,
- ) -> Option<Either<(Pointer<Option<Prov>>, MemPlaceMeta<Prov>), Immediate<Prov>>> {
- match self.value {
- LocalValue::Dead => None,
- LocalValue::Live(Operand::Indirect(mplace)) => Some(Left((mplace.ptr, mplace.meta))),
- LocalValue::Live(Operand::Immediate(imm)) => Some(Right(imm)),
- }
- }
-
- /// Read the local's value or error if the local is not yet live or not live anymore.
- #[inline(always)]
- pub(super) fn access(&self) -> InterpResult<'tcx, &Operand<Prov>> {
- match &self.value {
- LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
- LocalValue::Live(val) => Ok(val),
- }
- }
-
- /// Overwrite the local. If the local can be overwritten in place, return a reference
- /// to do so; otherwise return the `MemPlace` to consult instead.
- #[inline(always)]
- pub(super) fn access_mut(&mut self) -> InterpResult<'tcx, &mut Operand<Prov>> {
- match &mut self.value {
- LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
- LocalValue::Live(val) => Ok(val),
- }
- }
-}
-
-impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
- pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'tcx, Prov, Extra> {
- Frame {
- body: self.body,
- instance: self.instance,
- return_to_block: self.return_to_block,
- return_place: self.return_place,
- locals: self.locals,
- loc: self.loc,
- extra,
- tracing_span: self.tracing_span,
- }
- }
-}
-
-impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
- /// Get the current location within the Frame.
- ///
- /// If this is `Right`, we are not currently executing any particular statement in
- /// this frame (can happen e.g. during frame initialization, and during unwinding on
- /// frames without cleanup code).
- ///
- /// Used by priroda.
- pub fn current_loc(&self) -> Either<mir::Location, Span> {
- self.loc
- }
-
- /// Return the `SourceInfo` of the current instruction.
- pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
- self.loc.left().map(|loc| self.body.source_info(loc))
- }
-
- pub fn current_span(&self) -> Span {
- match self.loc {
- Left(loc) => self.body.source_info(loc).span,
- Right(span) => span,
- }
- }
-
- pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option<hir::HirId> {
- // We first try to get a HirId via the current source scope,
- // and fall back to `body.source`.
- self.current_source_info()
- .and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data {
- mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
- mir::ClearCrossCrate::Clear => None,
- })
- .or_else(|| {
- let def_id = self.body.source.def_id().as_local();
- def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
- })
- }
-
- /// Returns the address of the buffer where the locals are stored. This is used by `Place` as a
- /// sanity check to detect bugs where we mix up which stack frame a place refers to.
- #[inline(always)]
- pub(super) fn locals_addr(&self) -> usize {
- self.locals.raw.as_ptr().addr()
- }
-
- #[must_use]
- pub fn generate_stacktrace_from_stack(stack: &[Self]) -> Vec<FrameInfo<'tcx>> {
- let mut frames = Vec::new();
- // This deliberately does *not* honor `requires_caller_location` since it is used for much
- // more than just panics.
- for frame in stack.iter().rev() {
- let span = match frame.loc {
- Left(loc) => {
- // If the stacktrace passes through MIR-inlined source scopes, add them.
- let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc);
- let mut scope_data = &frame.body.source_scopes[scope];
- while let Some((instance, call_span)) = scope_data.inlined {
- frames.push(FrameInfo { span, instance });
- span = call_span;
- scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()];
- }
- span
- }
- Right(span) => span,
- };
- frames.push(FrameInfo { span, instance: frame.instance });
- }
- trace!("generate stacktrace: {:#?}", frames);
- frames
- }
-}
-
-// FIXME: only used by miri, should be removed once translatable.
-impl<'tcx> fmt::Display for FrameInfo<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- ty::tls::with(|tcx| {
- if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
- write!(f, "inside closure")
- } else {
- // Note: this triggers a `must_produce_diag` state, which means that if we ever
- // get here we must emit a diagnostic. We should never display a `FrameInfo` unless
- // we actually want to emit a warning or error to the user.
- write!(f, "inside `{}`", self.instance)
- }
- })
- }
-}
-
-impl<'tcx> FrameInfo<'tcx> {
- pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
- let span = self.span;
- if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
- errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
- } else {
- let instance = format!("{}", self.instance);
- // Note: this triggers a `must_produce_diag` state, which means that if we ever get
- // here we must emit a diagnostic. We should never display a `FrameInfo` unless we
- // actually want to emit a warning or error to the user.
- errors::FrameNote { where_: "instance", span, instance, times: 0 }
- }
- }
-}
-
impl<'tcx, M: Machine<'tcx>> HasDataLayout for InterpCx<'tcx, M> {
#[inline]
fn data_layout(&self) -> &TargetDataLayout {
@@ -561,17 +241,6 @@ pub fn body(&self) -> &'tcx mir::Body<'tcx> {
self.frame().body
}
- #[inline(always)]
- pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
- assert!(ty.abi.is_signed());
- ty.size.sign_extend(value)
- }
-
- #[inline(always)]
- pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 {
- ty.size.truncate(value)
- }
-
#[inline]
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(*self.tcx, self.param_env)
@@ -715,30 +384,6 @@ pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
span_bug!(self.cur_span(), "no non-`#[track_caller]` frame found")
}
- #[inline(always)]
- pub(super) fn layout_of_local(
- &self,
- frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
- local: mir::Local,
- layout: Option<TyAndLayout<'tcx>>,
- ) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
- let state = &frame.locals[local];
- if let Some(layout) = state.layout.get() {
- return Ok(layout);
- }
-
- let layout = from_known_layout(self.tcx, self.param_env, layout, || {
- let local_ty = frame.body.local_decls[local].ty;
- let local_ty =
- self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
- self.layout_of(local_ty)
- })?;
-
- // Layouts of locals are requested a lot, so we cache them.
- state.layout.set(Some(layout));
- Ok(layout)
- }
-
/// Returns the actual dynamic size and alignment of the place at the given type.
/// Only the "meta" (metadata) part of the place matters.
/// This can fail to provide an answer for extern types.
@@ -837,132 +482,6 @@ pub fn size_and_align_of_mplace(
self.size_and_align_of(&mplace.meta(), &mplace.layout)
}
- #[instrument(skip(self, body, return_place, return_to_block), level = "debug")]
- pub fn push_stack_frame(
- &mut self,
- instance: ty::Instance<'tcx>,
- body: &'tcx mir::Body<'tcx>,
- return_place: &MPlaceTy<'tcx, M::Provenance>,
- return_to_block: StackPopCleanup,
- ) -> InterpResult<'tcx> {
- trace!("body: {:#?}", body);
-
- // First push a stack frame so we have access to the local args
- self.push_new_stack_frame(instance, body, return_to_block, return_place.clone())?;
-
- self.after_stack_frame_push(instance, body)?;
-
- Ok(())
- }
-
- /// Creates a new stack frame, initializes it and pushes it onto the stack.
- /// A private helper for [`push_stack_frame`](InterpCx::push_stack_frame).
- fn push_new_stack_frame(
- &mut self,
- instance: ty::Instance<'tcx>,
- body: &'tcx mir::Body<'tcx>,
- return_to_block: StackPopCleanup,
- return_place: MPlaceTy<'tcx, M::Provenance>,
- ) -> InterpResult<'tcx> {
- let dead_local = LocalState { value: LocalValue::Dead, layout: Cell::new(None) };
- let locals = IndexVec::from_elem(dead_local, &body.local_decls);
- let pre_frame = Frame {
- body,
- loc: Right(body.span), // Span used for errors caused during preamble.
- return_to_block,
- return_place,
- locals,
- instance,
- tracing_span: SpanGuard::new(),
- extra: (),
- };
- let frame = M::init_frame(self, pre_frame)?;
- self.stack_mut().push(frame);
-
- Ok(())
- }
-
- /// A private helper for [`push_stack_frame`](InterpCx::push_stack_frame).
- fn after_stack_frame_push(
- &mut self,
- instance: ty::Instance<'tcx>,
- body: &'tcx mir::Body<'tcx>,
- ) -> InterpResult<'tcx> {
- // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
- for &const_ in &body.required_consts {
- let c =
- self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
- c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
- err.emit_note(*self.tcx);
- err
- })?;
- }
-
- // done
- M::after_stack_push(self)?;
- self.frame_mut().loc = Left(mir::Location::START);
-
- let span = info_span!("frame", "{}", instance);
- self.frame_mut().tracing_span.enter(span);
-
- Ok(())
- }
-
- /// Pops a stack frame from the stack and returns some information about it.
- ///
- /// This also deallocates locals, if necessary.
- ///
- /// [`M::before_stack_pop`] should be called before calling this function.
- /// [`M::after_stack_pop`] is called by this function automatically.
- ///
- /// [`M::before_stack_pop`]: Machine::before_stack_pop
- /// [`M::after_stack_pop`]: Machine::after_stack_pop
- pub fn pop_stack_frame(
- &mut self,
- unwinding: bool,
- ) -> InterpResult<'tcx, StackPopInfo<'tcx, M::Provenance>> {
- let cleanup = self.cleanup_current_frame_locals()?;
-
- let frame =
- self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
-
- let return_to_block = frame.return_to_block;
- let return_place = frame.return_place.clone();
-
- let return_action;
- if cleanup {
- return_action = M::after_stack_pop(self, frame, unwinding)?;
- assert_ne!(return_action, ReturnAction::NoCleanup);
- } else {
- return_action = ReturnAction::NoCleanup;
- };
-
- Ok(StackPopInfo { return_action, return_to_block, return_place })
- }
-
- /// A private helper for [`pop_stack_frame`](InterpCx::pop_stack_frame).
- /// Returns `true` if cleanup has been done, `false` otherwise.
- fn cleanup_current_frame_locals(&mut self) -> InterpResult<'tcx, bool> {
- // Cleanup: deallocate locals.
- // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
- // We do this while the frame is still on the stack, so errors point to the callee.
- let return_to_block = self.frame().return_to_block;
- let cleanup = match return_to_block {
- StackPopCleanup::Goto { .. } => true,
- StackPopCleanup::Root { cleanup, .. } => cleanup,
- };
-
- if cleanup {
- // We need to take the locals out, since we need to mutate while iterating.
- let locals = mem::take(&mut self.frame_mut().locals);
- for local in &locals {
- self.deallocate_local(local.value)?;
- }
- }
-
- Ok(cleanup)
- }
-
/// Jump to the given block.
#[inline]
pub fn go_to_block(&mut self, target: mir::BasicBlock) {
@@ -1009,248 +528,6 @@ pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tc
Ok(())
}
- /// Pops the current frame from the stack, deallocating the
- /// memory for allocated locals, and jumps to an appropriate place.
- ///
- /// If `unwinding` is `false`, then we are performing a normal return
- /// from a function. In this case, we jump back into the frame of the caller,
- /// and continue execution as normal.
- ///
- /// If `unwinding` is `true`, then we are in the middle of a panic,
- /// and need to unwind this frame. In this case, we jump to the
- /// `cleanup` block for the function, which is responsible for running
- /// `Drop` impls for any locals that have been initialized at this point.
- /// The cleanup block ends with a special `Resume` terminator, which will
- /// cause us to continue unwinding.
- #[instrument(skip(self), level = "debug")]
- pub(super) fn return_from_current_stack_frame(
- &mut self,
- unwinding: bool,
- ) -> InterpResult<'tcx> {
- info!(
- "popping stack frame ({})",
- if unwinding { "during unwinding" } else { "returning from function" }
- );
-
- // Check `unwinding`.
- assert_eq!(
- unwinding,
- match self.frame().loc {
- Left(loc) => self.body().basic_blocks[loc.block].is_cleanup,
- Right(_) => true,
- }
- );
- if unwinding && self.frame_idx() == 0 {
- throw_ub_custom!(fluent::const_eval_unwind_past_top);
- }
-
- M::before_stack_pop(self, self.frame())?;
-
- // Copy return value. Must of course happen *before* we deallocate the locals.
- let copy_ret_result = if !unwinding {
- let op = self
- .local_to_op(mir::RETURN_PLACE, None)
- .expect("return place should always be live");
- let dest = self.frame().return_place.clone();
- let err = if self.stack().len() == 1 {
- // The initializer of constants and statics will get validated separately
- // after the constant has been fully evaluated. While we could fall back to the default
- // code path, that will cause -Zenforce-validity to cycle on static initializers.
- // Reading from a static's memory is not allowed during its evaluation, and will always
- // trigger a cycle error. Validation must read from the memory of the current item.
- // For Miri this means we do not validate the root frame return value,
- // but Miri anyway calls `read_target_isize` on that so separate validation
- // is not needed.
- self.copy_op_no_dest_validation(&op, &dest)
- } else {
- self.copy_op_allow_transmute(&op, &dest)
- };
- trace!("return value: {:?}", self.dump_place(&dest.into()));
- // We delay actually short-circuiting on this error until *after* the stack frame is
- // popped, since we want this error to be attributed to the caller, whose type defines
- // this transmute.
- err
- } else {
- Ok(())
- };
-
- // All right, now it is time to actually pop the frame.
- let stack_pop_info = self.pop_stack_frame(unwinding)?;
-
- // Report error from return value copy, if any.
- copy_ret_result?;
-
- match stack_pop_info.return_action {
- ReturnAction::Normal => {}
- ReturnAction::NoJump => {
- // The hook already did everything.
- return Ok(());
- }
- ReturnAction::NoCleanup => {
- // If we are not doing cleanup, also skip everything else.
- assert!(self.stack().is_empty(), "only the topmost frame should ever be leaked");
- assert!(!unwinding, "tried to skip cleanup during unwinding");
- // Skip machine hook.
- return Ok(());
- }
- }
-
- // Normal return, figure out where to jump.
- if unwinding {
- // Follow the unwind edge.
- let unwind = match stack_pop_info.return_to_block {
- StackPopCleanup::Goto { unwind, .. } => unwind,
- StackPopCleanup::Root { .. } => {
- panic!("encountered StackPopCleanup::Root when unwinding!")
- }
- };
- // This must be the very last thing that happens, since it can in fact push a new stack frame.
- self.unwind_to_block(unwind)
- } else {
- // Follow the normal return edge.
- match stack_pop_info.return_to_block {
- StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret),
- StackPopCleanup::Root { .. } => {
- assert!(
- self.stack().is_empty(),
- "only the topmost frame can have StackPopCleanup::Root"
- );
- Ok(())
- }
- }
- }
- }
-
- /// In the current stack frame, mark all locals as live that are not arguments and don't have
- /// `Storage*` annotations (this includes the return place).
- pub fn storage_live_for_always_live_locals(&mut self) -> InterpResult<'tcx> {
- self.storage_live(mir::RETURN_PLACE)?;
-
- let body = self.body();
- let always_live = always_storage_live_locals(body);
- for local in body.vars_and_temps_iter() {
- if always_live.contains(local) {
- self.storage_live(local)?;
- }
- }
- Ok(())
- }
-
- pub fn storage_live_dyn(
- &mut self,
- local: mir::Local,
- meta: MemPlaceMeta<M::Provenance>,
- ) -> InterpResult<'tcx> {
- trace!("{:?} is now live", local);
-
- // We avoid `ty.is_trivially_sized` since that does something expensive for ADTs.
- fn is_very_trivially_sized(ty: Ty<'_>) -> bool {
- match ty.kind() {
- ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
- | ty::Uint(_)
- | ty::Int(_)
- | ty::Bool
- | ty::Float(_)
- | ty::FnDef(..)
- | ty::FnPtr(_)
- | ty::RawPtr(..)
- | ty::Char
- | ty::Ref(..)
- | ty::Coroutine(..)
- | ty::CoroutineWitness(..)
- | ty::Array(..)
- | ty::Closure(..)
- | ty::CoroutineClosure(..)
- | ty::Never
- | ty::Error(_)
- | ty::Dynamic(_, _, ty::DynStar) => true,
-
- ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
-
- ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
-
- ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
-
- // We don't want to do any queries, so there is not much we can do with ADTs.
- ty::Adt(..) => false,
-
- ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
-
- ty::Infer(ty::TyVar(_)) => false,
-
- ty::Bound(..)
- | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
- bug!("`is_very_trivially_sized` applied to unexpected type: {}", ty)
- }
- }
- }
-
- // This is a hot function, we avoid computing the layout when possible.
- // `unsized_` will be `None` for sized types and `Some(layout)` for unsized types.
- let unsized_ = if is_very_trivially_sized(self.body().local_decls[local].ty) {
- None
- } else {
- // We need the layout.
- let layout = self.layout_of_local(self.frame(), local, None)?;
- if layout.is_sized() { None } else { Some(layout) }
- };
-
- let local_val = LocalValue::Live(if let Some(layout) = unsized_ {
- if !meta.has_meta() {
- throw_unsup!(UnsizedLocal);
- }
- // Need to allocate some memory, since `Immediate::Uninit` cannot be unsized.
- let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?;
- Operand::Indirect(*dest_place.mplace())
- } else {
- assert!(!meta.has_meta()); // we're dropping the metadata
- // Just make this an efficient immediate.
- // Note that not calling `layout_of` here does have one real consequence:
- // if the type is too big, we'll only notice this when the local is actually initialized,
- // which is a bit too late -- we should ideally notice this already here, when the memory
- // is conceptually allocated. But given how rare that error is and that this is a hot function,
- // we accept this downside for now.
- Operand::Immediate(Immediate::Uninit)
- });
-
- // If the local is already live, deallocate its old memory.
- let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
- self.deallocate_local(old)?;
- Ok(())
- }
-
- /// Mark a storage as live, killing the previous content.
- #[inline(always)]
- pub fn storage_live(&mut self, local: mir::Local) -> InterpResult<'tcx> {
- self.storage_live_dyn(local, MemPlaceMeta::None)
- }
-
- pub fn storage_dead(&mut self, local: mir::Local) -> InterpResult<'tcx> {
- assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
- trace!("{:?} is now dead", local);
-
- // If the local is already dead, this is a NOP.
- let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead);
- self.deallocate_local(old)?;
- Ok(())
- }
-
- #[instrument(skip(self), level = "debug")]
- fn deallocate_local(&mut self, local: LocalValue<M::Provenance>) -> InterpResult<'tcx> {
- if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
- // All locals have a backing allocation, even if the allocation is empty
- // due to the local having ZST type. Hence we can `unwrap`.
- trace!(
- "deallocating local {:?}: {:?}",
- local,
- // Locals always have a `alloc_id` (they are never the result of a int2ptr).
- self.dump_alloc(ptr.provenance.unwrap().get_alloc_id().unwrap())
- );
- self.deallocate_ptr(ptr, None, MemoryKind::Stack)?;
- };
- Ok(())
- }
-
/// Call a query that can return `ErrorHandled`. Should be used for statics and other globals.
/// (`mir::Const`/`ty::Const` have `eval` methods that can be used directly instead.)
pub fn ctfe_query<T>(
@@ -1340,39 +617,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
}
write!(fmt, ":")?;
- match self.ecx.frame().locals[local].value {
- LocalValue::Dead => write!(fmt, " is dead")?,
- LocalValue::Live(Operand::Immediate(Immediate::Uninit)) => {
- write!(fmt, " is uninitialized")?
- }
- LocalValue::Live(Operand::Indirect(mplace)) => {
- write!(
- fmt,
- " by {} ref {:?}:",
- match mplace.meta {
- MemPlaceMeta::Meta(meta) => format!(" meta({meta:?})"),
- MemPlaceMeta::None => String::new(),
- },
- mplace.ptr,
- )?;
- allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id));
- }
- LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
- write!(fmt, " {val:?}")?;
- if let Scalar::Ptr(ptr, _size) = val {
- allocs.push(ptr.provenance.get_alloc_id());
- }
- }
- LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
- write!(fmt, " ({val1:?}, {val2:?})")?;
- if let Scalar::Ptr(ptr, _size) = val1 {
- allocs.push(ptr.provenance.get_alloc_id());
- }
- if let Scalar::Ptr(ptr, _size) = val2 {
- allocs.push(ptr.provenance.get_alloc_id());
- }
- }
- }
+ self.ecx.frame().locals[local].print(&mut allocs, fmt)?;
write!(fmt, ": {:?}", self.ecx.dump_allocs(allocs.into_iter().flatten().collect()))
}
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index b227565..3be1b74 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -2,27 +2,24 @@
//! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
//! and miri.
+use std::assert_matches::assert_matches;
+
use rustc_hir::def_id::DefId;
-use rustc_middle::ty;
-use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_middle::{
- bug,
- mir::{self, BinOp, ConstValue, NonDivergingIntrinsic},
- ty::layout::TyAndLayout,
-};
+use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
+use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
+use rustc_middle::ty::{GenericArgsRef, Ty, TyCtxt};
+use rustc_middle::{bug, ty};
use rustc_span::symbol::{sym, Symbol};
use rustc_target::abi::Size;
use tracing::trace;
+use super::memory::MemoryKind;
+use super::util::ensure_monomorphic_enough;
use super::{
- err_inval, err_ub_custom, err_unsup_format, memory::MemoryKind, throw_inval, throw_ub_custom,
- throw_ub_format, util::ensure_monomorphic_enough, Allocation, CheckInAllocMsg, ConstAllocation,
- GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Pointer, PointerArithmetic,
- Provenance, Scalar,
+ err_inval, err_ub_custom, err_unsup_format, throw_inval, throw_ub_custom, throw_ub_format,
+ Allocation, CheckInAllocMsg, ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult,
+ MPlaceTy, Machine, OpTy, Pointer, PointerArithmetic, Provenance, Scalar,
};
-
use crate::fluent_generated as fluent;
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
@@ -102,7 +99,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Returns `true` if emulation happened.
/// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
/// intrinsic handling.
- pub fn emulate_intrinsic(
+ pub fn eval_intrinsic(
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, M::Provenance>],
@@ -211,7 +208,7 @@ pub fn emulate_intrinsic(
} else {
(val_bits >> shift_bits) | (val_bits << inv_shift_bits)
};
- let truncated_bits = self.truncate(result_bits, layout_val);
+ let truncated_bits = layout_val.size.truncate(result_bits);
let result = Scalar::from_uint(truncated_bits, layout_val.size);
self.write_scalar(result, dest)?;
}
@@ -243,36 +240,22 @@ pub fn emulate_intrinsic(
let isize_layout = self.layout_of(self.tcx.types.isize)?;
// Get offsets for both that are at least relative to the same base.
- let (a_offset, b_offset) =
- match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
+ // With `OFFSET_IS_ADDR` this is trivial; without it we need either
+ // two integers or two pointers into the same allocation.
+ let (a_offset, b_offset, is_addr) = if M::Provenance::OFFSET_IS_ADDR {
+ (a.addr().bytes(), b.addr().bytes(), /*is_addr*/ true)
+ } else {
+ match (self.ptr_try_get_alloc_id(a, 0), self.ptr_try_get_alloc_id(b, 0)) {
(Err(a), Err(b)) => {
- // Neither pointer points to an allocation.
- // This is okay only if they are the same.
- if a != b {
- // We'd catch this below in the "dereferenceable" check, but
- // show a nicer error for this particular case.
- throw_ub_custom!(
- fluent::const_eval_offset_from_different_integers,
- name = intrinsic_name,
- );
- }
- // This will always return 0.
- (a, b)
+ // Neither pointer points to an allocation, so they are both absolute.
+ (a, b, /*is_addr*/ true)
}
- _ if M::Provenance::OFFSET_IS_ADDR && a.addr() == b.addr() => {
- // At least one of the pointers has provenance, but they also point to
- // the same address so it doesn't matter; this is fine. `(0, 0)` means
- // we pass all the checks below and return 0.
- (0, 0)
- }
- // From here onwards, the pointers are definitely for different addresses
- // (or we can't determine their absolute address).
(Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _)))
if a_alloc_id == b_alloc_id =>
{
// Found allocation for both, and it's the same.
// Use these offsets for distance calculation.
- (a_offset.bytes(), b_offset.bytes())
+ (a_offset.bytes(), b_offset.bytes(), /*is_addr*/ false)
}
_ => {
// Not into the same allocation -- this is UB.
@@ -281,9 +264,10 @@ pub fn emulate_intrinsic(
name = intrinsic_name,
);
}
- };
+ }
+ };
- // Compute distance.
+ // Compute distance: a - b.
let dist = {
// Addresses are unsigned, so this is a `usize` computation. We have to do the
// overflow check separately anyway.
@@ -300,6 +284,7 @@ pub fn emulate_intrinsic(
fluent::const_eval_offset_from_unsigned_overflow,
a_offset = a_offset,
b_offset = b_offset,
+ is_addr = is_addr,
);
}
// The signed form of the intrinsic allows this. If we interpret the
@@ -328,14 +313,23 @@ pub fn emulate_intrinsic(
}
};
- // Check that the range between them is dereferenceable ("in-bounds or one past the
- // end of the same allocation"). This is like the check in ptr_offset_inbounds.
- let min_ptr = if dist >= 0 { b } else { a };
- self.check_ptr_access(
- min_ptr,
- Size::from_bytes(dist.unsigned_abs()),
+ // Check that the memory between them is dereferenceable at all, starting from the
+ // origin pointer: `dist` is `a - b`, so it is based on `b`.
+ self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)?;
+ // Then check that this is also dereferenceable from `a`. This ensures that they are
+ // derived from the same allocation.
+ self.check_ptr_access_signed(
+ a,
+ dist.checked_neg().unwrap(), // i64::MIN is impossible as no allocation can be that large
CheckInAllocMsg::OffsetFromTest,
- )?;
+ )
+ .map_err(|_| {
+ // Make the error more specific.
+ err_ub_custom!(
+ fluent::const_eval_offset_from_different_allocations,
+ name = intrinsic_name,
+ )
+ })?;
// Perform division by size to compute return value.
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
@@ -455,7 +449,7 @@ pub fn emulate_intrinsic(
Ok(true)
}
- pub(super) fn emulate_nondiverging_intrinsic(
+ pub(super) fn eval_nondiverging_intrinsic(
&mut self,
intrinsic: &NonDivergingIntrinsic<'tcx>,
) -> InterpResult<'tcx> {
@@ -518,7 +512,7 @@ pub fn exact_div(
dest: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
assert_eq!(a.layout.ty, b.layout.ty);
- assert!(matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..)));
+ assert_matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..));
// Performs an exact division, resulting in undefined behavior where
// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
@@ -544,8 +538,8 @@ pub fn saturating_arith(
r: &ImmTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
assert_eq!(l.layout.ty, r.layout.ty);
- assert!(matches!(l.layout.ty.kind(), ty::Int(..) | ty::Uint(..)));
- assert!(matches!(mir_op, BinOp::Add | BinOp::Sub));
+ assert_matches!(l.layout.ty.kind(), ty::Int(..) | ty::Uint(..));
+ assert_matches!(mir_op, BinOp::Add | BinOp::Sub);
let (val, overflowed) =
self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair();
@@ -582,27 +576,16 @@ pub fn saturating_arith(
}
/// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
- /// allocation. For integer pointers, we consider each of them their own tiny allocation of size
- /// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.
+ /// allocation.
pub fn ptr_offset_inbounds(
&self,
ptr: Pointer<Option<M::Provenance>>,
offset_bytes: i64,
) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
- // The offset being in bounds cannot rely on "wrapping around" the address space.
- // So, first rule out overflows in the pointer arithmetic.
- let offset_ptr = ptr.signed_offset(offset_bytes, self)?;
- // ptr and offset_ptr must be in bounds of the same allocated object. This means all of the
- // memory between these pointers must be accessible. Note that we do not require the
- // pointers to be properly aligned (unlike a read/write operation).
- let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
- // This call handles checking for integer/null pointers.
- self.check_ptr_access(
- min_ptr,
- Size::from_bytes(offset_bytes.unsigned_abs()),
- CheckInAllocMsg::PointerArithmeticTest,
- )?;
- Ok(offset_ptr)
+ // The offset must be in bounds starting from `ptr`.
+ self.check_ptr_access_signed(ptr, offset_bytes, CheckInAllocMsg::PointerArithmeticTest)?;
+ // This also implies that there is no overflow, so we are done.
+ Ok(ptr.wrapping_signed_offset(offset_bytes, self))
}
/// Copy `count*size_of::<T>()` many bytes from `*src` to `*dst`.
@@ -709,9 +692,6 @@ pub(crate) fn raw_eq_intrinsic(
// zero-sized access
return Ok(&[]);
};
- if alloc_ref.has_provenance() {
- throw_ub_custom!(fluent::const_eval_raw_eq_with_provenance);
- }
alloc_ref.get_bytes_strip_provenance()
};
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 7f2e9ce..761ab81 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -8,10 +8,9 @@
use rustc_apfloat::{Float, FloatConvert};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_middle::mir;
use rustc_middle::query::TyCtxtAt;
-use rustc_middle::ty;
use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::{mir, ty};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_target::abi::{Align, Size};
@@ -20,7 +19,7 @@
use super::{
throw_unsup, throw_unsup_format, AllocBytes, AllocId, AllocKind, AllocRange, Allocation,
ConstAllocation, CtfeProvenance, FnArg, Frame, ImmTy, InterpCx, InterpResult, MPlaceTy,
- MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance,
+ MemoryKind, Misalignment, OpTy, PlaceTy, Pointer, Provenance, CTFE_ALLOC_SALT,
};
/// Data returned by [`Machine::after_stack_pop`], and consumed by
@@ -38,7 +37,7 @@ pub enum ReturnAction {
/// took care of everything.
NoJump,
- /// Returned by [`InterpCx::pop_stack_frame`] when no cleanup should be done.
+ /// Returned by [`InterpCx::pop_stack_frame_raw`] when no cleanup should be done.
NoCleanup,
}
@@ -166,6 +165,13 @@ fn alignment_check(
/// Whether to enforce the validity invariant for a specific layout.
fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool;
+ /// Whether to enforce the validity invariant *recursively*.
+ fn enforce_validity_recursively(
+ _ecx: &InterpCx<'tcx, Self>,
+ _layout: TyAndLayout<'tcx>,
+ ) -> bool {
+ false
+ }
/// Whether function calls should be [ABI](CallAbi)-checked.
fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool {
@@ -322,15 +328,21 @@ fn expose_ptr(
ptr: Pointer<Self::Provenance>,
) -> InterpResult<'tcx>;
- /// Convert a pointer with provenance into an allocation-offset pair
- /// and extra provenance info.
+ /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info.
+ /// `size` says how many bytes of memory are expected at that pointer. The *sign* of `size` can
+ /// be used to disambiguate situations where a wildcard pointer sits right in between two
+ /// allocations.
///
- /// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`.
+ /// If `ptr.provenance.get_alloc_id()` is `Some(p)`, the returned `AllocId` must be `p`.
+ /// The resulting `AllocId` will just be used for that one step and the forgotten again
+ /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be
+ /// stored in machine state).
///
/// When this fails, that means the pointer does not point to a live allocation.
fn ptr_get_alloc(
ecx: &InterpCx<'tcx, Self>,
ptr: Pointer<Self::Provenance>,
+ size: i64,
) -> Option<(AllocId, Size, Self::ProvenanceExtra)>;
/// Called to adjust global allocations to the Provenance and AllocExtra of this machine.
@@ -563,6 +575,14 @@ fn eval_mir_constant<F>(
{
eval(ecx, val, span, layout)
}
+
+ /// Returns the salt to be used for a deduplicated global alloation.
+ /// If the allocation is for a function, the instance is provided as well
+ /// (this lets Miri ensure unique addresses for some functions).
+ fn get_global_alloc_salt(
+ ecx: &InterpCx<'tcx, Self>,
+ instance: Option<ty::Instance<'tcx>>,
+ ) -> usize;
}
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
@@ -659,9 +679,18 @@ fn ptr_from_addr_cast(
fn ptr_get_alloc(
_ecx: &InterpCx<$tcx, Self>,
ptr: Pointer<CtfeProvenance>,
+ _size: i64,
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
// We know `offset` is relative to the allocation, so we can use `into_parts`.
let (prov, offset) = ptr.into_parts();
Some((prov.alloc_id(), offset, prov.immutable()))
}
+
+ #[inline(always)]
+ fn get_global_alloc_salt(
+ _ecx: &InterpCx<$tcx, Self>,
+ _instance: Option<ty::Instance<$tcx>>,
+ ) -> usize {
+ CTFE_ALLOC_SALT
+ }
}
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 36fe8df..910aec9 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -10,8 +10,7 @@
use std::borrow::Cow;
use std::cell::Cell;
use std::collections::VecDeque;
-use std::fmt;
-use std::ptr;
+use std::{fmt, ptr};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -20,17 +19,15 @@
use rustc_middle::mir::display_allocation;
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
use rustc_target::abi::{Align, HasDataLayout, Size};
-
use tracing::{debug, instrument, trace};
-use crate::fluent_generated as fluent;
-
use super::{
alloc_range, err_ub, err_ub_custom, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format,
AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckAlignMsg, CheckInAllocMsg,
CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Misalignment, Pointer,
PointerArithmetic, Provenance, Scalar,
};
+use crate::fluent_generated as fluent;
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum MemoryKind<T> {
@@ -198,7 +195,10 @@ pub fn global_root_pointer(
pub fn fn_ptr(&mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>) -> Pointer<M::Provenance> {
let id = match fn_val {
- FnVal::Instance(instance) => self.tcx.reserve_and_set_fn_alloc(instance),
+ FnVal::Instance(instance) => {
+ let salt = M::get_global_alloc_salt(self, Some(instance));
+ self.tcx.reserve_and_set_fn_alloc(instance, salt)
+ }
FnVal::Other(extra) => {
// FIXME(RalfJung): Should we have a cache here?
let id = self.tcx.reserve_alloc_id();
@@ -264,7 +264,7 @@ pub fn reallocate_ptr(
new_align: Align,
kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx, Pointer<M::Provenance>> {
- let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
if offset.bytes() != 0 {
throw_ub_custom!(
fluent::const_eval_realloc_or_alloc_with_offset,
@@ -294,7 +294,7 @@ pub fn deallocate_ptr(
old_size_and_align: Option<(Size, Align)>,
kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx> {
- let (alloc_id, offset, prov) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, prov) = self.ptr_get_alloc_id(ptr, 0)?;
trace!("deallocating: {alloc_id:?}");
if offset.bytes() != 0 {
@@ -386,6 +386,7 @@ fn get_ptr_access(
ptr: Pointer<Option<M::Provenance>>,
size: Size,
) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> {
+ let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
self.check_and_deref_ptr(
ptr,
size,
@@ -407,6 +408,23 @@ pub fn check_ptr_access(
size: Size,
msg: CheckInAllocMsg,
) -> InterpResult<'tcx> {
+ let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
+ self.check_and_deref_ptr(ptr, size, msg, |alloc_id, _, _| {
+ let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?;
+ Ok((size, align, ()))
+ })?;
+ Ok(())
+ }
+
+ /// Check whether the given pointer points to live memory for a signed amount of bytes.
+ /// A negative amounts means that the given range of memory to the left of the pointer
+ /// needs to be dereferenceable.
+ pub fn check_ptr_access_signed(
+ &self,
+ ptr: Pointer<Option<M::Provenance>>,
+ size: i64,
+ msg: CheckInAllocMsg,
+ ) -> InterpResult<'tcx> {
self.check_and_deref_ptr(ptr, size, msg, |alloc_id, _, _| {
let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?;
Ok((size, align, ()))
@@ -416,7 +434,8 @@ pub fn check_ptr_access(
/// Low-level helper function to check if a ptr is in-bounds and potentially return a reference
/// to the allocation it points to. Supports both shared and mutable references, as the actual
- /// checking is offloaded to a helper closure.
+ /// checking is offloaded to a helper closure. Supports signed sizes for checks "to the left" of
+ /// a pointer.
///
/// `alloc_size` will only get called for non-zero-sized accesses.
///
@@ -424,7 +443,7 @@ pub fn check_ptr_access(
fn check_and_deref_ptr<T>(
&self,
ptr: Pointer<Option<M::Provenance>>,
- size: Size,
+ size: i64,
msg: CheckInAllocMsg,
alloc_size: impl FnOnce(
AllocId,
@@ -433,25 +452,32 @@ fn check_and_deref_ptr<T>(
) -> InterpResult<'tcx, (Size, Align, T)>,
) -> InterpResult<'tcx, Option<T>> {
// Everything is okay with size 0.
- if size.bytes() == 0 {
+ if size == 0 {
return Ok(None);
}
- Ok(match self.ptr_try_get_alloc_id(ptr) {
+ Ok(match self.ptr_try_get_alloc_id(ptr, size) {
Err(addr) => {
// We couldn't get a proper allocation.
- throw_ub!(DanglingIntPointer(addr, msg));
+ throw_ub!(DanglingIntPointer { addr, inbounds_size: size, msg });
}
Ok((alloc_id, offset, prov)) => {
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
- // Test bounds.
- // It is sufficient to check this for the end pointer. Also check for overflow!
- if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
+ let offset = offset.bytes();
+ // Compute absolute begin and end of the range.
+ let (begin, end) = if size >= 0 {
+ (Some(offset), offset.checked_add(size as u64))
+ } else {
+ (offset.checked_sub(size.unsigned_abs()), Some(offset))
+ };
+ // Ensure both are within bounds.
+ let in_bounds = begin.is_some() && end.is_some_and(|e| e <= alloc_size.bytes());
+ if !in_bounds {
throw_ub!(PointerOutOfBounds {
alloc_id,
alloc_size,
- ptr_offset: self.target_usize_to_isize(offset.bytes()),
- ptr_size: size,
+ ptr_offset: self.sign_extend_to_target_isize(offset),
+ inbounds_size: size,
msg,
})
}
@@ -482,7 +508,7 @@ pub(super) fn is_ptr_misaligned(
}
#[inline]
- fn offset_misalignment(offset: u64, align: Align) -> Option<Misalignment> {
+ fn is_offset_misaligned(offset: u64, align: Align) -> Option<Misalignment> {
if offset % align.bytes() == 0 {
None
} else {
@@ -492,8 +518,8 @@ fn offset_misalignment(offset: u64, align: Align) -> Option<Misalignment> {
}
}
- match self.ptr_try_get_alloc_id(ptr) {
- Err(addr) => offset_misalignment(addr, align),
+ match self.ptr_try_get_alloc_id(ptr, 0) {
+ Err(addr) => is_offset_misaligned(addr, align),
Ok((alloc_id, offset, _prov)) => {
let (_size, alloc_align, kind) = self.get_alloc_info(alloc_id);
if let Some(misalign) =
@@ -501,14 +527,13 @@ fn offset_misalignment(offset: u64, align: Align) -> Option<Misalignment> {
{
Some(misalign)
} else if M::Provenance::OFFSET_IS_ADDR {
- // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true.
- offset_misalignment(ptr.addr().bytes(), align)
+ is_offset_misaligned(ptr.addr().bytes(), align)
} else {
// Check allocation alignment and offset alignment.
if alloc_align.bytes() < align.bytes() {
Some(Misalignment { has: alloc_align, required: align })
} else {
- offset_misalignment(offset.bytes(), align)
+ is_offset_misaligned(offset.bytes(), align)
}
}
}
@@ -644,9 +669,10 @@ pub fn get_ptr_alloc<'a>(
size: Size,
) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
{
+ let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
let ptr_and_alloc = self.check_and_deref_ptr(
ptr,
- size,
+ size_i64,
CheckInAllocMsg::MemoryAccessTest,
|alloc_id, offset, prov| {
let alloc = self.get_alloc_raw(alloc_id)?;
@@ -657,7 +683,7 @@ pub fn get_ptr_alloc<'a>(
// accesses. That means we cannot rely on the closure above or the `Some` branch below. We
// do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
if !self.memory.validation_in_progress.get() {
- if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr) {
+ if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
M::before_alloc_read(self, alloc_id)?;
}
}
@@ -878,7 +904,7 @@ pub fn get_ptr_fn(
ptr: Pointer<Option<M::Provenance>>,
) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
trace!("get_ptr_fn({:?})", ptr);
- let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
if offset.bytes() != 0 {
throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset)))
}
@@ -894,7 +920,7 @@ pub fn get_ptr_vtable_ty(
expected_trait: Option<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>,
) -> InterpResult<'tcx, Ty<'tcx>> {
trace!("get_ptr_vtable({:?})", ptr);
- let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr, 0)?;
if offset.bytes() != 0 {
throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset)))
}
@@ -983,8 +1009,11 @@ pub fn find_leaked_allocations(
})
}
- /// Runs the close in "validation" mode, which means the machine's memory read hooks will be
+ /// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
/// suppressed. Needless to say, this must only be set with great care! Cannot be nested.
+ ///
+ /// We do this so Miri's allocation access tracking does not show the validation
+ /// reads as spurious accesses.
pub(super) fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R {
// This deliberately uses `==` on `bool` to follow the pattern
// `assert!(val.replace(new) == old)`.
@@ -1375,7 +1404,7 @@ pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<
Err(_) => {
// Can only happen during CTFE.
let ptr = scalar.to_pointer(self)?;
- match self.ptr_try_get_alloc_id(ptr) {
+ match self.ptr_try_get_alloc_id(ptr, 0) {
Ok((alloc_id, offset, _)) => {
let (size, _align, _kind) = self.get_alloc_info(alloc_id);
// If the pointer is out-of-bounds, it may be null.
@@ -1391,6 +1420,12 @@ pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<
/// Turning a "maybe pointer" into a proper pointer (and some information
/// about where it points), or an absolute address.
///
+ /// `size` says how many bytes of memory are expected at that pointer. This is largely only used
+ /// for error messages; however, the *sign* of `size` can be used to disambiguate situations
+ /// where a wildcard pointer sits right in between two allocations.
+ /// It is almost always okay to just set the size to 0; this will be treated like a positive size
+ /// for handling wildcard pointers.
+ ///
/// The result must be used immediately; it is not allowed to convert
/// the returned data back into a `Pointer` and store that in machine state.
/// (In fact that's not even possible since `M::ProvenanceExtra` is generic and
@@ -1398,9 +1433,10 @@ pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<
pub fn ptr_try_get_alloc_id(
&self,
ptr: Pointer<Option<M::Provenance>>,
+ size: i64,
) -> Result<(AllocId, Size, M::ProvenanceExtra), u64> {
match ptr.into_pointer_or_addr() {
- Ok(ptr) => match M::ptr_get_alloc(self, ptr) {
+ Ok(ptr) => match M::ptr_get_alloc(self, ptr, size) {
Some((alloc_id, offset, extra)) => Ok((alloc_id, offset, extra)),
None => {
assert!(M::Provenance::OFFSET_IS_ADDR);
@@ -1414,6 +1450,12 @@ pub fn ptr_try_get_alloc_id(
/// Turning a "maybe pointer" into a proper pointer (and some information about where it points).
///
+ /// `size` says how many bytes of memory are expected at that pointer. This is largely only used
+ /// for error messages; however, the *sign* of `size` can be used to disambiguate situations
+ /// where a wildcard pointer sits right in between two allocations.
+ /// It is almost always okay to just set the size to 0; this will be treated like a positive size
+ /// for handling wildcard pointers.
+ ///
/// The result must be used immediately; it is not allowed to convert
/// the returned data back into a `Pointer` and store that in machine state.
/// (In fact that's not even possible since `M::ProvenanceExtra` is generic and
@@ -1422,9 +1464,15 @@ pub fn ptr_try_get_alloc_id(
pub fn ptr_get_alloc_id(
&self,
ptr: Pointer<Option<M::Provenance>>,
+ size: i64,
) -> InterpResult<'tcx, (AllocId, Size, M::ProvenanceExtra)> {
- self.ptr_try_get_alloc_id(ptr).map_err(|offset| {
- err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into()
+ self.ptr_try_get_alloc_id(ptr, size).map_err(|offset| {
+ err_ub!(DanglingIntPointer {
+ addr: offset,
+ inbounds_size: size,
+ msg: CheckInAllocMsg::InboundsTest
+ })
+ .into()
})
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index f703c6f..511756e 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -1,5 +1,6 @@
//! An interpreter for MIR used in CTFE and by miri
+mod call;
mod cast;
mod discriminant;
mod eval_context;
@@ -11,35 +12,32 @@
mod operator;
mod place;
mod projection;
+mod stack;
mod step;
-mod terminator;
mod traits;
mod util;
mod validity;
mod visitor;
+use eval_context::{from_known_layout, mir_assign_valid_types};
#[doc(no_inline)]
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
-pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup};
+pub use self::call::FnArg;
+pub use self::eval_context::{format_interp_error, InterpCx};
pub use self::intern::{
intern_const_alloc_for_constprop, intern_const_alloc_recursive, HasStaticRootDefId, InternKind,
InternResult,
};
+pub(crate) use self::intrinsics::eval_nullary_intrinsic;
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, ReturnAction};
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
+use self::operand::Operand;
pub use self::operand::{ImmTy, Immediate, OpTy, Readable};
pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
+use self::place::{MemPlace, Place};
pub use self::projection::{OffsetMode, Projectable};
-pub use self::terminator::FnArg;
+pub use self::stack::{Frame, FrameInfo, LocalState, StackPopCleanup, StackPopInfo};
+pub(crate) use self::util::create_static_alloc;
pub use self::validity::{CtfeValidationMode, RefTracking};
pub use self::visitor::ValueVisitor;
-
-use self::{
- operand::Operand,
- place::{MemPlace, Place},
-};
-
-pub(crate) use self::intrinsics::eval_nullary_intrinsic;
-pub(crate) use self::util::create_static_alloc;
-use eval_context::{from_known_layout, mir_assign_valid_types};
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 0a7e985..ad87d69 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -4,16 +4,14 @@
use std::assert_matches::assert_matches;
use either::{Either, Left, Right};
-use tracing::trace;
-
use rustc_hir::def::Namespace;
use rustc_middle::mir::interpret::ScalarSizeMismatch;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt};
-use rustc_middle::{bug, span_bug};
-use rustc_middle::{mir, ty};
+use rustc_middle::{bug, mir, span_bug, ty};
use rustc_target::abi::{self, Abi, HasDataLayout, Size};
+use tracing::trace;
use super::{
alloc_range, err_ub, from_known_layout, mir_assign_valid_types, throw_ub, CtfeProvenance,
@@ -186,6 +184,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
#[inline]
pub fn from_scalar(val: Scalar<Prov>, layout: TyAndLayout<'tcx>) -> Self {
debug_assert!(layout.abi.is_scalar(), "`ImmTy::from_scalar` on non-scalar layout");
+ debug_assert_eq!(val.size(), layout.size);
ImmTy { imm: val.into(), layout }
}
@@ -343,7 +342,7 @@ fn offset_(&self, offset: Size, layout: TyAndLayout<'tcx>, cx: &impl HasDataLayo
}
// extract fields from types with `ScalarPair` ABI
(Immediate::ScalarPair(a_val, b_val), Abi::ScalarPair(a, b)) => {
- assert!(matches!(layout.abi, Abi::Scalar(..)));
+ assert_matches!(layout.abi, Abi::Scalar(..));
Immediate::from(if offset.bytes() == 0 {
debug_assert_eq!(layout.size, a.size(cx));
a_val
@@ -835,8 +834,9 @@ pub(crate) fn const_val_to_op(
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(Immediate, 48);
static_assert_size!(ImmTy<'_>, 64);
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 2723507..2f860f9 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -1,15 +1,14 @@
use either::Either;
-
use rustc_apfloat::{Float, FloatConvert};
-use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
+use rustc_middle::mir::NullOp;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
-use rustc_middle::ty::{self, FloatTy, ScalarInt};
-use rustc_middle::{bug, span_bug};
+use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty};
+use rustc_middle::{bug, mir, span_bug};
use rustc_span::symbol::sym;
use tracing::trace;
-use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta};
+use super::{throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta};
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
@@ -300,17 +299,23 @@ fn binary_ptr_op(
// Pointer ops that are always supported.
Offset => {
let ptr = left.to_scalar().to_pointer(self)?;
- let offset_count = right.to_scalar().to_target_isize(self)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
+ let pointee_layout = self.layout_of(pointee_ty)?;
+ assert!(pointee_layout.abi.is_sized());
// We cannot overflow i64 as a type's size must be <= isize::MAX.
- let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
- // The computed offset, in bytes, must not overflow an isize.
- // `checked_mul` enforces a too small bound, but no actual allocation can be big enough for
- // the difference to be noticeable.
- let offset_bytes =
- offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
+ let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap();
+ let pointee_size = ImmTy::from_int(pointee_size, right.layout);
+ // Multiply element size and element count.
+ let (val, overflowed) = self
+ .binary_op(mir::BinOp::MulWithOverflow, right, &pointee_size)?
+ .to_scalar_pair();
+ // This must not overflow.
+ if overflowed.to_bool()? {
+ throw_ub!(PointerArithOverflow)
+ }
+ let offset_bytes = val.to_target_isize(self)?;
let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?;
Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout))
}
@@ -331,11 +336,7 @@ pub fn binary_op(
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
trace!(
"Running binary op {:?}: {:?} ({}), {:?} ({})",
- bin_op,
- *left,
- left.layout.ty,
- *right,
- right.layout.ty
+ bin_op, *left, left.layout.ty, *right, right.layout.ty
);
match left.layout.ty.kind() {
@@ -480,4 +481,38 @@ pub fn unary_op(
}
}
}
+
+ pub fn nullary_op(
+ &self,
+ null_op: NullOp<'tcx>,
+ arg_ty: Ty<'tcx>,
+ ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
+ use rustc_middle::mir::NullOp::*;
+
+ let layout = self.layout_of(arg_ty)?;
+ let usize_layout = || self.layout_of(self.tcx.types.usize).unwrap();
+
+ Ok(match null_op {
+ SizeOf => {
+ if !layout.abi.is_sized() {
+ span_bug!(self.cur_span(), "unsized type for `NullaryOp::SizeOf`");
+ }
+ let val = layout.size.bytes();
+ ImmTy::from_uint(val, usize_layout())
+ }
+ AlignOf => {
+ if !layout.abi.is_sized() {
+ span_bug!(self.cur_span(), "unsized type for `NullaryOp::AlignOf`");
+ }
+ let val = layout.align.abi.bytes();
+ ImmTy::from_uint(val, usize_layout())
+ }
+ OffsetOf(fields) => {
+ let val =
+ self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes();
+ ImmTy::from_uint(val, usize_layout())
+ }
+ UbChecks => ImmTy::from_bool(self.tcx.sess.ub_checks(), *self.tcx),
+ })
+ }
}
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 33c25b7..2afdd02 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -5,20 +5,17 @@
use std::assert_matches::assert_matches;
use either::{Either, Left, Right};
-use tracing::{instrument, trace};
-
use rustc_ast::Mutability;
-use rustc_middle::mir;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
-use rustc_middle::{bug, span_bug};
+use rustc_middle::{bug, mir, span_bug};
use rustc_target::abi::{Abi, Align, HasDataLayout, Size};
+use tracing::{instrument, trace};
use super::{
- alloc_range, mir_assign_valid_types, throw_ub, AllocRef, AllocRefMut, CheckAlignMsg,
- CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment,
- OffsetMode, OpTy, Operand, Pointer, PointerArithmetic, Projectable, Provenance, Readable,
- Scalar,
+ alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance,
+ ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy,
+ Operand, Pointer, Projectable, Provenance, Readable, Scalar,
};
#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
@@ -87,9 +84,6 @@ fn offset_with_meta_<'tcx, M: Machine<'tcx, Provenance = Prov>>(
!meta.has_meta() || self.meta.has_meta(),
"cannot use `offset_with_meta` to add metadata to a place"
);
- if offset > ecx.data_layout().max_size_of_val() {
- throw_ub!(PointerArithOverflow);
- }
let ptr = match mode {
OffsetMode::Inbounds => {
ecx.ptr_offset_inbounds(self.ptr, offset.bytes().try_into().unwrap())?
@@ -291,10 +285,8 @@ fn offset_with_meta<M: Machine<'tcx, Provenance = Prov>>(
// projections are type-checked and bounds-checked.
assert!(offset + layout.size <= self.layout.size);
- let new_offset = Size::from_bytes(
- ecx.data_layout()
- .offset(old_offset.unwrap_or(Size::ZERO).bytes(), offset.bytes())?,
- );
+ // Size `+`, ensures no overflow.
+ let new_offset = old_offset.unwrap_or(Size::ZERO) + offset;
PlaceTy {
place: Place::Local { local, offset: Some(new_offset), locals_addr },
@@ -580,7 +572,10 @@ pub fn write_immediate(
if M::enforce_validity(self, dest.layout()) {
// Data got changed, better make sure it matches the type!
- self.validate_operand(&dest.to_op(self)?)?;
+ self.validate_operand(
+ &dest.to_op(self)?,
+ M::enforce_validity_recursively(self, dest.layout()),
+ )?;
}
Ok(())
@@ -819,7 +814,10 @@ fn copy_op_inner(
// Generally for transmutation, data must be valid both at the old and new type.
// But if the types are the same, the 2nd validation below suffices.
if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) {
- self.validate_operand(&src.to_op(self)?)?;
+ self.validate_operand(
+ &src.to_op(self)?,
+ M::enforce_validity_recursively(self, src.layout()),
+ )?;
}
// Do the actual copy.
@@ -827,7 +825,10 @@ fn copy_op_inner(
if validate_dest && M::enforce_validity(self, dest.layout()) {
// Data got changed, better make sure it matches the type!
- self.validate_operand(&dest.to_op(self)?)?;
+ self.validate_operand(
+ &dest.to_op(self)?,
+ M::enforce_validity_recursively(self, dest.layout()),
+ )?;
}
Ok(())
@@ -1007,7 +1008,8 @@ pub fn allocate_str(
// Use cache for immutable strings.
let ptr = if mutbl.is_not() {
// Use dedup'd allocation function.
- let id = tcx.allocate_bytes_dedup(str.as_bytes());
+ let salt = M::get_global_alloc_salt(self, None);
+ let id = tcx.allocate_bytes_dedup(str.as_bytes(), salt);
// Turn untagged "global" pointers (obtained via `tcx`) into the machine pointer to the allocation.
M::adjust_alloc_root_pointer(&self, Pointer::from(id), Some(kind))?
@@ -1034,8 +1036,9 @@ pub fn raw_const_to_mplace(
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(MemPlace, 48);
static_assert_size!(MemPlaceMeta, 24);
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index cfa814c..dd8dd21 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -10,14 +10,10 @@
use std::marker::PhantomData;
use std::ops::Range;
-use rustc_middle::mir;
-use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::Ty;
-use rustc_middle::{bug, span_bug};
-use rustc_target::abi::Size;
-use rustc_target::abi::{self, VariantIdx};
-
+use rustc_middle::{bug, mir, span_bug, ty};
+use rustc_target::abi::{self, Size, VariantIdx};
use tracing::{debug, instrument};
use super::{
diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs
new file mode 100644
index 0000000..50dbced
--- /dev/null
+++ b/compiler/rustc_const_eval/src/interpret/stack.rs
@@ -0,0 +1,651 @@
+//! Manages the low-level pushing and popping of stack frames and the (de)allocation of local variables.
+//! For hadling of argument passing and return values, see the `call` module.
+use std::cell::Cell;
+use std::{fmt, mem};
+
+use either::{Either, Left, Right};
+use rustc_hir as hir;
+use rustc_hir::definitions::DefPathData;
+use rustc_index::IndexVec;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::{bug, mir};
+use rustc_mir_dataflow::storage::always_storage_live_locals;
+use rustc_span::Span;
+use tracing::{info_span, instrument, trace};
+
+use super::{
+ from_known_layout, throw_ub, throw_unsup, AllocId, CtfeProvenance, Immediate, InterpCx,
+ InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, MemoryKind, Operand, Pointer,
+ Provenance, ReturnAction, Scalar,
+};
+use crate::errors;
+
+// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
+// boundary and dropped in the other thread, it would exit the span in the other thread.
+struct SpanGuard(tracing::Span, std::marker::PhantomData<*const u8>);
+
+impl SpanGuard {
+ /// By default a `SpanGuard` does nothing.
+ fn new() -> Self {
+ Self(tracing::Span::none(), std::marker::PhantomData)
+ }
+
+ /// If a span is entered, we exit the previous span (if any, normally none) and enter the
+ /// new span. This is mainly so we don't have to use `Option` for the `tracing_span` field of
+ /// `Frame` by creating a dummy span to being with and then entering it once the frame has
+ /// been pushed.
+ fn enter(&mut self, span: tracing::Span) {
+ // This executes the destructor on the previous instance of `SpanGuard`, ensuring that
+ // we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we
+ // can't protect the tracing stack, but that'll just lead to weird logging, no actual
+ // problems.
+ *self = Self(span, std::marker::PhantomData);
+ self.0.with_subscriber(|(id, dispatch)| {
+ dispatch.enter(id);
+ });
+ }
+}
+
+impl Drop for SpanGuard {
+ fn drop(&mut self) {
+ self.0.with_subscriber(|(id, dispatch)| {
+ dispatch.exit(id);
+ });
+ }
+}
+
+/// A stack frame.
+pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
+ ////////////////////////////////////////////////////////////////////////////////
+ // Function and callsite information
+ ////////////////////////////////////////////////////////////////////////////////
+ /// The MIR for the function called on this frame.
+ pub(super) body: &'tcx mir::Body<'tcx>,
+
+ /// The def_id and args of the current function.
+ pub(super) instance: ty::Instance<'tcx>,
+
+ /// Extra data for the machine.
+ pub extra: Extra,
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Return place and locals
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Work to perform when returning from this function.
+ return_to_block: StackPopCleanup,
+
+ /// The location where the result of the current stack frame should be written to,
+ /// and its layout in the caller.
+ pub return_place: MPlaceTy<'tcx, Prov>,
+
+ /// The list of locals for this stack frame, stored in order as
+ /// `[return_ptr, arguments..., variables..., temporaries...]`.
+ /// The locals are stored as `Option<Value>`s.
+ /// `None` represents a local that is currently dead, while a live local
+ /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
+ ///
+ /// Do *not* access this directly; always go through the machine hook!
+ pub locals: IndexVec<mir::Local, LocalState<'tcx, Prov>>,
+
+ /// The span of the `tracing` crate is stored here.
+ /// When the guard is dropped, the span is exited. This gives us
+ /// a full stack trace on all tracing statements.
+ tracing_span: SpanGuard,
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Current position within the function
+ ////////////////////////////////////////////////////////////////////////////////
+ /// If this is `Right`, we are not currently executing any particular statement in
+ /// this frame (can happen e.g. during frame initialization, and during unwinding on
+ /// frames without cleanup code).
+ ///
+ /// Needs to be public because ConstProp does unspeakable things to it.
+ pub(super) loc: Either<mir::Location, Span>,
+}
+
+#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
+pub enum StackPopCleanup {
+ /// Jump to the next block in the caller, or cause UB if None (that's a function
+ /// that may never return). Also store layout of return place so
+ /// we can validate it at that layout.
+ /// `ret` stores the block we jump to on a normal return, while `unwind`
+ /// stores the block used for cleanup during unwinding.
+ Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction },
+ /// The root frame of the stack: nowhere else to jump to.
+ /// `cleanup` says whether locals are deallocated. Static computation
+ /// wants them leaked to intern what they need (and just throw away
+ /// the entire `ecx` when it is done).
+ Root { cleanup: bool },
+}
+
+/// Return type of [`InterpCx::pop_stack_frame_raw`].
+pub struct StackPopInfo<'tcx, Prov: Provenance> {
+ /// Additional information about the action to be performed when returning from the popped
+ /// stack frame.
+ pub return_action: ReturnAction,
+
+ /// [`return_to_block`](Frame::return_to_block) of the popped stack frame.
+ pub return_to_block: StackPopCleanup,
+
+ /// [`return_place`](Frame::return_place) of the popped stack frame.
+ pub return_place: MPlaceTy<'tcx, Prov>,
+}
+
+/// State of a local variable including a memoized layout
+#[derive(Clone)]
+pub struct LocalState<'tcx, Prov: Provenance = CtfeProvenance> {
+ value: LocalValue<Prov>,
+ /// Don't modify if `Some`, this is only used to prevent computing the layout twice.
+ /// Avoids computing the layout of locals that are never actually initialized.
+ layout: Cell<Option<TyAndLayout<'tcx>>>,
+}
+
+impl<Prov: Provenance> std::fmt::Debug for LocalState<'_, Prov> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("LocalState")
+ .field("value", &self.value)
+ .field("ty", &self.layout.get().map(|l| l.ty))
+ .finish()
+ }
+}
+
+/// Current value of a local variable
+///
+/// This does not store the type of the local; the type is given by `body.local_decls` and can never
+/// change, so by not storing here we avoid having to maintain that as an invariant.
+#[derive(Copy, Clone, Debug)] // Miri debug-prints these
+pub(super) enum LocalValue<Prov: Provenance = CtfeProvenance> {
+ /// This local is not currently alive, and cannot be used at all.
+ Dead,
+ /// A normal, live local.
+ /// Mostly for convenience, we re-use the `Operand` type here.
+ /// This is an optimization over just always having a pointer here;
+ /// we can thus avoid doing an allocation when the local just stores
+ /// immediate values *and* never has its address taken.
+ Live(Operand<Prov>),
+}
+
+impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
+ pub fn make_live_uninit(&mut self) {
+ self.value = LocalValue::Live(Operand::Immediate(Immediate::Uninit));
+ }
+
+ /// This is a hack because Miri needs a way to visit all the provenance in a `LocalState`
+ /// without having a layout or `TyCtxt` available, and we want to keep the `Operand` type
+ /// private.
+ pub fn as_mplace_or_imm(
+ &self,
+ ) -> Option<Either<(Pointer<Option<Prov>>, MemPlaceMeta<Prov>), Immediate<Prov>>> {
+ match self.value {
+ LocalValue::Dead => None,
+ LocalValue::Live(Operand::Indirect(mplace)) => Some(Left((mplace.ptr, mplace.meta))),
+ LocalValue::Live(Operand::Immediate(imm)) => Some(Right(imm)),
+ }
+ }
+
+ /// Read the local's value or error if the local is not yet live or not live anymore.
+ #[inline(always)]
+ pub(super) fn access(&self) -> InterpResult<'tcx, &Operand<Prov>> {
+ match &self.value {
+ LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
+ LocalValue::Live(val) => Ok(val),
+ }
+ }
+
+ /// Overwrite the local. If the local can be overwritten in place, return a reference
+ /// to do so; otherwise return the `MemPlace` to consult instead.
+ #[inline(always)]
+ pub(super) fn access_mut(&mut self) -> InterpResult<'tcx, &mut Operand<Prov>> {
+ match &mut self.value {
+ LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
+ LocalValue::Live(val) => Ok(val),
+ }
+ }
+}
+
+/// What we store about a frame in an interpreter backtrace.
+#[derive(Clone, Debug)]
+pub struct FrameInfo<'tcx> {
+ pub instance: ty::Instance<'tcx>,
+ pub span: Span,
+}
+
+// FIXME: only used by miri, should be removed once translatable.
+impl<'tcx> fmt::Display for FrameInfo<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ ty::tls::with(|tcx| {
+ if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
+ write!(f, "inside closure")
+ } else {
+ // Note: this triggers a `must_produce_diag` state, which means that if we ever
+ // get here we must emit a diagnostic. We should never display a `FrameInfo` unless
+ // we actually want to emit a warning or error to the user.
+ write!(f, "inside `{}`", self.instance)
+ }
+ })
+ }
+}
+
+impl<'tcx> FrameInfo<'tcx> {
+ pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
+ let span = self.span;
+ if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
+ errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
+ } else {
+ let instance = format!("{}", self.instance);
+ // Note: this triggers a `must_produce_diag` state, which means that if we ever get
+ // here we must emit a diagnostic. We should never display a `FrameInfo` unless we
+ // actually want to emit a warning or error to the user.
+ errors::FrameNote { where_: "instance", span, instance, times: 0 }
+ }
+ }
+}
+
+impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
+ pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'tcx, Prov, Extra> {
+ Frame {
+ body: self.body,
+ instance: self.instance,
+ return_to_block: self.return_to_block,
+ return_place: self.return_place,
+ locals: self.locals,
+ loc: self.loc,
+ extra,
+ tracing_span: self.tracing_span,
+ }
+ }
+}
+
+impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
+ /// Get the current location within the Frame.
+ ///
+ /// If this is `Right`, we are not currently executing any particular statement in
+ /// this frame (can happen e.g. during frame initialization, and during unwinding on
+ /// frames without cleanup code).
+ ///
+ /// Used by [priroda](https://github.com/oli-obk/priroda).
+ pub fn current_loc(&self) -> Either<mir::Location, Span> {
+ self.loc
+ }
+
+ pub fn body(&self) -> &'tcx mir::Body<'tcx> {
+ self.body
+ }
+
+ pub fn instance(&self) -> ty::Instance<'tcx> {
+ self.instance
+ }
+
+ /// Return the `SourceInfo` of the current instruction.
+ pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
+ self.loc.left().map(|loc| self.body.source_info(loc))
+ }
+
+ pub fn current_span(&self) -> Span {
+ match self.loc {
+ Left(loc) => self.body.source_info(loc).span,
+ Right(span) => span,
+ }
+ }
+
+ pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option<hir::HirId> {
+ // We first try to get a HirId via the current source scope,
+ // and fall back to `body.source`.
+ self.current_source_info()
+ .and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data {
+ mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
+ mir::ClearCrossCrate::Clear => None,
+ })
+ .or_else(|| {
+ let def_id = self.body.source.def_id().as_local();
+ def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
+ })
+ }
+
+ /// Returns the address of the buffer where the locals are stored. This is used by `Place` as a
+ /// sanity check to detect bugs where we mix up which stack frame a place refers to.
+ #[inline(always)]
+ pub(super) fn locals_addr(&self) -> usize {
+ self.locals.raw.as_ptr().addr()
+ }
+
+ #[must_use]
+ pub fn generate_stacktrace_from_stack(stack: &[Self]) -> Vec<FrameInfo<'tcx>> {
+ let mut frames = Vec::new();
+ // This deliberately does *not* honor `requires_caller_location` since it is used for much
+ // more than just panics.
+ for frame in stack.iter().rev() {
+ let span = match frame.loc {
+ Left(loc) => {
+ // If the stacktrace passes through MIR-inlined source scopes, add them.
+ let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc);
+ let mut scope_data = &frame.body.source_scopes[scope];
+ while let Some((instance, call_span)) = scope_data.inlined {
+ frames.push(FrameInfo { span, instance });
+ span = call_span;
+ scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()];
+ }
+ span
+ }
+ Right(span) => span,
+ };
+ frames.push(FrameInfo { span, instance: frame.instance });
+ }
+ trace!("generate stacktrace: {:#?}", frames);
+ frames
+ }
+}
+
+impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
+ /// Very low-level helper that pushes a stack frame without initializing
+ /// the arguments or local variables.
+ ///
+ /// The high-level version of this is `init_stack_frame`.
+ #[instrument(skip(self, body, return_place, return_to_block), level = "debug")]
+ pub(crate) fn push_stack_frame_raw(
+ &mut self,
+ instance: ty::Instance<'tcx>,
+ body: &'tcx mir::Body<'tcx>,
+ return_place: &MPlaceTy<'tcx, M::Provenance>,
+ return_to_block: StackPopCleanup,
+ ) -> InterpResult<'tcx> {
+ trace!("body: {:#?}", body);
+
+ // We can push a `Root` frame if and only if the stack is empty.
+ debug_assert_eq!(
+ self.stack().is_empty(),
+ matches!(return_to_block, StackPopCleanup::Root { .. })
+ );
+
+ // First push a stack frame so we have access to `instantiate_from_current_frame` and other
+ // `self.frame()`-based functions.
+ let dead_local = LocalState { value: LocalValue::Dead, layout: Cell::new(None) };
+ let locals = IndexVec::from_elem(dead_local, &body.local_decls);
+ let pre_frame = Frame {
+ body,
+ loc: Right(body.span), // Span used for errors caused during preamble.
+ return_to_block,
+ return_place: return_place.clone(),
+ locals,
+ instance,
+ tracing_span: SpanGuard::new(),
+ extra: (),
+ };
+ let frame = M::init_frame(self, pre_frame)?;
+ self.stack_mut().push(frame);
+
+ // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
+ for &const_ in body.required_consts() {
+ let c =
+ self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
+ c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| {
+ err.emit_note(*self.tcx);
+ err
+ })?;
+ }
+
+ // Finish things up.
+ M::after_stack_push(self)?;
+ self.frame_mut().loc = Left(mir::Location::START);
+ let span = info_span!("frame", "{}", instance);
+ self.frame_mut().tracing_span.enter(span);
+
+ Ok(())
+ }
+
+ /// Low-level helper that pops a stack frame from the stack and returns some information about
+ /// it.
+ ///
+ /// This also deallocates locals, if necessary.
+ ///
+ /// [`M::before_stack_pop`] should be called before calling this function.
+ /// [`M::after_stack_pop`] is called by this function automatically.
+ ///
+ /// The high-level version of this is `return_from_current_stack_frame`.
+ ///
+ /// [`M::before_stack_pop`]: Machine::before_stack_pop
+ /// [`M::after_stack_pop`]: Machine::after_stack_pop
+ pub(super) fn pop_stack_frame_raw(
+ &mut self,
+ unwinding: bool,
+ ) -> InterpResult<'tcx, StackPopInfo<'tcx, M::Provenance>> {
+ let cleanup = self.cleanup_current_frame_locals()?;
+
+ let frame =
+ self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
+
+ let return_to_block = frame.return_to_block;
+ let return_place = frame.return_place.clone();
+
+ let return_action;
+ if cleanup {
+ return_action = M::after_stack_pop(self, frame, unwinding)?;
+ assert_ne!(return_action, ReturnAction::NoCleanup);
+ } else {
+ return_action = ReturnAction::NoCleanup;
+ };
+
+ Ok(StackPopInfo { return_action, return_to_block, return_place })
+ }
+
+ /// A private helper for [`pop_stack_frame_raw`](InterpCx::pop_stack_frame_raw).
+ /// Returns `true` if cleanup has been done, `false` otherwise.
+ fn cleanup_current_frame_locals(&mut self) -> InterpResult<'tcx, bool> {
+ // Cleanup: deallocate locals.
+ // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
+ // We do this while the frame is still on the stack, so errors point to the callee.
+ let return_to_block = self.frame().return_to_block;
+ let cleanup = match return_to_block {
+ StackPopCleanup::Goto { .. } => true,
+ StackPopCleanup::Root { cleanup, .. } => cleanup,
+ };
+
+ if cleanup {
+ // We need to take the locals out, since we need to mutate while iterating.
+ let locals = mem::take(&mut self.frame_mut().locals);
+ for local in &locals {
+ self.deallocate_local(local.value)?;
+ }
+ }
+
+ Ok(cleanup)
+ }
+
+ /// In the current stack frame, mark all locals as live that are not arguments and don't have
+ /// `Storage*` annotations (this includes the return place).
+ pub(crate) fn storage_live_for_always_live_locals(&mut self) -> InterpResult<'tcx> {
+ self.storage_live(mir::RETURN_PLACE)?;
+
+ let body = self.body();
+ let always_live = always_storage_live_locals(body);
+ for local in body.vars_and_temps_iter() {
+ if always_live.contains(local) {
+ self.storage_live(local)?;
+ }
+ }
+ Ok(())
+ }
+
+ pub fn storage_live_dyn(
+ &mut self,
+ local: mir::Local,
+ meta: MemPlaceMeta<M::Provenance>,
+ ) -> InterpResult<'tcx> {
+ trace!("{:?} is now live", local);
+
+ // We avoid `ty.is_trivially_sized` since that does something expensive for ADTs.
+ fn is_very_trivially_sized(ty: Ty<'_>) -> bool {
+ match ty.kind() {
+ ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
+ | ty::Uint(_)
+ | ty::Int(_)
+ | ty::Bool
+ | ty::Float(_)
+ | ty::FnDef(..)
+ | ty::FnPtr(_)
+ | ty::RawPtr(..)
+ | ty::Char
+ | ty::Ref(..)
+ | ty::Coroutine(..)
+ | ty::CoroutineWitness(..)
+ | ty::Array(..)
+ | ty::Closure(..)
+ | ty::CoroutineClosure(..)
+ | ty::Never
+ | ty::Error(_)
+ | ty::Dynamic(_, _, ty::DynStar) => true,
+
+ ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
+
+ ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
+
+ ty::Pat(ty, ..) => is_very_trivially_sized(*ty),
+
+ // We don't want to do any queries, so there is not much we can do with ADTs.
+ ty::Adt(..) => false,
+
+ ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
+
+ ty::Infer(ty::TyVar(_)) => false,
+
+ ty::Bound(..)
+ | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ bug!("`is_very_trivially_sized` applied to unexpected type: {}", ty)
+ }
+ }
+ }
+
+ // This is a hot function, we avoid computing the layout when possible.
+ // `unsized_` will be `None` for sized types and `Some(layout)` for unsized types.
+ let unsized_ = if is_very_trivially_sized(self.body().local_decls[local].ty) {
+ None
+ } else {
+ // We need the layout.
+ let layout = self.layout_of_local(self.frame(), local, None)?;
+ if layout.is_sized() { None } else { Some(layout) }
+ };
+
+ let local_val = LocalValue::Live(if let Some(layout) = unsized_ {
+ if !meta.has_meta() {
+ throw_unsup!(UnsizedLocal);
+ }
+ // Need to allocate some memory, since `Immediate::Uninit` cannot be unsized.
+ let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?;
+ Operand::Indirect(*dest_place.mplace())
+ } else {
+ assert!(!meta.has_meta()); // we're dropping the metadata
+ // Just make this an efficient immediate.
+ // Note that not calling `layout_of` here does have one real consequence:
+ // if the type is too big, we'll only notice this when the local is actually initialized,
+ // which is a bit too late -- we should ideally notice this already here, when the memory
+ // is conceptually allocated. But given how rare that error is and that this is a hot function,
+ // we accept this downside for now.
+ Operand::Immediate(Immediate::Uninit)
+ });
+
+ // If the local is already live, deallocate its old memory.
+ let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
+ self.deallocate_local(old)?;
+ Ok(())
+ }
+
+ /// Mark a storage as live, killing the previous content.
+ #[inline(always)]
+ pub fn storage_live(&mut self, local: mir::Local) -> InterpResult<'tcx> {
+ self.storage_live_dyn(local, MemPlaceMeta::None)
+ }
+
+ pub fn storage_dead(&mut self, local: mir::Local) -> InterpResult<'tcx> {
+ assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
+ trace!("{:?} is now dead", local);
+
+ // If the local is already dead, this is a NOP.
+ let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead);
+ self.deallocate_local(old)?;
+ Ok(())
+ }
+
+ fn deallocate_local(&mut self, local: LocalValue<M::Provenance>) -> InterpResult<'tcx> {
+ if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
+ // All locals have a backing allocation, even if the allocation is empty
+ // due to the local having ZST type. Hence we can `unwrap`.
+ trace!(
+ "deallocating local {:?}: {:?}",
+ local,
+ // Locals always have a `alloc_id` (they are never the result of a int2ptr).
+ self.dump_alloc(ptr.provenance.unwrap().get_alloc_id().unwrap())
+ );
+ self.deallocate_ptr(ptr, None, MemoryKind::Stack)?;
+ };
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(super) fn layout_of_local(
+ &self,
+ frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
+ local: mir::Local,
+ layout: Option<TyAndLayout<'tcx>>,
+ ) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+ let state = &frame.locals[local];
+ if let Some(layout) = state.layout.get() {
+ return Ok(layout);
+ }
+
+ let layout = from_known_layout(self.tcx, self.param_env, layout, || {
+ let local_ty = frame.body.local_decls[local].ty;
+ let local_ty =
+ self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
+ self.layout_of(local_ty)
+ })?;
+
+ // Layouts of locals are requested a lot, so we cache them.
+ state.layout.set(Some(layout));
+ Ok(layout)
+ }
+}
+
+impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
+ pub(super) fn print(
+ &self,
+ allocs: &mut Vec<Option<AllocId>>,
+ fmt: &mut std::fmt::Formatter<'_>,
+ ) -> std::fmt::Result {
+ match self.value {
+ LocalValue::Dead => write!(fmt, " is dead")?,
+ LocalValue::Live(Operand::Immediate(Immediate::Uninit)) => {
+ write!(fmt, " is uninitialized")?
+ }
+ LocalValue::Live(Operand::Indirect(mplace)) => {
+ write!(
+ fmt,
+ " by {} ref {:?}:",
+ match mplace.meta {
+ MemPlaceMeta::Meta(meta) => format!(" meta({meta:?})"),
+ MemPlaceMeta::None => String::new(),
+ },
+ mplace.ptr,
+ )?;
+ allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id));
+ }
+ LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
+ write!(fmt, " {val:?}")?;
+ if let Scalar::Ptr(ptr, _size) = val {
+ allocs.push(ptr.provenance.get_alloc_id());
+ }
+ }
+ LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
+ write!(fmt, " ({val1:?}, {val2:?})")?;
+ if let Scalar::Ptr(ptr, _size) = val1 {
+ allocs.push(ptr.provenance.get_alloc_id());
+ }
+ if let Scalar::Ptr(ptr, _size) = val2 {
+ allocs.push(ptr.provenance.get_alloc_id());
+ }
+ }
+ }
+
+ Ok(())
+ }
+}
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index b3124df..2527eca 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -3,19 +3,30 @@
//! The main entry point is the `step` method.
use either::Either;
+use rustc_index::IndexSlice;
+use rustc_middle::ty::layout::FnAbiOf;
+use rustc_middle::ty::{self, Instance, Ty};
+use rustc_middle::{bug, mir, span_bug};
+use rustc_span::source_map::Spanned;
+use rustc_target::abi::call::FnAbi;
+use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use tracing::{info, instrument, trace};
-use rustc_index::IndexSlice;
-use rustc_middle::mir;
-use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::{bug, span_bug};
-use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
-
use super::{
- ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta, PlaceTy, Projectable, Scalar,
+ throw_ub, FnArg, FnVal, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemPlaceMeta,
+ PlaceTy, Projectable, Scalar,
};
use crate::util;
+struct EvaluatedCalleeAndArgs<'tcx, M: Machine<'tcx>> {
+ callee: FnVal<'tcx, M::ExtraFnVal>,
+ args: Vec<FnArg<'tcx, M::Provenance>>,
+ fn_sig: ty::FnSig<'tcx>,
+ fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
+ /// True if the function is marked as `#[track_caller]` ([`ty::InstanceKind::requires_caller_location`])
+ with_caller_location: bool,
+}
+
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// Returns `true` as long as there are more things to do.
///
@@ -39,7 +50,7 @@ pub fn step(&mut self) -> InterpResult<'tcx, bool> {
if let Some(stmt) = basic_block.statements.get(loc.statement_index) {
let old_frames = self.frame_idx();
- self.statement(stmt)?;
+ self.eval_statement(stmt)?;
// Make sure we are not updating `statement_index` of the wrong frame.
assert_eq!(old_frames, self.frame_idx());
// Advance the program counter.
@@ -50,7 +61,12 @@ pub fn step(&mut self) -> InterpResult<'tcx, bool> {
M::before_terminator(self)?;
let terminator = basic_block.terminator();
- self.terminator(terminator)?;
+ self.eval_terminator(terminator)?;
+ if !self.stack().is_empty() {
+ if let Either::Left(loc) = self.frame().loc {
+ info!("// executing {:?}", loc.block);
+ }
+ }
Ok(true)
}
@@ -58,7 +74,7 @@ pub fn step(&mut self) -> InterpResult<'tcx, bool> {
/// statement counter.
///
/// This does NOT move the statement counter forward, the caller has to do that!
- pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
+ pub fn eval_statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
info!("{:?}", stmt);
use rustc_middle::mir::StatementKind::*;
@@ -96,7 +112,7 @@ pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
M::retag_place_contents(self, *kind, &dest)?;
}
- Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
+ Intrinsic(box intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?,
// Evaluate the place expression, without reading from it.
PlaceMention(box place) => {
@@ -181,6 +197,12 @@ pub fn eval_rvalue_into_place(
self.write_immediate(*result, &dest)?;
}
+ NullaryOp(null_op, ty) => {
+ let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?;
+ let val = self.nullary_op(null_op, ty)?;
+ self.write_immediate(*val, &dest)?;
+ }
+
Aggregate(box ref kind, ref operands) => {
self.write_aggregate(kind, operands, &dest)?;
}
@@ -232,38 +254,6 @@ pub fn eval_rvalue_into_place(
self.write_immediate(*val, &dest)?;
}
- NullaryOp(ref null_op, ty) => {
- let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?;
- let layout = self.layout_of(ty)?;
- if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op
- && layout.is_unsized()
- {
- span_bug!(
- self.frame().current_span(),
- "{null_op:?} MIR operator called for unsized type {ty}",
- );
- }
- let val = match null_op {
- mir::NullOp::SizeOf => {
- let val = layout.size.bytes();
- Scalar::from_target_usize(val, self)
- }
- mir::NullOp::AlignOf => {
- let val = layout.align.abi.bytes();
- Scalar::from_target_usize(val, self)
- }
- mir::NullOp::OffsetOf(fields) => {
- let val = self
- .tcx
- .offset_of_subfield(self.param_env, layout, fields.iter())
- .bytes();
- Scalar::from_target_usize(val, self)
- }
- mir::NullOp::UbChecks => Scalar::from_bool(self.tcx.sess.ub_checks()),
- };
- self.write_scalar(val, &dest)?;
- }
-
ShallowInitBox(ref operand, _) => {
let src = self.eval_operand(operand, None)?;
let v = self.read_immediate(&src)?;
@@ -364,7 +354,7 @@ fn write_repeat(
// of the first element.
let elem_size = first.layout.size;
let first_ptr = first.ptr();
- let rest_ptr = first_ptr.offset(elem_size, self)?;
+ let rest_ptr = first_ptr.wrapping_offset(elem_size, self);
// No alignment requirement since `copy_op` above already checked it.
self.mem_copy_repeatedly(
first_ptr,
@@ -378,16 +368,222 @@ fn write_repeat(
Ok(())
}
- /// Evaluate the given terminator. Will also adjust the stack frame and statement position accordingly.
- fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
+ /// Evaluate the arguments of a function call
+ fn eval_fn_call_argument(
+ &self,
+ op: &mir::Operand<'tcx>,
+ ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
+ Ok(match op {
+ mir::Operand::Copy(_) | mir::Operand::Constant(_) => {
+ // Make a regular copy.
+ let op = self.eval_operand(op, None)?;
+ FnArg::Copy(op)
+ }
+ mir::Operand::Move(place) => {
+ // If this place lives in memory, preserve its location.
+ // We call `place_to_op` which will be an `MPlaceTy` whenever there exists
+ // an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local`
+ // which can return a local even if that has an mplace.)
+ let place = self.eval_place(*place)?;
+ let op = self.place_to_op(&place)?;
+
+ match op.as_mplace_or_imm() {
+ Either::Left(mplace) => FnArg::InPlace(mplace),
+ Either::Right(_imm) => {
+ // This argument doesn't live in memory, so there's no place
+ // to make inaccessible during the call.
+ // We rely on there not being any stray `PlaceTy` that would let the
+ // caller directly access this local!
+ // This is also crucial for tail calls, where we want the `FnArg` to
+ // stay valid when the old stack frame gets popped.
+ FnArg::Copy(op)
+ }
+ }
+ }
+ })
+ }
+
+ /// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
+ /// necessary information about callee and arguments to make a call.
+ fn eval_callee_and_args(
+ &self,
+ terminator: &mir::Terminator<'tcx>,
+ func: &mir::Operand<'tcx>,
+ args: &[Spanned<mir::Operand<'tcx>>],
+ ) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> {
+ let func = self.eval_operand(func, None)?;
+ let args = args
+ .iter()
+ .map(|arg| self.eval_fn_call_argument(&arg.node))
+ .collect::<InterpResult<'tcx, Vec<_>>>()?;
+
+ let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
+ let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder);
+ let extra_args = &args[fn_sig.inputs().len()..];
+ let extra_args =
+ self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));
+
+ let (callee, fn_abi, with_caller_location) = match *func.layout.ty.kind() {
+ ty::FnPtr(_sig) => {
+ let fn_ptr = self.read_pointer(&func)?;
+ let fn_val = self.get_ptr_fn(fn_ptr)?;
+ (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false)
+ }
+ ty::FnDef(def_id, args) => {
+ let instance = self.resolve(def_id, args)?;
+ (
+ FnVal::Instance(instance),
+ self.fn_abi_of_instance(instance, extra_args)?,
+ instance.def.requires_caller_location(*self.tcx),
+ )
+ }
+ _ => {
+ span_bug!(terminator.source_info.span, "invalid callee of type {}", func.layout.ty)
+ }
+ };
+
+ Ok(EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location })
+ }
+
+ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
info!("{:?}", terminator.kind);
- self.eval_terminator(terminator)?;
- if !self.stack().is_empty() {
- if let Either::Left(loc) = self.frame().loc {
- info!("// executing {:?}", loc.block);
+ use rustc_middle::mir::TerminatorKind::*;
+ match terminator.kind {
+ Return => {
+ self.return_from_current_stack_frame(/* unwinding */ false)?
+ }
+
+ Goto { target } => self.go_to_block(target),
+
+ SwitchInt { ref discr, ref targets } => {
+ let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;
+ trace!("SwitchInt({:?})", *discr);
+
+ // Branch to the `otherwise` case by default, if no match is found.
+ let mut target_block = targets.otherwise();
+
+ for (const_int, target) in targets.iter() {
+ // Compare using MIR BinOp::Eq, to also support pointer values.
+ // (Avoiding `self.binary_op` as that does some redundant layout computation.)
+ let res = self.binary_op(
+ mir::BinOp::Eq,
+ &discr,
+ &ImmTy::from_uint(const_int, discr.layout),
+ )?;
+ if res.to_scalar().to_bool()? {
+ target_block = target;
+ break;
+ }
+ }
+
+ self.go_to_block(target_block);
+ }
+
+ Call {
+ ref func,
+ ref args,
+ destination,
+ target,
+ unwind,
+ call_source: _,
+ fn_span: _,
+ } => {
+ let old_stack = self.frame_idx();
+ let old_loc = self.frame().loc;
+
+ let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
+ self.eval_callee_and_args(terminator, func, args)?;
+
+ let destination = self.force_allocation(&self.eval_place(destination)?)?;
+ self.init_fn_call(
+ callee,
+ (fn_sig.abi, fn_abi),
+ &args,
+ with_caller_location,
+ &destination,
+ target,
+ if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable },
+ )?;
+ // Sanity-check that `eval_fn_call` either pushed a new frame or
+ // did a jump to another block.
+ if self.frame_idx() == old_stack && self.frame().loc == old_loc {
+ span_bug!(terminator.source_info.span, "evaluating this call made no progress");
+ }
+ }
+
+ TailCall { ref func, ref args, fn_span: _ } => {
+ let old_frame_idx = self.frame_idx();
+
+ let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
+ self.eval_callee_and_args(terminator, func, args)?;
+
+ self.init_fn_tail_call(callee, (fn_sig.abi, fn_abi), &args, with_caller_location)?;
+
+ if self.frame_idx() != old_frame_idx {
+ span_bug!(
+ terminator.source_info.span,
+ "evaluating this tail call pushed a new stack frame"
+ );
+ }
+ }
+
+ Drop { place, target, unwind, replace: _ } => {
+ let place = self.eval_place(place)?;
+ let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
+ if let ty::InstanceKind::DropGlue(_, None) = instance.def {
+ // This is the branch we enter if and only if the dropped type has no drop glue
+ // whatsoever. This can happen as a result of monomorphizing a drop of a
+ // generic. In order to make sure that generic and non-generic code behaves
+ // roughly the same (and in keeping with Mir semantics) we do nothing here.
+ self.go_to_block(target);
+ return Ok(());
+ }
+ trace!("TerminatorKind::drop: {:?}, type {}", place, place.layout.ty);
+ self.init_drop_in_place_call(&place, instance, target, unwind)?;
+ }
+
+ Assert { ref cond, expected, ref msg, target, unwind } => {
+ let ignored =
+ M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check();
+ let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
+ if ignored || expected == cond_val {
+ self.go_to_block(target);
+ } else {
+ M::assert_panic(self, msg, unwind)?;
+ }
+ }
+
+ UnwindTerminate(reason) => {
+ M::unwind_terminate(self, reason)?;
+ }
+
+ // When we encounter Resume, we've finished unwinding
+ // cleanup for the current stack frame. We pop it in order
+ // to continue unwinding the next frame
+ UnwindResume => {
+ trace!("unwinding: resuming from cleanup");
+ // By definition, a Resume terminator means
+ // that we're unwinding
+ self.return_from_current_stack_frame(/* unwinding */ true)?;
+ return Ok(());
+ }
+
+ // It is UB to ever encounter this.
+ Unreachable => throw_ub!(Unreachable),
+
+ // These should never occur for MIR we actually run.
+ FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | CoroutineDrop => span_bug!(
+ terminator.source_info.span,
+ "{:#?} should have been eliminated by MIR pass",
+ terminator.kind
+ ),
+
+ InlineAsm { template, ref operands, options, ref targets, .. } => {
+ M::eval_inline_asm(self, template, operands, options, targets)?;
}
}
+
Ok(())
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
deleted file mode 100644
index 56d3dc9..0000000
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ /dev/null
@@ -1,1083 +0,0 @@
-use std::borrow::Cow;
-
-use either::Either;
-use tracing::trace;
-
-use rustc_middle::{
- bug, mir, span_bug,
- ty::{
- self,
- layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout},
- AdtDef, Instance, Ty,
- },
-};
-use rustc_span::{source_map::Spanned, sym};
-use rustc_target::abi::{self, FieldIdx};
-use rustc_target::abi::{
- call::{ArgAbi, FnAbi, PassMode},
- Integer,
-};
-use rustc_target::spec::abi::Abi;
-
-use super::{
- throw_ub, throw_ub_custom, throw_unsup_format, CtfeProvenance, FnVal, ImmTy, InterpCx,
- InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Projectable, Provenance, Scalar,
- StackPopCleanup,
-};
-use crate::{
- fluent_generated as fluent,
- interpret::{eval_context::StackPopInfo, ReturnAction},
-};
-
-/// An argment passed to a function.
-#[derive(Clone, Debug)]
-pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> {
- /// Pass a copy of the given operand.
- Copy(OpTy<'tcx, Prov>),
- /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and
- /// make the place inaccessible for the duration of the function call.
- InPlace(MPlaceTy<'tcx, Prov>),
-}
-
-impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
- pub fn layout(&self) -> &TyAndLayout<'tcx> {
- match self {
- FnArg::Copy(op) => &op.layout,
- FnArg::InPlace(mplace) => &mplace.layout,
- }
- }
-}
-
-struct EvaluatedCalleeAndArgs<'tcx, M: Machine<'tcx>> {
- callee: FnVal<'tcx, M::ExtraFnVal>,
- args: Vec<FnArg<'tcx, M::Provenance>>,
- fn_sig: ty::FnSig<'tcx>,
- fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
- /// True if the function is marked as `#[track_caller]` ([`ty::InstanceKind::requires_caller_location`])
- with_caller_location: bool,
-}
-
-impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
- /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
- /// original memory occurs.
- pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {
- match arg {
- FnArg::Copy(op) => op.clone(),
- FnArg::InPlace(mplace) => mplace.clone().into(),
- }
- }
-
- /// Make a copy of the given fn_args. Any `InPlace` are degenerated to copies, no protection of the
- /// original memory occurs.
- pub fn copy_fn_args(
- &self,
- args: &[FnArg<'tcx, M::Provenance>],
- ) -> Vec<OpTy<'tcx, M::Provenance>> {
- args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect()
- }
-
- pub fn fn_arg_field(
- &self,
- arg: &FnArg<'tcx, M::Provenance>,
- field: usize,
- ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
- Ok(match arg {
- FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?),
- FnArg::InPlace(mplace) => FnArg::InPlace(self.project_field(mplace, field)?),
- })
- }
-
- pub(super) fn eval_terminator(
- &mut self,
- terminator: &mir::Terminator<'tcx>,
- ) -> InterpResult<'tcx> {
- use rustc_middle::mir::TerminatorKind::*;
- match terminator.kind {
- Return => {
- self.return_from_current_stack_frame(/* unwinding */ false)?
- }
-
- Goto { target } => self.go_to_block(target),
-
- SwitchInt { ref discr, ref targets } => {
- let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;
- trace!("SwitchInt({:?})", *discr);
-
- // Branch to the `otherwise` case by default, if no match is found.
- let mut target_block = targets.otherwise();
-
- for (const_int, target) in targets.iter() {
- // Compare using MIR BinOp::Eq, to also support pointer values.
- // (Avoiding `self.binary_op` as that does some redundant layout computation.)
- let res = self.binary_op(
- mir::BinOp::Eq,
- &discr,
- &ImmTy::from_uint(const_int, discr.layout),
- )?;
- if res.to_scalar().to_bool()? {
- target_block = target;
- break;
- }
- }
-
- self.go_to_block(target_block);
- }
-
- Call {
- ref func,
- ref args,
- destination,
- target,
- unwind,
- call_source: _,
- fn_span: _,
- } => {
- let old_stack = self.frame_idx();
- let old_loc = self.frame().loc;
-
- let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
- self.eval_callee_and_args(terminator, func, args)?;
-
- let destination = self.force_allocation(&self.eval_place(destination)?)?;
- self.eval_fn_call(
- callee,
- (fn_sig.abi, fn_abi),
- &args,
- with_caller_location,
- &destination,
- target,
- if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable },
- )?;
- // Sanity-check that `eval_fn_call` either pushed a new frame or
- // did a jump to another block.
- if self.frame_idx() == old_stack && self.frame().loc == old_loc {
- span_bug!(terminator.source_info.span, "evaluating this call made no progress");
- }
- }
-
- TailCall { ref func, ref args, fn_span: _ } => {
- let old_frame_idx = self.frame_idx();
-
- let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
- self.eval_callee_and_args(terminator, func, args)?;
-
- self.eval_fn_tail_call(callee, (fn_sig.abi, fn_abi), &args, with_caller_location)?;
-
- if self.frame_idx() != old_frame_idx {
- span_bug!(
- terminator.source_info.span,
- "evaluating this tail call pushed a new stack frame"
- );
- }
- }
-
- Drop { place, target, unwind, replace: _ } => {
- let place = self.eval_place(place)?;
- let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
- if let ty::InstanceKind::DropGlue(_, None) = instance.def {
- // This is the branch we enter if and only if the dropped type has no drop glue
- // whatsoever. This can happen as a result of monomorphizing a drop of a
- // generic. In order to make sure that generic and non-generic code behaves
- // roughly the same (and in keeping with Mir semantics) we do nothing here.
- self.go_to_block(target);
- return Ok(());
- }
- trace!("TerminatorKind::drop: {:?}, type {}", place, place.layout.ty);
- self.drop_in_place(&place, instance, target, unwind)?;
- }
-
- Assert { ref cond, expected, ref msg, target, unwind } => {
- let ignored =
- M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check();
- let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
- if ignored || expected == cond_val {
- self.go_to_block(target);
- } else {
- M::assert_panic(self, msg, unwind)?;
- }
- }
-
- UnwindTerminate(reason) => {
- M::unwind_terminate(self, reason)?;
- }
-
- // When we encounter Resume, we've finished unwinding
- // cleanup for the current stack frame. We pop it in order
- // to continue unwinding the next frame
- UnwindResume => {
- trace!("unwinding: resuming from cleanup");
- // By definition, a Resume terminator means
- // that we're unwinding
- self.return_from_current_stack_frame(/* unwinding */ true)?;
- return Ok(());
- }
-
- // It is UB to ever encounter this.
- Unreachable => throw_ub!(Unreachable),
-
- // These should never occur for MIR we actually run.
- FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | CoroutineDrop => span_bug!(
- terminator.source_info.span,
- "{:#?} should have been eliminated by MIR pass",
- terminator.kind
- ),
-
- InlineAsm { template, ref operands, options, ref targets, .. } => {
- M::eval_inline_asm(self, template, operands, options, targets)?;
- }
- }
-
- Ok(())
- }
-
- /// Evaluate the arguments of a function call
- pub(super) fn eval_fn_call_arguments(
- &self,
- ops: &[Spanned<mir::Operand<'tcx>>],
- ) -> InterpResult<'tcx, Vec<FnArg<'tcx, M::Provenance>>> {
- ops.iter()
- .map(|op| {
- let arg = match &op.node {
- mir::Operand::Copy(_) | mir::Operand::Constant(_) => {
- // Make a regular copy.
- let op = self.eval_operand(&op.node, None)?;
- FnArg::Copy(op)
- }
- mir::Operand::Move(place) => {
- // If this place lives in memory, preserve its location.
- // We call `place_to_op` which will be an `MPlaceTy` whenever there exists
- // an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local`
- // which can return a local even if that has an mplace.)
- let place = self.eval_place(*place)?;
- let op = self.place_to_op(&place)?;
-
- match op.as_mplace_or_imm() {
- Either::Left(mplace) => FnArg::InPlace(mplace),
- Either::Right(_imm) => {
- // This argument doesn't live in memory, so there's no place
- // to make inaccessible during the call.
- // We rely on there not being any stray `PlaceTy` that would let the
- // caller directly access this local!
- // This is also crucial for tail calls, where we want the `FnArg` to
- // stay valid when the old stack frame gets popped.
- FnArg::Copy(op)
- }
- }
- }
- };
-
- Ok(arg)
- })
- .collect()
- }
-
- /// Find the wrapped inner type of a transparent wrapper.
- /// Must not be called on 1-ZST (as they don't have a uniquely defined "wrapped field").
- ///
- /// We work with `TyAndLayout` here since that makes it much easier to iterate over all fields.
- fn unfold_transparent(
- &self,
- layout: TyAndLayout<'tcx>,
- may_unfold: impl Fn(AdtDef<'tcx>) -> bool,
- ) -> TyAndLayout<'tcx> {
- match layout.ty.kind() {
- ty::Adt(adt_def, _) if adt_def.repr().transparent() && may_unfold(*adt_def) => {
- assert!(!adt_def.is_enum());
- // Find the non-1-ZST field, and recurse.
- let (_, field) = layout.non_1zst_field(self).unwrap();
- self.unfold_transparent(field, may_unfold)
- }
- // Not a transparent type, no further unfolding.
- _ => layout,
- }
- }
-
- /// Unwrap types that are guaranteed a null-pointer-optimization
- fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
- // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and
- // another type.
- let ty::Adt(def, args) = layout.ty.kind() else {
- // Not an ADT, so definitely no NPO.
- return Ok(layout);
- };
- let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) {
- // The wrapped type is the only arg.
- self.layout_of(args[0].as_type().unwrap())?
- } else if self.tcx.is_diagnostic_item(sym::Result, def.did()) {
- // We want to extract which (if any) of the args is not a 1-ZST.
- let lhs = self.layout_of(args[0].as_type().unwrap())?;
- let rhs = self.layout_of(args[1].as_type().unwrap())?;
- if lhs.is_1zst() {
- rhs
- } else if rhs.is_1zst() {
- lhs
- } else {
- return Ok(layout); // no NPO
- }
- } else {
- return Ok(layout); // no NPO
- };
-
- // Check if the inner type is one of the NPO-guaranteed ones.
- // For that we first unpeel transparent *structs* (but not unions).
- let is_npo = |def: AdtDef<'tcx>| {
- self.tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed)
- };
- let inner = self.unfold_transparent(inner, /* may_unfold */ |def| {
- // Stop at NPO tpyes so that we don't miss that attribute in the check below!
- def.is_struct() && !is_npo(def)
- });
- Ok(match inner.ty.kind() {
- ty::Ref(..) | ty::FnPtr(..) => {
- // Option<&T> behaves like &T, and same for fn()
- inner
- }
- ty::Adt(def, _) if is_npo(*def) => {
- // Once we found a `nonnull_optimization_guaranteed` type, further strip off
- // newtype structs from it to find the underlying ABI type.
- self.unfold_transparent(inner, /* may_unfold */ |def| def.is_struct())
- }
- _ => {
- // Everything else we do not unfold.
- layout
- }
- })
- }
-
- /// Check if these two layouts look like they are fn-ABI-compatible.
- /// (We also compare the `PassMode`, so this doesn't have to check everything. But it turns out
- /// that only checking the `PassMode` is insufficient.)
- fn layout_compat(
- &self,
- caller: TyAndLayout<'tcx>,
- callee: TyAndLayout<'tcx>,
- ) -> InterpResult<'tcx, bool> {
- // Fast path: equal types are definitely compatible.
- if caller.ty == callee.ty {
- return Ok(true);
- }
- // 1-ZST are compatible with all 1-ZST (and with nothing else).
- if caller.is_1zst() || callee.is_1zst() {
- return Ok(caller.is_1zst() && callee.is_1zst());
- }
- // Unfold newtypes and NPO optimizations.
- let unfold = |layout: TyAndLayout<'tcx>| {
- self.unfold_npo(self.unfold_transparent(layout, /* may_unfold */ |_def| true))
- };
- let caller = unfold(caller)?;
- let callee = unfold(callee)?;
- // Now see if these inner types are compatible.
-
- // Compatible pointer types. For thin pointers, we have to accept even non-`repr(transparent)`
- // things as compatible due to `DispatchFromDyn`. For instance, `Rc<i32>` and `*mut i32`
- // must be compatible. So we just accept everything with Pointer ABI as compatible,
- // even if this will accept some code that is not stably guaranteed to work.
- // This also handles function pointers.
- let thin_pointer = |layout: TyAndLayout<'tcx>| match layout.abi {
- abi::Abi::Scalar(s) => match s.primitive() {
- abi::Primitive::Pointer(addr_space) => Some(addr_space),
- _ => None,
- },
- _ => None,
- };
- if let (Some(caller), Some(callee)) = (thin_pointer(caller), thin_pointer(callee)) {
- return Ok(caller == callee);
- }
- // For wide pointers we have to get the pointee type.
- let pointee_ty = |ty: Ty<'tcx>| -> InterpResult<'tcx, Option<Ty<'tcx>>> {
- // We cannot use `builtin_deref` here since we need to reject `Box<T, MyAlloc>`.
- Ok(Some(match ty.kind() {
- ty::Ref(_, ty, _) => *ty,
- ty::RawPtr(ty, _) => *ty,
- // We only accept `Box` with the default allocator.
- _ if ty.is_box_global(*self.tcx) => ty.boxed_ty(),
- _ => return Ok(None),
- }))
- };
- if let (Some(caller), Some(callee)) = (pointee_ty(caller.ty)?, pointee_ty(callee.ty)?) {
- // This is okay if they have the same metadata type.
- let meta_ty = |ty: Ty<'tcx>| {
- // Even if `ty` is normalized, the search for the unsized tail will project
- // to fields, which can yield non-normalized types. So we need to provide a
- // normalization function.
- let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty);
- ty.ptr_metadata_ty(*self.tcx, normalize)
- };
- return Ok(meta_ty(caller) == meta_ty(callee));
- }
-
- // Compatible integer types (in particular, usize vs ptr-sized-u32/u64).
- // `char` counts as `u32.`
- let int_ty = |ty: Ty<'tcx>| {
- Some(match ty.kind() {
- ty::Int(ity) => (Integer::from_int_ty(&self.tcx, *ity), /* signed */ true),
- ty::Uint(uty) => (Integer::from_uint_ty(&self.tcx, *uty), /* signed */ false),
- ty::Char => (Integer::I32, /* signed */ false),
- _ => return None,
- })
- };
- if let (Some(caller), Some(callee)) = (int_ty(caller.ty), int_ty(callee.ty)) {
- // This is okay if they are the same integer type.
- return Ok(caller == callee);
- }
-
- // Fall back to exact equality.
- // FIXME: We are missing the rules for "repr(C) wrapping compatible types".
- Ok(caller == callee)
- }
-
- fn check_argument_compat(
- &self,
- caller_abi: &ArgAbi<'tcx, Ty<'tcx>>,
- callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
- ) -> InterpResult<'tcx, bool> {
- // We do not want to accept things as ABI-compatible that just "happen to be" compatible on the current target,
- // so we implement a type-based check that reflects the guaranteed rules for ABI compatibility.
- if self.layout_compat(caller_abi.layout, callee_abi.layout)? {
- // Ensure that our checks imply actual ABI compatibility for this concrete call.
- assert!(caller_abi.eq_abi(callee_abi));
- return Ok(true);
- } else {
- trace!(
- "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
- caller_abi,
- callee_abi
- );
- return Ok(false);
- }
- }
-
- /// Initialize a single callee argument, checking the types for compatibility.
- fn pass_argument<'x, 'y>(
- &mut self,
- caller_args: &mut impl Iterator<
- Item = (&'x FnArg<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>),
- >,
- callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
- callee_arg: &mir::Place<'tcx>,
- callee_ty: Ty<'tcx>,
- already_live: bool,
- ) -> InterpResult<'tcx>
- where
- 'tcx: 'x,
- 'tcx: 'y,
- {
- assert_eq!(callee_ty, callee_abi.layout.ty);
- if matches!(callee_abi.mode, PassMode::Ignore) {
- // This one is skipped. Still must be made live though!
- if !already_live {
- self.storage_live(callee_arg.as_local().unwrap())?;
- }
- return Ok(());
- }
- // Find next caller arg.
- let Some((caller_arg, caller_abi)) = caller_args.next() else {
- throw_ub_custom!(fluent::const_eval_not_enough_caller_args);
- };
- assert_eq!(caller_arg.layout().layout, caller_abi.layout.layout);
- // Sadly we cannot assert that `caller_arg.layout().ty` and `caller_abi.layout.ty` are
- // equal; in closures the types sometimes differ. We just hope that `caller_abi` is the
- // right type to print to the user.
-
- // Check compatibility
- if !self.check_argument_compat(caller_abi, callee_abi)? {
- throw_ub!(AbiMismatchArgument {
- caller_ty: caller_abi.layout.ty,
- callee_ty: callee_abi.layout.ty
- });
- }
- // We work with a copy of the argument for now; if this is in-place argument passing, we
- // will later protect the source it comes from. This means the callee cannot observe if we
- // did in-place of by-copy argument passing, except for pointer equality tests.
- let caller_arg_copy = self.copy_fn_arg(caller_arg);
- if !already_live {
- let local = callee_arg.as_local().unwrap();
- let meta = caller_arg_copy.meta();
- // `check_argument_compat` ensures that if metadata is needed, both have the same type,
- // so we know they will use the metadata the same way.
- assert!(!meta.has_meta() || caller_arg_copy.layout.ty == callee_ty);
-
- self.storage_live_dyn(local, meta)?;
- }
- // Now we can finally actually evaluate the callee place.
- let callee_arg = self.eval_place(*callee_arg)?;
- // We allow some transmutes here.
- // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This
- // is true for all `copy_op`, but there are a lot of special cases for argument passing
- // specifically.)
- self.copy_op_allow_transmute(&caller_arg_copy, &callee_arg)?;
- // If this was an in-place pass, protect the place it comes from for the duration of the call.
- if let FnArg::InPlace(mplace) = caller_arg {
- M::protect_in_place_function_argument(self, mplace)?;
- }
- Ok(())
- }
-
- /// Shared part of `Call` and `TailCall` implementation — finding and evaluating all the
- /// necessary information about callee and arguments to make a call.
- fn eval_callee_and_args(
- &self,
- terminator: &mir::Terminator<'tcx>,
- func: &mir::Operand<'tcx>,
- args: &[Spanned<mir::Operand<'tcx>>],
- ) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> {
- let func = self.eval_operand(func, None)?;
- let args = self.eval_fn_call_arguments(args)?;
-
- let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
- let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder);
- let extra_args = &args[fn_sig.inputs().len()..];
- let extra_args =
- self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));
-
- let (callee, fn_abi, with_caller_location) = match *func.layout.ty.kind() {
- ty::FnPtr(_sig) => {
- let fn_ptr = self.read_pointer(&func)?;
- let fn_val = self.get_ptr_fn(fn_ptr)?;
- (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false)
- }
- ty::FnDef(def_id, args) => {
- let instance = self.resolve(def_id, args)?;
- (
- FnVal::Instance(instance),
- self.fn_abi_of_instance(instance, extra_args)?,
- instance.def.requires_caller_location(*self.tcx),
- )
- }
- _ => {
- span_bug!(terminator.source_info.span, "invalid callee of type {}", func.layout.ty)
- }
- };
-
- Ok(EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location })
- }
-
- /// Call this function -- pushing the stack frame and initializing the arguments.
- ///
- /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way.
- /// However, we also need `caller_abi` to determine if we need to do untupling of arguments.
- ///
- /// `with_caller_location` indicates whether the caller passed a caller location. Miri
- /// implements caller locations without argument passing, but to match `FnAbi` we need to know
- /// when those arguments are present.
- pub(crate) fn eval_fn_call(
- &mut self,
- fn_val: FnVal<'tcx, M::ExtraFnVal>,
- (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
- args: &[FnArg<'tcx, M::Provenance>],
- with_caller_location: bool,
- destination: &MPlaceTy<'tcx, M::Provenance>,
- target: Option<mir::BasicBlock>,
- mut unwind: mir::UnwindAction,
- ) -> InterpResult<'tcx> {
- trace!("eval_fn_call: {:#?}", fn_val);
-
- let instance = match fn_val {
- FnVal::Instance(instance) => instance,
- FnVal::Other(extra) => {
- return M::call_extra_fn(
- self,
- extra,
- caller_abi,
- args,
- destination,
- target,
- unwind,
- );
- }
- };
-
- match instance.def {
- ty::InstanceKind::Intrinsic(def_id) => {
- assert!(self.tcx.intrinsic(def_id).is_some());
- // FIXME: Should `InPlace` arguments be reset to uninit?
- if let Some(fallback) = M::call_intrinsic(
- self,
- instance,
- &self.copy_fn_args(args),
- destination,
- target,
- unwind,
- )? {
- assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden);
- assert!(matches!(fallback.def, ty::InstanceKind::Item(_)));
- return self.eval_fn_call(
- FnVal::Instance(fallback),
- (caller_abi, caller_fn_abi),
- args,
- with_caller_location,
- destination,
- target,
- unwind,
- );
- } else {
- Ok(())
- }
- }
- ty::InstanceKind::VTableShim(..)
- | ty::InstanceKind::ReifyShim(..)
- | ty::InstanceKind::ClosureOnceShim { .. }
- | ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
- | ty::InstanceKind::CoroutineKindShim { .. }
- | ty::InstanceKind::FnPtrShim(..)
- | ty::InstanceKind::DropGlue(..)
- | ty::InstanceKind::CloneShim(..)
- | ty::InstanceKind::FnPtrAddrShim(..)
- | ty::InstanceKind::ThreadLocalShim(..)
- | ty::InstanceKind::AsyncDropGlueCtorShim(..)
- | ty::InstanceKind::Item(_) => {
- // We need MIR for this fn
- let Some((body, instance)) = M::find_mir_or_eval_fn(
- self,
- instance,
- caller_abi,
- args,
- destination,
- target,
- unwind,
- )?
- else {
- return Ok(());
- };
-
- // Compute callee information using the `instance` returned by
- // `find_mir_or_eval_fn`.
- // FIXME: for variadic support, do we have to somehow determine callee's extra_args?
- let callee_fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
-
- if callee_fn_abi.c_variadic || caller_fn_abi.c_variadic {
- throw_unsup_format!("calling a c-variadic function is not supported");
- }
-
- if M::enforce_abi(self) {
- if caller_fn_abi.conv != callee_fn_abi.conv {
- throw_ub_custom!(
- fluent::const_eval_incompatible_calling_conventions,
- callee_conv = format!("{:?}", callee_fn_abi.conv),
- caller_conv = format!("{:?}", caller_fn_abi.conv),
- )
- }
- }
-
- // Check that all target features required by the callee (i.e., from
- // the attribute `#[target_feature(enable = ...)]`) are enabled at
- // compile time.
- self.check_fn_target_features(instance)?;
-
- if !callee_fn_abi.can_unwind {
- // The callee cannot unwind, so force the `Unreachable` unwind handling.
- unwind = mir::UnwindAction::Unreachable;
- }
-
- self.push_stack_frame(
- instance,
- body,
- destination,
- StackPopCleanup::Goto { ret: target, unwind },
- )?;
-
- // If an error is raised here, pop the frame again to get an accurate backtrace.
- // To this end, we wrap it all in a `try` block.
- let res: InterpResult<'tcx> = try {
- trace!(
- "caller ABI: {:?}, args: {:#?}",
- caller_abi,
- args.iter()
- .map(|arg| (
- arg.layout().ty,
- match arg {
- FnArg::Copy(op) => format!("copy({op:?})"),
- FnArg::InPlace(mplace) => format!("in-place({mplace:?})"),
- }
- ))
- .collect::<Vec<_>>()
- );
- trace!(
- "spread_arg: {:?}, locals: {:#?}",
- body.spread_arg,
- body.args_iter()
- .map(|local| (
- local,
- self.layout_of_local(self.frame(), local, None).unwrap().ty,
- ))
- .collect::<Vec<_>>()
- );
-
- // In principle, we have two iterators: Where the arguments come from, and where
- // they go to.
-
- // For where they come from: If the ABI is RustCall, we untuple the
- // last incoming argument. These two iterators do not have the same type,
- // so to keep the code paths uniform we accept an allocation
- // (for RustCall ABI only).
- let caller_args: Cow<'_, [FnArg<'tcx, M::Provenance>]> =
- if caller_abi == Abi::RustCall && !args.is_empty() {
- // Untuple
- let (untuple_arg, args) = args.split_last().unwrap();
- trace!("eval_fn_call: Will pass last argument by untupling");
- Cow::from(
- args.iter()
- .map(|a| Ok(a.clone()))
- .chain(
- (0..untuple_arg.layout().fields.count())
- .map(|i| self.fn_arg_field(untuple_arg, i)),
- )
- .collect::<InterpResult<'_, Vec<_>>>()?,
- )
- } else {
- // Plain arg passing
- Cow::from(args)
- };
- // If `with_caller_location` is set we pretend there is an extra argument (that
- // we will not pass).
- assert_eq!(
- caller_args.len() + if with_caller_location { 1 } else { 0 },
- caller_fn_abi.args.len(),
- "mismatch between caller ABI and caller arguments",
- );
- let mut caller_args = caller_args
- .iter()
- .zip(caller_fn_abi.args.iter())
- .filter(|arg_and_abi| !matches!(arg_and_abi.1.mode, PassMode::Ignore));
-
- // Now we have to spread them out across the callee's locals,
- // taking into account the `spread_arg`. If we could write
- // this is a single iterator (that handles `spread_arg`), then
- // `pass_argument` would be the loop body. It takes care to
- // not advance `caller_iter` for ignored arguments.
- let mut callee_args_abis = callee_fn_abi.args.iter();
- for local in body.args_iter() {
- // Construct the destination place for this argument. At this point all
- // locals are still dead, so we cannot construct a `PlaceTy`.
- let dest = mir::Place::from(local);
- // `layout_of_local` does more than just the instantiation we need to get the
- // type, but the result gets cached so this avoids calling the instantiation
- // query *again* the next time this local is accessed.
- let ty = self.layout_of_local(self.frame(), local, None)?.ty;
- if Some(local) == body.spread_arg {
- // Make the local live once, then fill in the value field by field.
- self.storage_live(local)?;
- // Must be a tuple
- let ty::Tuple(fields) = ty.kind() else {
- span_bug!(self.cur_span(), "non-tuple type for `spread_arg`: {ty}")
- };
- for (i, field_ty) in fields.iter().enumerate() {
- let dest = dest.project_deeper(
- &[mir::ProjectionElem::Field(
- FieldIdx::from_usize(i),
- field_ty,
- )],
- *self.tcx,
- );
- let callee_abi = callee_args_abis.next().unwrap();
- self.pass_argument(
- &mut caller_args,
- callee_abi,
- &dest,
- field_ty,
- /* already_live */ true,
- )?;
- }
- } else {
- // Normal argument. Cannot mark it as live yet, it might be unsized!
- let callee_abi = callee_args_abis.next().unwrap();
- self.pass_argument(
- &mut caller_args,
- callee_abi,
- &dest,
- ty,
- /* already_live */ false,
- )?;
- }
- }
- // If the callee needs a caller location, pretend we consume one more argument from the ABI.
- if instance.def.requires_caller_location(*self.tcx) {
- callee_args_abis.next().unwrap();
- }
- // Now we should have no more caller args or callee arg ABIs
- assert!(
- callee_args_abis.next().is_none(),
- "mismatch between callee ABI and callee body arguments"
- );
- if caller_args.next().is_some() {
- throw_ub_custom!(fluent::const_eval_too_many_caller_args);
- }
- // Don't forget to check the return type!
- if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
- throw_ub!(AbiMismatchReturn {
- caller_ty: caller_fn_abi.ret.layout.ty,
- callee_ty: callee_fn_abi.ret.layout.ty
- });
- }
-
- // Protect return place for in-place return value passing.
- M::protect_in_place_function_argument(self, &destination)?;
-
- // Don't forget to mark "initially live" locals as live.
- self.storage_live_for_always_live_locals()?;
- };
- match res {
- Err(err) => {
- self.stack_mut().pop();
- Err(err)
- }
- Ok(()) => Ok(()),
- }
- }
- // `InstanceKind::Virtual` does not have callable MIR. Calls to `Virtual` instances must be
- // codegen'd / interpreted as virtual calls through the vtable.
- ty::InstanceKind::Virtual(def_id, idx) => {
- let mut args = args.to_vec();
- // We have to implement all "object safe receivers". So we have to go search for a
- // pointer or `dyn Trait` type, but it could be wrapped in newtypes. So recursively
- // unwrap those newtypes until we are there.
- // An `InPlace` does nothing here, we keep the original receiver intact. We can't
- // really pass the argument in-place anyway, and we are constructing a new
- // `Immediate` receiver.
- let mut receiver = self.copy_fn_arg(&args[0]);
- let receiver_place = loop {
- match receiver.layout.ty.kind() {
- ty::Ref(..) | ty::RawPtr(..) => {
- // We do *not* use `deref_pointer` here: we don't want to conceptually
- // create a place that must be dereferenceable, since the receiver might
- // be a raw pointer and (for `*const dyn Trait`) we don't need to
- // actually access memory to resolve this method.
- // Also see <https://github.com/rust-lang/miri/issues/2786>.
- let val = self.read_immediate(&receiver)?;
- break self.ref_to_mplace(&val)?;
- }
- ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
- ty::Dynamic(.., ty::DynStar) => {
- // Not clear how to handle this, so far we assume the receiver is always a pointer.
- span_bug!(
- self.cur_span(),
- "by-value calls on a `dyn*`... are those a thing?"
- );
- }
- _ => {
- // Not there yet, search for the only non-ZST field.
- // (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
- let (idx, _) = receiver.layout.non_1zst_field(self).expect(
- "not exactly one non-1-ZST field in a `DispatchFromDyn` type",
- );
- receiver = self.project_field(&receiver, idx)?;
- }
- }
- };
-
- // Obtain the underlying trait we are working on, and the adjusted receiver argument.
- let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
- receiver_place.layout.ty.kind()
- {
- let recv = self.unpack_dyn_star(&receiver_place, data)?;
-
- (data.principal(), recv.layout.ty, recv.ptr())
- } else {
- // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
- // (For that reason we also cannot use `unpack_dyn_trait`.)
- let receiver_tail = self
- .tcx
- .struct_tail_erasing_lifetimes(receiver_place.layout.ty, self.param_env);
- let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
- span_bug!(
- self.cur_span(),
- "dynamic call on non-`dyn` type {}",
- receiver_tail
- )
- };
- assert!(receiver_place.layout.is_unsized());
-
- // Get the required information from the vtable.
- let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
- let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
-
- // It might be surprising that we use a pointer as the receiver even if this
- // is a by-val case; this works because by-val passing of an unsized `dyn
- // Trait` to a function is actually desugared to a pointer.
- (receiver_trait.principal(), dyn_ty, receiver_place.ptr())
- };
-
- // Now determine the actual method to call. Usually we use the easy way of just
- // looking up the method at index `idx`.
- let vtable_entries = self.vtable_entries(trait_, dyn_ty);
- let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else {
- // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
- throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
- };
- trace!("Virtual call dispatches to {fn_inst:#?}");
- // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that
- // produces the same result.
- if cfg!(debug_assertions) {
- let tcx = *self.tcx;
-
- let trait_def_id = tcx.trait_of_item(def_id).unwrap();
- let virtual_trait_ref =
- ty::TraitRef::from_method(tcx, trait_def_id, instance.args);
- let existential_trait_ref =
- ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref);
- let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty);
-
- let concrete_method = Instance::expect_resolve_for_vtable(
- tcx,
- self.param_env,
- def_id,
- instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
- self.cur_span(),
- );
- assert_eq!(fn_inst, concrete_method);
- }
-
- // Adjust receiver argument. Layout can be any (thin) ptr.
- let receiver_ty = Ty::new_mut_ptr(self.tcx.tcx, dyn_ty);
- args[0] = FnArg::Copy(
- ImmTy::from_immediate(
- Scalar::from_maybe_pointer(adjusted_recv, self).into(),
- self.layout_of(receiver_ty)?,
- )
- .into(),
- );
- trace!("Patched receiver operand to {:#?}", args[0]);
- // Need to also adjust the type in the ABI. Strangely, the layout there is actually
- // already fine! Just the type is bogus. This is due to what `force_thin_self_ptr`
- // does in `fn_abi_new_uncached`; supposedly, codegen relies on having the bogus
- // type, so we just patch this up locally.
- let mut caller_fn_abi = caller_fn_abi.clone();
- caller_fn_abi.args[0].layout.ty = receiver_ty;
-
- // recurse with concrete function
- self.eval_fn_call(
- FnVal::Instance(fn_inst),
- (caller_abi, &caller_fn_abi),
- &args,
- with_caller_location,
- destination,
- target,
- unwind,
- )
- }
- }
- }
-
- pub(crate) fn eval_fn_tail_call(
- &mut self,
- fn_val: FnVal<'tcx, M::ExtraFnVal>,
- (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
- args: &[FnArg<'tcx, M::Provenance>],
- with_caller_location: bool,
- ) -> InterpResult<'tcx> {
- trace!("eval_fn_call: {:#?}", fn_val);
-
- // This is the "canonical" implementation of tails calls,
- // a pop of the current stack frame, followed by a normal call
- // which pushes a new stack frame, with the return address from
- // the popped stack frame.
- //
- // Note that we are using `pop_stack_frame` and not `return_from_current_stack_frame`,
- // as the latter "executes" the goto to the return block, but we don't want to,
- // only the tail called function should return to the current return block.
- M::before_stack_pop(self, self.frame())?;
-
- let StackPopInfo { return_action, return_to_block, return_place } =
- self.pop_stack_frame(false)?;
-
- assert_eq!(return_action, ReturnAction::Normal);
-
- let StackPopCleanup::Goto { ret, unwind } = return_to_block else {
- bug!("can't tailcall as root");
- };
-
- // FIXME(explicit_tail_calls):
- // we should check if both caller&callee can/n't unwind,
- // see <https://github.com/rust-lang/rust/pull/113128#issuecomment-1614979803>
-
- self.eval_fn_call(
- fn_val,
- (caller_abi, caller_fn_abi),
- args,
- with_caller_location,
- &return_place,
- ret,
- unwind,
- )
- }
-
- fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> {
- // Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
- let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
- if !self.tcx.sess.target.is_like_wasm
- && attrs
- .target_features
- .iter()
- .any(|feature| !self.tcx.sess.target_features.contains(feature))
- {
- throw_ub_custom!(
- fluent::const_eval_unavailable_target_features_for_fn,
- unavailable_feats = attrs
- .target_features
- .iter()
- .filter(|&feature| !self.tcx.sess.target_features.contains(feature))
- .fold(String::new(), |mut s, feature| {
- if !s.is_empty() {
- s.push_str(", ");
- }
- s.push_str(feature.as_str());
- s
- }),
- );
- }
- Ok(())
- }
-
- fn drop_in_place(
- &mut self,
- place: &PlaceTy<'tcx, M::Provenance>,
- instance: ty::Instance<'tcx>,
- target: mir::BasicBlock,
- unwind: mir::UnwindAction,
- ) -> InterpResult<'tcx> {
- trace!("drop_in_place: {:?},\n instance={:?}", place, instance);
- // We take the address of the object. This may well be unaligned, which is fine
- // for us here. However, unaligned accesses will probably make the actual drop
- // implementation fail -- a problem shared by rustc.
- let place = self.force_allocation(place)?;
-
- // We behave a bit different from codegen here.
- // Codegen creates an `InstanceKind::Virtual` with index 0 (the slot of the drop method) and
- // then dispatches that to the normal call machinery. However, our call machinery currently
- // only supports calling `VtblEntry::Method`; it would choke on a `MetadataDropInPlace`. So
- // instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call`
- // since we can just get a place of the underlying type and use `mplace_to_ref`.
- let place = match place.layout.ty.kind() {
- ty::Dynamic(data, _, ty::Dyn) => {
- // Dropping a trait object. Need to find actual drop fn.
- self.unpack_dyn_trait(&place, data)?
- }
- ty::Dynamic(data, _, ty::DynStar) => {
- // Dropping a `dyn*`. Need to find actual drop fn.
- self.unpack_dyn_star(&place, data)?
- }
- _ => {
- debug_assert_eq!(
- instance,
- ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty)
- );
- place
- }
- };
- let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
- let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
-
- let arg = self.mplace_to_ref(&place)?;
- let ret = MPlaceTy::fake_alloc_zst(self.layout_of(self.tcx.types.unit)?);
-
- self.eval_fn_call(
- FnVal::Instance(instance),
- (Abi::Rust, fn_abi),
- &[FnArg::Copy(arg.into())],
- false,
- &ret.into(),
- Some(target),
- unwind,
- )
- }
-}
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index fb50661..cd4faf0 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -28,7 +28,9 @@ pub fn get_vtable_ptr(
ensure_monomorphic_enough(*self.tcx, ty)?;
ensure_monomorphic_enough(*self.tcx, poly_trait_ref)?;
- let vtable_symbolic_allocation = self.tcx.reserve_and_set_vtable_alloc(ty, poly_trait_ref);
+ let salt = M::get_global_alloc_salt(self, None);
+ let vtable_symbolic_allocation =
+ self.tcx.reserve_and_set_vtable_alloc(ty, poly_trait_ref, salt);
let vtable_ptr = self.global_root_pointer(Pointer::from(vtable_symbolic_allocation))?;
Ok(vtable_ptr.into())
}
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index bbe5e5f..6f5bceb 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -1,4 +1,5 @@
-use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult};
+use std::ops::ControlFlow;
+
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{Allocation, InterpResult, Pointer};
@@ -6,10 +7,10 @@
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
-use std::ops::ControlFlow;
use tracing::debug;
use super::{throw_inval, InterpCx, MPlaceTy, MemPlaceMeta, MemoryKind};
+use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult};
/// Checks whether a type contains generic parameters which must be instantiated.
///
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 3dc3e6c..fadc4ee 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -9,17 +9,15 @@
use std::num::NonZero;
use either::{Left, Right};
-use tracing::trace;
-
use hir::def::DefKind;
use rustc_ast::Mutability;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_middle::bug;
+use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
use rustc_middle::mir::interpret::{
ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
UnsupportedOpInfo, ValidationErrorInfo,
- ValidationErrorKind::{self, *},
};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Ty};
@@ -27,11 +25,13 @@
use rustc_target::abi::{
Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
};
+use tracing::trace;
+use super::machine::AllocMap;
use super::{
- err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
- GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
- Pointer, Projectable, Scalar, ValueVisitor,
+ err_ub, format_interp_error, throw_ub, AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy,
+ Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy, Pointer, Projectable,
+ Scalar, ValueVisitor,
};
// for the validation errors
@@ -155,8 +155,8 @@ fn allow_immutable_unsafe_cell(self) -> bool {
/// State for tracking recursive validation of references
pub struct RefTracking<T, PATH = ()> {
- pub seen: FxHashSet<T>,
- pub todo: Vec<(T, PATH)>,
+ seen: FxHashSet<T>,
+ todo: Vec<(T, PATH)>,
}
impl<T: Clone + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH> {
@@ -169,8 +169,11 @@ pub fn new(op: T) -> Self {
ref_tracking_for_consts.seen.insert(op);
ref_tracking_for_consts
}
+ pub fn next(&mut self) -> Option<(T, PATH)> {
+ self.todo.pop()
+ }
- pub fn track(&mut self, op: T, path: impl FnOnce() -> PATH) {
+ fn track(&mut self, op: T, path: impl FnOnce() -> PATH) {
if self.seen.insert(op.clone()) {
trace!("Recursing below ptr {:#?}", op);
let path = path();
@@ -340,7 +343,7 @@ fn check_wide_ptr_meta(
meta: MemPlaceMeta<M::Provenance>,
pointee: TyAndLayout<'tcx>,
) -> InterpResult<'tcx> {
- let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
+ let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.param_env);
match tail.kind() {
ty::Dynamic(data, _, ty::Dyn) => {
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
@@ -348,7 +351,7 @@ fn check_wide_ptr_meta(
try_validation!(
self.ecx.get_ptr_vtable_ty(vtable, Some(data)),
self.path,
- Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
+ Ub(DanglingIntPointer{ .. } | InvalidVTablePointer(..)) =>
InvalidVTablePtr { value: format!("{vtable}") },
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
@@ -405,8 +408,8 @@ fn check_safe_pointer(
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
),
self.path,
- Ub(DanglingIntPointer(0, _)) => NullPtr { ptr_kind },
- Ub(DanglingIntPointer(i, _)) => DanglingPtrNoProvenance {
+ Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind },
+ Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
ptr_kind,
// FIXME this says "null pointer" when null but we need translate
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(*i))
@@ -435,88 +438,96 @@ fn check_safe_pointer(
if self.ecx.scalar_may_be_null(Scalar::from_maybe_pointer(place.ptr(), self.ecx))? {
throw_validation_failure!(self.path, NullPtr { ptr_kind })
}
- // Do not allow pointers to uninhabited types.
+ // Do not allow references to uninhabited types.
if place.layout.abi.is_uninhabited() {
let ty = place.layout.ty;
throw_validation_failure!(self.path, PtrToUninhabited { ptr_kind, ty })
}
// Recursive checking
if let Some(ref_tracking) = self.ref_tracking.as_deref_mut() {
- // Determine whether this pointer expects to be pointing to something mutable.
- let ptr_expected_mutbl = match ptr_kind {
- PointerKind::Box => Mutability::Mut,
- PointerKind::Ref(mutbl) => {
- // We do not take into account interior mutability here since we cannot know if
- // there really is an `UnsafeCell` inside `Option<UnsafeCell>` -- so we check
- // that in the recursive descent behind this reference (controlled by
- // `allow_immutable_unsafe_cell`).
- mutbl
- }
- };
// Proceed recursively even for ZST, no reason to skip them!
// `!` is a ZST and we want to validate it.
- if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr()) {
+ if let Some(ctfe_mode) = self.ctfe_mode {
let mut skip_recursive_check = false;
- if let Some(GlobalAlloc::Static(did)) = self.ecx.tcx.try_get_global_alloc(alloc_id)
+ // CTFE imposes restrictions on what references can point to.
+ if let Ok((alloc_id, _offset, _prov)) =
+ self.ecx.ptr_try_get_alloc_id(place.ptr(), 0)
{
- let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { bug!() };
- // Special handling for pointers to statics (irrespective of their type).
- assert!(!self.ecx.tcx.is_thread_local_static(did));
- assert!(self.ecx.tcx.is_static(did));
- // Mode-specific checks
- match self.ctfe_mode {
- Some(
- CtfeValidationMode::Static { .. } | CtfeValidationMode::Promoted { .. },
- ) => {
- // We skip recursively checking other statics. These statics must be sound by
- // themselves, and the only way to get broken statics here is by using
- // unsafe code.
- // The reasons we don't check other statics is twofold. For one, in all
- // sound cases, the static was already validated on its own, and second, we
- // trigger cycle errors if we try to compute the value of the other static
- // and that static refers back to us (potentially through a promoted).
- // This could miss some UB, but that's fine.
- // We still walk nested allocations, as they are fundamentally part of this validation run.
- // This means we will also recurse into nested statics of *other*
- // statics, even though we do not recurse into other statics directly.
- // That's somewhat inconsistent but harmless.
- skip_recursive_check = !nested;
- }
- Some(CtfeValidationMode::Const { .. }) => {
- // We can't recursively validate `extern static`, so we better reject them.
- if self.ecx.tcx.is_foreign_item(did) {
- throw_validation_failure!(self.path, ConstRefToExtern);
+ if let Some(GlobalAlloc::Static(did)) =
+ self.ecx.tcx.try_get_global_alloc(alloc_id)
+ {
+ let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else {
+ bug!()
+ };
+ // Special handling for pointers to statics (irrespective of their type).
+ assert!(!self.ecx.tcx.is_thread_local_static(did));
+ assert!(self.ecx.tcx.is_static(did));
+ // Mode-specific checks
+ match ctfe_mode {
+ CtfeValidationMode::Static { .. }
+ | CtfeValidationMode::Promoted { .. } => {
+ // We skip recursively checking other statics. These statics must be sound by
+ // themselves, and the only way to get broken statics here is by using
+ // unsafe code.
+ // The reasons we don't check other statics is twofold. For one, in all
+ // sound cases, the static was already validated on its own, and second, we
+ // trigger cycle errors if we try to compute the value of the other static
+ // and that static refers back to us (potentially through a promoted).
+ // This could miss some UB, but that's fine.
+ // We still walk nested allocations, as they are fundamentally part of this validation run.
+ // This means we will also recurse into nested statics of *other*
+ // statics, even though we do not recurse into other statics directly.
+ // That's somewhat inconsistent but harmless.
+ skip_recursive_check = !nested;
+ }
+ CtfeValidationMode::Const { .. } => {
+ // We can't recursively validate `extern static`, so we better reject them.
+ if self.ecx.tcx.is_foreign_item(did) {
+ throw_validation_failure!(self.path, ConstRefToExtern);
+ }
}
}
- None => {}
}
- }
- // Dangling and Mutability check.
- let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
- if alloc_kind == AllocKind::Dead {
- // This can happen for zero-sized references. We can't have *any* references to non-existing
- // allocations though, interning rejects them all as the rest of rustc isn't happy with them...
- // so we throw an error, even though this isn't really UB.
- // A potential future alternative would be to resurrect this as a zero-sized allocation
- // (which codegen will then compile to an aligned dummy pointer anyway).
- throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
- }
- // If this allocation has size zero, there is no actual mutability here.
- if size != Size::ZERO {
- let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
- // Mutable pointer to immutable memory is no good.
- if ptr_expected_mutbl == Mutability::Mut
- && alloc_actual_mutbl == Mutability::Not
- {
- throw_validation_failure!(self.path, MutableRefToImmutable);
+ // Dangling and Mutability check.
+ let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
+ if alloc_kind == AllocKind::Dead {
+ // This can happen for zero-sized references. We can't have *any* references to
+ // non-existing allocations in const-eval though, interning rejects them all as
+ // the rest of rustc isn't happy with them... so we throw an error, even though
+ // this isn't really UB.
+ // A potential future alternative would be to resurrect this as a zero-sized allocation
+ // (which codegen will then compile to an aligned dummy pointer anyway).
+ throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
}
- // In a const, everything must be completely immutable.
- if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) {
+ // If this allocation has size zero, there is no actual mutability here.
+ if size != Size::ZERO {
+ // Determine whether this pointer expects to be pointing to something mutable.
+ let ptr_expected_mutbl = match ptr_kind {
+ PointerKind::Box => Mutability::Mut,
+ PointerKind::Ref(mutbl) => {
+ // We do not take into account interior mutability here since we cannot know if
+ // there really is an `UnsafeCell` inside `Option<UnsafeCell>` -- so we check
+ // that in the recursive descent behind this reference (controlled by
+ // `allow_immutable_unsafe_cell`).
+ mutbl
+ }
+ };
+ // Determine what it actually points to.
+ let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
+ // Mutable pointer to immutable memory is no good.
if ptr_expected_mutbl == Mutability::Mut
- || alloc_actual_mutbl == Mutability::Mut
+ && alloc_actual_mutbl == Mutability::Not
{
- throw_validation_failure!(self.path, ConstRefToMutable);
+ throw_validation_failure!(self.path, MutableRefToImmutable);
+ }
+ // In a const, everything must be completely immutable.
+ if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) {
+ if ptr_expected_mutbl == Mutability::Mut
+ || alloc_actual_mutbl == Mutability::Mut
+ {
+ throw_validation_failure!(self.path, ConstRefToMutable);
+ }
}
}
}
@@ -524,6 +535,15 @@ fn check_safe_pointer(
if skip_recursive_check {
return Ok(());
}
+ } else {
+ // This is not CTFE, so it's Miri with recursive checking.
+ // FIXME: we do *not* check behind boxes, since creating a new box first creates it uninitialized
+ // and then puts the value in there, so briefly we have a box with uninit contents.
+ // FIXME: should we also skip `UnsafeCell` behind shared references? Currently that is not
+ // needed since validation reads bypass Stacked Borrows and data race checks.
+ if matches!(ptr_kind, PointerKind::Box) {
+ return Ok(());
+ }
}
let path = &self.path;
ref_tracking.track(place, || {
@@ -605,7 +625,7 @@ fn try_visit_primitive(
let _fn = try_validation!(
self.ecx.get_ptr_fn(ptr),
self.path,
- Ub(DanglingIntPointer(..) | InvalidFunctionPointer(..)) =>
+ Ub(DanglingIntPointer{ .. } | InvalidFunctionPointer(..)) =>
InvalidFnPtr { value: format!("{ptr}") },
);
// FIXME: Check if the signature matches
@@ -1072,11 +1092,23 @@ pub(crate) fn const_validate_operand(
/// `op` is assumed to cover valid memory if it is an indirect operand.
/// It will error if the bits at the destination do not match the ones described by the layout.
#[inline(always)]
- pub fn validate_operand(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
+ pub fn validate_operand(
+ &self,
+ op: &OpTy<'tcx, M::Provenance>,
+ recursive: bool,
+ ) -> InterpResult<'tcx> {
// Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
// still correct to not use `ctfe_mode`: that mode is for validation of the final constant
- // value, it rules out things like `UnsafeCell` in awkward places. It also can make checking
- // recurse through references which, for now, we don't want here, either.
- self.validate_operand_internal(op, vec![], None, None)
+ // value, it rules out things like `UnsafeCell` in awkward places.
+ if !recursive {
+ return self.validate_operand_internal(op, vec![], None, None);
+ }
+ // Do a recursive check.
+ let mut ref_tracking = RefTracking::empty();
+ self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?;
+ while let Some((mplace, path)) = ref_tracking.todo.pop() {
+ self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?;
+ }
+ Ok(())
}
}
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 71c057e..fd649d6 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -1,15 +1,14 @@
//! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound
//! types until we arrive at the leaves, with custom handling for primitive types.
+use std::num::NonZero;
+
use rustc_index::IndexVec;
use rustc_middle::mir::interpret::InterpResult;
use rustc_middle::ty::{self, Ty};
-use rustc_target::abi::FieldIdx;
-use rustc_target::abi::{FieldsShape, VariantIdx, Variants};
+use rustc_target::abi::{FieldIdx, FieldsShape, VariantIdx, Variants};
use tracing::trace;
-use std::num::NonZero;
-
use super::{throw_inval, InterpCx, MPlaceTy, Machine, Projectable};
/// How to traverse a value and what to do when we are at the leaves.
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 50a4d061..7804042 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -26,8 +26,8 @@
use std::sync::atomic::AtomicBool;
pub use errors::ReportErrorExt;
-
-use rustc_middle::{ty, util::Providers};
+use rustc_middle::ty;
+use rustc_middle::util::Providers;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs
index 528274e..5ad5596 100644
--- a/compiler/rustc_const_eval/src/util/alignment.rs
+++ b/compiler/rustc_const_eval/src/util/alignment.rs
@@ -22,7 +22,7 @@ pub fn is_disaligned<'tcx, L>(
};
let ty = place.ty(local_decls, tcx).ty;
- let unsized_tail = || tcx.struct_tail_with_normalize(ty, |ty| ty, || {});
+ let unsized_tail = || tcx.struct_tail_for_codegen(ty, param_env);
match tcx.layout_of(param_env.and(ty)) {
Ok(layout)
if layout.align.abi <= pack
diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs
index 3b07bee..eb185be 100644
--- a/compiler/rustc_const_eval/src/util/caller_location.rs
+++ b/compiler/rustc_const_eval/src/util/caller_location.rs
@@ -1,9 +1,8 @@
use rustc_hir::LangItem;
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Mutability};
+use rustc_middle::{bug, mir};
use rustc_span::symbol::Symbol;
use tracing::trace;
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index daf5728..cbd1fde 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,6 +1,6 @@
use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
-use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
@@ -30,10 +30,10 @@ pub fn check_validity_requirement<'tcx>(
return Ok(!layout.abi.is_uninhabited());
}
+ let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
- might_permit_raw_init_strict(layout, tcx, kind)
+ might_permit_raw_init_strict(layout, &layout_cx, kind)
} else {
- let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
might_permit_raw_init_lax(layout, &layout_cx, kind)
}
}
@@ -42,12 +42,12 @@ pub fn check_validity_requirement<'tcx>(
/// details.
fn might_permit_raw_init_strict<'tcx>(
ty: TyAndLayout<'tcx>,
- tcx: TyCtxt<'tcx>,
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
kind: ValidityRequirement,
) -> Result<bool, &'tcx LayoutError<'tcx>> {
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
- let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
+ let mut cx = InterpCx::new(cx.tcx, rustc_span::DUMMY_SP, cx.param_env, machine);
let allocated = cx
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
@@ -67,7 +67,7 @@ fn might_permit_raw_init_strict<'tcx>(
// This does *not* actually check that references are dereferenceable, but since all types that
// require dereferenceability also require non-null, we don't actually get any false negatives
// due to this.
- Ok(cx.validate_operand(&ot).is_ok())
+ Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok())
}
/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 01e5172..3aa3b3b 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -1,13 +1,11 @@
+use std::fmt::Write;
+
use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::CrateNum;
use rustc_hir::definitions::DisambiguatedDefPathData;
use rustc_middle::bug;
-use rustc_middle::ty::{
- self,
- print::{PrettyPrinter, Print, PrintError, Printer},
- GenericArg, GenericArgKind, Ty, TyCtxt,
-};
-use std::fmt::Write;
+use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer};
+use rustc_middle::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt};
struct AbsolutePathPrinter<'tcx> {
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs
index 80810df..1c23216 100644
--- a/compiler/rustc_data_structures/src/base_n.rs
+++ b/compiler/rustc_data_structures/src/base_n.rs
@@ -1,8 +1,7 @@
//! Converts unsigned integers into a string representation with some base.
//! Bases up to and including 36 can be used for case-insensitive things.
-use std::ascii;
-use std::fmt;
+use std::{ascii, fmt};
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 30e3d6a..efc56dc 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -1,8 +1,11 @@
-use crate::stable_hasher::impl_stable_traits_for_trivial_type;
-use crate::stable_hasher::{FromStableHash, Hash64, StableHasherHash};
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::hash::{Hash, Hasher};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+
+use crate::stable_hasher::{
+ impl_stable_traits_for_trivial_type, FromStableHash, Hash64, StableHasherHash,
+};
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/flat_map_in_place.rs b/compiler/rustc_data_structures/src/flat_map_in_place.rs
index f58844f..e66b00b 100644
--- a/compiler/rustc_data_structures/src/flat_map_in_place.rs
+++ b/compiler/rustc_data_structures/src/flat_map_in_place.rs
@@ -1,5 +1,6 @@
-use smallvec::{Array, SmallVec};
use std::ptr;
+
+use smallvec::{Array, SmallVec};
use thin_vec::ThinVec;
pub trait FlatMapInPlace<T>: Sized {
diff --git a/compiler/rustc_data_structures/src/flock/unix.rs b/compiler/rustc_data_structures/src/flock/unix.rs
index eff9e8f..12b8b41 100644
--- a/compiler/rustc_data_structures/src/flock/unix.rs
+++ b/compiler/rustc_data_structures/src/flock/unix.rs
@@ -1,8 +1,7 @@
use std::fs::{File, OpenOptions};
-use std::io;
-use std::mem;
use std::os::unix::prelude::*;
use std::path::Path;
+use std::{io, mem};
#[derive(Debug)]
pub struct Lock {
diff --git a/compiler/rustc_data_structures/src/flock/windows.rs b/compiler/rustc_data_structures/src/flock/windows.rs
index 7dc7266..0d76df2 100644
--- a/compiler/rustc_data_structures/src/flock/windows.rs
+++ b/compiler/rustc_data_structures/src/flock/windows.rs
@@ -2,16 +2,14 @@
use std::io;
use std::os::windows::prelude::*;
use std::path::Path;
-use tracing::debug;
-use windows::{
- Win32::Foundation::{ERROR_INVALID_FUNCTION, HANDLE},
- Win32::Storage::FileSystem::{
- LockFileEx, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, LOCKFILE_EXCLUSIVE_LOCK,
- LOCKFILE_FAIL_IMMEDIATELY, LOCK_FILE_FLAGS,
- },
- Win32::System::IO::OVERLAPPED,
+use tracing::debug;
+use windows::Win32::Foundation::{ERROR_INVALID_FUNCTION, HANDLE};
+use windows::Win32::Storage::FileSystem::{
+ LockFileEx, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, LOCKFILE_EXCLUSIVE_LOCK,
+ LOCKFILE_FAIL_IMMEDIATELY, LOCK_FILE_FLAGS,
};
+use windows::Win32::System::IO::OVERLAPPED;
#[derive(Debug)]
pub struct Lock {
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index d1d2de6..7cb013f 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -9,10 +9,11 @@
//! Thomas Lengauer and Robert Endre Tarjan.
//! <https://www.cs.princeton.edu/courses/archive/spr03/cs423/download/dominators.pdf>
-use super::ControlFlowGraph;
+use std::cmp::Ordering;
+
use rustc_index::{Idx, IndexSlice, IndexVec};
-use std::cmp::Ordering;
+use super::ControlFlowGraph;
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
index 39725ba..6c078ca 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
@@ -1,6 +1,5 @@
-use super::*;
-
use super::super::tests::TestGraph;
+use super::*;
#[test]
fn diamond() {
diff --git a/compiler/rustc_data_structures/src/graph/implementation/mod.rs b/compiler/rustc_data_structures/src/graph/implementation/mod.rs
index 8cf4b41..43fdfe6 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/mod.rs
@@ -20,8 +20,9 @@
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).
-use rustc_index::bit_set::BitSet;
use std::fmt::Debug;
+
+use rustc_index::bit_set::BitSet;
use tracing::debug;
#[cfg(test)]
diff --git a/compiler/rustc_data_structures/src/graph/implementation/tests.rs b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
index b4dbd65..32a6d9e 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
@@ -1,6 +1,7 @@
-use crate::graph::implementation::*;
use tracing::debug;
+use crate::graph::implementation::*;
+
type TestGraph = Graph<&'static str, &'static str>;
fn create_graph() -> TestGraph {
diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
index 6fca57d..cbc6664 100644
--- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
@@ -1,7 +1,9 @@
-use super::{DirectedGraph, StartNode, Successors};
+use std::ops::ControlFlow;
+
use rustc_index::bit_set::BitSet;
use rustc_index::{IndexSlice, IndexVec};
-use std::ops::ControlFlow;
+
+use super::{DirectedGraph, StartNode, Successors};
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/graph/iterate/tests.rs b/compiler/rustc_data_structures/src/graph/iterate/tests.rs
index c498c28..eb7d0bd 100644
--- a/compiler/rustc_data_structures/src/graph/iterate/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/iterate/tests.rs
@@ -1,5 +1,4 @@
use super::super::tests::TestGraph;
-
use super::*;
#[test]
diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs
index 8b96b36..2a457ff 100644
--- a/compiler/rustc_data_structures/src/graph/scc/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs
@@ -8,13 +8,16 @@
//! Typical examples would include: minimum element in SCC, maximum element
//! reachable from it, etc.
+use std::assert_matches::debug_assert_matches;
+use std::fmt::Debug;
+use std::ops::Range;
+
+use rustc_index::{Idx, IndexSlice, IndexVec};
+use tracing::{debug, instrument};
+
use crate::fx::FxHashSet;
use crate::graph::vec_graph::VecGraph;
use crate::graph::{DirectedGraph, NumEdges, Successors};
-use rustc_index::{Idx, IndexSlice, IndexVec};
-use std::fmt::Debug;
-use std::ops::Range;
-use tracing::{debug, instrument};
#[cfg(test)]
mod tests;
@@ -567,7 +570,7 @@ struct VisitingNodeFrame<G: DirectedGraph, Successors, A> {
// This None marks that we still have the initialize this node's frame.
debug!(?depth, ?node);
- debug_assert!(matches!(self.node_states[node], NodeState::NotVisited));
+ debug_assert_matches!(self.node_states[node], NodeState::NotVisited);
// Push `node` onto the stack.
self.node_states[node] = NodeState::BeingVisited {
diff --git a/compiler/rustc_data_structures/src/graph/tests.rs b/compiler/rustc_data_structures/src/graph/tests.rs
index 85c2703..b69b9db 100644
--- a/compiler/rustc_data_structures/src/graph/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/tests.rs
@@ -1,7 +1,7 @@
-use crate::fx::FxHashMap;
use std::cmp::max;
use super::*;
+use crate::fx::FxHashMap;
pub struct TestGraph {
num_nodes: usize,
diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
index 120244c..96784c2 100644
--- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
@@ -1,6 +1,7 @@
-use crate::graph::{DirectedGraph, NumEdges, Predecessors, Successors};
use rustc_index::{Idx, IndexVec};
+use crate::graph::{DirectedGraph, NumEdges, Predecessors, Successors};
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/tests.rs b/compiler/rustc_data_structures/src/graph/vec_graph/tests.rs
index a077d9d..78caf75 100644
--- a/compiler/rustc_data_structures/src/graph/vec_graph/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/vec_graph/tests.rs
@@ -1,6 +1,5 @@
-use crate::graph;
-
use super::*;
+use crate::graph;
fn create_graph() -> VecGraph<usize> {
// Create a simple graph
diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs
index ef5d2e8..f98c8de 100644
--- a/compiler/rustc_data_structures/src/hashes.rs
+++ b/compiler/rustc_data_structures/src/hashes.rs
@@ -11,11 +11,13 @@
//! connect the fact that they can only be produced by a `StableHasher` to their
//! `Encode`/`Decode` impls.
-use crate::stable_hasher::{FromStableHash, StableHasherHash};
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fmt;
use std::ops::BitXorAssign;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+
+use crate::stable_hasher::{FromStableHash, StableHasherHash};
+
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub struct Hash64 {
inner: u64,
diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs
index e0f8c35..850b052 100644
--- a/compiler/rustc_data_structures/src/intern.rs
+++ b/compiler/rustc_data_structures/src/intern.rs
@@ -1,10 +1,11 @@
-use crate::stable_hasher::{HashStable, StableHasher};
use std::cmp::Ordering;
use std::fmt::{self, Debug};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ptr;
+use crate::stable_hasher::{HashStable, StableHasher};
+
mod private {
#[derive(Clone, Copy, Debug)]
pub struct PrivateZst;
diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs
index 89088bc..d09f7ef 100644
--- a/compiler/rustc_data_structures/src/jobserver.rs
+++ b/compiler/rustc_data_structures/src/jobserver.rs
@@ -1,9 +1,8 @@
-pub use jobserver_crate::Client;
-
-use jobserver_crate::{FromEnv, FromEnvErrorKind};
-
use std::sync::{LazyLock, OnceLock};
+pub use jobserver_crate::Client;
+use jobserver_crate::{FromEnv, FromEnvErrorKind};
+
// We can only call `from_env_ext` once per process
// We stick this in a global because there could be multiple rustc instances
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 3f18b03..a35f5b1 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -10,7 +10,6 @@
#![allow(internal_features)]
#![allow(rustc::default_hash_types)]
#![allow(rustc::potential_query_instability)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
#![cfg_attr(not(parallel_compiler), feature(cell_leak))]
#![deny(unsafe_op_in_unsafe_fn)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
@@ -19,6 +18,7 @@
#![feature(array_windows)]
#![feature(ascii_char)]
#![feature(ascii_char_variants)]
+#![feature(assert_matches)]
#![feature(auto_traits)]
#![feature(cfg_match)]
#![feature(core_intrinsics)]
@@ -39,14 +39,12 @@
#![feature(unwrap_infallible)]
// tidy-alphabetical-end
-pub use atomic_ref::AtomicRef;
-pub use ena::snapshot_vec;
-pub use ena::undo_log;
-pub use ena::unify;
-pub use rustc_index::static_assert_size;
-
use std::fmt;
+pub use atomic_ref::AtomicRef;
+pub use ena::{snapshot_vec, undo_log, unify};
+pub use rustc_index::static_assert_size;
+
pub mod aligned;
pub mod base_n;
pub mod binary_search_util;
diff --git a/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs b/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs
index 4b6aa11..60cde9a 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs
@@ -1,11 +1,12 @@
-use crate::obligation_forest::{ForestObligation, ObligationForest};
-use rustc_graphviz as dot;
use std::env::var_os;
use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use rustc_graphviz as dot;
+
+use crate::obligation_forest::{ForestObligation, ObligationForest};
impl<O: ForestObligation> ObligationForest<O> {
/// Creates a graphviz representation of the obligation forest. Given a directory this will
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 3883b07..cfe7dd1 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -69,14 +69,16 @@
//! step, we compress the vector to remove completed and error nodes, which
//! aren't needed anymore.
-use crate::fx::{FxHashMap, FxHashSet};
use std::cell::Cell;
use std::collections::hash_map::Entry;
use std::fmt::Debug;
use std::hash;
use std::marker::PhantomData;
+
use tracing::debug;
+use crate::fx::{FxHashMap, FxHashSet};
+
mod graphviz;
#[cfg(test)]
diff --git a/compiler/rustc_data_structures/src/obligation_forest/tests.rs b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
index d09c8e5..a58c6ee 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/tests.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
@@ -1,7 +1,7 @@
-use super::*;
-
use std::fmt;
+use super::*;
+
impl<'a> super::ForestObligation for &'a str {
type CacheKey = &'a str;
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index bb66479..bbe6691 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -1,10 +1,11 @@
-use std::{borrow::Borrow, ops::Deref};
+use std::borrow::Borrow;
+use std::ops::Deref;
-use crate::sync::Lrc;
// Use our fake Send/Sync traits when on not parallel compiler,
// so that `OwnedSlice` only implements/requires Send/Sync
// for parallel compiler builds.
use crate::sync;
+use crate::sync::Lrc;
/// An owned slice.
///
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
index 520871a..324b8ec 100644
--- a/compiler/rustc_data_structures/src/owned_slice/tests.rs
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -1,15 +1,9 @@
-use std::{
- ops::Deref,
- sync::{
- atomic::{self, AtomicBool},
- Arc,
- },
-};
+use std::ops::Deref;
+use std::sync::atomic::{self, AtomicBool};
+use std::sync::Arc;
-use crate::{
- defer,
- owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
-};
+use crate::defer;
+use crate::owned_slice::{slice_owned, try_slice_owned, OwnedSlice};
#[test]
fn smoke() {
diff --git a/compiler/rustc_data_structures/src/packed.rs b/compiler/rustc_data_structures/src/packed.rs
index 0a392d9..f54b12b 100644
--- a/compiler/rustc_data_structures/src/packed.rs
+++ b/compiler/rustc_data_structures/src/packed.rs
@@ -1,8 +1,10 @@
-use crate::stable_hasher::{HashStable, StableHasher};
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cmp::Ordering;
use std::fmt;
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+
+use crate::stable_hasher::{HashStable, StableHasher};
+
/// A packed 128-bit integer. Useful for reducing the size of structures in
/// some cases.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index 240f267..1905074 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -81,19 +81,15 @@
//!
//! [mm]: https://github.com/rust-lang/measureme/
-use crate::fx::FxHashMap;
-use crate::outline;
-
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::error::Error;
use std::fmt::Display;
-use std::fs;
use std::intrinsics::unlikely;
use std::path::Path;
-use std::process;
use std::sync::Arc;
use std::time::{Duration, Instant};
+use std::{fs, process};
pub use measureme::EventId;
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
@@ -101,6 +97,9 @@
use smallvec::SmallVec;
use tracing::warn;
+use crate::fx::FxHashMap;
+use crate::outline;
+
bitflags::bitflags! {
#[derive(Clone, Copy)]
struct EventFilter: u16 {
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 4b02b18..03aa1d8 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -1,14 +1,15 @@
+use std::borrow::Borrow;
+use std::collections::hash_map::RawEntryMut;
+use std::hash::{Hash, Hasher};
+use std::{iter, mem};
+
+#[cfg(parallel_compiler)]
+use either::Either;
+
use crate::fx::{FxHashMap, FxHasher};
#[cfg(parallel_compiler)]
use crate::sync::{is_dyn_thread_safe, CacheAligned};
use crate::sync::{Lock, LockGuard, Mode};
-#[cfg(parallel_compiler)]
-use either::Either;
-use std::borrow::Borrow;
-use std::collections::hash_map::RawEntryMut;
-use std::hash::{Hash, Hasher};
-use std::iter;
-use std::mem;
// 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700,
// but this should be tested on higher core count CPUs. How the `Sharded` type gets used
diff --git a/compiler/rustc_data_structures/src/snapshot_map/mod.rs b/compiler/rustc_data_structures/src/snapshot_map/mod.rs
index 8a50179..d50365b 100644
--- a/compiler/rustc_data_structures/src/snapshot_map/mod.rs
+++ b/compiler/rustc_data_structures/src/snapshot_map/mod.rs
@@ -1,11 +1,11 @@
-use crate::fx::FxHashMap;
-use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog};
use std::borrow::{Borrow, BorrowMut};
use std::hash::Hash;
use std::marker::PhantomData;
use std::ops;
+use crate::fx::FxHashMap;
pub use crate::undo_log::Snapshot;
+use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog};
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index 885f023..066ea03 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -1,10 +1,12 @@
-use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
-use rustc_macros::{Decodable_Generic, Encodable_Generic};
use std::borrow::Borrow;
use std::fmt::Debug;
use std::mem;
use std::ops::{Bound, Index, IndexMut, RangeBounds};
+use rustc_macros::{Decodable_Generic, Encodable_Generic};
+
+use crate::stable_hasher::{HashStable, StableHasher, StableOrd};
+
mod index_map;
pub use index_map::SortedIndexMultiMap;
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index c172ee1..e9a5fb5 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -2,9 +2,10 @@
use std::hash::{Hash, Hasher};
-use crate::stable_hasher::{HashStable, StableHasher};
use rustc_index::{Idx, IndexVec};
+use crate::stable_hasher::{HashStable, StableHasher};
+
/// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of
/// an item by key and *O*(1) lookup by index.
///
diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index 2ef4a2c..3200249 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -1,10 +1,12 @@
-use crate::fx::FxHashMap;
-use arrayvec::ArrayVec;
-use either::Either;
use std::fmt;
use std::hash::Hash;
use std::ops::Index;
+use arrayvec::ArrayVec;
+use either::Either;
+
+use crate::fx::FxHashMap;
+
/// For pointer-sized arguments arrays
/// are faster than set/map for up to 64
/// arguments.
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 83883ee..9673f94 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -1,19 +1,20 @@
-use rustc_index::bit_set::{self, BitSet};
-use rustc_index::{Idx, IndexSlice, IndexVec};
-use smallvec::SmallVec;
use std::hash::{BuildHasher, Hash, Hasher};
use std::marker::PhantomData;
use std::mem;
use std::num::NonZero;
+use rustc_index::bit_set::{self, BitSet};
+use rustc_index::{Idx, IndexSlice, IndexVec};
+use smallvec::SmallVec;
+
#[cfg(test)]
mod tests;
-pub use crate::hashes::{Hash128, Hash64};
+pub use rustc_stable_hash::{
+ FromStableHash, SipHasher128Hash as StableHasherHash, StableSipHasher128 as StableHasher,
+};
-pub use rustc_stable_hash::FromStableHash;
-pub use rustc_stable_hash::SipHasher128Hash as StableHasherHash;
-pub use rustc_stable_hash::StableSipHasher128 as StableHasher;
+pub use crate::hashes::{Hash128, Hash64};
/// Something that implements `HashStable<CTX>` can be hashed in a way that is
/// stable across multiple compilation sessions.
diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs
index 9a0fd526..0f2c0ee 100644
--- a/compiler/rustc_data_structures/src/steal.rs
+++ b/compiler/rustc_data_structures/src/steal.rs
@@ -51,6 +51,15 @@ pub fn steal(&self) -> T {
let value = value_ref.take();
value.expect("attempt to steal from stolen value")
}
+
+ /// Writers of rustc drivers often encounter stealing issues. This function makes it possible to
+ /// handle these errors gracefully.
+ ///
+ /// This should not be used within rustc as it leaks information not tracked
+ /// by the query system, breaking incremental compilation.
+ pub fn is_stolen(&self) -> bool {
+ self.value.borrow().is_none()
+ }
}
impl<CTX, T: HashStable<CTX>> HashStable<CTX> for Steal<T> {
diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs
index 38629ea..391a7c9 100644
--- a/compiler/rustc_data_structures/src/svh.rs
+++ b/compiler/rustc_data_structures/src/svh.rs
@@ -5,10 +5,12 @@
//! mismatches where we have two versions of the same crate that were
//! compiled from distinct sources.
+use std::fmt;
+
+use rustc_macros::{Decodable_Generic, Encodable_Generic};
+
use crate::fingerprint::Fingerprint;
use crate::stable_hasher;
-use rustc_macros::{Decodable_Generic, Encodable_Generic};
-use std::fmt;
#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable_Generic, Decodable_Generic, Hash)]
pub struct Svh {
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 058a675..6df94bc 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -41,10 +41,11 @@
//!
//! [^2]: `MTRef`, `MTLockRef` are type aliases.
-pub use crate::marker::*;
use std::collections::HashMap;
use std::hash::{BuildHasher, Hash};
+pub use crate::marker::*;
+
mod lock;
#[doc(no_inline)]
pub use lock::{Lock, LockGuard, Mode};
@@ -56,7 +57,6 @@
#[cfg(parallel_compiler)]
pub use parallel::scope;
pub use parallel::{join, par_for_each_in, par_map, parallel_guard, try_par_for_each_in};
-
pub use vec::{AppendOnlyIndexVec, AppendOnlyVec};
mod vec;
diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs
index 466c44f..fad5f58 100644
--- a/compiler/rustc_data_structures/src/sync/freeze.rs
+++ b/compiler/rustc_data_structures/src/sync/freeze.rs
@@ -1,14 +1,13 @@
+use std::cell::UnsafeCell;
+use std::intrinsics::likely;
+use std::marker::PhantomData;
+use std::ops::{Deref, DerefMut};
+use std::ptr::NonNull;
+use std::sync::atomic::Ordering;
+
use crate::sync::{AtomicBool, ReadGuard, RwLock, WriteGuard};
#[cfg(parallel_compiler)]
use crate::sync::{DynSend, DynSync};
-use std::{
- cell::UnsafeCell,
- intrinsics::likely,
- marker::PhantomData,
- ops::{Deref, DerefMut},
- ptr::NonNull,
- sync::atomic::Ordering,
-};
/// A type which allows mutation using a lock until
/// the value is frozen and can be accessed lock-free.
diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs
index 780be77..7cf9426 100644
--- a/compiler/rustc_data_structures/src/sync/lock.rs
+++ b/compiler/rustc_data_structures/src/sync/lock.rs
@@ -19,19 +19,20 @@ pub enum Mode {
}
mod maybe_sync {
- use super::Mode;
- use crate::sync::mode;
- #[cfg(parallel_compiler)]
- use crate::sync::{DynSend, DynSync};
- use parking_lot::lock_api::RawMutex as _;
- use parking_lot::RawMutex;
- use std::cell::Cell;
- use std::cell::UnsafeCell;
+ use std::cell::{Cell, UnsafeCell};
use std::intrinsics::unlikely;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::{Deref, DerefMut};
+ use parking_lot::lock_api::RawMutex as _;
+ use parking_lot::RawMutex;
+
+ use super::Mode;
+ use crate::sync::mode;
+ #[cfg(parallel_compiler)]
+ use crate::sync::{DynSend, DynSync};
+
/// A guard holding mutable access to a `Lock` which is in a locked state.
#[must_use = "if unused the Lock will immediately unlock"]
pub struct LockGuard<'a, T> {
@@ -186,12 +187,12 @@ unsafe impl<T: DynSend> DynSync for Lock<T> {}
}
mod no_sync {
- use super::Mode;
use std::cell::RefCell;
-
#[doc(no_inline)]
pub use std::cell::RefMut as LockGuard;
+ use super::Mode;
+
pub struct Lock<T>(RefCell<T>);
impl<T> Lock<T> {
diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs
index 7783de5..2b89431 100644
--- a/compiler/rustc_data_structures/src/sync/parallel.rs
+++ b/compiler/rustc_data_structures/src/sync/parallel.rs
@@ -3,9 +3,6 @@
#![allow(dead_code)]
-use crate::sync::IntoDynSyncSend;
-use crate::FatalErrorMarker;
-use parking_lot::Mutex;
use std::any::Any;
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
@@ -13,6 +10,10 @@
pub use disabled::*;
#[cfg(parallel_compiler)]
pub use enabled::*;
+use parking_lot::Mutex;
+
+use crate::sync::IntoDynSyncSend;
+use crate::FatalErrorMarker;
/// A guard used to hold panics that occur during a parallel section to later by unwound.
/// This is used for the parallel compiler to prevent fatal errors from non-deterministically
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index 07a361b..4950481 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -1,11 +1,10 @@
-use parking_lot::Mutex;
-use std::cell::Cell;
-use std::cell::OnceCell;
+use std::cell::{Cell, OnceCell};
use std::num::NonZero;
use std::ops::Deref;
use std::ptr;
use std::sync::Arc;
+use parking_lot::Mutex;
#[cfg(parallel_compiler)]
use {crate::outline, crate::sync::CacheAligned};
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
index 8b9e834..25e107b 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs
@@ -1,5 +1,3 @@
-use super::{Pointer, Tag};
-use crate::stable_hasher::{HashStable, StableHasher};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
@@ -8,6 +6,9 @@
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
+use super::{Pointer, Tag};
+use crate::stable_hasher::{HashStable, StableHasher};
+
/// A [`Copy`] tagged pointer.
///
/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer.
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
index 4e42b5b..319a8cd 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs
@@ -2,8 +2,7 @@
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
-use super::CopyTaggedPtr;
-use super::{Pointer, Tag};
+use super::{CopyTaggedPtr, Pointer, Tag};
use crate::stable_hasher::{HashStable, StableHasher};
/// A tagged pointer that supports pointers that implement [`Drop`].
diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
index 2c17d67..4d342c7 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs
@@ -1,4 +1,5 @@
-use std::{ptr, sync::Arc};
+use std::ptr;
+use std::sync::Arc;
use crate::tagged_ptr::{Pointer, Tag, Tag2, TaggedPtr};
diff --git a/compiler/rustc_data_structures/src/temp_dir.rs b/compiler/rustc_data_structures/src/temp_dir.rs
index 621d301..4dbe11d 100644
--- a/compiler/rustc_data_structures/src/temp_dir.rs
+++ b/compiler/rustc_data_structures/src/temp_dir.rs
@@ -1,5 +1,6 @@
use std::mem::ManuallyDrop;
use std::path::Path;
+
use tempfile::TempDir;
/// This is used to avoid TempDir being dropped on error paths unintentionally.
diff --git a/compiler/rustc_data_structures/src/transitive_relation.rs b/compiler/rustc_data_structures/src/transitive_relation.rs
index cd391fe..e81ebb9a 100644
--- a/compiler/rustc_data_structures/src/transitive_relation.rs
+++ b/compiler/rustc_data_structures/src/transitive_relation.rs
@@ -1,11 +1,13 @@
-use crate::frozen::Frozen;
-use crate::fx::{FxHashSet, FxIndexSet};
-use rustc_index::bit_set::BitMatrix;
use std::fmt::Debug;
use std::hash::Hash;
use std::mem;
use std::ops::Deref;
+use rustc_index::bit_set::BitMatrix;
+
+use crate::frozen::Frozen;
+use crate::fx::{FxHashSet, FxIndexSet};
+
#[cfg(test)]
mod tests;
@@ -201,9 +203,9 @@ pub fn postdom_upper_bound(&self, a: T, b: T) -> Option<T> {
/// exists). See `postdom_upper_bound` for details.
pub fn mutual_immediate_postdominator(&self, mut mubs: Vec<T>) -> Option<T> {
loop {
- match mubs.len() {
- 0 => return None,
- 1 => return Some(mubs[0]),
+ match mubs[..] {
+ [] => return None,
+ [mub] => return Some(mub),
_ => {
let m = mubs.pop().unwrap();
let n = mubs.pop().unwrap();
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
index 1ccd22a..bafb16a 100644
--- a/compiler/rustc_data_structures/src/unord.rs
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -2,21 +2,17 @@
//! ordering. This is a useful property for deterministic computations, such
//! as required by the query system.
+use std::borrow::{Borrow, BorrowMut};
+use std::collections::hash_map::{Entry, OccupiedError};
+use std::hash::Hash;
+use std::iter::{Product, Sum};
+use std::ops::Index;
+
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_macros::{Decodable_Generic, Encodable_Generic};
-use std::collections::hash_map::OccupiedError;
-use std::{
- borrow::{Borrow, BorrowMut},
- collections::hash_map::Entry,
- hash::Hash,
- iter::{Product, Sum},
- ops::Index,
-};
-use crate::{
- fingerprint::Fingerprint,
- stable_hasher::{HashStable, StableCompare, StableHasher, ToStableHashKey},
-};
+use crate::fingerprint::Fingerprint;
+use crate::stable_hasher::{HashStable, StableCompare, StableHasher, ToStableHashKey};
/// `UnordItems` is the order-less version of `Iterator`. It only contains methods
/// that don't (easily) expose an ordering of the underlying items.
diff --git a/compiler/rustc_data_structures/src/work_queue.rs b/compiler/rustc_data_structures/src/work_queue.rs
index 9db6b6f..490d7d3 100644
--- a/compiler/rustc_data_structures/src/work_queue.rs
+++ b/compiler/rustc_data_structures/src/work_queue.rs
@@ -1,6 +1,7 @@
+use std::collections::VecDeque;
+
use rustc_index::bit_set::BitSet;
use rustc_index::Idx;
-use std::collections::VecDeque;
/// A work queue is a handy data structure for tracking work left to
/// do. (For example, basic blocks left to process.) It is basically a
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index ad2acb0..2b7dc04 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -17,8 +17,23 @@
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
+use std::cmp::max;
+use std::collections::BTreeMap;
+use std::ffi::OsString;
+use std::fmt::Write as _;
+use std::fs::{self, File};
+use std::io::{self, IsTerminal, Read, Write};
+use std::panic::{self, catch_unwind, PanicHookInfo};
+use std::path::PathBuf;
+use std::process::{self, Command, Stdio};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::{Arc, OnceLock};
+use std::time::{Duration, Instant, SystemTime};
+use std::{env, str};
+
use rustc_ast as ast;
-use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
+use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_codegen_ssa::{CodegenErrors, CodegenResults};
use rustc_const_eval::CTRL_C_RECEIVED;
use rustc_data_structures::profiling::{
get_resident_set_size, print_time_passes_entry, TimePassesFormat,
@@ -35,8 +50,10 @@
use rustc_metadata::creader::MetadataLoader;
use rustc_metadata::locator;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
-use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
-use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
+use rustc_session::config::{
+ nightly_options, ErrorOutputType, Input, OutFileName, OutputType, UnstableOptions, CG_OPTIONS,
+ Z_OPTIONS,
+};
use rustc_session::getopts::{self, Matches};
use rustc_session::lint::{Lint, LintId};
use rustc_session::output::collect_crate_types;
@@ -46,20 +63,6 @@
use rustc_span::FileName;
use rustc_target::json::ToJson;
use rustc_target::spec::{Target, TargetTriple};
-use std::cmp::max;
-use std::collections::BTreeMap;
-use std::env;
-use std::ffi::OsString;
-use std::fmt::Write as _;
-use std::fs::{self, File};
-use std::io::{self, IsTerminal, Read, Write};
-use std::panic::{self, catch_unwind, PanicHookInfo};
-use std::path::PathBuf;
-use std::process::{self, Command, Stdio};
-use std::str;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::{Arc, OnceLock};
-use std::time::{Duration, Instant, SystemTime};
use time::OffsetDateTime;
use tracing::trace;
@@ -299,6 +302,8 @@ fn run_compiler(
let Some(matches) = handle_options(&default_early_dcx, &args) else { return Ok(()) };
let sopts = config::build_session_options(&mut default_early_dcx, &matches);
+ // fully initialize ice path static once unstable options are available as context
+ let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone();
if let Some(ref code) = matches.opt_str("explain") {
handle_explain(&default_early_dcx, diagnostics_registry(), code, sopts.color);
@@ -313,7 +318,7 @@ fn run_compiler(
input: Input::File(PathBuf::new()),
output_file: ofile,
output_dir: odir,
- ice_file: ice_path().clone(),
+ ice_file,
file_loader,
locale_resources: DEFAULT_LOCALE_RESOURCES,
lint_caps: Default::default(),
@@ -333,12 +338,11 @@ fn run_compiler(
config.input = input;
true // has input: normal compilation
}
- Ok(None) => match matches.free.len() {
- 0 => false, // no input: we will exit early
- 1 => panic!("make_input should have provided valid inputs"),
- _ => default_early_dcx.early_fatal(format!(
- "multiple input filenames provided (first two filenames are `{}` and `{}`)",
- matches.free[0], matches.free[1],
+ Ok(None) => match matches.free.as_slice() {
+ [] => false, // no input: we will exit early
+ [_] => panic!("make_input should have provided valid inputs"),
+ [fst, snd, ..] => default_early_dcx.early_fatal(format!(
+ "multiple input filenames provided (first two filenames are `{fst}` and `{snd}`)"
)),
},
};
@@ -486,34 +490,30 @@ fn make_input(
early_dcx: &EarlyDiagCtxt,
free_matches: &[String],
) -> Result<Option<Input>, ErrorGuaranteed> {
- if free_matches.len() == 1 {
- let ifile = &free_matches[0];
- if ifile == "-" {
- let mut src = String::new();
- if io::stdin().read_to_string(&mut src).is_err() {
- // Immediately stop compilation if there was an issue reading
- // the input (for example if the input stream is not UTF-8).
- let reported = early_dcx
- .early_err("couldn't read from stdin, as it did not contain valid UTF-8");
- return Err(reported);
- }
- if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
- let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
- "when UNSTABLE_RUSTDOC_TEST_PATH is set \
+ let [ifile] = free_matches else { return Ok(None) };
+ if ifile == "-" {
+ let mut src = String::new();
+ if io::stdin().read_to_string(&mut src).is_err() {
+ // Immediately stop compilation if there was an issue reading
+ // the input (for example if the input stream is not UTF-8).
+ let reported =
+ early_dcx.early_err("couldn't read from stdin, as it did not contain valid UTF-8");
+ return Err(reported);
+ }
+ if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
+ let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
+ "when UNSTABLE_RUSTDOC_TEST_PATH is set \
UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
- );
- let line = isize::from_str_radix(&line, 10)
- .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
- let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
- Ok(Some(Input::Str { name: file_name, input: src }))
- } else {
- Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
- }
+ );
+ let line = isize::from_str_radix(&line, 10)
+ .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
+ let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
+ Ok(Some(Input::Str { name: file_name, input: src }))
} else {
- Ok(Some(Input::File(PathBuf::from(ifile))))
+ Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
}
} else {
- Ok(None)
+ Ok(Some(Input::File(PathBuf::from(ifile))))
}
}
@@ -689,7 +689,6 @@ fn print_crate_info(
parse_attrs: bool,
) -> Compilation {
use rustc_session::config::PrintKind::*;
-
// This import prevents the following code from using the printing macros
// used by the rest of the module. Within this function, we only write to
// the output specified by `sess.io.output_file`.
@@ -908,6 +907,15 @@ pub fn version_at_macro_invocation(
) {
let verbose = matches.opt_present("verbose");
+ let mut version = version;
+ let mut release = release;
+ let tmp;
+ if let Ok(force_version) = std::env::var("RUSTC_OVERRIDE_VERSION_STRING") {
+ tmp = force_version;
+ version = &tmp;
+ release = &tmp;
+ }
+
safe_println!("{binary} {version}");
if verbose {
@@ -1296,25 +1304,43 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
static ICE_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
+// This function should only be called from the ICE hook.
+//
+// The intended behavior is that `run_compiler` will invoke `ice_path_with_config` early in the
+// initialization process to properly initialize the ICE_PATH static based on parsed CLI flags.
+//
+// Subsequent calls to either function will then return the proper ICE path as configured by
+// the environment and cli flags
fn ice_path() -> &'static Option<PathBuf> {
+ ice_path_with_config(None)
+}
+
+fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<PathBuf> {
+ if ICE_PATH.get().is_some() && config.is_some() && cfg!(debug_assertions) {
+ tracing::warn!(
+ "ICE_PATH has already been initialized -- files may be emitted at unintended paths"
+ )
+ }
+
ICE_PATH.get_or_init(|| {
if !rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() {
return None;
}
- if let Some(s) = std::env::var_os("RUST_BACKTRACE")
- && s == "0"
- {
- return None;
- }
let mut path = match std::env::var_os("RUSTC_ICE") {
Some(s) => {
if s == "0" {
// Explicitly opting out of writing ICEs to disk.
return None;
}
+ if let Some(unstable_opts) = config && unstable_opts.metrics_dir.is_some() {
+ tracing::warn!("ignoring -Zerror-metrics in favor of RUSTC_ICE for destination of ICE report files");
+ }
PathBuf::from(s)
}
- None => std::env::current_dir().unwrap_or_default(),
+ None => config
+ .and_then(|unstable_opts| unstable_opts.metrics_dir.to_owned())
+ .or_else(|| std::env::current_dir().ok())
+ .unwrap_or_default(),
};
let now: OffsetDateTime = SystemTime::now().into();
let file_now = now
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 31de0a7..c973fce 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -1,9 +1,10 @@
//! The various pretty-printing routines.
-use rustc_ast as ast;
+use std::cell::Cell;
+use std::fmt::Write;
+
use rustc_ast_pretty::pprust as pprust_ast;
use rustc_errors::FatalError;
-use rustc_hir_pretty as pprust_hir;
use rustc_middle::bug;
use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
use rustc_middle::ty::{self, TyCtxt};
@@ -12,9 +13,8 @@
use rustc_smir::rustc_internal::pretty::write_smir_pretty;
use rustc_span::symbol::Ident;
use rustc_span::FileName;
-use std::cell::Cell;
-use std::fmt::Write;
use tracing::debug;
+use {rustc_ast as ast, rustc_hir_pretty as pprust_hir};
pub use self::PpMode::*;
pub use self::PpSourceMode::*;
diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs
index 441219e..51f2a50 100644
--- a/compiler/rustc_driver_impl/src/signal_handler.rs
+++ b/compiler/rustc_driver_impl/src/signal_handler.rs
@@ -1,10 +1,11 @@
//! Signal handler for rustc
//! Primarily used to extract a backtrace from stack overflow
-use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
use std::alloc::{alloc, Layout};
use std::{fmt, mem, ptr};
+use rustc_interface::util::{DEFAULT_STACK_SIZE, STACK_SIZE};
+
extern "C" {
fn backtrace_symbols_fd(buffer: *const *mut libc::c_void, size: libc::c_int, fd: libc::c_int);
}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0517.md b/compiler/rustc_error_codes/src/error_codes/E0517.md
index ae80224..5354a08 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0517.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0517.md
@@ -25,14 +25,17 @@
These attributes do not work on typedefs, since typedefs are just aliases.
Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the
-discriminant size for enums with no data fields on any of the variants, e.g.
-`enum Color {Red, Blue, Green}`, effectively setting the size of the enum to
-the size of the provided type. Such an enum can be cast to a value of the same
-type as well. In short, `#[repr(u8)]` makes the enum behave like an integer
-with a constrained set of allowed values.
+discriminant size for enums. For enums with no data fields on any of the
+variants, e.g. `enum Color {Red, Blue, Green}`, this effectively sets the size
+of the enum to the size of the provided type. Such an enum can be cast to a
+value of the same type as well. In short, `#[repr(u8)]` makes a field-less enum
+behave like an integer with a constrained set of allowed values.
-Only field-less enums can be cast to numerical primitives, so this attribute
-will not apply to structs.
+For a description of how `#[repr(C)]` and representations like `#[repr(u8)]`
+affect the layout of enums with data fields, see [RFC 2195][rfc2195].
+
+Only field-less enums can be cast to numerical primitives. Representations like
+`#[repr(u8)]` will not apply to structs.
`#[repr(packed)]` reduces padding to make the struct size smaller. The
representation of enums isn't strictly defined in Rust, and this attribute
@@ -42,3 +45,5 @@
types (i.e., `u8`, `i32`, etc) a representation that permits vectorization via
SIMD. This doesn't make much sense for enums since they don't consist of a
single list of data.
+
+[rfc2195]: https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md
diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md
index ad77d72..69e61f7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0795.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0795.md
@@ -3,7 +3,7 @@
Erroneous code example:
```compile_fail,E0795
-#![feature(offset_of_enum, offset_of_nested)]
+#![feature(offset_of_enum)]
let x = std::mem::offset_of!(Option<u8>, Some);
```
@@ -16,7 +16,7 @@
the field name `0`:
```
-#![feature(offset_of_enum, offset_of_nested)]
+#![feature(offset_of_enum)]
let x: usize = std::mem::offset_of!(Option<u8>, Some.0);
```
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 26a6845..87dee28 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -6,31 +6,28 @@
#![feature(type_alias_impl_trait)]
// tidy-alphabetical-end
-use fluent_bundle::FluentResource;
-use fluent_syntax::parser::ParserError;
-use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
-use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
-use rustc_macros::{Decodable, Encodable};
-use rustc_span::Span;
use std::borrow::Cow;
-use std::error::Error;
-use std::fmt;
-use std::fs;
-use std::io;
-use std::path::{Path, PathBuf};
-use tracing::{instrument, trace};
-
#[cfg(not(parallel_compiler))]
use std::cell::LazyCell as Lazy;
+use std::error::Error;
+use std::path::{Path, PathBuf};
#[cfg(parallel_compiler)]
use std::sync::LazyLock as Lazy;
+use std::{fmt, fs, io};
+pub use fluent_bundle::types::FluentType;
+use fluent_bundle::FluentResource;
+pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
+use fluent_syntax::parser::ParserError;
+use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
#[cfg(parallel_compiler)]
use intl_memoizer::concurrent::IntlLangMemoizer;
#[cfg(not(parallel_compiler))]
use intl_memoizer::IntlLangMemoizer;
-
-pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue};
+use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
+use rustc_macros::{Decodable, Encodable};
+use rustc_span::Span;
+use tracing::{instrument, trace};
pub use unic_langid::{langid, LanguageIdentifier};
pub type FluentBundle =
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index b71b93c..df4e979 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -5,6 +5,12 @@
//!
//! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/
+use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
+use rustc_data_structures::sync::Lrc;
+use rustc_error_messages::FluentArgs;
+use rustc_span::source_map::SourceMap;
+use rustc_span::SourceFile;
+
use crate::emitter::FileWithAnnotatedLines;
use crate::snippet::Line;
use crate::translation::{to_fluent_args, Translate};
@@ -12,11 +18,6 @@
CodeSuggestion, DiagInner, DiagMessage, Emitter, ErrCode, FluentBundle, LazyFallbackBundle,
Level, MultiSpan, Style, Subdiag,
};
-use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
-use rustc_data_structures::sync::Lrc;
-use rustc_error_messages::FluentArgs;
-use rustc_span::source_map::SourceMap;
-use rustc_span::SourceFile;
/// Generates diagnostics using annotate-snippet
pub struct AnnotateSnippetEmitter {
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index d500f6d..fae8b56 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,16 +1,3 @@
-use crate::snippet::Style;
-use crate::{
- CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
- MultiSpan, StashKey, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
-};
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
-use rustc_error_messages::FluentValue;
-use rustc_lint_defs::{Applicability, LintExpectationId};
-use rustc_macros::{Decodable, Encodable};
-use rustc_span::source_map::Spanned;
-use rustc_span::symbol::Symbol;
-use rustc_span::{Span, DUMMY_SP};
use std::borrow::Cow;
use std::fmt::{self, Debug};
use std::hash::{Hash, Hasher};
@@ -18,8 +5,22 @@
use std::ops::{Deref, DerefMut};
use std::panic;
use std::thread::panicking;
+
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_error_messages::{fluent_value_from_str_list_sep_by_and, FluentValue};
+use rustc_lint_defs::{Applicability, LintExpectationId};
+use rustc_macros::{Decodable, Encodable};
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::Symbol;
+use rustc_span::{Span, DUMMY_SP};
use tracing::debug;
+use crate::snippet::Style;
+use crate::{
+ CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level,
+ MultiSpan, StashKey, SubdiagMessage, Substitution, SubstitutionPart, SuggestionStyle,
+};
+
/// Error type for `DiagInner`'s `suggestions` field, indicating that
/// `.disable_suggestions()` was called on the `DiagInner`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
@@ -740,6 +741,16 @@ pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
self
}
+ #[rustc_lint_diagnostics]
+ pub fn highlighted_span_note(
+ &mut self,
+ span: impl Into<MultiSpan>,
+ msg: Vec<StringPart>,
+ ) -> &mut Self {
+ self.sub_with_highlights(Level::Note, msg, span.into());
+ self
+ }
+
/// This is like [`Diag::note()`], but it's only printed once.
#[rustc_lint_diagnostics]
pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
@@ -814,6 +825,17 @@ pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
self
}
+ /// Add a help message attached to this diagnostic with a customizable highlighted message.
+ #[rustc_lint_diagnostics]
+ pub fn highlighted_span_help(
+ &mut self,
+ span: impl Into<MultiSpan>,
+ msg: Vec<StringPart>,
+ ) -> &mut Self {
+ self.sub_with_highlights(Level::Help, msg, span.into());
+ self
+ }
+
/// Prints the span with some help above it.
/// This is like [`Diag::help()`], but it gets its own span.
#[rustc_lint_diagnostics]
@@ -898,8 +920,8 @@ pub fn multipart_suggestion_with_style(
applicability: Applicability,
style: SuggestionStyle,
) -> &mut Self {
- suggestion.sort_unstable();
- suggestion.dedup_by(|(s1, m1), (s2, m2)| s1.source_equal(*s2) && m1 == m2);
+ let mut seen = crate::FxHashSet::default();
+ suggestion.retain(|(span, msg)| seen.insert((span.lo(), span.hi(), msg.clone())));
let parts = suggestion
.into_iter()
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index e6ca1bf7..9e3bc3e 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,12 +1,11 @@
-use crate::diagnostic::DiagLocation;
-use crate::{fluent_generated as fluent, DiagCtxtHandle, Subdiagnostic};
-use crate::{
- Diag, DiagArgValue, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level,
- SubdiagMessageOp,
-};
-use rustc_ast as ast;
+use std::backtrace::Backtrace;
+use std::borrow::Cow;
+use std::fmt;
+use std::num::ParseIntError;
+use std::path::{Path, PathBuf};
+use std::process::ExitStatus;
+
use rustc_ast_pretty::pprust;
-use rustc_hir as hir;
use rustc_macros::Subdiagnostic;
use rustc_span::edition::Edition;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
@@ -14,12 +13,13 @@
use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
use rustc_type_ir::{ClosureKind, FloatTy};
-use std::backtrace::Backtrace;
-use std::borrow::Cow;
-use std::fmt;
-use std::num::ParseIntError;
-use std::path::{Path, PathBuf};
-use std::process::ExitStatus;
+use {rustc_ast as ast, rustc_hir as hir};
+
+use crate::diagnostic::DiagLocation;
+use crate::{
+ fluent_generated as fluent, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee,
+ ErrCode, IntoDiagArg, Level, SubdiagMessageOp, Subdiagnostic,
+};
pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
@@ -66,6 +66,7 @@ macro_rules! into_diag_arg_for_number {
impl IntoDiagArg for $ty {
fn into_diag_arg(self) -> DiagArgValue {
// Convert to a string if it won't fit into `Number`.
+ #[allow(irrefutable_let_patterns)]
if let Ok(n) = TryInto::<i32>::try_into(self) {
DiagArgValue::Number(n)
} else {
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 58220c6..9ce5d77 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -7,25 +7,6 @@
//!
//! The output types are defined in `rustc_session::config::ErrorOutputType`.
-use rustc_span::source_map::SourceMap;
-use rustc_span::{char_width, FileLines, FileName, SourceFile, Span};
-
-use crate::snippet::{
- Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
-};
-use crate::styled_buffer::StyledBuffer;
-use crate::translation::{to_fluent_args, Translate};
-use crate::{
- diagnostic::DiagLocation, CodeSuggestion, DiagCtxt, DiagInner, DiagMessage, ErrCode,
- FluentBundle, LazyFallbackBundle, Level, MultiSpan, Subdiag, SubstitutionHighlight,
- SuggestionStyle, TerminalUrl,
-};
-use derive_setters::Setters;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
-use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
-use rustc_error_messages::{FluentArgs, SpanLabel};
-use rustc_lint_defs::pluralize;
-use rustc_span::hygiene::{ExpnKind, MacroKind};
use std::borrow::Cow;
use std::cmp::{max, min, Reverse};
use std::error::Report;
@@ -33,29 +14,43 @@
use std::io::{self, IsTerminal};
use std::iter;
use std::path::Path;
-use termcolor::{Buffer, BufferWriter, ColorChoice, ColorSpec, StandardStream};
-use termcolor::{Color, WriteColor};
+
+use derive_setters::Setters;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
+use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc};
+use rustc_error_messages::{FluentArgs, SpanLabel};
+use rustc_lint_defs::pluralize;
+use rustc_span::hygiene::{ExpnKind, MacroKind};
+use rustc_span::source_map::SourceMap;
+use rustc_span::{char_width, FileLines, FileName, SourceFile, Span};
+use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
use tracing::{debug, instrument, trace, warn};
+use crate::diagnostic::DiagLocation;
+use crate::snippet::{
+ Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
+};
+use crate::styled_buffer::StyledBuffer;
+use crate::translation::{to_fluent_args, Translate};
+use crate::{
+ CodeSuggestion, DiagCtxt, DiagInner, DiagMessage, ErrCode, FluentBundle, LazyFallbackBundle,
+ Level, MultiSpan, Subdiag, SubstitutionHighlight, SuggestionStyle, TerminalUrl,
+};
+
/// Default column width, used in tests and when terminal dimensions cannot be determined.
const DEFAULT_COLUMN_WIDTH: usize = 140;
/// Describes the way the content of the `rendered` field of the json output is generated
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HumanReadableErrorType {
- Default(ColorConfig),
- AnnotateSnippet(ColorConfig),
- Short(ColorConfig),
+ Default,
+ AnnotateSnippet,
+ Short,
}
impl HumanReadableErrorType {
- /// Returns a (`short`, `color`) tuple
- pub fn unzip(self) -> (bool, ColorConfig) {
- match self {
- HumanReadableErrorType::Default(cc) => (false, cc),
- HumanReadableErrorType::Short(cc) => (true, cc),
- HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc),
- }
+ pub fn short(&self) -> bool {
+ *self == HumanReadableErrorType::Short
}
}
@@ -231,17 +226,17 @@ fn primary_span_formatted(
) {
if let Some((sugg, rest)) = suggestions.split_first() {
let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap();
- if rest.is_empty() &&
+ if rest.is_empty()
// ^ if there is only one suggestion
// don't display multi-suggestions as labels
- sugg.substitutions.len() == 1 &&
+ && let [substitution] = sugg.substitutions.as_slice()
// don't display multipart suggestions as labels
- sugg.substitutions[0].parts.len() == 1 &&
+ && let [part] = substitution.parts.as_slice()
// don't display long messages as labels
- msg.split_whitespace().count() < 10 &&
+ && msg.split_whitespace().count() < 10
// don't display multiline suggestions as labels
- !sugg.substitutions[0].parts[0].snippet.contains('\n') &&
- ![
+ && !part.snippet.contains('\n')
+ && ![
// when this style is set we want the suggestion to be a message, not inline
SuggestionStyle::HideCodeAlways,
// trivial suggestion for tooling's sake, never shown
@@ -250,8 +245,8 @@ fn primary_span_formatted(
SuggestionStyle::ShowAlways,
].contains(&sugg.style)
{
- let substitution = &sugg.substitutions[0].parts[0].snippet.trim();
- let msg = if substitution.is_empty() || sugg.style.hide_inline() {
+ let snippet = part.snippet.trim();
+ let msg = if snippet.is_empty() || sugg.style.hide_inline() {
// This substitution is only removal OR we explicitly don't want to show the
// code inline (`hide_inline`). Therefore, we don't show the substitution.
format!("help: {msg}")
@@ -260,19 +255,18 @@ fn primary_span_formatted(
format!(
"help: {}{}: `{}`",
msg,
- if self.source_map().is_some_and(|sm| is_case_difference(
- sm,
- substitution,
- sugg.substitutions[0].parts[0].span,
- )) {
+ if self
+ .source_map()
+ .is_some_and(|sm| is_case_difference(sm, snippet, part.span,))
+ {
" (notice the capitalization)"
} else {
""
},
- substitution,
+ snippet,
)
};
- primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg);
+ primary_span.push_span_label(part.span, msg);
// We return only the modified primary_span
suggestions.clear();
@@ -1346,10 +1340,11 @@ fn emit_messages_default_inner(
buffer.append(0, ": ", header_style);
label_width += 2;
}
- for (text, _) in msgs.iter() {
+ let mut line = 0;
+ for (text, style) in msgs.iter() {
let text = self.translate_message(text, args).map_err(Report::new).unwrap();
// Account for newlines to align output to its label.
- for (line, text) in normalize_whitespace(&text).lines().enumerate() {
+ for text in normalize_whitespace(&text).lines() {
buffer.append(
line,
&format!(
@@ -1357,8 +1352,38 @@ fn emit_messages_default_inner(
if line == 0 { String::new() } else { " ".repeat(label_width) },
text
),
- header_style,
+ match style {
+ Style::Highlight => *style,
+ _ => header_style,
+ },
);
+ line += 1;
+ }
+ // We add lines above, but if the last line has no explicit newline (which would
+ // yield an empty line), then we revert one line up to continue with the next
+ // styled text chunk on the same line as the last one from the prior one. Otherwise
+ // every `text` would appear on their own line (because even though they didn't end
+ // in '\n', they advanced `line` by one).
+ if line > 0 {
+ line -= 1;
+ }
+ }
+ if self.short_message {
+ let labels = msp
+ .span_labels()
+ .into_iter()
+ .filter_map(|label| match label.label {
+ Some(msg) if label.is_primary => {
+ let text = self.translate_message(&msg, args).ok()?;
+ if !text.trim().is_empty() { Some(text.to_string()) } else { None }
+ }
+ _ => None,
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+ if !labels.is_empty() {
+ buffer.append(line, ": ", Style::NoStyle);
+ buffer.append(line, &labels, Style::NoStyle);
}
}
}
@@ -1767,7 +1792,10 @@ fn emit_suggestion_default(
debug!(?suggestions);
if suggestions.is_empty() {
- // Suggestions coming from macros can have malformed spans. This is a heavy handed
+ // Here we check if there are suggestions that have actual code changes. We sometimes
+ // suggest the same code that is already there, instead of changing how we produce the
+ // suggestions and filtering there, we just don't emit the suggestion.
+ // Suggestions coming from macros can also have malformed spans. This is a heavy handed
// approach to avoid ICEs by ignoring the suggestion outright.
return Ok(());
}
@@ -2046,7 +2074,9 @@ fn emit_suggestion_default(
assert!(underline_start >= 0 && underline_end >= 0);
let padding: usize = max_line_num_len + 3;
for p in underline_start..underline_end {
- if let DisplaySuggestion::Underline = show_code_change {
+ if let DisplaySuggestion::Underline = show_code_change
+ && is_different(sm, &part.snippet, part.span)
+ {
// If this is a replacement, underline with `~`, if this is an addition
// underline with `+`.
buffer.putc(
@@ -2560,21 +2590,10 @@ fn num_decimal_digits(num: usize) -> usize {
// We replace some characters so the CLI output is always consistent and underlines aligned.
// Keep the following list in sync with `rustc_span::char_width`.
const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
- ('\t', " "), // We do our own tab replacement
- ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters.
- ('\u{202A}', "�"), // The following unicode text flow control characters are inconsistently
- ('\u{202B}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk
- ('\u{202D}', "�"), // not corresponding to the visible source code, so we replace them always.
- ('\u{202E}', "�"),
- ('\u{2066}', "�"),
- ('\u{2067}', "�"),
- ('\u{2068}', "�"),
- ('\u{202C}', "�"),
- ('\u{2069}', "�"),
// In terminals without Unicode support the following will be garbled, but in *all* terminals
// the underlying codepoint will be as well. We could gate this replacement behind a "unicode
// support" gate.
- ('\u{0000}', "␀"),
+ ('\0', "␀"),
('\u{0001}', "␁"),
('\u{0002}', "␂"),
('\u{0003}', "␃"),
@@ -2583,11 +2602,12 @@ fn num_decimal_digits(num: usize) -> usize {
('\u{0006}', "␆"),
('\u{0007}', "␇"),
('\u{0008}', "␈"),
- ('\u{000B}', "␋"),
- ('\u{000C}', "␌"),
- ('\u{000D}', "␍"),
- ('\u{000E}', "␎"),
- ('\u{000F}', "␏"),
+ ('\t', " "), // We do our own tab replacement
+ ('\u{000b}', "␋"),
+ ('\u{000c}', "␌"),
+ ('\u{000d}', "␍"),
+ ('\u{000e}', "␎"),
+ ('\u{000f}', "␏"),
('\u{0010}', "␐"),
('\u{0011}', "␑"),
('\u{0012}', "␒"),
@@ -2598,21 +2618,47 @@ fn num_decimal_digits(num: usize) -> usize {
('\u{0017}', "␗"),
('\u{0018}', "␘"),
('\u{0019}', "␙"),
- ('\u{001A}', "␚"),
- ('\u{001B}', "␛"),
- ('\u{001C}', "␜"),
- ('\u{001D}', "␝"),
- ('\u{001E}', "␞"),
- ('\u{001F}', "␟"),
- ('\u{007F}', "␡"),
+ ('\u{001a}', "␚"),
+ ('\u{001b}', "␛"),
+ ('\u{001c}', "␜"),
+ ('\u{001d}', "␝"),
+ ('\u{001e}', "␞"),
+ ('\u{001f}', "␟"),
+ ('\u{007f}', "␡"),
+ ('\u{200d}', ""), // Replace ZWJ for consistent terminal output of grapheme clusters.
+ ('\u{202a}', "�"), // The following unicode text flow control characters are inconsistently
+ ('\u{202b}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk
+ ('\u{202c}', "�"), // not corresponding to the visible source code, so we replace them always.
+ ('\u{202d}', "�"),
+ ('\u{202e}', "�"),
+ ('\u{2066}', "�"),
+ ('\u{2067}', "�"),
+ ('\u{2068}', "�"),
+ ('\u{2069}', "�"),
];
-fn normalize_whitespace(str: &str) -> String {
- let mut s = str.to_string();
- for (c, replacement) in OUTPUT_REPLACEMENTS {
- s = s.replace(*c, replacement);
+fn normalize_whitespace(s: &str) -> String {
+ const {
+ let mut i = 1;
+ while i < OUTPUT_REPLACEMENTS.len() {
+ assert!(
+ OUTPUT_REPLACEMENTS[i - 1].0 < OUTPUT_REPLACEMENTS[i].0,
+ "The OUTPUT_REPLACEMENTS array must be sorted (for binary search to work) \
+ and must contain no duplicate entries"
+ );
+ i += 1;
+ }
}
- s
+ // Scan the input string for a character in the ordered table above.
+ // If it's present, replace it with its alternative string (it can be more than 1 char!).
+ // Otherwise, retain the input char.
+ s.chars().fold(String::with_capacity(s.len()), |mut s, c| {
+ match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) {
+ Ok(i) => s.push_str(OUTPUT_REPLACEMENTS[i].1),
+ _ => s.push(c),
+ }
+ s
+ })
}
fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
@@ -2824,6 +2870,18 @@ fn color_spec(&self, lvl: Level) -> ColorSpec {
}
}
+/// Whether the original and suggested code are the same.
+pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
+ let found = match sm.span_to_snippet(sp) {
+ Ok(snippet) => snippet,
+ Err(e) => {
+ warn!(error = ?e, "Invalid span {:?}", sp);
+ return true;
+ }
+ };
+ found != suggested
+}
+
/// Whether the original and suggested code are visually similar enough to warrant extra wording.
pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool {
// FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode.
diff --git a/compiler/rustc_errors/src/error.rs b/compiler/rustc_errors/src/error.rs
index ca818a4..462467d 100644
--- a/compiler/rustc_errors/src/error.rs
+++ b/compiler/rustc_errors/src/error.rs
@@ -1,11 +1,10 @@
-use rustc_error_messages::{
- fluent_bundle::resolver::errors::{ReferenceKind, ResolverError},
- FluentArgs, FluentError,
-};
use std::borrow::Cow;
use std::error::Error;
use std::fmt;
+use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
+use rustc_error_messages::{FluentArgs, FluentError};
+
#[derive(Debug)]
pub enum TranslateError<'args> {
One {
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 764134d..32e59f9 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -9,16 +9,12 @@
// FIXME: spec the JSON output properly.
-use crate::emitter::{
- should_show_source_code, ColorConfig, Destination, Emitter, HumanEmitter,
- HumanReadableErrorType,
-};
-use crate::registry::Registry;
-use crate::translation::{to_fluent_args, Translate};
-use crate::{
- diagnostic::IsLint, CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel,
- Subdiag, TerminalUrl,
-};
+use std::error::Report;
+use std::io::{self, Write};
+use std::path::Path;
+use std::sync::{Arc, Mutex};
+use std::vec;
+
use derive_setters::Setters;
use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
use rustc_error_messages::FluentArgs;
@@ -27,13 +23,19 @@
use rustc_span::source_map::SourceMap;
use rustc_span::Span;
use serde::Serialize;
-use std::error::Report;
-use std::io::{self, Write};
-use std::path::Path;
-use std::sync::{Arc, Mutex};
-use std::vec;
use termcolor::{ColorSpec, WriteColor};
+use crate::diagnostic::IsLint;
+use crate::emitter::{
+ should_show_source_code, ColorConfig, Destination, Emitter, HumanEmitter,
+ HumanReadableErrorType,
+};
+use crate::registry::Registry;
+use crate::translation::{to_fluent_args, Translate};
+use crate::{
+ CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, Subdiag, TerminalUrl,
+};
+
#[cfg(test)]
mod tests;
@@ -53,6 +55,7 @@ pub struct JsonEmitter {
ignored_directories_in_source_blocks: Vec<String>,
#[setters(skip)]
json_rendered: HumanReadableErrorType,
+ color_config: ColorConfig,
diagnostic_width: Option<usize>,
macro_backtrace: bool,
track_diagnostics: bool,
@@ -66,6 +69,7 @@ pub fn new(
fallback_bundle: LazyFallbackBundle,
pretty: bool,
json_rendered: HumanReadableErrorType,
+ color_config: ColorConfig,
) -> JsonEmitter {
JsonEmitter {
dst: IntoDynSyncSend(dst),
@@ -77,6 +81,7 @@ pub fn new(
ui_testing: false,
ignored_directories_in_source_blocks: Vec::new(),
json_rendered,
+ color_config,
diagnostic_width: None,
macro_backtrace: false,
track_diagnostics: false,
@@ -171,7 +176,7 @@ fn source_map(&self) -> Option<&Lrc<SourceMap>> {
}
fn should_show_explain(&self) -> bool {
- !matches!(self.json_rendered, HumanReadableErrorType::Short(_))
+ !self.json_rendered.short()
}
}
@@ -351,8 +356,8 @@ fn reset(&mut self) -> io::Result<()> {
let buf = BufWriter::default();
let mut dst: Destination = Box::new(buf.clone());
- let (short, color_config) = je.json_rendered.unzip();
- match color_config {
+ let short = je.json_rendered.short();
+ match je.color_config {
ColorConfig::Always | ColorConfig::Auto => dst = Box::new(termcolor::Ansi::new(dst)),
ColorConfig::Never => {}
}
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs
index e4b29fc..6af376d 100644
--- a/compiler/rustc_errors/src/json/tests.rs
+++ b/compiler/rustc_errors/src/json/tests.rs
@@ -1,13 +1,12 @@
-use super::*;
-
-use crate::DiagCtxt;
-use rustc_span::source_map::FilePathMapping;
-use rustc_span::BytePos;
-
use std::str;
+use rustc_span::source_map::FilePathMapping;
+use rustc_span::BytePos;
use serde::Deserialize;
+use super::*;
+use crate::DiagCtxt;
+
#[derive(Deserialize, Debug, PartialEq, Eq)]
struct TestData {
spans: Vec<SpanTestData>,
@@ -51,7 +50,8 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
sm,
fallback_bundle,
true, // pretty
- HumanReadableErrorType::Short(ColorConfig::Never),
+ HumanReadableErrorType::Short,
+ ColorConfig::Never,
);
let span = Span::with_root_ctxt(BytePos(span.0), BytePos(span.1));
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 2a850d9..3bc03a1 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -10,6 +10,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(array_windows)]
+#![feature(assert_matches)]
#![feature(associated_type_defaults)]
#![feature(box_into_inner)]
#![feature(box_patterns)]
@@ -28,6 +29,18 @@
extern crate self as rustc_errors;
+use std::assert_matches::assert_matches;
+use std::backtrace::{Backtrace, BacktraceStatus};
+use std::borrow::Cow;
+use std::cell::Cell;
+use std::error::Report;
+use std::hash::Hash;
+use std::io::Write;
+use std::num::NonZero;
+use std::ops::DerefMut;
+use std::path::{Path, PathBuf};
+use std::{fmt, panic};
+
pub use codes::*;
pub use diagnostic::{
BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString,
@@ -39,42 +52,28 @@
IndicateAnonymousLifetime, SingleLabelManySpans,
};
pub use emitter::ColorConfig;
-pub use rustc_error_messages::{
- fallback_fluent_bundle, fluent_bundle, DiagMessage, FluentBundle, LanguageIdentifier,
- LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
-};
-pub use rustc_lint_defs::{pluralize, Applicability};
-pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
-pub use rustc_span::ErrorGuaranteed;
-pub use snippet::Style;
-
-// Used by external projects such as `rust-gpu`.
-// See https://github.com/rust-lang/rust/pull/115393.
-pub use termcolor::{Color, ColorSpec, WriteColor};
-
-use emitter::{is_case_difference, DynEmitter, Emitter};
+use emitter::{is_case_difference, is_different, DynEmitter, Emitter};
use registry::Registry;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::stable_hasher::{Hash128, StableHasher};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_data_structures::AtomicRef;
+pub use rustc_error_messages::{
+ fallback_fluent_bundle, fluent_bundle, DiagMessage, FluentBundle, LanguageIdentifier,
+ LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
+};
use rustc_lint_defs::LintExpectationId;
+pub use rustc_lint_defs::{pluralize, Applicability};
use rustc_macros::{Decodable, Encodable};
+pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
use rustc_span::source_map::SourceMap;
+pub use rustc_span::ErrorGuaranteed;
use rustc_span::{Loc, Span, DUMMY_SP};
-use std::backtrace::{Backtrace, BacktraceStatus};
-use std::borrow::Cow;
-use std::cell::Cell;
-use std::error::Report;
-use std::fmt;
-use std::hash::Hash;
-use std::io::Write;
-use std::num::NonZero;
-use std::ops::DerefMut;
-use std::panic;
-use std::path::{Path, PathBuf};
+pub use snippet::Style;
+// Used by external projects such as `rust-gpu`.
+// See https://github.com/rust-lang/rust/pull/115393.
+pub use termcolor::{Color, ColorSpec, WriteColor};
use tracing::debug;
-
use Level::*;
pub mod annotate_snippet_emitter_writer;
@@ -360,10 +359,16 @@ fn push_trailing(
_ => 1,
})
.sum();
- line_highlight.push(SubstitutionHighlight {
- start: (cur_lo.col.0 as isize + acc) as usize,
- end: (cur_lo.col.0 as isize + acc + len) as usize,
- });
+ if !is_different(sm, &part.snippet, part.span) {
+ // Account for cases where we are suggesting the same code that's already
+ // there. This shouldn't happen often, but in some cases for multipart
+ // suggestions it's much easier to handle it here than in the origin.
+ } else {
+ line_highlight.push(SubstitutionHighlight {
+ start: (cur_lo.col.0 as isize + acc) as usize,
+ end: (cur_lo.col.0 as isize + acc + len) as usize,
+ });
+ }
buf.push_str(&part.snippet);
let cur_hi = sm.lookup_char_pos(part.span.hi());
// Account for the difference between the width of the current code and the
@@ -395,7 +400,11 @@ fn push_trailing(
while buf.ends_with('\n') {
buf.pop();
}
- Some((buf, substitution.parts, highlights, only_capitalization))
+ if highlights.iter().all(|parts| parts.is_empty()) {
+ None
+ } else {
+ Some((buf, substitution.parts, highlights, only_capitalization))
+ }
})
.collect()
}
@@ -1483,7 +1492,7 @@ fn emit_diagnostic(
// Future breakages aren't emitted if they're `Level::Allow` or
// `Level::Expect`, but they still need to be constructed and
// stashed below, so they'll trigger the must_produce_diag check.
- assert!(matches!(diagnostic.level, Error | Warning | Allow | Expect(_)));
+ assert_matches!(diagnostic.level, Error | Warning | Allow | Expect(_));
self.future_breakage_diagnostics.push(diagnostic.clone());
}
@@ -2017,11 +2026,11 @@ pub fn a_or_an(s: &str) -> &'static str {
///
/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c"
pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
- match v.len() {
- 0 => "".to_string(),
- 1 => v[0].to_string(),
- 2 => format!("{} and {}", v[0], v[1]),
- _ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])),
+ match v {
+ [] => "".to_string(),
+ [a] => a.to_string(),
+ [a, b] => format!("{a} and {b}"),
+ [a, v @ ..] => format!("{a}, {}", display_list_with_comma_and(v)),
}
}
diff --git a/compiler/rustc_errors/src/lock.rs b/compiler/rustc_errors/src/lock.rs
index 0aeb511..915542c 100644
--- a/compiler/rustc_errors/src/lock.rs
+++ b/compiler/rustc_errors/src/lock.rs
@@ -16,10 +16,10 @@ pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
use std::ffi::CString;
use std::io;
- use windows::{
- core::PCSTR,
- Win32::Foundation::{CloseHandle, HANDLE, WAIT_ABANDONED, WAIT_OBJECT_0},
- Win32::System::Threading::{CreateMutexA, ReleaseMutex, WaitForSingleObject, INFINITE},
+ use windows::core::PCSTR;
+ use windows::Win32::Foundation::{CloseHandle, HANDLE, WAIT_ABANDONED, WAIT_OBJECT_0};
+ use windows::Win32::System::Threading::{
+ CreateMutexA, ReleaseMutex, WaitForSingleObject, INFINITE,
};
struct Handle(HANDLE);
diff --git a/compiler/rustc_errors/src/markdown/parse.rs b/compiler/rustc_errors/src/markdown/parse.rs
index 69e7120..c44f136 100644
--- a/compiler/rustc_errors/src/markdown/parse.rs
+++ b/compiler/rustc_errors/src/markdown/parse.rs
@@ -1,6 +1,7 @@
-use crate::markdown::{MdStream, MdTree};
use std::{iter, mem, str};
+use crate::markdown::{MdStream, MdTree};
+
/// Short aliases that we can use in match patterns. If an end pattern is not
/// included, this type may be variable
const ANC_E: &[u8] = b">";
diff --git a/compiler/rustc_errors/src/markdown/tests/parse.rs b/compiler/rustc_errors/src/markdown/tests/parse.rs
index e2e3f35..bfcb3de 100644
--- a/compiler/rustc_errors/src/markdown/tests/parse.rs
+++ b/compiler/rustc_errors/src/markdown/tests/parse.rs
@@ -1,6 +1,7 @@
-use super::*;
use ParseOpt as PO;
+use super::*;
+
#[test]
fn test_parse_simple() {
let buf = "**abcd** rest";
diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs
index bab47dc..e025870 100644
--- a/compiler/rustc_errors/src/markdown/tests/term.rs
+++ b/compiler/rustc_errors/src/markdown/tests/term.rs
@@ -1,5 +1,6 @@
use std::io::BufWriter;
use std::path::PathBuf;
+
use termcolor::{BufferWriter, ColorChoice};
use super::*;
diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs
index 8834d04..baca770 100644
--- a/compiler/rustc_errors/src/registry.rs
+++ b/compiler/rustc_errors/src/registry.rs
@@ -1,6 +1,7 @@
-use crate::ErrCode;
use rustc_data_structures::fx::FxHashMap;
+use crate::ErrCode;
+
#[derive(Debug)]
pub struct InvalidErrorCode;
diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs
index d6119fb..50abf8a 100644
--- a/compiler/rustc_errors/src/snippet.rs
+++ b/compiler/rustc_errors/src/snippet.rs
@@ -1,8 +1,9 @@
// Code for annotating snippets.
-use crate::{Level, Loc};
use rustc_macros::{Decodable, Encodable};
+use crate::{Level, Loc};
+
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Line {
pub line_index: usize,
diff --git a/compiler/rustc_errors/src/tests.rs b/compiler/rustc_errors/src/tests.rs
index 50d58ae..bfe4c9f 100644
--- a/compiler/rustc_errors/src/tests.rs
+++ b/compiler/rustc_errors/src/tests.rs
@@ -1,11 +1,11 @@
+use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
+use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
+use rustc_error_messages::{langid, DiagMessage};
+
use crate::error::{TranslateError, TranslateErrorKind};
use crate::fluent_bundle::*;
use crate::translation::Translate;
use crate::FluentBundle;
-use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
-use rustc_error_messages::fluent_bundle::resolver::errors::{ReferenceKind, ResolverError};
-use rustc_error_messages::langid;
-use rustc_error_messages::DiagMessage;
struct Dummy {
bundle: FluentBundle,
diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs
index 445e9b4..a44e794 100644
--- a/compiler/rustc_errors/src/translation.rs
+++ b/compiler/rustc_errors/src/translation.rs
@@ -1,13 +1,15 @@
-use crate::error::{TranslateError, TranslateErrorKind};
-use crate::snippet::Style;
-use crate::{DiagArg, DiagMessage, FluentBundle};
-use rustc_data_structures::sync::Lrc;
-pub use rustc_error_messages::FluentArgs;
use std::borrow::Cow;
use std::env;
use std::error::Report;
+
+use rustc_data_structures::sync::Lrc;
+pub use rustc_error_messages::FluentArgs;
use tracing::{debug, trace};
+use crate::error::{TranslateError, TranslateErrorKind};
+use crate::snippet::Style;
+use crate::{DiagArg, DiagMessage, FluentBundle};
+
/// Convert diagnostic arguments (a rustc internal type that exists to implement
/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
///
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 18d95a3..766d96e 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -129,6 +129,9 @@
expand_must_repeat_once =
this must repeat at least once
+expand_non_inline_modules_in_proc_macro_input_are_unstable =
+ non-inline modules in proc macro input are unstable
+
expand_not_a_meta_item =
not a meta item
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index b439ec7..8f91041 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1,7 +1,7 @@
-use crate::base::ast::NestedMetaItem;
-use crate::errors;
-use crate::expand::{self, AstFragment, Invocation};
-use crate::module::DirOwnership;
+use std::default::Default;
+use std::iter;
+use std::path::{Path, PathBuf};
+use std::rc::Rc;
use rustc_ast::attr::MarkedAttrs;
use rustc_ast::ptr::P;
@@ -15,9 +15,11 @@
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
use rustc_feature::Features;
use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
-use rustc_parse::{parser::Parser, MACRO_ARGUMENTS};
+use rustc_parse::parser::Parser;
+use rustc_parse::MACRO_ARGUMENTS;
use rustc_session::config::CollapseMacroDebuginfo;
-use rustc_session::{parse::ParseSess, Limit, Session};
+use rustc_session::parse::ParseSess;
+use rustc_session::{Limit, Session};
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
@@ -25,12 +27,13 @@
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-use std::default::Default;
-use std::iter;
-use std::path::{Path, PathBuf};
-use std::rc::Rc;
use thin_vec::ThinVec;
+use crate::base::ast::NestedMetaItem;
+use crate::errors;
+use crate::expand::{self, AstFragment, Invocation};
+use crate::module::DirOwnership;
+
// When adding new variants, make sure to
// adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector`
// to use `assign_id!`
@@ -1303,12 +1306,12 @@ pub fn parse_macro_name_and_helper_attrs(
// that it's of the form `#[proc_macro_derive(Foo)]` or
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
- if list.len() != 1 && list.len() != 2 {
+ let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
dcx.emit_err(errors::AttrNoArguments { span: attr.span });
return None;
- }
- let Some(trait_attr) = list[0].meta_item() else {
- dcx.emit_err(errors::NotAMetaItem { span: list[0].span() });
+ };
+ let Some(trait_attr) = trait_attr.meta_item() else {
+ dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() });
return None;
};
let trait_ident = match trait_attr.ident() {
@@ -1395,8 +1398,6 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) {
};
if crate_matches {
- // FIXME: make this translatable
- #[allow(rustc::untranslatable_diagnostic)]
sess.dcx().emit_fatal(errors::ProcMacroBackCompat {
crate_name: "rental".to_string(),
fixed_version: "0.5.6".to_string(),
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 37dfd83..8ecdb55 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -1,12 +1,15 @@
-use crate::base::ExtCtxt;
use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp};
-use rustc_ast::{attr, token, util::literal};
+use rustc_ast::util::literal;
+use rustc_ast::{
+ self as ast, attr, token, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp,
+};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use thin_vec::{thin_vec, ThinVec};
+use crate::base::ExtCtxt;
+
impl<'a> ExtCtxt<'a> {
pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
self.path_all(span, false, strs, vec![])
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 6c02c23..f6bf9f5 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -1,19 +1,16 @@
//! Conditional compilation stripping.
-use crate::errors::{
- FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute,
- MalformedFeatureAttributeHelp, RemoveExprNotSupported,
-};
use rustc_ast::ptr::P;
use rustc_ast::token::{Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, Spacing};
-use rustc_ast::tokenstream::{LazyAttrTokenStream, TokenTree};
-use rustc_ast::NodeId;
-use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem};
+use rustc_ast::tokenstream::{
+ AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
+};
+use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NodeId};
use rustc_attr as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
-use rustc_feature::Features;
-use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES};
+use rustc_feature::{
+ AttributeSafety, Features, ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES,
+};
use rustc_lint_defs::BuiltinLintDiag;
use rustc_parse::validate_attr;
use rustc_session::parse::feature_err;
@@ -23,6 +20,11 @@
use thin_vec::ThinVec;
use tracing::instrument;
+use crate::errors::{
+ FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute,
+ MalformedFeatureAttributeHelp, RemoveExprNotSupported,
+};
+
/// A folder that strips out items that do not belong in the current configuration.
pub struct StripUnconfigured<'a> {
pub sess: &'a Session,
@@ -117,6 +119,12 @@ fn feature_list(attr: &Attribute) -> ThinVec<ast::NestedMetaItem> {
// Otherwise, the feature is unknown. Record it as a lib feature.
// It will be checked later.
features.set_declared_lib_feature(name, mi.span());
+
+ // Similar to above, detect internal lib features to suppress
+ // the ICE message that asks for a report.
+ if features.internal(name) && ![sym::core, sym::alloc, sym::std].contains(&crate_name) {
+ sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
+ }
}
}
@@ -257,6 +265,13 @@ fn process_cfg_attr(&self, attr: &Attribute) -> Vec<Attribute> {
/// is in the original source file. Gives a compiler error if the syntax of
/// the attribute is incorrect.
pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
+ validate_attr::check_attribute_safety(
+ self.features.unwrap_or(&Features::default()),
+ &self.sess.psess,
+ AttributeSafety::Normal,
+ &cfg_attr,
+ );
+
let Some((cfg_predicate, expanded_attrs)) =
rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess)
else {
@@ -379,6 +394,13 @@ pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option<MetaItem>) {
return (true, None);
}
};
+
+ validate_attr::deny_builtin_meta_unsafety(
+ self.features.unwrap_or(&Features::default()),
+ &self.sess.psess,
+ &meta_item,
+ );
+
(
parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| {
attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features)
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 6f1a0f1..c30a9b0 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -1,10 +1,11 @@
+use std::borrow::Cow;
+
use rustc_ast::ast;
use rustc_errors::codes::*;
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::Limit;
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
use rustc_span::{Span, Symbol};
-use std::borrow::Cow;
#[derive(Diagnostic)]
#[diag(expand_expr_repeat_no_syntax_vars)]
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 3c43d47..37679e1 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1,13 +1,7 @@
-use crate::base::*;
-use crate::config::StripUnconfigured;
-use crate::errors::{
- EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
- RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
- WrongFragmentKind,
-};
-use crate::mbe::diagnostics::annotate_err_with_kind;
-use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
-use crate::placeholders::{placeholder, PlaceholderExpander};
+use std::ops::Deref;
+use std::path::PathBuf;
+use std::rc::Rc;
+use std::{iter, mem};
use rustc_ast as ast;
use rustc_ast::mut_visit::*;
@@ -15,10 +9,11 @@
use rustc_ast::token::{self, Delimiter};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{self, try_visit, walk_list, AssocCtxt, Visitor, VisitorResult};
-use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind};
-use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId};
-use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind};
-use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
+use rustc_ast::{
+ AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind, ForeignItemKind,
+ HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem,
+ NodeId, PatKind, StmtKind, TyKind,
+};
use rustc_ast_pretty::pprust;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::sync::Lrc;
@@ -35,12 +30,19 @@
use rustc_span::hygiene::SyntaxContext;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{ErrorGuaranteed, FileName, LocalExpnId, Span};
-
use smallvec::SmallVec;
-use std::ops::Deref;
-use std::path::PathBuf;
-use std::rc::Rc;
-use std::{iter, mem};
+
+use crate::base::*;
+use crate::config::StripUnconfigured;
+use crate::errors::{
+ EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
+ RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
+ WrongFragmentKind,
+};
+use crate::fluent_generated;
+use crate::mbe::diagnostics::annotate_err_with_kind;
+use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
+use crate::placeholders::{placeholder, PlaceholderExpander};
macro_rules! ast_fragments {
(
@@ -881,7 +883,6 @@ struct GateProcMacroInput<'a> {
}
impl<'ast, 'a> Visitor<'ast> for GateProcMacroInput<'a> {
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn visit_item(&mut self, item: &'ast ast::Item) {
match &item.kind {
ItemKind::Mod(_, mod_kind)
@@ -891,7 +892,7 @@ fn visit_item(&mut self, item: &'ast ast::Item) {
self.sess,
sym::proc_macro_hygiene,
item.span,
- "non-inline modules in proc macro input are unstable",
+ fluent_generated::expand_non_inline_modules_in_proc_macro_input_are_unstable,
)
.emit();
}
@@ -1875,7 +1876,6 @@ fn take_first_attr(
// Detect use of feature-gated or invalid attributes on macro invocations
// since they will not be detected after macro expansion.
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
let features = self.cx.ecfg.features;
let mut attrs = attrs.iter().peekable();
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 2df8b8f..628c6bf 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -1,36 +1,34 @@
-use crate::base::{DummyResult, ExtCtxt, MacResult};
-use crate::expand::{parse_ast_fragment, AstFragmentKind};
-use crate::mbe::{
- macro_parser::{MatcherLoc, NamedParseResult, ParseResult::*, TtParser},
- macro_rules::{try_match_macro, Tracker},
-};
+use std::borrow::Cow;
+
use rustc_ast::token::{self, Token, TokenKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, Diag, DiagMessage};
+use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage};
use rustc_macros::Subdiagnostic;
use rustc_parse::parser::{Parser, Recovery};
+use rustc_session::parse::ParseSess;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Ident;
use rustc_span::{ErrorGuaranteed, Span};
-use std::borrow::Cow;
use tracing::debug;
use super::macro_rules::{parser_from_cx, NoopTracker};
+use crate::expand::{parse_ast_fragment, AstFragmentKind};
+use crate::mbe::macro_parser::ParseResult::*;
+use crate::mbe::macro_parser::{MatcherLoc, NamedParseResult, TtParser};
+use crate::mbe::macro_rules::{try_match_macro, Tracker};
-pub(super) fn failed_to_match_macro<'cx>(
- cx: &'cx mut ExtCtxt<'_>,
+pub(super) fn failed_to_match_macro(
+ psess: &ParseSess,
sp: Span,
def_span: Span,
name: Ident,
arg: TokenStream,
lhses: &[Vec<MatcherLoc>],
-) -> Box<dyn MacResult + 'cx> {
- let psess = &cx.sess.psess;
-
+) -> (Span, ErrorGuaranteed) {
// An error occurred, try the expansion again, tracking the expansion closely for better
// diagnostics.
- let mut tracker = CollectTrackerAndEmitter::new(cx, sp);
+ let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);
let try_success_result = try_match_macro(psess, name, &arg, lhses, &mut tracker);
@@ -38,7 +36,7 @@ pub(super) fn failed_to_match_macro<'cx>(
// Nonterminal parser recovery might turn failed matches into successful ones,
// but for that it must have emitted an error already
assert!(
- tracker.cx.dcx().has_errors().is_some(),
+ tracker.dcx.has_errors().is_some(),
"Macro matching returned a success on the second try"
);
}
@@ -50,15 +48,15 @@ pub(super) fn failed_to_match_macro<'cx>(
let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
else {
- return DummyResult::any(sp, cx.dcx().span_delayed_bug(sp, "failed to match a macro"));
+ return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
};
let span = token.span.substitute_dummy(sp);
- let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token, None));
+ let mut err = psess.dcx().struct_span_err(span, parse_failure_msg(&token, None));
err.span_label(span, label);
- if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
- err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
+ if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
+ err.span_label(psess.source_map().guess_head_span(def_span), "when calling this macro");
}
annotate_doc_comment(&mut err, psess.source_map(), span);
@@ -76,7 +74,7 @@ pub(super) fn failed_to_match_macro<'cx>(
err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens");
err.note("see <https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment> for more information");
- if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
+ if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
err.help("try using `:tt` instead in the macro definition");
}
}
@@ -104,18 +102,17 @@ pub(super) fn failed_to_match_macro<'cx>(
}
}
let guar = err.emit();
- cx.trace_macros_diag();
- DummyResult::any(sp, guar)
+ (sp, guar)
}
/// The tracker used for the slow error path that collects useful info for diagnostics.
-struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
- cx: &'a mut ExtCtxt<'cx>,
+struct CollectTrackerAndEmitter<'dcx, 'matcher> {
+ dcx: DiagCtxtHandle<'dcx>,
remaining_matcher: Option<&'matcher MatcherLoc>,
/// Which arm's failure should we report? (the one furthest along)
best_failure: Option<BestFailure>,
root_span: Span,
- result: Option<Box<dyn MacResult + 'cx>>,
+ result: Option<(Span, ErrorGuaranteed)>,
}
struct BestFailure {
@@ -131,7 +128,7 @@ fn is_better_position(&self, position: u32) -> bool {
}
}
-impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> {
+impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'matcher> {
type Failure = (Token, u32, &'static str);
fn build_failure(tok: Token, position: u32, msg: &'static str) -> Self::Failure {
@@ -151,7 +148,7 @@ fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
Success(_) => {
// Nonterminal parser recovery might turn failed matches into successful ones,
// but for that it must have emitted an error already
- self.cx.dcx().span_delayed_bug(
+ self.dcx.span_delayed_bug(
self.root_span,
"should not collect detailed info for successful macro match",
);
@@ -177,10 +174,10 @@ fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
}
Error(err_sp, msg) => {
let span = err_sp.substitute_dummy(self.root_span);
- let guar = self.cx.dcx().span_err(span, msg.clone());
- self.result = Some(DummyResult::any(span, guar));
+ let guar = self.dcx.span_err(span, msg.clone());
+ self.result = Some((span, guar));
}
- ErrorReported(guar) => self.result = Some(DummyResult::any(self.root_span, *guar)),
+ ErrorReported(guar) => self.result = Some((self.root_span, *guar)),
}
}
@@ -193,9 +190,9 @@ fn recovery() -> Recovery {
}
}
-impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> {
- fn new(cx: &'a mut ExtCtxt<'cx>, root_span: Span) -> Self {
- Self { cx, remaining_matcher: None, best_failure: None, root_span, result: None }
+impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> {
+ fn new(dcx: DiagCtxtHandle<'dcx>, root_span: Span) -> Self {
+ Self { dcx, remaining_matcher: None, best_failure: None, root_span, result: None }
}
}
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 161e27f..68eeba6 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -105,8 +105,7 @@
//! stored when entering a macro definition starting from the state in which the meta-variable is
//! bound.
-use crate::errors;
-use crate::mbe::{KleeneToken, TokenTree};
+use std::iter;
use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::{NodeId, DUMMY_NODE_ID};
@@ -116,14 +115,13 @@
use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
use rustc_session::parse::ParseSess;
use rustc_span::edition::Edition;
-use rustc_span::symbol::kw;
-use rustc_span::{symbol::MacroRulesNormalizedIdent, ErrorGuaranteed, Span};
-
+use rustc_span::symbol::{kw, MacroRulesNormalizedIdent};
+use rustc_span::{ErrorGuaranteed, Span};
use smallvec::SmallVec;
-use std::iter;
-
use super::quoted::VALID_FRAGMENT_NAMES_MSG_2021;
+use crate::errors;
+use crate::mbe::{KleeneToken, TokenTree};
/// Stack represented as linked list.
///
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 99a9d4f..e5b9c62 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -70,10 +70,10 @@
//! eof: [a $( a )* a b ·]
//! ```
-pub(crate) use NamedMatch::*;
-pub(crate) use ParseResult::*;
-
-use crate::mbe::{macro_rules::Tracker, KleeneOp, TokenTree};
+use std::borrow::Cow;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
+use std::fmt::Display;
+use std::rc::Rc;
use rustc_ast::token::{self, DocComment, NonterminalKind, Token};
use rustc_ast_pretty::pprust;
@@ -81,13 +81,13 @@
use rustc_errors::ErrorGuaranteed;
use rustc_lint_defs::pluralize;
use rustc_parse::parser::{ParseNtResult, Parser};
-use rustc_span::symbol::Ident;
-use rustc_span::symbol::MacroRulesNormalizedIdent;
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
use rustc_span::Span;
-use std::borrow::Cow;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::fmt::Display;
-use std::rc::Rc;
+pub(crate) use NamedMatch::*;
+pub(crate) use ParseResult::*;
+
+use crate::mbe::macro_rules::Tracker;
+use crate::mbe::{KleeneOp, TokenTree};
/// A unit within a matcher that a `MatcherPos` can refer to. Similar to (and derived from)
/// `mbe::TokenTree`, but designed specifically for fast and easy traversal during matching.
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 88ec3d8..6f17710 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -1,18 +1,12 @@
-use crate::base::{DummyResult, SyntaxExtension, SyntaxExtensionKind};
-use crate::base::{ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, TTMacroExpander};
-use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind};
-use crate::mbe;
-use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
-use crate::mbe::macro_check;
-use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success, TtParser};
-use crate::mbe::macro_parser::{MatcherLoc, NamedMatch::*};
-use crate::mbe::transcribe::transcribe;
+use std::borrow::Cow;
+use std::collections::hash_map::Entry;
+use std::{mem, slice};
use ast::token::IdentIsRaw;
use rustc_ast as ast;
-use rustc_ast::token::{
- self, Delimiter, NonterminalKind, NtPatKind::*, Token, TokenKind, TokenKind::*,
-};
+use rustc_ast::token::NtPatKind::*;
+use rustc_ast::token::TokenKind::*;
+use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{NodeId, DUMMY_NODE_ID};
use rustc_ast_pretty::pprust;
@@ -33,12 +27,19 @@
use rustc_span::Span;
use tracing::{debug, instrument, trace, trace_span};
-use std::borrow::Cow;
-use std::collections::hash_map::Entry;
-use std::{mem, slice};
-
use super::diagnostics;
use super::macro_parser::{NamedMatches, NamedParseResult};
+use crate::base::{
+ DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension,
+ SyntaxExtensionKind, TTMacroExpander,
+};
+use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind};
+use crate::mbe;
+use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg};
+use crate::mbe::macro_check;
+use crate::mbe::macro_parser::NamedMatch::*;
+use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser};
+use crate::mbe::transcribe::transcribe;
pub(crate) struct ParserAnyMacro<'a> {
parser: Parser<'a>,
@@ -267,7 +268,10 @@ fn expand_macro<'cx>(
}
Err(CanRetry::Yes) => {
// Retry and emit a better error.
- diagnostics::failed_to_match_macro(cx, sp, def_span, name, arg, lhses)
+ let (span, guar) =
+ diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, lhses);
+ cx.trace_macros_diag();
+ DummyResult::any(span, guar)
}
}
}
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 57b6947..e5a1c6c 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -1,18 +1,18 @@
-use crate::errors;
-use crate::mbe::macro_parser::count_metavar_decls;
-use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
-
-use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, NtExprKind::*, Token};
+use rustc_ast::token::NtExprKind::*;
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, Token};
use rustc_ast::{tokenstream, NodeId};
use rustc_ast_pretty::pprust;
use rustc_feature::Features;
use rustc_session::parse::feature_err;
use rustc_session::Session;
-use rustc_span::symbol::{kw, sym, Ident};
-
use rustc_span::edition::Edition;
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
+use crate::errors;
+use crate::mbe::macro_parser::count_metavar_decls;
+use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
+
const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
`literal`, `path`, `meta`, `tt`, `item` and `vis`";
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 0da542d..b069105 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,26 +1,27 @@
-use crate::errors::{
- CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
- NoSyntaxVarsExprRepeat, VarStillRepeating,
-};
-use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
-use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
-use crate::mbe::{self, KleeneOp, MetaVarExpr};
+use std::mem;
+
use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
-use rustc_ast::token::{IdentIsRaw, Lit, LitKind};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, LitKind, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_ast::ExprKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, Diag, DiagCtxtHandle, PResult};
use rustc_parse::lexer::nfc_normalize;
use rustc_parse::parser::ParseNtResult;
-use rustc_session::parse::ParseSess;
-use rustc_session::parse::SymbolGallery;
+use rustc_session::parse::{ParseSess, SymbolGallery};
use rustc_span::hygiene::{LocalExpnId, Transparency};
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
use rustc_span::{with_metavar_spans, Span, Symbol, SyntaxContext};
use smallvec::{smallvec, SmallVec};
-use std::mem;
+
+use crate::errors::{
+ CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
+ NoSyntaxVarsExprRepeat, VarStillRepeating,
+};
+use crate::mbe::macro_parser::NamedMatch;
+use crate::mbe::macro_parser::NamedMatch::*;
+use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
+use crate::mbe::{self, KleeneOp, MetaVarExpr};
// A Marker adds the given mark to the syntax context.
struct Marker(LocalExpnId, Transparency, FxHashMap<SyntaxContext, SyntaxContext>);
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 506bd44..1334837 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -1,20 +1,21 @@
-use crate::base::ModuleData;
-use crate::errors::{
- ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates,
-};
+use std::iter::once;
+use std::path::{self, Path, PathBuf};
+
use rustc_ast::ptr::P;
use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
use rustc_errors::{Diag, ErrorGuaranteed};
-use rustc_parse::validate_attr;
-use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal};
+use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, validate_attr};
use rustc_session::parse::ParseSess;
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
-use std::iter::once;
-use std::path::{self, Path, PathBuf};
use thin_vec::ThinVec;
+use crate::base::ModuleData;
+use crate::errors::{
+ ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates,
+};
+
#[derive(Copy, Clone)]
pub enum DirOwnership {
Owned {
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 3fa9098..1e455d4 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -1,14 +1,16 @@
-use crate::expand::{AstFragment, AstFragmentKind};
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::token::Delimiter;
-use rustc_ast::{self as ast, visit::AssocCtxt};
+use rustc_ast::visit::AssocCtxt;
+use rustc_ast::{self as ast};
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::Ident;
use rustc_span::DUMMY_SP;
use smallvec::{smallvec, SmallVec};
use thin_vec::ThinVec;
+use crate::expand::{AstFragment, AstFragmentKind};
+
pub(crate) fn placeholder(
kind: AstFragmentKind,
id: ast::NodeId,
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 96145af..24f631e 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -1,7 +1,3 @@
-use crate::base::{self, *};
-use crate::errors;
-use crate::proc_macro_server;
-
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
@@ -11,6 +7,9 @@
use rustc_span::profiling::SpannedEventArgRecorder;
use rustc_span::Span;
+use crate::base::{self, *};
+use crate::{errors, proc_macro_server};
+
struct MessagePipe<T> {
tx: std::sync::mpsc::SyncSender<T>,
rx: std::sync::mpsc::Receiver<T>,
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 5508358..1438d1a 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -1,4 +1,5 @@
-use crate::base::ExtCtxt;
+use std::ops::{Bound, Range};
+
use ast::token::IdentIsRaw;
use pm::bridge::{
server, DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree,
@@ -20,7 +21,8 @@
use rustc_span::symbol::{self, sym, Symbol};
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span};
use smallvec::{smallvec, SmallVec};
-use std::ops::{Bound, Range};
+
+use crate::base::ExtCtxt;
trait FromInternal<T> {
fn from_internal(x: T) -> Self;
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e671c76..44286cf 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -1,8 +1,9 @@
//! List of the accepted feature gates.
-use super::{to_nonzero, Feature};
use rustc_span::symbol::sym;
+use super::{to_nonzero, Feature};
+
macro_rules! declare_features {
($(
$(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr),
@@ -85,7 +86,7 @@ macro_rules! declare_features {
/// Allows `c"foo"` literals.
(accepted, c_str_literals, "1.77.0", Some(105723)),
/// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries and treat `extern "C" fn` as nounwind.
- (accepted, c_unwind, "CURRENT_RUSTC_VERSION", Some(74990)),
+ (accepted, c_unwind, "1.81.0", Some(74990)),
/// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
(accepted, cfg_attr_multi, "1.33.0", Some(54881)),
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
@@ -237,7 +238,7 @@ macro_rules! declare_features {
/// Allows `let...else` statements.
(accepted, let_else, "1.65.0", Some(87335)),
/// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
- (accepted, lint_reasons, "CURRENT_RUSTC_VERSION", Some(54503)),
+ (accepted, lint_reasons, "1.81.0", Some(54503)),
/// Allows `break {expr}` with a value inside `loop`s.
(accepted, loop_break_value, "1.19.0", Some(37339)),
/// Allows use of `?` as the Kleene "at most one" operator in macros.
@@ -266,6 +267,8 @@ macro_rules! declare_features {
(accepted, min_const_generics, "1.51.0", Some(74878)),
/// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
(accepted, min_const_unsafe_fn, "1.33.0", Some(55607)),
+ /// Allows exhaustive pattern matching on uninhabited types when matched by value.
+ (accepted, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)),
/// Allows using `Self` and associated types in struct expressions and patterns.
(accepted, more_struct_aliases, "1.16.0", Some(37544)),
/// Allows using the MOVBE target feature.
@@ -291,6 +294,8 @@ macro_rules! declare_features {
(accepted, non_exhaustive, "1.40.0", Some(44109)),
/// Allows `foo.rs` as an alternative to `foo/mod.rs`.
(accepted, non_modrs_mods, "1.30.0", Some(44660)),
+ /// Allows using multiple nested field accesses in offset_of!
+ (accepted, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)),
/// Allows the use of or-patterns (e.g., `0 | 1`).
(accepted, or_patterns, "1.53.0", Some(54883)),
/// Allows using `+bundle,+whole-archive` link modifiers with native libs.
@@ -387,6 +392,8 @@ macro_rules! declare_features {
(accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
/// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
(accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
+ /// Allows unsafe on extern declarations and safety qualifiers over internal items.
+ (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
/// Allows importing and reexporting macros with `use`,
/// enables macro modularization in general.
(accepted, use_extern_macros, "1.30.0", Some(35896)),
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 7b27049..72ea55d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1,16 +1,15 @@
//! Built-in attributes and `cfg` flag gating.
+use std::sync::LazyLock;
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::symbol::{sym, Symbol};
use AttributeDuplicates::*;
use AttributeGate::*;
use AttributeType::*;
use crate::{Features, Stability};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_span::symbol::{sym, Symbol};
-
-use std::sync::LazyLock;
-
type GateFn = fn(&Features) -> bool;
macro_rules! cfg_fn {
@@ -704,21 +703,21 @@ pub struct BuiltinAttribute {
EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator),
),
gated!(
- panic_runtime, Normal, template!(Word), WarnFollowing,
+ panic_runtime, CrateLevel, template!(Word), WarnFollowing,
EncodeCrossCrate::No, experimental!(panic_runtime)
),
gated!(
- needs_panic_runtime, Normal, template!(Word), WarnFollowing,
+ needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing,
EncodeCrossCrate::No, experimental!(needs_panic_runtime)
),
gated!(
- compiler_builtins, Normal, template!(Word), WarnFollowing,
+ compiler_builtins, CrateLevel, template!(Word), WarnFollowing,
EncodeCrossCrate::No,
"the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
which contains compiler-rt intrinsics and will never be stable",
),
gated!(
- profiler_runtime, Normal, template!(Word), WarnFollowing,
+ profiler_runtime, CrateLevel, template!(Word), WarnFollowing,
EncodeCrossCrate::No,
"the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
which contains the profiler runtime and will never be stable",
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index e9d3ce0..dcc1c32 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -25,9 +25,10 @@
#[cfg(test)]
mod tests;
-use rustc_span::symbol::Symbol;
use std::num::NonZero;
+use rustc_span::symbol::Symbol;
+
#[derive(Debug, Clone)]
pub struct Feature {
pub name: Symbol,
@@ -126,11 +127,10 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
}
pub use accepted::ACCEPTED_FEATURES;
-pub use builtin_attrs::AttributeDuplicates;
pub use builtin_attrs::{
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
- is_valid_for_get_attr, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
- BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
+ is_valid_for_get_attr, AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate,
+ AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
};
pub use removed::REMOVED_FEATURES;
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 80a108d..b7f0ed5 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -1,8 +1,9 @@
//! List of the removed feature gates.
-use super::{to_nonzero, Feature};
use rustc_span::symbol::sym;
+use super::{to_nonzero, Feature};
+
pub struct RemovedFeature {
pub feature: Feature,
pub reason: Option<&'static str>,
@@ -81,6 +82,9 @@ macro_rules! declare_features {
/// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`.
(removed, custom_derive, "1.32.0", Some(29644),
Some("subsumed by `#[proc_macro_derive]`")),
+ /// Allows default type parameters to influence type inference.
+ (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336),
+ Some("never properly implemented; requires significant design work")),
/// Allows using `#[doc(keyword = "...")]`.
(removed, doc_keyword, "1.28.0", Some(51315),
Some("merged into `#![feature(rustdoc_internals)]`")),
@@ -222,7 +226,7 @@ macro_rules! declare_features {
(removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead")),
(removed, visible_private_types, "1.0.0", None, None),
/// Allows `extern "wasm" fn`
- (removed, wasm_abi, "CURRENT_RUSTC_VERSION", Some(83788),
+ (removed, wasm_abi, "1.81.0", Some(83788),
Some("non-standard wasm ABI is no longer supported")),
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
// Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d3d0718..47810bc 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -1,11 +1,11 @@
//! List of the unstable feature gates.
-use super::{to_nonzero, Feature};
-
use rustc_data_structures::fx::FxHashSet;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
+use super::{to_nonzero, Feature};
+
pub struct UnstableFeature {
pub feature: Feature,
pub set_enabled: fn(&mut Features),
@@ -431,8 +431,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, custom_test_frameworks, "1.30.0", Some(50297)),
/// Allows declarative macros 2.0 (`macro`).
(unstable, decl_macro, "1.17.0", Some(39412)),
- /// Allows default type parameters to influence type inference.
- (unstable, default_type_parameter_fallback, "1.3.0", Some(27336)),
/// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
(unstable, deprecated_safe, "1.61.0", Some(94978)),
/// Allows having using `suggestion` in the `#[deprecated]` attribute.
@@ -518,12 +516,9 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Give access to additional metadata about declarative macro meta-variables.
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
/// Provides a way to concatenate identifiers using metavariable expressions.
- (unstable, macro_metavar_expr_concat, "CURRENT_RUSTC_VERSION", Some(124225)),
+ (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
- /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
- /// unambiguously sound.
- (unstable, min_exhaustive_patterns, "1.77.0", Some(119612)),
/// A minimal, sound subset of specialization intended to be used by the
/// standard library until the soundness issues with specialization
/// are fixed.
@@ -560,14 +555,12 @@ pub fn internal(&self, feature: Symbol) -> bool {
(unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
/// Allows using enums in offset_of!
(unstable, offset_of_enum, "1.75.0", Some(120141)),
- /// Allows using multiple nested field accesses in offset_of!
- (unstable, offset_of_nested, "1.77.0", Some(120140)),
/// Allows using fields with slice type in offset_of!
- (unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
+ (unstable, offset_of_slice, "1.81.0", Some(126151)),
/// Allows using `#[optimize(X)]`.
(unstable, optimize_attribute, "1.34.0", Some(54882)),
/// Allows specifying nop padding on functions for dynamic patching.
- (unstable, patchable_function_entry, "CURRENT_RUSTC_VERSION", Some(123115)),
+ (unstable, patchable_function_entry, "1.81.0", Some(123115)),
/// Allows postfix match `expr.match { ... }`
(unstable, postfix_match, "1.79.0", Some(121618)),
/// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
@@ -579,7 +572,7 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
(incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)),
/// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant
- (incomplete, ref_pat_eat_one_layer_2024_structural, "CURRENT_RUSTC_VERSION", Some(123076)),
+ (incomplete, ref_pat_eat_one_layer_2024_structural, "1.81.0", Some(123076)),
/// Allows using the `#[register_tool]` attribute.
(unstable, register_tool, "1.41.0", Some(66079)),
/// Allows the `#[repr(i128)]` attribute for enums.
@@ -593,6 +586,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
(incomplete, return_type_notation, "1.70.0", Some(109417)),
/// Allows `extern "rust-cold"`.
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
+ /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
+ (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)),
/// Shortern the tail expression lifetime
(unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)),
/// Allows the use of SIMD types in functions declared in `extern` blocks.
@@ -631,8 +626,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
/// Allows unsafe attributes.
(unstable, unsafe_attributes, "1.80.0", Some(123757)),
- /// Allows unsafe on extern declarations and safety qualifiers over internal items.
- (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
/// Allows const generic parameters to be defined with types that
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
(incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
@@ -645,9 +638,9 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
(unstable, used_with_arg, "1.60.0", Some(93798)),
/// Allows use of x86 `AMX` target-feature attributes and intrinsics
- (unstable, x86_amx_intrinsics, "CURRENT_RUSTC_VERSION", Some(126622)),
+ (unstable, x86_amx_intrinsics, "1.81.0", Some(126622)),
/// Allows use of the `xop` target-feature
- (unstable, xop_target_feature, "CURRENT_RUSTC_VERSION", Some(127208)),
+ (unstable, xop_target_feature, "1.81.0", Some(127208)),
/// Allows `do yeet` expressions
(unstable, yeet_expr, "1.62.0", Some(96373)),
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 68fdabd..23795a9 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -1,20 +1,16 @@
+use std::collections::{HashMap, HashSet};
+use std::fs::read_to_string;
+use std::path::{Path, PathBuf};
+
use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
use fluent_bundle::{FluentBundle, FluentError, FluentResource};
-use fluent_syntax::{
- ast::{
- Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern,
- PatternElement,
- },
- parser::ParserError,
+use fluent_syntax::ast::{
+ Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement,
};
+use fluent_syntax::parser::ParserError;
use proc_macro::{Diagnostic, Level, Span};
use proc_macro2::TokenStream;
use quote::quote;
-use std::{
- collections::{HashMap, HashSet},
- fs::read_to_string,
- path::{Path, PathBuf},
-};
use syn::{parse_macro_input, Ident, LitStr};
use unic_langid::langid;
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index d376c24..91eae98 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -1,7 +1,6 @@
use std::ffi::CString;
-use std::fs;
-use std::io;
use std::path::{absolute, Path, PathBuf};
+use std::{fs, io};
// Unfortunately, on windows, it looks like msvcrt.dll is silently translating
// verbatim paths under the hood to non-verbatim paths! This manifests itself as
diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index c0fe982..c8f8fd5 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -279,12 +279,12 @@
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
-use LabelText::*;
-
use std::borrow::Cow;
use std::io;
use std::io::prelude::*;
+use LabelText::*;
+
/// The text for a graphviz label on a node or edge.
pub enum LabelText<'a> {
/// This kind of label preserves the text directly as is.
diff --git a/compiler/rustc_graphviz/src/tests.rs b/compiler/rustc_graphviz/src/tests.rs
index 154bae4..01e6cb9 100644
--- a/compiler/rustc_graphviz/src/tests.rs
+++ b/compiler/rustc_graphviz/src/tests.rs
@@ -1,9 +1,11 @@
-use super::LabelText::{self, EscStr, HtmlStr, LabelStr};
-use super::{render, Edges, GraphWalk, Id, Labeller, Nodes, Style};
use std::io;
use std::io::prelude::*;
+
use NodeLabels::*;
+use super::LabelText::{self, EscStr, HtmlStr, LabelStr};
+use super::{render, Edges, GraphWalk, Id, Labeller, Nodes, Style};
+
/// each node is an index in a vector in the graph.
type Node = usize;
struct Edge {
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index b185492..59204d7 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -1,5 +1,5 @@
-use crate::definitions::DefPathData;
-use crate::hir;
+use std::array::IntoIter;
+use std::fmt::Debug;
use rustc_ast as ast;
use rustc_ast::NodeId;
@@ -11,8 +11,8 @@
use rustc_span::symbol::kw;
use rustc_span::Symbol;
-use std::array::IntoIter;
-use std::fmt::Debug;
+use crate::definitions::DefPathData;
+use crate::hir;
/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 5c86135..8c2be21 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -4,18 +4,20 @@
//! There are also some rather random cases (like const initializer
//! expressions) that are mostly just leftovers.
-pub use crate::def_id::DefPathHash;
-use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use crate::def_path_hash_map::DefPathHashMap;
+use std::fmt::{self, Write};
+use std::hash::Hash;
+
use rustc_data_structures::stable_hasher::{Hash64, StableHasher};
use rustc_data_structures::unord::UnordMap;
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable};
use rustc_span::symbol::{kw, sym, Symbol};
-use std::fmt::{self, Write};
-use std::hash::Hash;
use tracing::{debug, instrument};
+pub use crate::def_id::DefPathHash;
+use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::def_path_hash_map::DefPathHashMap;
+
/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
/// stores the `DefIndex` of its parent.
diff --git a/compiler/rustc_hir/src/diagnostic_items.rs b/compiler/rustc_hir/src/diagnostic_items.rs
index d4d09f9..23a83a5 100644
--- a/compiler/rustc_hir/src/diagnostic_items.rs
+++ b/compiler/rustc_hir/src/diagnostic_items.rs
@@ -1,9 +1,10 @@
-use crate::def_id::DefId;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_span::def_id::DefIdMap;
use rustc_span::Symbol;
+use crate::def_id::DefId;
+
#[derive(Debug, Default)]
pub struct DiagnosticItems {
pub id_to_name: DefIdMap<Symbol>,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 8c8f760..33e8432 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1,28 +1,34 @@
+use std::fmt;
+
+use rustc_ast as ast;
+use rustc_ast::util::parser::ExprPrecedence;
+use rustc_ast::{
+ Attribute, FloatTy, InlineAsmOptions, InlineAsmTemplatePiece, IntTy, Label, LitKind,
+ TraitObjectSyntax, UintTy,
+};
+pub use rustc_ast::{
+ BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
+ Mutability, UnOp,
+};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::sorted_map::SortedMap;
+use rustc_index::IndexVec;
+use rustc_macros::{Decodable, Encodable, HashStable_Generic};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::hygiene::MacroKind;
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{BytePos, ErrorGuaranteed, Span, DUMMY_SP};
+use rustc_target::asm::InlineAsmRegOrRegClass;
+use rustc_target::spec::abi::Abi;
+use smallvec::SmallVec;
+use tracing::debug;
+
use crate::def::{CtorKind, DefKind, Res};
use crate::def_id::{DefId, LocalDefIdMap};
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
use crate::intravisit::FnKind;
use crate::LangItem;
-use rustc_ast as ast;
-use rustc_ast::util::parser::ExprPrecedence;
-use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, TraitObjectSyntax, UintTy};
-pub use rustc_ast::{BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy};
-pub use rustc_ast::{ImplPolarity, IsAuto, Movability, Mutability, UnOp};
-use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::sorted_map::SortedMap;
-use rustc_index::IndexVec;
-use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::hygiene::MacroKind;
-use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::ErrorGuaranteed;
-use rustc_span::{def_id::LocalDefId, BytePos, Span, DUMMY_SP};
-use rustc_target::asm::InlineAsmRegOrRegClass;
-use rustc_target::spec::abi::Abi;
-use smallvec::SmallVec;
-use std::fmt;
-use tracing::debug;
#[derive(Debug, Copy, Clone, HashStable_Generic)]
pub struct Lifetime {
@@ -2946,6 +2952,17 @@ pub struct FnDecl<'hir> {
pub lifetime_elision_allowed: bool,
}
+impl<'hir> FnDecl<'hir> {
+ pub fn opt_delegation_sig_id(&self) -> Option<DefId> {
+ if let FnRetTy::Return(ty) = self.output
+ && let TyKind::InferDelegation(sig_id, _) = ty.kind
+ {
+ return Some(sig_id);
+ }
+ None
+ }
+}
+
/// Represents what type of implicit self a function has, if any.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum ImplicitSelfKind {
@@ -3683,6 +3700,11 @@ pub fn def_id(self) -> OwnerId {
}
}
+ /// Check if node is an impl block.
+ pub fn is_impl_block(&self) -> bool {
+ matches!(self, OwnerNode::Item(Item { kind: ItemKind::Impl(_), .. }))
+ }
+
expect_methods_self! {
expect_item, &'hir Item<'hir>, OwnerNode::Item(n), n;
expect_foreign_item, &'hir ForeignItem<'hir>, OwnerNode::ForeignItem(n), n;
@@ -4008,8 +4030,9 @@ pub fn fn_kind(self) -> Option<FnKind<'hir>> {
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(Block<'_>, 48);
static_assert_size!(Body<'_>, 24);
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index c0ca1a8..f214235 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,8 +1,11 @@
-use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
+use std::fmt::{self, Debug};
+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::{def_id::DefPathHash, HashStableContext};
-use std::fmt::{self, Debug};
+use rustc_span::def_id::DefPathHash;
+use rustc_span::HashStableContext;
+
+use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
pub struct OwnerId {
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 696f548..dd501f84 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -64,13 +64,14 @@
//! This order consistency is required in a few places in rustc, for
//! example coroutine inference, and possibly also HIR borrowck.
-use crate::hir::*;
use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult};
use rustc_ast::{Attribute, Label};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
+use crate::hir::*;
+
pub trait IntoVisitor<'hir> {
type Visitor: Visitor<'hir>;
fn into_visitor(&self) -> Self::Visitor;
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 1821387..e7398fd 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -7,9 +7,6 @@
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
//! * Functions called by the compiler itself.
-use crate::def_id::DefId;
-use crate::{MethodKind, Target};
-
use rustc_ast as ast;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -17,6 +14,9 @@
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
+use crate::def_id::DefId;
+use crate::{MethodKind, Target};
+
/// All of the lang items, defined or not.
/// Defined lang items can come from the current crate or its dependencies.
#[derive(HashStable_Generic, Debug)]
diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs
index 9991b02..73d1ea4 100644
--- a/compiler/rustc_hir/src/pat_util.rs
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -1,10 +1,11 @@
-use crate::def::{CtorOf, DefKind, Res};
-use crate::def_id::{DefId, DefIdSet};
-use crate::hir::{self, BindingMode, ByRef, HirId, PatKind};
+use std::iter::Enumerate;
+
use rustc_span::symbol::Ident;
use rustc_span::Span;
-use std::iter::Enumerate;
+use crate::def::{CtorOf, DefKind, Res};
+use crate::def_id::{DefId, DefIdSet};
+use crate::hir::{self, BindingMode, ByRef, HirId, PatKind};
pub struct EnumerateAndAdjust<I> {
enumerate: Enumerate<I>,
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index baa1635..fe169e9 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -1,10 +1,10 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_span::def_id::DefPathHash;
use crate::hir::{
AttributeMap, BodyId, Crate, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId,
};
use crate::hir_id::{HirId, ItemLocalId};
-use rustc_span::def_id::DefPathHash;
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index e448d29..f43008e 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -4,11 +4,10 @@
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::hir;
-use crate::{Item, ItemKind, TraitItem, TraitItemKind};
+use std::fmt::{self, Display};
use crate::def::DefKind;
-use std::fmt::{self, Display};
+use crate::{hir, Item, ItemKind, TraitItem, TraitItemKind};
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum GenericParamKind {
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 571923b..16b3c4a 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,9 +1,10 @@
-use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
use rustc_data_structures::stable_hasher::Hash64;
use rustc_span::def_id::{DefPathHash, StableCrateId};
use rustc_span::edition::Edition;
use rustc_span::{create_session_globals_then, Symbol};
+use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
+
#[test]
fn def_path_hash_depends_on_crate_id() {
// This test makes sure that *both* halves of a DefPathHash depend on
diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs
index 0cc50c6..ca133c5 100644
--- a/compiler/rustc_hir/src/weak_lang_items.rs
+++ b/compiler/rustc_hir/src/weak_lang_items.rs
@@ -1,9 +1,9 @@
//! Validity checking for weak lang items
-use crate::LangItem;
-
use rustc_span::symbol::{sym, Symbol};
+use crate::LangItem;
+
macro_rules! weak_lang_items {
($($item:ident, $sym:ident;)*) => {
pub static WEAK_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 367f6e1..bde94be 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -341,8 +341,7 @@
hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args
-hir_analysis_not_supported_delegation =
- {$descr} is not supported yet
+hir_analysis_not_supported_delegation = {$descr}
.label = callee defined here
hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 2bf14a2..53c8586 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -1,14 +1,13 @@
+use rustc_infer::infer::InferCtxt;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_session::Limit;
+use rustc_span::def_id::{LocalDefId, LOCAL_CRATE};
+use rustc_span::Span;
+use rustc_trait_selection::traits::ObligationCtxt;
+
use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_infer::infer::InferCtxt;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_session::Limit;
-use rustc_span::def_id::LocalDefId;
-use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::Span;
-use rustc_trait_selection::traits::ObligationCtxt;
#[derive(Copy, Clone, Debug)]
pub enum AutoderefKind {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 27db541..2e778fd 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,12 +1,9 @@
-use crate::check::intrinsicck::InlineAsmCtxt;
+use std::cell::LazyCell;
+use std::ops::ControlFlow;
-use super::compare_impl_item::check_type_bounds;
-use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
-use super::*;
-use rustc_attr as attr;
use rustc_data_structures::unord::{UnordMap, UnordSet};
-use rustc_errors::{codes::*, MultiSpan};
-use rustc_hir as hir;
+use rustc_errors::codes::*;
+use rustc_errors::MultiSpan;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::Node;
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
@@ -19,9 +16,9 @@
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
-use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{
- AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ AdtDef, GenericArgKind, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt,
};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_target::abi::FieldIdx;
@@ -30,9 +27,11 @@
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_type_ir::fold::TypeFoldable;
+use {rustc_attr as attr, rustc_hir as hir};
-use std::cell::LazyCell;
-use std::ops::ControlFlow;
+use super::compare_impl_item::{check_type_bounds, compare_impl_method, compare_impl_ty};
+use super::*;
+use crate::check::intrinsicck::InlineAsmCtxt;
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
match tcx.sess.target.is_abi_supported(abi) {
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index c99f134..3557761 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1,24 +1,24 @@
-use super::potentially_plural_count;
-use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
use core::ops::ControlFlow;
+use std::borrow::Cow;
+use std::iter;
+
use hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
+use rustc_errors::codes::*;
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::intravisit;
-use rustc_hir::{GenericParamKind, ImplItemKind};
+use rustc_hir::{intravisit, GenericParamKind, ImplItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::util::ExplicitSelf;
-use rustc_middle::ty::Upcast;
use rustc_middle::ty::{
- self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+ self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder,
+ TypeSuperFoldable, TypeVisitableExt, Upcast,
};
-use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@@ -28,8 +28,9 @@
use rustc_trait_selection::traits::{
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
};
-use std::borrow::Cow;
-use std::iter;
+
+use super::potentially_plural_count;
+use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture};
mod refine;
@@ -1116,7 +1117,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
.dcx()
.create_err(LifetimesOrBoundsMismatchOnTrait {
span,
- item_kind: assoc_item_kind_str(&impl_m),
+ item_kind: impl_m.descr(),
ident: impl_m.ident(tcx),
generics_span,
bounds_span,
@@ -1293,7 +1294,7 @@ fn compare_number_of_generics<'tcx>(
("const", trait_own_counts.consts, impl_own_counts.consts),
];
- let item_kind = assoc_item_kind_str(&impl_);
+ let item_kind = impl_.descr();
let mut err_occurred = None;
for (kind, trait_count, impl_count) in matchings {
@@ -1675,7 +1676,7 @@ fn compare_generic_param_kinds<'tcx>(
param_impl_span,
E0053,
"{} `{}` has an incompatible generic parameter for trait `{}`",
- assoc_item_kind_str(&impl_item),
+ impl_item.descr(),
trait_item.name,
&tcx.def_path_str(tcx.parent(trait_item.def_id))
);
@@ -2248,14 +2249,6 @@ fn param_env_with_gat_bounds<'tcx>(
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
}
-fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
- match impl_item.kind {
- ty::AssocKind::Const => "const",
- ty::AssocKind::Fn => "method",
- ty::AssocKind::Type => "type",
- }
-}
-
/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`,
/// and extract a better error if so.
fn try_report_async_mismatch<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index ad3324f..80daaa6 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -1,7 +1,8 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_infer::infer::{outlives::env::OutlivesEnvironment, TyCtxtInferExt};
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE};
use rustc_middle::span_bug;
use rustc_middle::traits::{ObligationCause, Reveal};
@@ -10,9 +11,8 @@
};
use rustc_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt;
-use rustc_trait_selection::traits::{
- elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt,
-};
+use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt;
+use rustc_trait_selection::traits::{elaborate, normalize_param_env_or_error, ObligationCtxt};
/// Check that an implementation does not refine an RPITIT from a trait method signature.
pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>(
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 06ec014..d173915 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -3,13 +3,13 @@
// We don't do any drop checking during hir typeck.
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::util::CheckRegions;
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_middle::ty::{GenericArgsRef, Ty};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{self, ObligationCtxt};
diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index e4d4b7d..1f72458 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -1,3 +1,5 @@
+use std::ops::Not;
+
use rustc_hir as hir;
use rustc_hir::Node;
use rustc_infer::infer::TyCtxtInferExt;
@@ -5,13 +7,12 @@
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config::EntryFnType;
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
-use rustc_span::{symbol::sym, Span};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
-use std::ops::Not;
-
use super::check_function_signature;
use crate::errors;
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 6282499..4b45ced 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -1,13 +1,8 @@
//! Type-checking for the rust-intrinsic and platform-intrinsic
//! intrinsics that the compiler exposes.
-use crate::check::check_function_signature;
-use crate::errors::{
- UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
- WrongNumberOfGenericArgumentsToIntrinsic,
-};
-
-use rustc_errors::{codes::*, struct_span_code_err, DiagMessage};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, DiagMessage};
use rustc_hir as hir;
use rustc_middle::bug;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
@@ -17,6 +12,12 @@
use rustc_span::{Span, Symbol};
use rustc_target::spec::abi::Abi;
+use crate::check::check_function_signature;
+use crate::errors::{
+ UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
+ WrongNumberOfGenericArgumentsToIntrinsic,
+};
+
fn equate_intrinsic_type<'tcx>(
tcx: TyCtxt<'tcx>,
span: Span,
@@ -119,6 +120,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
| sym::type_id
| sym::likely
| sym::unlikely
+ | sym::select_unpredictable
| sym::ptr_guaranteed_cmp
| sym::minnumf16
| sym::minnumf32
@@ -487,6 +489,7 @@ pub fn check_intrinsic_type(
sym::assume => (0, 0, vec![tcx.types.bool], tcx.types.unit),
sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
+ sym::select_unpredictable => (1, 0, vec![tcx.types.bool, param(0), param(0)], param(0)),
sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
sym::write_via_move => {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 2e965c5..79ecdee 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,8 +1,10 @@
+use std::assert_matches::debug_assert_matches;
+
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::bug;
-use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
+use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::Symbol;
@@ -455,32 +457,22 @@ pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) {
);
}
}
- // No special checking is needed for these:
- // - Typeck has checked that Const operands are integers.
- // - AST lowering guarantees that SymStatic points to a static.
- hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymStatic { .. } => {}
- // Check that sym actually points to a function. Later passes
- // depend on this.
- hir::InlineAsmOperand::SymFn { anon_const } => {
- let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
- match ty.kind() {
- ty::Never | ty::Error(_) => {}
- ty::FnDef(..) => {}
- _ => {
- self.tcx
- .dcx()
- .struct_span_err(*op_sp, "invalid `sym` operand")
- .with_span_label(
- self.tcx.def_span(anon_const.def_id),
- format!("is {} `{}`", ty.kind().article(), ty),
- )
- .with_help(
- "`sym` operands must refer to either a function or a static",
- )
- .emit();
- }
- };
+ // Typeck has checked that Const operands are integers.
+ hir::InlineAsmOperand::Const { anon_const } => {
+ debug_assert_matches!(
+ self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
+ ty::Error(_) | ty::Int(_) | ty::Uint(_)
+ );
}
+ // Typeck has checked that SymFn refers to a function.
+ hir::InlineAsmOperand::SymFn { anon_const } => {
+ debug_assert_matches!(
+ self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
+ ty::Error(_) | ty::FnDef(..)
+ );
+ }
+ // AST lowering guarantees that SymStatic points to a static.
+ hir::InlineAsmOperand::SymStatic { .. } => {}
// No special checking is needed for labels.
hir::InlineAsmOperand::Label { .. } => {}
}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 4c230ad..678b8c8 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -72,13 +72,11 @@
mod region;
pub mod wfcheck;
-pub use check::check_abi;
-
use std::num::NonZero;
+pub use check::check_abi;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
-use rustc_errors::ErrorGuaranteed;
-use rustc_errors::{pluralize, struct_span_code_err, Diag};
+use rustc_errors::{pluralize, struct_span_code_err, Diag, ErrorGuaranteed};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_index::bit_set::BitSet;
@@ -87,12 +85,12 @@
use rustc_infer::traits::ObligationCause;
use rustc_middle::query::Providers;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
+use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
+use rustc_span::{BytePos, Span, Symbol, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::infer::ObligationCauseExt as _;
@@ -100,11 +98,9 @@
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::ObligationCtxt;
-use crate::errors;
-use crate::require_c_abi_if_c_variadic;
-
use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
use self::region::region_scope_tree;
+use crate::{errors, require_c_abi_if_c_variadic};
pub fn provide(providers: &mut Providers) {
wfcheck::provide(providers);
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 2b5efd3..bc6641c 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -6,6 +6,8 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
+use std::mem;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@@ -19,8 +21,6 @@
use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut};
-use std::mem;
-
#[derive(Debug, Copy, Clone)]
pub struct Context {
/// The scope that contains any new variables declared, plus its depth in
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 456dc4e..a9f8630 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,14 +1,10 @@
-use crate::autoderef::Autoderef;
-use crate::collect::CollectItemTypesVisitor;
-use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
-use crate::errors;
-use crate::fluent_generated as fluent;
+use std::cell::LazyCell;
+use std::ops::{ControlFlow, Deref};
use hir::intravisit::{self, Visitor};
-use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
-use rustc_hir as hir;
+use rustc_errors::codes::*;
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::lang_items::LangItem;
@@ -20,10 +16,9 @@
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
- self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast,
+ self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast,
};
-use rustc_middle::ty::{GenericArgKind, GenericArgs};
use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident};
@@ -41,9 +36,12 @@
};
use rustc_type_ir::solve::NoSolution;
use rustc_type_ir::TypeFlags;
+use {rustc_ast as ast, rustc_hir as hir};
-use std::cell::LazyCell;
-use std::ops::{ControlFlow, Deref};
+use crate::autoderef::Autoderef;
+use crate::collect::CollectItemTypesVisitor;
+use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
+use crate::{errors, fluent_generated as fluent};
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
pub(super) ocx: ObligationCtxt<'a, 'tcx, FulfillmentError<'tcx>>,
@@ -1278,7 +1276,7 @@ fn check_item_type(
UnsizedHandling::Forbid => true,
UnsizedHandling::Allow => false,
UnsizedHandling::AllowIfForeignTail => {
- let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
+ let tail = tcx.struct_tail_for_codegen(item_ty, wfcx.param_env);
!matches!(tail.kind(), ty::Foreign(_))
}
};
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index b35ee27..fecd78b 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -1,7 +1,8 @@
//! Check properties that are required by built-in traits and set
//! up data structures required by type-checking/codegen.
-use crate::errors;
+use std::assert_matches::assert_matches;
+use std::collections::BTreeMap;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{ErrorGuaranteed, MultiSpan};
@@ -10,8 +11,7 @@
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::infer::{self, RegionResolutionError};
+use rustc_infer::infer::{self, RegionResolutionError, TyCtxtInferExt};
use rustc_infer::traits::Obligation;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::print::PrintTraitRefExt as _;
@@ -22,9 +22,9 @@
type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
};
-use rustc_trait_selection::traits::ObligationCtxt;
-use rustc_trait_selection::traits::{self, ObligationCause};
-use std::collections::BTreeMap;
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
+
+use crate::errors;
pub(super) fn check_trait<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -130,7 +130,7 @@ fn visit_implementation_of_const_param_ty(
checker: &Checker<'_>,
kind: LangItem,
) -> Result<(), ErrorGuaranteed> {
- assert!(matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy));
+ assert_matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
let tcx = checker.tcx;
let header = checker.impl_header;
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 3aef29f..cd5cc33 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -1,6 +1,6 @@
-use rustc_data_structures::fx::IndexEntry;
-use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry};
+use rustc_errors::codes::*;
+use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index e9961d3..8e4da90 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -5,8 +5,8 @@
// done by the orphan and overlap modules. Then we build up various
// mappings. That mapping code resides here.
-use crate::errors;
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::codes::*;
+use rustc_errors::struct_span_code_err;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::LangItem;
use rustc_middle::query::Providers;
@@ -14,6 +14,8 @@
use rustc_session::parse::feature_err;
use rustc_span::{sym, ErrorGuaranteed};
+use crate::errors;
+
mod builtin;
mod inherent_impls;
mod inherent_impls_overlap;
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index f2804ce..dcd0e31 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -1,19 +1,21 @@
//! Orphan checker: every impl either implements a trait defined in this
//! crate or pertains to a type defined in this crate.
-use crate::errors;
-
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+use rustc_middle::ty::{
+ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
+ TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::{DefId, LocalDefId};
-use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
-use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
+use rustc_trait_selection::traits::{
+ self, IsFirstInputType, OrphanCheckErr, OrphanCheckMode, UncoveredTyParams,
+};
+
+use crate::errors;
#[instrument(level = "debug", skip(tcx))]
pub(crate) fn orphan_check_impl(
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index 5fe21e9..7513f68 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -1,10 +1,12 @@
//! Unsafety checker: every impl either implements a trait defined in this
//! crate or pertains to a type defined in this crate.
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::codes::*;
+use rustc_errors::struct_span_code_err;
use rustc_hir::Safety;
use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TraitDef, TyCtxt};
+use rustc_middle::ty::ImplPolarity::*;
+use rustc_middle::ty::{ImplTraitHeader, TraitDef, TyCtxt};
use rustc_span::def_id::LocalDefId;
use rustc_span::ErrorGuaranteed;
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 5653512..91fa066 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -14,6 +14,10 @@
//! At present, however, we do run collection across all items in the
//! crate as a kind of pass. This should eventually be factored away.
+use std::cell::Cell;
+use std::iter;
+use std::ops::Bound;
+
use rustc_ast::Recovered;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
@@ -24,8 +28,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, walk_generics, Visitor};
-use rustc_hir::{self as hir};
-use rustc_hir::{GenericParamKind, Node};
+use rustc_hir::{self as hir, GenericParamKind, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter;
@@ -39,9 +42,6 @@
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
-use std::cell::Cell;
-use std::iter;
-use std::ops::Bound;
use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::errors;
@@ -67,6 +67,7 @@ pub fn provide(providers: &mut Providers) {
item_super_predicates: item_bounds::item_super_predicates,
explicit_item_super_predicates: item_bounds::explicit_item_super_predicates,
item_non_self_assumptions: item_bounds::item_non_self_assumptions,
+ impl_super_outlives: item_bounds::impl_super_outlives,
generics_of: generics_of::generics_of,
predicates_of: predicates_of::predicates_of,
predicates_defined_on,
@@ -1207,25 +1208,29 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
let item = tcx.hir().expect_item(def_id);
- let (is_auto, safety, items) = match item.kind {
+ let (is_alias, is_auto, safety, items) = match item.kind {
hir::ItemKind::Trait(is_auto, safety, .., items) => {
- (is_auto == hir::IsAuto::Yes, safety, items)
+ (false, is_auto == hir::IsAuto::Yes, safety, items)
}
- hir::ItemKind::TraitAlias(..) => (false, hir::Safety::Safe, &[][..]),
+ hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]),
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
};
- let constness = if tcx.has_attr(def_id, sym::const_trait) {
+ // Only regular traits can be const.
+ let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
+
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
if paren_sugar && !tcx.features().unboxed_closures {
tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
}
- let is_marker = tcx.has_attr(def_id, sym::marker);
+ // Only regular traits can be marker.
+ let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
+
let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
@@ -1695,6 +1700,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
trait_ref: ty::EarlyBinder::bind(trait_ref),
safety: impl_.safety,
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
+ do_not_recommend: tcx.features().do_not_recommend
+ && tcx.has_attrs_with_path(def_id, &[sym::diagnostic, sym::do_not_recommend]),
}
})
}
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 6904234..28d6cab 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -1,10 +1,8 @@
+use std::assert_matches::assert_matches;
use std::ops::ControlFlow;
-use crate::middle::resolve_bound_vars as rbv;
-use hir::{
- intravisit::{self, Visitor},
- GenericParamKind, HirId, Node,
-};
+use hir::intravisit::{self, Visitor};
+use hir::{GenericParamKind, HirId, Node};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -13,6 +11,9 @@
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
+use crate::delegation::inherit_generics_for_delegation_item;
+use crate::middle::resolve_bound_vars as rbv;
+
#[instrument(level = "debug", skip(tcx), ret)]
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*;
@@ -207,9 +208,9 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
..
}) => {
if in_trait {
- assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
+ assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn);
} else {
- assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
+ assert_matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn);
}
Some(fn_def_id.to_def_id())
}
@@ -218,15 +219,25 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
..
}) => {
if in_assoc_ty {
- assert!(matches!(tcx.def_kind(parent), DefKind::AssocTy));
+ assert_matches!(tcx.def_kind(parent), DefKind::AssocTy);
} else {
- assert!(matches!(tcx.def_kind(parent), DefKind::TyAlias));
+ assert_matches!(tcx.def_kind(parent), DefKind::TyAlias);
}
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent);
// Opaque types are always nested within another item, and
// inherit the generics of the item.
Some(parent.to_def_id())
}
+ ItemKind::Fn(sig, _, _) => {
+ // For a delegation item inherit generics from callee.
+ if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
+ && let Some(generics) =
+ inherit_generics_for_delegation_item(tcx, def_id, sig_id)
+ {
+ return generics;
+ }
+ None
+ }
_ => None,
},
_ => None,
@@ -328,8 +339,6 @@ enum Defaults {
if default.is_some() {
match allow_defaults {
Defaults::Allowed => {}
- Defaults::FutureCompatDisallowed
- if tcx.features().default_type_parameter_fallback => {}
Defaults::FutureCompatDisallowed => {
tcx.node_span_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index c03e074..ec48c78 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -1,15 +1,17 @@
-use super::ItemCtxt;
-use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_infer::traits::util;
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::{
+ self, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
use rustc_type_ir::Upcast;
+use super::ItemCtxt;
+use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
+
/// For associated types we include both bounds written on the type
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
///
@@ -210,6 +212,8 @@ pub(super) fn item_super_predicates(
})
}
+/// This exists as an optimization to compute only the item bounds of the item
+/// that are not `Self` bounds.
pub(super) fn item_non_self_assumptions(
tcx: TyCtxt<'_>,
def_id: DefId,
@@ -224,6 +228,25 @@ pub(super) fn item_non_self_assumptions(
}
}
+/// This exists as an optimization to compute only the supertraits of this impl's
+/// trait that are outlives bounds.
+pub(super) fn impl_super_outlives(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+) -> ty::EarlyBinder<'_, ty::Clauses<'_>> {
+ tcx.impl_trait_header(def_id).expect("expected an impl of trait").trait_ref.map_bound(
+ |trait_ref| {
+ let clause: ty::Clause<'_> = trait_ref.upcast(tcx);
+ tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| {
+ matches!(
+ clause.kind().skip_binder(),
+ ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_)
+ )
+ }))
+ },
+ )
+}
+
struct AssocTyToOpaque<'tcx> {
tcx: TyCtxt<'tcx>,
fn_def_id: DefId,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 9e430c8..6ac4802 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,19 +1,22 @@
-use crate::bounds::Bounds;
-use crate::collect::ItemCtxt;
-use crate::constrained_generic_params as cgp;
-use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason};
+use std::assert_matches::assert_matches;
+
use hir::{HirId, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, Upcast};
+use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
+use crate::bounds::Bounds;
+use crate::collect::ItemCtxt;
+use crate::constrained_generic_params as cgp;
+use crate::delegation::inherit_predicates_for_delegation_item;
+use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason};
+
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
/// `Self: Trait` predicates for traits.
@@ -143,6 +146,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
is_trait = Some(self_bounds);
}
+
+ ItemKind::Fn(sig, _, _) => {
+ // For a delegation item inherit predicates from callee.
+ if let Some(sig_id) = sig.decl.opt_delegation_sig_id()
+ && let Some(predicates) =
+ inherit_predicates_for_delegation_item(tcx, def_id, sig_id)
+ {
+ return predicates;
+ }
+ }
_ => {}
}
};
@@ -590,7 +603,7 @@ pub(super) fn implied_predicates_with_filter(
let Some(trait_def_id) = trait_def_id.as_local() else {
// if `assoc_name` is None, then the query should've been redirected to an
// external provider
- assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
+ assert_matches!(filter, PredicateFilter::SelfThatDefines(_));
return tcx.explicit_super_predicates_of(trait_def_id);
};
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 02ea958..e11d3c9 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -7,6 +7,8 @@
//! is also responsible for assigning their semantics to implicit lifetimes in trait objects.
use core::ops::ControlFlow;
+use std::fmt;
+
use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir as hir;
@@ -23,7 +25,6 @@
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
-use std::fmt;
use crate::errors;
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 9affd65..8cb4ba6 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -1,4 +1,5 @@
use core::ops::ControlFlow;
+
use rustc_errors::{Applicability, StashKey};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -6,17 +7,15 @@
use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
+use super::{bad_placeholder, ItemCtxt};
use crate::errors::TypeofReservedKeywordUsed;
use crate::hir_ty_lowering::HirTyLowerer;
-use super::bad_placeholder;
-use super::ItemCtxt;
-
mod opaque;
fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
@@ -35,6 +34,20 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let parent_node_id = tcx.parent_hir_id(hir_id);
let parent_node = tcx.hir_node(parent_node_id);
+ let find_sym_fn = |&(op, op_sp)| match op {
+ hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => {
+ Some((anon_const, op_sp))
+ }
+ _ => None,
+ };
+
+ let find_const = |&(op, op_sp)| match op {
+ hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
+ Some((anon_const, op_sp))
+ }
+ _ => None,
+ };
+
match parent_node {
// Anon consts "inside" the type system.
Node::ConstArg(&ConstArg {
@@ -46,13 +59,51 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// Anon consts outside the type system.
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
- if asm.operands.iter().any(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const }
- | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
- _ => false,
- }) =>
+ if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) =>
{
- tcx.typeck(def_id).node_type(hir_id)
+ let ty = tcx.typeck(def_id).node_type(hir_id);
+
+ match ty.kind() {
+ ty::Error(_) => ty,
+ ty::FnDef(..) => ty,
+ _ => {
+ let guar = tcx
+ .dcx()
+ .struct_span_err(op_sp, "invalid `sym` operand")
+ .with_span_label(
+ tcx.def_span(anon_const.def_id),
+ format!("is {} `{}`", ty.kind().article(), ty),
+ )
+ .with_help("`sym` operands must refer to either a function or a static")
+ .emit();
+
+ Ty::new_error(tcx, guar)
+ }
+ }
+ }
+ Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
+ | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
+ if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
+ {
+ let ty = tcx.typeck(def_id).node_type(hir_id);
+
+ match ty.kind() {
+ ty::Error(_) => ty,
+ ty::Int(_) | ty::Uint(_) => ty,
+ _ => {
+ let guar = tcx
+ .dcx()
+ .struct_span_err(op_sp, "invalid type for `const` operand")
+ .with_span_label(
+ tcx.def_span(anon_const.def_id),
+ format!("is {} `{}`", ty.kind().article(), ty),
+ )
+ .with_help("`const` operands must be of an integer type")
+ .emit();
+
+ Ty::new_error(tcx, guar)
+ }
+ }
}
Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs
new file mode 100644
index 0000000..20aaa43
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -0,0 +1,261 @@
+use std::assert_matches::debug_assert_matches;
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::ErrorGuaranteed;
+use rustc_type_ir::visit::TypeVisitableExt;
+
+type RemapTable = FxHashMap<u32, u32>;
+
+struct ParamIndexRemapper<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ remap_table: RemapTable,
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamIndexRemapper<'tcx> {
+ fn cx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+ if !ty.has_param() {
+ return ty;
+ }
+
+ if let ty::Param(param) = ty.kind()
+ && let Some(index) = self.remap_table.get(¶m.index)
+ {
+ return Ty::new_param(self.tcx, *index, param.name);
+ }
+ ty.super_fold_with(self)
+ }
+
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ if let ty::ReEarlyParam(param) = r.kind()
+ && let Some(index) = self.remap_table.get(¶m.index).copied()
+ {
+ return ty::Region::new_early_param(
+ self.tcx,
+ ty::EarlyParamRegion { index, name: param.name },
+ );
+ }
+ r
+ }
+
+ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ if let ty::ConstKind::Param(param) = ct.kind()
+ && let Some(idx) = self.remap_table.get(¶m.index)
+ {
+ let param = ty::ParamConst::new(*idx, param.name);
+ return ty::Const::new_param(self.tcx, param);
+ }
+ ct.super_fold_with(self)
+ }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum FnKind {
+ Free,
+ AssocInherentImpl,
+ AssocTrait,
+ AssocTraitImpl,
+}
+
+fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind {
+ debug_assert_matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
+
+ let parent = tcx.parent(def_id);
+ match tcx.def_kind(parent) {
+ DefKind::Trait => FnKind::AssocTrait,
+ DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl,
+ DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl,
+ _ => FnKind::Free,
+ }
+}
+
+fn create_generic_args<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+ sig_id: DefId,
+) -> ty::GenericArgsRef<'tcx> {
+ let caller_generics = tcx.generics_of(def_id);
+ let callee_generics = tcx.generics_of(sig_id);
+
+ let caller_kind = fn_kind(tcx, def_id.into());
+ let callee_kind = fn_kind(tcx, sig_id);
+ // FIXME(fn_delegation): Support generics on associated delegation items.
+ // Error will be reported in `check_constraints`.
+ match (caller_kind, callee_kind) {
+ (FnKind::Free, _) => {
+ // Lifetime parameters must be declared before type and const parameters.
+ // Therefore, When delegating from a free function to a associated function,
+ // generic parameters need to be reordered:
+ //
+ // trait Trait<'a, A> {
+ // fn foo<'b, B>(...) {...}
+ // }
+ //
+ // reuse Trait::foo;
+ // desugaring:
+ // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) {
+ // Trait::foo(...)
+ // }
+ let mut remap_table = RemapTable::default();
+ for caller_param in &caller_generics.own_params {
+ let callee_index =
+ callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap();
+ remap_table.insert(callee_index, caller_param.index);
+ }
+ let mut folder = ParamIndexRemapper { tcx, remap_table };
+ ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder)
+ }
+ // FIXME(fn_delegation): Only `Self` param supported here.
+ (FnKind::AssocTraitImpl, FnKind::AssocTrait)
+ | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => {
+ let parent = tcx.parent(def_id.into());
+ let self_ty = tcx.type_of(parent).instantiate_identity();
+ let generic_self_ty = ty::GenericArg::from(self_ty);
+ tcx.mk_args_from_iter(std::iter::once(generic_self_ty))
+ }
+ _ => ty::GenericArgs::identity_for_item(tcx, sig_id),
+ }
+}
+
+pub(crate) fn inherit_generics_for_delegation_item<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+ sig_id: DefId,
+) -> Option<ty::Generics> {
+ // FIXME(fn_delegation): Support generics on associated delegation items.
+ // Error will be reported in `check_constraints`.
+ if fn_kind(tcx, def_id.into()) != FnKind::Free {
+ return None;
+ }
+
+ let mut own_params = vec![];
+
+ let callee_generics = tcx.generics_of(sig_id);
+ if let Some(parent_sig_id) = callee_generics.parent {
+ let parent_sig_generics = tcx.generics_of(parent_sig_id);
+ own_params.append(&mut parent_sig_generics.own_params.clone());
+ }
+ own_params.append(&mut callee_generics.own_params.clone());
+
+ // Lifetimes go first.
+ own_params.sort_by_key(|key| key.kind.is_ty_or_const());
+
+ for (idx, param) in own_params.iter_mut().enumerate() {
+ param.index = idx as u32;
+ // Default parameters are not inherited: they are not allowed
+ // in fn's.
+ if let ty::GenericParamDefKind::Type { has_default, .. }
+ | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind
+ {
+ *has_default = false;
+ }
+ }
+
+ let param_def_id_to_index =
+ own_params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ Some(ty::Generics {
+ parent: None,
+ parent_count: 0,
+ own_params,
+ param_def_id_to_index,
+ has_self: false,
+ has_late_bound_regions: callee_generics.has_late_bound_regions,
+ host_effect_index: callee_generics.host_effect_index,
+ })
+}
+
+pub(crate) fn inherit_predicates_for_delegation_item<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+ sig_id: DefId,
+) -> Option<ty::GenericPredicates<'tcx>> {
+ // FIXME(fn_delegation): Support generics on associated delegation items.
+ // Error will be reported in `check_constraints`.
+ if fn_kind(tcx, def_id.into()) != FnKind::Free {
+ return None;
+ }
+
+ let callee_predicates = tcx.predicates_of(sig_id);
+ let args = create_generic_args(tcx, def_id, sig_id);
+
+ let mut preds = vec![];
+ if let Some(parent_id) = callee_predicates.parent {
+ preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args));
+ }
+ preds.extend(callee_predicates.instantiate_own(tcx, args));
+
+ Some(ty::GenericPredicates {
+ parent: None,
+ predicates: tcx.arena.alloc_from_iter(preds),
+ effects_min_tys: ty::List::empty(),
+ })
+}
+
+fn check_constraints<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+ sig_id: DefId,
+) -> Result<(), ErrorGuaranteed> {
+ let mut ret = Ok(());
+
+ let mut emit = |descr| {
+ ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation {
+ span: tcx.def_span(def_id),
+ descr,
+ callee_span: tcx.def_span(sig_id),
+ }));
+ };
+
+ if tcx.has_host_param(sig_id) {
+ emit("delegation to a function with effect parameter is not supported yet");
+ }
+
+ if let Some(local_sig_id) = sig_id.as_local()
+ && tcx.hir().opt_delegation_sig_id(local_sig_id).is_some()
+ {
+ emit("recursive delegation is not supported yet");
+ }
+
+ if fn_kind(tcx, def_id.into()) != FnKind::Free {
+ let sig_generics = tcx.generics_of(sig_id);
+ let parent = tcx.parent(def_id.into());
+ let parent_generics = tcx.generics_of(parent);
+
+ let parent_has_self = parent_generics.has_self as usize;
+ let sig_has_self = sig_generics.has_self as usize;
+
+ if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self {
+ emit("early bound generics are not supported for associated delegation items");
+ }
+ }
+
+ ret
+}
+
+pub(crate) fn inherit_sig_for_delegation_item<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+) -> &'tcx [Ty<'tcx>] {
+ let sig_id = tcx.hir().opt_delegation_sig_id(def_id).unwrap();
+ let caller_sig = tcx.fn_sig(sig_id);
+ if let Err(err) = check_constraints(tcx, def_id, sig_id) {
+ let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1;
+ let err_type = Ty::new_error(tcx, err);
+ return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type));
+ }
+ let args = create_generic_args(tcx, def_id, sig_id);
+
+ // Bound vars are also inherited from `sig_id`.
+ // They will be rebound later in `lower_fn_ty`.
+ let sig = caller_sig.instantiate(tcx, args).skip_binder();
+ let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output()));
+ tcx.arena.alloc_from_iter(sig_iter)
+}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index c364a56..7034735 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1,12 +1,15 @@
//! Errors emitted by `rustc_hir_analysis`.
-use crate::fluent_generated as fluent;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
+ Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan,
};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
-use rustc_span::{symbol::Ident, Span, Symbol};
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
+
+use crate::fluent_generated as fluent;
mod pattern_types;
pub use pattern_types::*;
pub mod wrong_number_of_generic_args;
@@ -1572,7 +1575,7 @@ pub struct RefOfMutStatic<'a> {
#[derive(Diagnostic)]
#[diag(hir_analysis_not_supported_delegation)]
-pub struct NotSupportedDelegation<'a> {
+pub struct UnsupportedDelegation<'a> {
#[primary_span]
pub span: Span,
pub descr: &'a str,
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index db91a6a..8ecf53b 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -1,11 +1,10 @@
-use rustc_errors::{
- codes::*, pluralize, Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan,
-};
+use std::iter;
+
+use rustc_errors::codes::*;
+use rustc_errors::{pluralize, Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan};
use rustc_hir as hir;
use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
use rustc_span::def_id::DefId;
-use std::iter;
-
use GenericArgsInfo::*;
/// Handles the `wrong number of type / lifetime / ... arguments` family of error messages.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 30c04aa..7f4c75d 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -1,7 +1,8 @@
use std::ops::ControlFlow;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::codes::*;
+use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -15,8 +16,9 @@
use crate::bounds::Bounds;
use crate::errors;
-use crate::hir_ty_lowering::HirTyLowerer;
-use crate::hir_ty_lowering::{AssocItemQSelf, OnlySelfBounds, PredicateFilter, RegionInferReason};
+use crate::hir_ty_lowering::{
+ AssocItemQSelf, HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason,
+};
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Add a `Sized` bound to the `bounds` if appropriate.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 20f06d7..d77cbe3 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -1,15 +1,9 @@
-use crate::errors::{
- self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
- ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
-};
-use crate::fluent_generated as fluent;
-use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::unord::UnordMap;
-use rustc_errors::MultiSpan;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed,
+ pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@@ -17,21 +11,26 @@
use rustc_middle::bug;
use rustc_middle::query::Key;
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
-use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, suggest_constraining_type_param};
-use rustc_middle::ty::{AdtDef, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{Binder, TraitRef};
+use rustc_middle::ty::{
+ self, suggest_constraining_type_param, AdtDef, Binder, GenericParamDefKind, TraitRef, Ty,
+ TyCtxt, TypeVisitableExt,
+};
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::BytePos;
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{BytePos, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::traits::report_object_safety_error;
-use rustc_trait_selection::traits::FulfillmentError;
use rustc_trait_selection::traits::{
- object_safety_violations_for_assoc_item, TraitAliasExpansionInfo,
+ object_safety_violations_for_assoc_item, FulfillmentError, TraitAliasExpansionInfo,
};
+use crate::errors::{
+ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
+ ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
+};
+use crate::fluent_generated as fluent;
+use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
+
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
/// the type parameter's name as a placeholder.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index abe2cff..a59e9aa 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -1,13 +1,6 @@
-use super::{HirTyLowerer, IsMethodCall};
-use crate::errors::wrong_number_of_generic_args::{GenericArgsInfo, WrongNumberOfGenericArgs};
-use crate::hir_ty_lowering::{
- errors::prohibit_assoc_item_constraint, ExplicitLateBound, GenericArgCountMismatch,
- GenericArgCountResult, GenericArgPosition, GenericArgsLowerer,
-};
use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{
- codes::*, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
-};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
@@ -19,6 +12,14 @@
use rustc_span::symbol::{kw, sym};
use smallvec::SmallVec;
+use super::{HirTyLowerer, IsMethodCall};
+use crate::errors::wrong_number_of_generic_args::{GenericArgsInfo, WrongNumberOfGenericArgs};
+use crate::hir_ty_lowering::errors::prohibit_assoc_item_constraint;
+use crate::hir_ty_lowering::{
+ ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
+ GenericArgsLowerer,
+};
+
/// Report an error that a generic argument did not match the generic parameter that was
/// expected.
fn generic_arg_mismatch_err(
@@ -252,32 +253,6 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
match (args_iter.peek(), params.peek()) {
(Some(&arg), Some(¶m)) => {
match (arg, ¶m.kind, arg_count.explicit_late_bound) {
- (
- GenericArg::Const(hir::ConstArg {
- is_desugared_from_effects: true,
- ..
- }),
- GenericParamDefKind::Const { is_host_effect: false, .. }
- | GenericParamDefKind::Type { .. }
- | GenericParamDefKind::Lifetime,
- _,
- ) => {
- // FIXME(effects): this should be removed
- // SPECIAL CASE FOR DESUGARED EFFECT PARAMS
- // This comes from the following example:
- //
- // ```
- // #[const_trait]
- // pub trait PartialEq<Rhs: ?Sized = Self> {}
- // impl const PartialEq for () {}
- // ```
- //
- // Since this is a const impl, we need to insert a host arg at the end of
- // `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
- // To work around this, we infer all arguments until we reach the host param.
- args.push(ctx.inferred_kind(&args, param, infer_args));
- params.next();
- }
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
| (
GenericArg::Type(_) | GenericArg::Infer(_),
@@ -551,21 +526,34 @@ pub(crate) fn check_generic_arg_count(
synth_provided,
}
} else {
- let num_missing_args = expected_max - provided;
+ // Check if associated type bounds are incorrectly written in impl block header like:
+ // ```
+ // trait Foo<T> {}
+ // impl Foo<T: Default> for u8 {}
+ // ```
+ let parent_is_impl_block = cx
+ .tcx()
+ .hir()
+ .parent_owner_iter(seg.hir_id)
+ .next()
+ .is_some_and(|(_, owner_node)| owner_node.is_impl_block());
+ if parent_is_impl_block {
+ let constraint_names: Vec<_> =
+ gen_args.constraints.iter().map(|b| b.ident.name).collect();
+ let param_names: Vec<_> = gen_params
+ .own_params
+ .iter()
+ .filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
+ .map(|param| param.name)
+ .collect();
+ if constraint_names == param_names {
+ // We set this to true and delay emitting `WrongNumberOfGenericArgs`
+ // to provide a succinct error for cases like issue #113073
+ all_params_are_binded = true;
+ };
+ }
- let constraint_names: Vec<_> =
- gen_args.constraints.iter().map(|b| b.ident.name).collect();
- let param_names: Vec<_> = gen_params
- .own_params
- .iter()
- .filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
- .map(|param| param.name)
- .collect();
- if constraint_names == param_names {
- // We set this to true and delay emitting `WrongNumberOfGenericArgs`
- // to provide a succinct error for cases like issue #113073
- all_params_are_binded = true;
- };
+ let num_missing_args = expected_max - provided;
GenericArgsInfo::MissingTypesOrConsts {
num_missing_args,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index e7aad0a..6aff518 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -1,8 +1,10 @@
use rustc_ast::TraitObjectSyntax;
-use rustc_errors::{codes::*, Diag, EmissionGuarantee, StashKey};
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, EmissionGuarantee, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
+use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS;
+use rustc_lint_defs::Applicability;
use rustc_span::Span;
use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index ce29864..d865357 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -20,17 +20,13 @@
mod lint;
mod object_safety;
-use crate::bounds::Bounds;
-use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
-use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
-use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
-use crate::middle::resolve_bound_vars as rbv;
-use crate::require_c_abi_if_c_variadic;
+use std::slice;
+
use rustc_ast::TraitObjectSyntax;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, struct_span_code_err, Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed,
- FatalError,
+ struct_span_code_err, Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError,
};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -55,7 +51,12 @@
use rustc_trait_selection::traits::wf::object_region_bounds;
use rustc_trait_selection::traits::{self, ObligationCtxt};
-use std::slice;
+use crate::bounds::Bounds;
+use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
+use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
+use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
+use crate::middle::resolve_bound_vars as rbv;
+use crate::require_c_abi_if_c_variadic;
/// A path segment that is semantically allowed to have generic arguments.
#[derive(Debug)]
@@ -2006,93 +2007,11 @@ pub fn lower_ty_in_path(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
self.lower_ty_common(hir_ty, false, true)
}
- fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool {
- let mut error_occured = false;
- let sig_span = self.tcx().def_span(sig_id);
- let mut try_emit = |descr| {
- if emit {
- self.dcx().emit_err(crate::errors::NotSupportedDelegation {
- span,
- descr,
- callee_span: sig_span,
- });
- }
- error_occured = true;
- };
-
- if let Some(node) = self.tcx().hir().get_if_local(sig_id)
- && let Some(decl) = node.fn_decl()
- && let hir::FnRetTy::Return(ty) = decl.output
- && let hir::TyKind::InferDelegation(_, _) = ty.kind
- {
- try_emit("recursive delegation");
- }
-
- let sig_generics = self.tcx().generics_of(sig_id);
- let parent = self.tcx().local_parent(self.item_def_id());
- let parent_generics = self.tcx().generics_of(parent);
-
- let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize;
- let sig_has_self = sig_generics.has_self as usize;
-
- if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait {
- try_emit("delegation with early bound generics");
- }
-
- // There is no way to instantiate `Self` param for caller if
- // 1. callee is a trait method
- // 2. delegation item isn't an associative item
- if let DefKind::AssocFn = self.tcx().def_kind(sig_id)
- && let DefKind::Fn = self.tcx().def_kind(self.item_def_id())
- && self.tcx().associated_item(sig_id).container
- == ty::AssocItemContainer::TraitContainer
- {
- try_emit("delegation to a trait method from a free function");
- }
-
- error_occured
- }
-
- fn lower_delegation_ty(
- &self,
- sig_id: DefId,
- idx: hir::InferDelegationKind,
- span: Span,
- ) -> Ty<'tcx> {
- if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output)
- {
- let e = self.dcx().span_delayed_bug(span, "not supported delegation case");
- return Ty::new_error(self.tcx(), e);
- };
- let sig = self.tcx().fn_sig(sig_id);
- let sig_generics = self.tcx().generics_of(sig_id);
-
- let parent = self.tcx().local_parent(self.item_def_id());
- let parent_def_kind = self.tcx().def_kind(parent);
-
- let sig = if let DefKind::Impl { .. } = parent_def_kind
- && sig_generics.has_self
- {
- // Generic params can't be here except the trait self type.
- // They are not supported yet.
- assert_eq!(sig_generics.count(), 1);
- assert_eq!(self.tcx().generics_of(parent).count(), 0);
-
- let self_ty = self.tcx().type_of(parent).instantiate_identity();
- let generic_self_ty = ty::GenericArg::from(self_ty);
- let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty));
- sig.instantiate(self.tcx(), args)
- } else {
- sig.instantiate_identity()
- };
-
- // Bound vars are also inherited from `sig_id`.
- // They will be rebound later in `lower_fn_ty`.
- let sig = sig.skip_binder();
-
+ fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
+ let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
match idx {
- hir::InferDelegationKind::Input(id) => sig.inputs()[id],
- hir::InferDelegationKind::Output => sig.output(),
+ hir::InferDelegationKind::Input(idx) => delegation_sig[idx],
+ hir::InferDelegationKind::Output => *delegation_sig.last().unwrap(),
}
}
@@ -2109,9 +2028,7 @@ fn lower_ty_common(&self, hir_ty: &hir::Ty<'tcx>, borrowed: bool, in_path: bool)
let tcx = self.tcx();
let result_ty = match &hir_ty.kind {
- hir::TyKind::InferDelegation(sig_id, idx) => {
- self.lower_delegation_ty(*sig_id, *idx, hir_ty.span)
- }
+ hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx),
hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)),
hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl),
hir::TyKind::Ref(region, mt) => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
index b3c7a1f..31d1750 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs
@@ -1,24 +1,25 @@
-use crate::bounds::Bounds;
-use crate::hir_ty_lowering::{
- GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds, RegionInferReason,
-};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::codes::*;
+use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
use rustc_middle::span_bug;
use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable};
-use rustc_middle::ty::{DynKind, Upcast};
+use rustc_middle::ty::{
+ self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, Upcast,
+};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::traits::report_object_safety_error;
use rustc_trait_selection::traits::{self, hir_ty_lowering_object_safety_violations};
-
use smallvec::{smallvec, SmallVec};
use super::HirTyLowerer;
+use crate::bounds::Bounds;
+use crate::hir_ty_lowering::{
+ GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds, RegionInferReason,
+};
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Lower a trait object type from the HIR to our internal notion of a type.
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 13993a1..7d2cabd 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -1,4 +1,3 @@
-use crate::collect::ItemCtxt;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{ForeignItem, ForeignItemKind};
@@ -10,6 +9,8 @@
use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt};
+use crate::collect::ItemCtxt;
+
pub fn provide(providers: &mut Providers) {
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
}
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index f0fcbd5..ab441ed 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -8,9 +8,9 @@
//! specialization errors. These things can (and probably should) be
//! fixed, but for the moment it's easier to do these checks early.
-use crate::{constrained_generic_params as cgp, errors::UnconstrainedGenericParameter};
-use min_specialization::check_min_specialization;
+use std::assert_matches::debug_assert_matches;
+use min_specialization::check_min_specialization;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::codes::*;
use rustc_hir::def::DefKind;
@@ -18,6 +18,9 @@
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::ErrorGuaranteed;
+use crate::constrained_generic_params as cgp;
+use crate::errors::UnconstrainedGenericParameter;
+
mod min_specialization;
/// Checks that all the type/lifetime parameters on an impl also
@@ -53,7 +56,7 @@
pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
let min_specialization = tcx.features().min_specialization;
let mut res = Ok(());
- debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }));
+ debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. });
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
if min_specialization {
res = res.and(check_min_specialization(tcx, impl_def_id));
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 2e5f99b..f44a78b 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -65,9 +65,6 @@
//! cause use after frees with purely safe code in the same way as specializing
//! on traits with methods can.
-use crate::errors::GenericArgsOnOverriddenImpl;
-use crate::{constrained_generic_params as cgp, errors};
-
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -75,13 +72,15 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
-use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{GenericArg, GenericArgs, GenericArgsRef};
+use rustc_middle::ty::{self, GenericArg, GenericArgs, GenericArgsRef, TyCtxt, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, translate_args_with_cause, wf, ObligationCtxt};
+use crate::errors::GenericArgsOnOverriddenImpl;
+use crate::{constrained_generic_params as cgp, errors};
+
pub(super) fn check_min_specialization(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 89b981a..291d57f 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -62,6 +62,7 @@
#![allow(rustc::untranslatable_diagnostic)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
+#![feature(assert_matches)]
#![feature(control_flow_enum)]
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
@@ -83,6 +84,7 @@
mod bounds;
mod check_unused;
mod coherence;
+mod delegation;
pub mod hir_ty_lowering;
// FIXME: This module shouldn't be public.
pub mod collect;
@@ -100,7 +102,8 @@
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::parse::feature_err;
-use rustc_span::{symbol::sym, Span};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
@@ -145,6 +148,10 @@ pub fn provide(providers: &mut Providers) {
variance::provide(providers);
outlives::provide(providers);
hir_wf_check::provide(providers);
+ *providers = Providers {
+ inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
+ ..*providers
+ };
}
pub fn check_crate(tcx: TyCtxt<'_>) {
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index d953736..454c20d 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -1,8 +1,7 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
+use rustc_middle::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt};
use rustc_span::Span;
use super::explicit::ExplicitPredicatesMap;
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index 1f74ebf..cb61ef7 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -1,8 +1,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
-use rustc_middle::ty::GenericArgKind;
-use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt, Upcast};
+use rustc_middle::ty::{self, CratePredicatesMap, GenericArgKind, TyCtxt, Upcast};
use rustc_span::Span;
pub(crate) mod dump;
diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 08015c2..a1eccc9 100644
--- a/compiler/rustc_hir_analysis/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -1,6 +1,5 @@
use rustc_data_structures::fx::FxIndexMap;
-use rustc_middle::ty::{self, Region, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
+use rustc_middle::ty::{self, GenericArg, GenericArgKind, Region, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
use rustc_type_ir::outlives::{push_outlives_components, Component};
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 0c436e2..92baa41 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -6,8 +6,7 @@
use hir::def_id::{DefId, LocalDefId};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
+use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use super::terms::VarianceTerm::*;
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 29f96e2..8a4114c 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -9,8 +9,9 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
-use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{
+ self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
+};
/// Defines the `TermsContext` basically houses an arena where we can
/// allocate terms.
diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
index 275df24..36bff60 100644
--- a/compiler/rustc_hir_analysis/src/variance/terms.rs
+++ b/compiler/rustc_hir_analysis/src/variance/terms.rs
@@ -9,11 +9,12 @@
// `InferredIndex` is a newtype'd int representing the index of such
// a variable.
+use std::fmt;
+
use rustc_arena::DroplessArena;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
use rustc_middle::ty::{self, TyCtxt};
-use std::fmt;
use self::VarianceTerm::*;
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index e25f43e..089cee2 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -5,12 +5,13 @@
#![recursion_limit = "256"]
// tidy-alphabetical-end
-use rustc_ast as ast;
+use std::cell::Cell;
+use std::vec;
+
use rustc_ast::util::parser::{self, AssocOp, Fixity};
use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
use rustc_ast_pretty::pp::{self, Breaks};
use rustc_ast_pretty::pprust::{Comments, PrintState};
-use rustc_hir as hir;
use rustc_hir::{
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
@@ -20,9 +21,7 @@
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::FileName;
use rustc_target::spec::abi::Abi;
-
-use std::cell::Cell;
-use std::vec;
+use {rustc_ast as ast, rustc_hir as hir};
pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: HirId) -> String {
to_string(&map, |s| s.print_node(map.hir_node(hir_id)))
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 4e2104f..bc0ed4a 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -1,5 +1,3 @@
-use crate::coercion::{AsCoercionSite, CoerceMany};
-use crate::{Diverges, Expectation, FnCtxt, Needs};
use rustc_errors::{Applicability, Diag};
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::LocalDefId;
@@ -11,6 +9,9 @@
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
};
+use crate::coercion::{AsCoercionSite, CoerceMany};
+use crate::{Diverges, Expectation, FnCtxt, Needs};
+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug", ret)]
pub fn check_match(
diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 5db7159..69c4889 100644
--- a/compiler/rustc_hir_typeck/src/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
@@ -1,7 +1,6 @@
//! Some helper functions for `AutoDeref`.
-use super::method::MethodCallee;
-use super::{FnCtxt, PlaceOp};
+use std::iter;
use itertools::Itertools;
use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind};
@@ -10,7 +9,8 @@
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
-use std::iter;
+use super::method::MethodCallee;
+use super::{FnCtxt, PlaceOp};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 0d2a55a..07f64ea 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -1,24 +1,17 @@
-use super::method::probe::ProbeScope;
-use super::method::MethodCallee;
-use super::{Expectation, FnCtxt, TupleArgumentsFlag};
+use std::{iter, slice};
-use crate::errors;
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_hir_analysis::autoderef::Autoderef;
-use rustc_infer::traits::ObligationCauseCode;
-use rustc_infer::{
- infer,
- traits::{self, Obligation, ObligationCause},
-};
+use rustc_infer::infer;
+use rustc_infer::traits::{self, Obligation, ObligationCause, ObligationCauseCode};
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident};
@@ -28,7 +21,10 @@
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use std::{iter, slice};
+use super::method::probe::ProbeScope;
+use super::method::MethodCallee;
+use super::{Expectation, FnCtxt, TupleArgumentsFlag};
+use crate::errors;
/// Checks that it is legal to call methods of the trait corresponding
/// to `trait_id` (this only cares about the trait, not the specific
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 6522972..7cd9716 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -28,12 +28,9 @@
//! expression, `e as U2` is not necessarily so (in fact it will only be valid if
//! `U1` coerces to `U2`).
-use super::FnCtxt;
-
-use crate::errors;
-use crate::type_error_struct;
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{codes::*, Applicability, Diag, ErrorGuaranteed};
+use rustc_errors::codes::*;
+use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
use rustc_hir::{self as hir, ExprKind};
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::bug;
@@ -41,15 +38,16 @@
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::cast::{CastKind, CastTy};
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitableExt, VariantDef};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef};
use rustc_session::lint;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::sym;
-use rustc_span::Span;
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt;
+use super::FnCtxt;
+use crate::{errors, type_error_struct};
+
/// Reifies a cast check to be checked once we have full type information for
/// a function context.
#[derive(Debug)]
@@ -99,6 +97,8 @@ fn pointer_kind(
return Ok(Some(PointerKind::Thin));
}
+ let t = self.try_structurally_resolve_type(span, t);
+
Ok(match *t.kind() {
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty)),
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 843d9e3..89df464 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -1,8 +1,5 @@
use std::cell::RefCell;
-use crate::coercion::CoerceMany;
-use crate::gather_locals::GatherLocalsVisitor;
-use crate::{CoroutineTypes, Diverges, FnCtxt};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::intravisit::Visitor;
@@ -16,6 +13,10 @@
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
+use crate::coercion::CoerceMany;
+use crate::gather_locals::GatherLocalsVisitor;
+use crate::{CoroutineTypes, Diverges, FnCtxt};
+
/// Helper used for fns and closures. Does the grungy work of checking a function
/// body and returns the function context used for that purpose, since in the case of a fn item
/// there is still a bit more to do.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 7985497..a7953ac 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -1,27 +1,26 @@
//! Code for type-checking closure expressions.
-use super::{check_fn, CoroutineTypes, Expectation, FnCtxt};
+use std::iter;
+use std::ops::ControlFlow;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
-use rustc_infer::infer::{InferOk, InferResult};
+use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult};
use rustc_infer::traits::ObligationCauseCode;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::span_bug;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::{self, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::error_reporting::traits::ArgKind;
use rustc_trait_selection::traits;
use rustc_type_ir::ClosureKind;
-use std::iter;
-use std::ops::ControlFlow;
+
+use super::{check_fn, CoroutineTypes, Expectation, FnCtxt};
/// What signature do we *expect* the closure to have from context?
#[derive(Debug, Clone, TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 1bfe973..fcd3798 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -35,16 +35,18 @@
//! // and are then unable to coerce `&7i32` to `&mut i32`.
//! ```
-use crate::errors::SuggestBoxingForReturnImplTrait;
-use crate::FnCtxt;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
+use std::ops::Deref;
+
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
use rustc_infer::infer::relate::RelateResult;
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
-use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
-use rustc_infer::traits::{Obligation, PredicateObligation};
+use rustc_infer::traits::{
+ IfExpressionCause, MatchExpressionArmCause, Obligation, PredicateObligation,
+};
use rustc_middle::lint::in_external_macro;
use rustc_middle::span_bug;
use rustc_middle::traits::BuiltinImplSource;
@@ -63,9 +65,10 @@
use rustc_trait_selection::traits::{
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
};
-
use smallvec::{smallvec, SmallVec};
-use std::ops::Deref;
+
+use crate::errors::SuggestBoxingForReturnImplTrait;
+use crate::FnCtxt;
struct Coerce<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 4f1c2fd..0a9fa5c 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1,6 +1,4 @@
-use crate::FnCtxt;
-use rustc_errors::MultiSpan;
-use rustc_errors::{Applicability, Diag};
+use rustc_errors::{Applicability, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::intravisit::Visitor;
@@ -17,6 +15,7 @@
use rustc_trait_selection::traits::ObligationCause;
use super::method::probe;
+use crate::FnCtxt;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn emit_type_mismatch_suggestions(
diff --git a/compiler/rustc_hir_typeck/src/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs
index 0b559a0..aa30fb0 100644
--- a/compiler/rustc_hir_typeck/src/diverges.rs
+++ b/compiler/rustc_hir_typeck/src/diverges.rs
@@ -1,6 +1,7 @@
-use rustc_span::{Span, DUMMY_SP};
use std::{cmp, ops};
+use rustc_span::{Span, DUMMY_SP};
+
/// Tracks whether executing a node may exit normally (versus
/// return/break/panic, which "diverge", leaving dead code in their
/// wake). Tracked semi-automatically (through type variables marked
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 9a38d6d..f802b8c 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -2,18 +2,18 @@
use std::borrow::Cow;
-use crate::fluent_generated as fluent;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg,
- MultiSpan, SubdiagMessageOp, Subdiagnostic,
+ Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg, MultiSpan,
+ SubdiagMessageOp, Subdiagnostic,
};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, Ty};
-use rustc_span::{
- edition::{Edition, LATEST_STABLE_EDITION},
- symbol::Ident,
- Span, Symbol,
-};
+use rustc_span::edition::{Edition, LATEST_STABLE_EDITION};
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
+
+use crate::fluent_generated as fluent;
#[derive(Diagnostic)]
#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)]
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 91deae4..76ae41d 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -70,7 +70,8 @@ pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<
/// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
/// for examples of where this comes up,.
pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
- match fcx.tcx.struct_tail_without_normalization(ty).kind() {
+ // FIXME: This is not right, even in the old solver...
+ match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}).kind() {
ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty),
_ => ExpectHasType(ty),
}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 0d002c5..fec6efd 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2,33 +2,13 @@
//!
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.
-use crate::cast;
-use crate::coercion::CoerceMany;
-use crate::coercion::DynamicCoerceMany;
-use crate::errors::ReturnLikeStatementKind;
-use crate::errors::TypeMismatchFruTypo;
-use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
-use crate::errors::{
- FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition,
- YieldExprOutsideOfCoroutine,
-};
-use crate::fatally_break_rust;
-use crate::type_error_struct;
-use crate::CoroutineTypes;
-use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
-use crate::{
- report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs,
- TupleArgumentsFlag::DontTupleArguments,
-};
-use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::unord::UnordMap;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey,
- Subdiagnostic,
+ pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, Subdiagnostic,
};
-use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
@@ -36,14 +16,12 @@
use rustc_hir::{ExprKind, HirId, QPath};
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
use rustc_infer::infer;
-use rustc_infer::infer::DefineOpaqueTypes;
-use rustc_infer::infer::InferOk;
+use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, AdtKind, Ty, TypeVisitableExt};
+use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
@@ -54,10 +32,23 @@
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::ObligationCtxt;
-use rustc_trait_selection::traits::{self, ObligationCauseCode};
-
+use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
use smallvec::SmallVec;
+use {rustc_ast as ast, rustc_hir as hir};
+
+use crate::coercion::{CoerceMany, DynamicCoerceMany};
+use crate::errors::{
+ AddressOfTemporaryTaken, FieldMultiplySpecifiedInInitializer,
+ FunctionalRecordUpdateOnNonStruct, HelpUseLatestEdition, ReturnLikeStatementKind,
+ ReturnStmtOutsideOfFnBody, StructExprNonExhaustive, TypeMismatchFruTypo,
+ YieldExprOutsideOfCoroutine,
+};
+use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
+use crate::TupleArgumentsFlag::DontTupleArguments;
+use crate::{
+ cast, fatally_break_rust, report_unexpected_variant_res, type_error_struct, BreakableCtxt,
+ CoroutineTypes, Diverges, FnCtxt, Needs,
+};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn check_expr_has_type_or_error(
@@ -1315,6 +1306,8 @@ fn check_expr_loop(
// No way to know whether it's diverging because
// of a `break` or an outer `break` or `return`.
self.diverges.set(Diverges::Maybe);
+ } else {
+ self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
}
// If we permit break with a value, then result type is
@@ -1743,6 +1736,15 @@ fn check_expr_struct_fields(
Ty::new_error(tcx, guar)
};
+ // Check that the expected field type is WF. Otherwise, we emit no use-site error
+ // in the case of coercions for non-WF fields, which leads to incorrect error
+ // tainting. See issue #126272.
+ self.register_wf_obligation(
+ field_type.into(),
+ field.expr.span,
+ ObligationCauseCode::WellFormed(None),
+ );
+
// Make sure to give a type to the field even if there's
// an error, so we can continue type-checking.
let ty = self.check_expr_with_hint(field.expr, field_type);
@@ -2741,15 +2743,8 @@ fn ban_take_value_of_method(
} else if let ty::RawPtr(ptr_ty, _) = expr_t.kind()
&& let ty::Adt(adt_def, _) = ptr_ty.kind()
&& let ExprKind::Field(base_expr, _) = expr.kind
- && adt_def.variants().len() == 1
- && adt_def
- .variants()
- .iter()
- .next()
- .unwrap()
- .fields
- .iter()
- .any(|f| f.ident(self.tcx) == field)
+ && let [variant] = &adt_def.variants().raw
+ && variant.fields.iter().any(|f| f.ident(self.tcx) == field)
{
err.multipart_suggestion(
"to access the field, dereference first",
@@ -3347,18 +3342,6 @@ fn check_offset_of(
) -> Ty<'tcx> {
let container = self.lower_ty(container).normalized;
- if let Some(ident_2) = fields.get(1)
- && !self.tcx.features().offset_of_nested
- {
- rustc_session::parse::feature_err(
- &self.tcx.sess,
- sym::offset_of_nested,
- ident_2.span,
- "only a single ident or integer is stable as the field in offset_of",
- )
- .emit();
- }
-
let mut field_indices = Vec::with_capacity(fields.len());
let mut current_container = container;
let mut fields = fields.into_iter();
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 193dbbb..548d5a7 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -9,16 +9,15 @@
use hir::def::DefKind;
use hir::pat_util::EnumerateAndAdjustIterator as _;
use hir::Expr;
-use rustc_lint::LateContext;
-// Export these here so that Clippy can use them.
-pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
-
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{HirId, PatKind};
+use rustc_lint::LateContext;
use rustc_middle::hir::place::ProjectionKind;
+// Export these here so that Clippy can use them.
+pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{
self, adjustment, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _,
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 9f3aeac..6e1b750 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -1,10 +1,9 @@
use std::cell::OnceCell;
-use crate::{errors, FnCtxt, TypeckRootCtxt};
-use rustc_data_structures::{
- graph::{self, iterate::DepthFirstSearch, vec_graph::VecGraph},
- unord::{UnordBag, UnordMap, UnordSet},
-};
+use rustc_data_structures::graph::iterate::DepthFirstSearch;
+use rustc_data_structures::graph::vec_graph::VecGraph;
+use rustc_data_structures::graph::{self};
+use rustc_data_structures::unord::{UnordBag, UnordMap, UnordSet};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
use rustc_hir::HirId;
@@ -12,10 +11,12 @@
use rustc_middle::bug;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_session::lint;
-use rustc_span::DUMMY_SP;
-use rustc_span::{def_id::LocalDefId, Span};
+use rustc_span::def_id::LocalDefId;
+use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
+use crate::{errors, FnCtxt, TypeckRootCtxt};
+
#[derive(Copy, Clone)]
pub enum DivergingFallbackBehavior {
/// Always fallback to `()` (aka "always spontaneous decay")
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 87e8afe..b169f75 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1,8 +1,6 @@
-use crate::callee::{self, DeferredCallResolution};
-use crate::errors::{self, CtorIsPrivate};
-use crate::method::{self, MethodCallee};
-use crate::rvalue_scopes;
-use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
+use std::collections::hash_map::Entry;
+use std::slice;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey};
use rustc_hir as hir;
@@ -26,9 +24,9 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{
- self, AdtKind, CanonicalUserType, GenericParamDefKind, IsIdentity, Ty, TyCtxt, UserType,
+ self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind,
+ IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, UserType,
};
-use rustc_middle::ty::{GenericArgKind, GenericArgsRef, UserArgs, UserSelfTy};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
@@ -41,37 +39,51 @@
self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
};
-use std::collections::hash_map::Entry;
-use std::slice;
+use crate::callee::{self, DeferredCallResolution};
+use crate::errors::{self, CtorIsPrivate};
+use crate::method::{self, MethodCallee};
+use crate::{rvalue_scopes, BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Produces warning on the given node, if the current point in the
/// function is unreachable, and there hasn't been another warning.
pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) {
- // FIXME: Combine these two 'if' expressions into one once
- // let chains are implemented
- if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() {
- // If span arose from a desugaring of `if` or `while`, then it is the condition itself,
- // which diverges, that we are about to lint on. This gives suboptimal diagnostics.
- // Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
- if !span.is_desugaring(DesugaringKind::CondTemporary)
- && !span.is_desugaring(DesugaringKind::Async)
- && !orig_span.is_desugaring(DesugaringKind::Await)
- {
- self.diverges.set(Diverges::WarnedAlways);
+ let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() else {
+ return;
+ };
- debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
+ match span.desugaring_kind() {
+ // If span arose from a desugaring of `if` or `while`, then it is the condition
+ // itself, which diverges, that we are about to lint on. This gives suboptimal
+ // diagnostics. Instead, stop here so that the `if`- or `while`-expression's
+ // block is linted instead.
+ Some(DesugaringKind::CondTemporary) => return,
- let msg = format!("unreachable {kind}");
- self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
- lint.primary_message(msg.clone());
- lint.span_label(span, msg).span_label(
- orig_span,
- custom_note.unwrap_or("any code following this expression is unreachable"),
- );
- })
- }
+ // Don't lint if the result of an async block or async function is `!`.
+ // This does not affect the unreachable lints *within* the body.
+ Some(DesugaringKind::Async) => return,
+
+ // Don't lint *within* the `.await` operator, since that's all just desugaring
+ // junk. We only want to lint if there is a subsequent expression after the
+ // `.await` operator.
+ Some(DesugaringKind::Await) => return,
+
+ _ => {}
}
+
+ // Don't warn twice.
+ self.diverges.set(Diverges::WarnedAlways);
+
+ debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
+
+ let msg = format!("unreachable {kind}");
+ self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
+ lint.primary_message(msg.clone());
+ lint.span_label(span, msg).span_label(
+ orig_span,
+ custom_note.unwrap_or("any code following this expression is unreachable"),
+ );
+ })
}
/// Resolves type and const variables in `ty` if possible. Unlike the infcx
@@ -392,8 +404,17 @@ pub fn require_type_has_static_alignment(
code: traits::ObligationCauseCode<'tcx>,
) {
if !ty.references_error() {
- let tail =
- self.tcx.struct_tail_with_normalize(ty, |ty| self.normalize(span, ty), || {});
+ let tail = self.tcx.struct_tail_raw(
+ ty,
+ |ty| {
+ if self.next_trait_solver() {
+ self.try_structurally_resolve_type(span, ty)
+ } else {
+ self.normalize(span, ty)
+ }
+ },
+ || {},
+ );
// Sized types have static alignment, and so do slices.
if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) {
// Nothing else is required here.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 8e35efa..130fd13 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -1,13 +1,15 @@
-use crate::FnCtxt;
+use std::ops::ControlFlow;
+
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_span::{symbol::kw, Span};
+use rustc_span::symbol::kw;
+use rustc_span::Span;
use rustc_trait_selection::traits;
-use std::ops::ControlFlow;
+use crate::FnCtxt;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn adjust_fulfillment_error_for_expr_obligation(
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index 566d407d..7889568 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
@@ -1,7 +1,8 @@
use core::cmp::Ordering;
+use std::cmp;
+
use rustc_index::IndexVec;
use rustc_middle::ty::error::TypeError;
-use std::cmp;
rustc_index::newtype_index! {
#[orderable]
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 7c96a99..89e7227 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1,3 +1,33 @@
+use std::{iter, mem};
+
+use itertools::Itertools;
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::codes::*;
+use rustc_errors::{
+ a_or_an, display_list_with_comma_and, pluralize, Applicability, Diag, ErrorGuaranteed,
+ MultiSpan, StashKey,
+};
+use rustc_hir::def::{CtorOf, DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{ExprKind, HirId, Node, QPath};
+use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
+use rustc_hir_analysis::check::potentially_plural_count;
+use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
+use rustc_index::IndexVec;
+use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace};
+use rustc_middle::ty::adjustment::AllowTwoPhase;
+use rustc_middle::ty::visit::TypeVisitableExt;
+use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
+use rustc_session::Session;
+use rustc_span::symbol::{kw, Ident};
+use rustc_span::{sym, Span, DUMMY_SP};
+use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
+use {rustc_ast as ast, rustc_hir as hir};
+
use crate::coercion::CoerceMany;
use crate::errors::SuggestPtrNullMut;
use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
@@ -7,43 +37,12 @@
use crate::method::probe::Mode::MethodCall;
use crate::method::probe::ProbeScope::TraitsInScope;
use crate::method::MethodCallee;
+use crate::Expectation::*;
use crate::TupleArgumentsFlag::*;
-use crate::{errors, Expectation::*};
use crate::{
- struct_span_code_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy, Needs,
+ errors, struct_span_code_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy, Needs,
TupleArgumentsFlag,
};
-use itertools::Itertools;
-use rustc_ast as ast;
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{
- a_or_an, codes::*, display_list_with_comma_and, pluralize, Applicability, Diag,
- ErrorGuaranteed, MultiSpan, StashKey,
-};
-use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{ExprKind, HirId, Node, QPath};
-use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
-use rustc_hir_analysis::check::potentially_plural_count;
-use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
-use rustc_index::IndexVec;
-use rustc_infer::infer::TypeTrace;
-use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
-use rustc_middle::ty::adjustment::AllowTwoPhase;
-use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
-use rustc_middle::{bug, span_bug};
-use rustc_session::Session;
-use rustc_span::symbol::{kw, Ident};
-use rustc_span::{sym, BytePos, Span, DUMMY_SP};
-use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt};
-use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
-
-use std::iter;
-use std::mem;
#[derive(Clone, Copy, Default)]
pub enum DivergingBlockBehavior {
@@ -1141,8 +1140,11 @@ enum SuggestionText {
.get(arg_idx + 1)
.map(|&(_, sp)| sp)
.unwrap_or_else(|| {
- // Subtract one to move before `)`
- call_expr.span.with_lo(call_expr.span.hi() - BytePos(1))
+ // Try to move before `)`. Note that `)` here is not necessarily
+ // the latin right paren, it could be a Unicode-confusable that
+ // looks like a `)`, so we must not use `- BytePos(1)`
+ // manipulations here.
+ self.tcx().sess.source_map().end_point(call_expr.span)
});
// Include next comma
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
index 90dd5f7..be4db29 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs
@@ -1,12 +1,14 @@
//! A utility module to inspect currently ambiguous obligations in the current context.
-use crate::FnCtxt;
use rustc_infer::traits::{self, ObligationCause};
use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_span::Span;
-use rustc_trait_selection::solve::inspect::ProofTreeInferCtxtExt;
-use rustc_trait_selection::solve::inspect::{InspectConfig, InspectGoal, ProofTreeVisitor};
+use rustc_trait_selection::solve::inspect::{
+ InspectConfig, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor,
+};
+
+use crate::FnCtxt;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Returns a list of all obligations whose self type has been unified
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 39d73da..33f80dd 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -5,13 +5,11 @@
mod inspect_obligations;
mod suggestions;
-use rustc_errors::DiagCtxtHandle;
+use std::cell::{Cell, RefCell};
+use std::ops::Deref;
-use crate::coercion::DynamicCoerceMany;
-use crate::fallback::DivergingFallbackBehavior;
-use crate::fn_ctxt::checks::DivergingBlockBehavior;
-use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
use hir::def_id::CRATE_DEF_ID;
+use rustc_errors::DiagCtxtHandle;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
@@ -24,8 +22,10 @@
use rustc_trait_selection::error_reporting::TypeErrCtxt;
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
-use std::cell::{Cell, RefCell};
-use std::ops::Deref;
+use crate::coercion::DynamicCoerceMany;
+use crate::fallback::DivergingFallbackBehavior;
+use crate::fn_ctxt::checks::DivergingBlockBehavior;
+use crate::{CoroutineTypes, Diverges, EnclosingBreakables, TypeckRootCtxt};
/// The `FnCtxt` stores type-checking context needed to type-check bodies of
/// functions, closures, and `const`s, including performing type inference
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index fe7495d..6b4edcd 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1,20 +1,12 @@
-use super::FnCtxt;
-
-use crate::errors;
-use crate::fluent_generated as fluent;
-use crate::fn_ctxt::rustc_span::BytePos;
-use crate::hir::is_range_literal;
-use crate::method::probe;
-use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
use core::cmp::min;
use core::iter;
+
use hir::def_id::LocalDefId;
use rustc_ast::util::parser::{ExprPrecedence, PREC_UNAMBIGUOUS};
use rustc_data_structures::packed::Pu128;
use rustc_errors::{Applicability, Diag, MultiSpan};
use rustc_hir as hir;
-use rustc_hir::def::Res;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId,
@@ -26,8 +18,10 @@
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug;
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder};
-use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast};
+use rustc_middle::ty::{
+ self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TyCtxt,
+ TypeVisitableExt, Upcast,
+};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
@@ -38,6 +32,13 @@
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
+use super::FnCtxt;
+use crate::fn_ctxt::rustc_span::BytePos;
+use crate::hir::is_range_literal;
+use crate::method::probe;
+use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
+use crate::{errors, fluent_generated as fluent};
+
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(crate) fn body_fn_sig(&self) -> Option<ty::FnSig<'tcx>> {
self.typeck_results
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 13e4b62..0fd450e 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -1,13 +1,13 @@
-use crate::FnCtxt;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, PatKind};
use rustc_infer::traits::ObligationCauseCode;
-use rustc_middle::ty::Ty;
-use rustc_middle::ty::UserType;
+use rustc_middle::ty::{Ty, UserType};
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use crate::FnCtxt;
+
/// Provides context for checking patterns in declarations. More specifically this
/// allows us to infer array types if the pattern is irrefutable and allows us to infer
/// the size of the array. See issue #76342.
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 0389c06..a9c929e 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -1,5 +1,6 @@
use hir::HirId;
-use rustc_errors::{codes::*, struct_span_code_err};
+use rustc_errors::codes::*;
+use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_index::Idx;
use rustc_middle::bug;
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 2c79366..758a1ce 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -44,16 +44,9 @@
pub use coercion::can_coerce;
use fn_ctxt::FnCtxt;
-use typeck_root_ctxt::TypeckRootCtxt;
-
-use crate::check::check_fn;
-use crate::coercion::DynamicCoerceMany;
-use crate::diverges::Diverges;
-use crate::expectation::Expectation;
-use crate::fn_ctxt::LoweredTy;
-use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuaranteed};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
@@ -67,6 +60,14 @@
use rustc_session::config;
use rustc_span::def_id::LocalDefId;
use rustc_span::Span;
+use typeck_root_ctxt::TypeckRootCtxt;
+
+use crate::check::check_fn;
+use crate::coercion::DynamicCoerceMany;
+use crate::diverges::Diverges;
+use crate::expectation::Expectation;
+use crate::fn_ctxt::LoweredTy;
+use crate::gather_locals::GatherLocalsVisitor;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
@@ -264,11 +265,10 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
asm.operands.iter().find_map(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
- // Inline assembly constants must be integers.
- Some(fcx.next_int_var())
- }
- hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const }
+ if anon_const.hir_id == id =>
+ {
Some(fcx.next_ty_var(span))
}
_ => None,
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index e70431a..e0c0ada 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -1,6 +1,5 @@
-use super::{probe, MethodCallee};
+use std::ops::Deref;
-use crate::{callee, FnCtxt};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
@@ -12,17 +11,20 @@
};
use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
-use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
-use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
+use rustc_middle::ty::adjustment::{
+ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion,
+};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{
- self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, UserArgs, UserType,
+ self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, UserArgs,
+ UserType,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits;
-use std::ops::Deref;
+use super::{probe, MethodCallee};
+use crate::{callee, FnCtxt};
struct ConfirmContext<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
@@ -268,6 +270,17 @@ fn fresh_receiver_args(
probe::ObjectPick => {
let trait_def_id = pick.item.container_id(self.tcx);
+
+ // This shouldn't happen for non-region error kinds, but may occur
+ // when we have error regions. Specifically, since we canonicalize
+ // during method steps, we may successfully deref when we assemble
+ // the pick, but fail to deref when we try to extract the object
+ // type from the pick during confirmation. This is fine, we're basically
+ // already doomed by this point.
+ if self_ty.references_error() {
+ return ty::GenericArgs::extend_with_error(self.tcx, trait_def_id, &[]);
+ }
+
self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
// The object data has no entry for the Self
// Type. For the purposes of this method call, we
@@ -641,17 +654,17 @@ fn upcast(
traits::upcast_choices(self.tcx, source_trait_ref, target_trait_def_id);
// must be exactly one trait ref or we'd get an ambig error etc
- if upcast_trait_refs.len() != 1 {
+ let [upcast_trait_ref] = upcast_trait_refs.as_slice() else {
span_bug!(
self.span,
"cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
source_trait_ref,
target_trait_def_id,
upcast_trait_refs
- );
- }
+ )
+ };
- upcast_trait_refs.into_iter().next().unwrap()
+ *upcast_trait_ref
}
fn instantiate_binder_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index daf4ef5..d6110ab 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -7,9 +7,6 @@
pub mod probe;
mod suggest;
-pub use self::MethodError::*;
-
-use crate::FnCtxt;
use rustc_errors::{Applicability, Diag, SubdiagMessage};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace};
@@ -17,8 +14,9 @@
use rustc_infer::infer::{self, InferOk};
use rustc_middle::query::Providers;
use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
-use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::ty::{
+ self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt,
+};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Ident;
use rustc_span::Span;
@@ -26,6 +24,8 @@
use rustc_trait_selection::traits::{self, NormalizeExt};
use self::probe::{IsSuggestion, ProbeScope};
+pub use self::MethodError::*;
+use crate::FnCtxt;
pub fn provide(providers: &mut Providers) {
probe::provide(providers);
diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
index 3ee10f7..0a4c3dc 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs
@@ -1,20 +1,20 @@
-use crate::method::probe::{self, Pick};
-use crate::FnCtxt;
+use std::fmt::Write;
use hir::def_id::DefId;
-use hir::HirId;
-use hir::ItemKind;
+use hir::{HirId, ItemKind};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty};
-use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
+use rustc_session::lint::builtin::{RUST_2021_PRELUDE_COLLISIONS, RUST_2024_PRELUDE_COLLISIONS};
use rustc_span::symbol::kw::{Empty, Underscore};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
-use std::fmt::Write;
+
+use crate::method::probe::{self, Pick};
+use crate::FnCtxt;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(super) fn lint_edition_dependent_dot_call(
@@ -35,6 +35,21 @@ pub(super) fn lint_edition_dependent_dot_call(
let (prelude_or_array_lint, edition) = match segment.ident.name {
// `try_into` was added to the prelude in Rust 2021.
sym::try_into if !span.at_least_rust_2021() => (RUST_2021_PRELUDE_COLLISIONS, "2021"),
+ // `Future::poll` was added to the prelude in Rust 2024.
+ sym::poll
+ // We check that the self type is `Pin<&mut _>` to avoid false positives for this common name.
+ if !span.at_least_rust_2024()
+ && let ty::Adt(adt_def, args) = self_ty.kind()
+ && self.tcx.is_lang_item(adt_def.did(), hir::LangItem::Pin)
+ && let ty::Ref(_, _, ty::Mutability::Mut) =
+ args[0].as_type().unwrap().kind() =>
+ {
+ (RUST_2024_PRELUDE_COLLISIONS, "2024")
+ }
+ // `IntoFuture::into_future` was added to the prelude in Rust 2024.
+ sym::into_future if !span.at_least_rust_2024() => {
+ (RUST_2024_PRELUDE_COLLISIONS, "2024")
+ }
// `into_iter` wasn't added to the prelude,
// but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
// before Rust 2021, which results in the same problem.
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index ae34dde..28f537c 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1,58 +1,46 @@
-use super::suggest;
-use super::CandidateSource;
-use super::MethodError;
-use super::NoMatchData;
+use std::cell::{Cell, RefCell};
+use std::cmp::max;
+use std::iter;
+use std::ops::Deref;
-use crate::FnCtxt;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::HirId;
use rustc_hir_analysis::autoderef::{self, Autoderef};
-use rustc_infer::infer::canonical::OriginalQueryValues;
-use rustc_infer::infer::canonical::{Canonical, QueryResponse};
-use rustc_infer::infer::DefineOpaqueTypes;
-use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
+use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::middle::stability;
use rustc_middle::query::Providers;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::AssocItem;
-use rustc_middle::ty::AssocItemContainer;
-use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::Upcast;
-use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::ty::{
+ self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind,
+ ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast,
+};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
-use rustc_span::def_id::DefId;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::edit_distance::{
edit_distance_with_substrings, find_best_match_for_name_with_substrings,
};
-use rustc_span::symbol::sym;
-use rustc_span::{symbol::Ident, Span, Symbol, DUMMY_SP};
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy;
use rustc_trait_selection::traits::query::method_autoderef::{
- CandidateStep, MethodAutoderefStepsResult,
+ CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult,
};
use rustc_trait_selection::traits::query::CanonicalTyGoal;
-use rustc_trait_selection::traits::ObligationCtxt;
-use rustc_trait_selection::traits::{self, ObligationCause};
-use std::cell::Cell;
-use std::cell::RefCell;
-use std::cmp::max;
-use std::iter;
-use std::ops::Deref;
-
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
use smallvec::{smallvec, SmallVec};
use self::CandidateKind::*;
pub use self::PickKind::*;
+use super::{suggest, CandidateSource, MethodError, NoMatchData};
+use crate::FnCtxt;
/// Boolean flag used to indicate if this search is for a suggestion
/// or not. If true, we can allow ambiguity and so forth.
@@ -786,18 +774,23 @@ fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
// instantiation that replaces `Self` with the object type itself. Hence,
// a `&self` method will wind up with an argument type like `&dyn Trait`.
let trait_ref = principal.with_self_ty(self.tcx, self_ty);
- self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| {
- this.push_candidate(
- Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] },
- true,
- );
- });
+ self.assemble_candidates_for_bounds(
+ traits::supertraits(self.tcx, trait_ref),
+ |this, new_trait_ref, item| {
+ this.push_candidate(
+ Candidate {
+ item,
+ kind: ObjectCandidate(new_trait_ref),
+ import_ids: smallvec![],
+ },
+ true,
+ );
+ },
+ );
}
#[instrument(level = "debug", skip(self))]
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
- // FIXME: do we want to commit to this behavior for param bounds?
-
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
@@ -818,7 +811,7 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
}
});
- self.elaborate_bounds(bounds, |this, poly_trait_ref, item| {
+ self.assemble_candidates_for_bounds(bounds, |this, poly_trait_ref, item| {
this.push_candidate(
Candidate {
item,
@@ -832,15 +825,14 @@ fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
// Do a search through a list of bounds, using a callback to actually
// create the candidates.
- fn elaborate_bounds<F>(
+ fn assemble_candidates_for_bounds<F>(
&mut self,
bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
mut mk_cand: F,
) where
F: for<'b> FnMut(&mut ProbeContext<'b, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssocItem),
{
- let tcx = self.tcx;
- for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
+ for bound_trait_ref in bounds {
debug!("elaborate_bounds(bound_trait_ref={:?})", bound_trait_ref);
for item in self.impl_or_trait_item(bound_trait_ref.def_id()) {
if !self.has_applicable_self(&item) {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index da3ac2f..61287d9 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3,49 +3,45 @@
// ignore-tidy-filelength
-use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
-use crate::Expectation;
-use crate::FnCtxt;
use core::ops::ControlFlow;
+use std::borrow::Cow;
+
use hir::Expr;
use rustc_ast::ast::Mutability;
use rustc_attr::parse_confusables;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{
- codes::*, pluralize, struct_span_code_err, Applicability, Diag, MultiSpan, StashKey,
-};
+use rustc_errors::codes::*;
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, Diag, MultiSpan, StashKey};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::lang_items::LangItem;
-use rustc_hir::PathSegment;
-use rustc_hir::{self as hir, HirId};
-use rustc_hir::{ExprKind, Node, QPath};
+use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath};
use rustc_infer::infer::{self, RegionVariableOrigin};
use rustc_middle::bug;
-use rustc_middle::ty::fast_reject::DeepRejectCtxt;
-use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
+use rustc_middle::ty::fast_reject::{simplify_type, DeepRejectCtxt, TreatParams};
use rustc_middle::ty::print::{
with_crate_prefix, with_forced_trimmed_paths, PrintTraitRefExt as _,
};
-use rustc_middle::ty::IsSuggestable;
-use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::def_id::DefIdSet;
use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::{edit_distance, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span};
-use rustc_span::{Symbol, DUMMY_SP};
+use rustc_span::{
+ edit_distance, ErrorGuaranteed, ExpnKind, FileName, MacroKind, Span, Symbol, DUMMY_SP,
+};
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
supertraits, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
};
-use std::borrow::Cow;
use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
-use rustc_hir::intravisit::{self, Visitor};
+use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
+use crate::{Expectation, FnCtxt};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
@@ -325,19 +321,18 @@ pub fn report_method_error(
);
};
let suggest_for_privacy =
- |err: &mut Diag<'_>, mut msg: String, sugg: Vec<String>| {
- if sugg.len() == 1 {
- let msg = format!("\
+ |err: &mut Diag<'_>, mut msg: String, suggs: Vec<String>| {
+ if let [sugg] = suggs.as_slice() {
+ err.help(format!("\
trait `{}` provides `{item_name}` is implemented but not reachable",
- sugg[0].trim()
- );
- err.help(msg);
+ sugg.trim(),
+ ));
} else {
- msg += &format!(" but {} not reachable", pluralize!("is", sugg.len()));
+ msg += &format!(" but {} not reachable", pluralize!("is", suggs.len()));
err.span_suggestions(
span,
msg,
- sugg,
+ suggs,
Applicability::MaybeIncorrect,
);
}
@@ -2992,11 +2987,11 @@ pub(crate) fn note_unmet_impls_on_type(
}
}
if local_spans.primary_span().is_some() {
- let msg = if local_preds.len() == 1 {
+ let msg = if let [local_pred] = local_preds.as_slice() {
format!(
"an implementation of `{}` might be missing for `{}`",
- local_preds[0].trait_ref.print_trait_sugared(),
- local_preds[0].self_ty()
+ local_pred.trait_ref.print_trait_sugared(),
+ local_pred.self_ty()
)
} else {
format!(
@@ -3038,11 +3033,11 @@ pub(crate) fn note_unmet_impls_on_type(
}
}
if foreign_spans.primary_span().is_some() {
- let msg = if foreign_preds.len() == 1 {
+ let msg = if let [foreign_pred] = foreign_preds.as_slice() {
format!(
"the foreign item type `{}` doesn't implement `{}`",
- foreign_preds[0].self_ty(),
- foreign_preds[0].trait_ref.print_trait_sugared()
+ foreign_pred.self_ty(),
+ foreign_pred.trait_ref.print_trait_sugared()
)
} else {
format!(
@@ -3392,26 +3387,26 @@ fn suggest_valid_traits(
);
self.suggest_use_candidates(candidates, |accessible_sugg, inaccessible_sugg, span| {
- let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| {
+ let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, suggs: Vec<_>| {
msg += &format!(
"; perhaps you want to import {one_of}",
- one_of = if sugg.len() == 1 { "it" } else { "one of them" },
+ one_of = if suggs.len() == 1 { "it" } else { "one of them" },
);
- err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
+ err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect);
};
- let suggest_for_privacy = |err: &mut Diag<'_>, sugg: Vec<String>| {
+ let suggest_for_privacy = |err: &mut Diag<'_>, suggs: Vec<String>| {
let msg = format!(
"{this_trait_is} implemented but not reachable",
- this_trait_is = if sugg.len() == 1 {
- format!("trait `{}` which provides `{item_name}` is", sugg[0].trim())
+ this_trait_is = if let [sugg] = suggs.as_slice() {
+ format!("trait `{}` which provides `{item_name}` is", sugg.trim())
} else {
format!("the following traits which provide `{item_name}` are")
}
);
- if sugg.len() == 1 {
+ if suggs.len() == 1 {
err.help(msg);
} else {
- err.span_suggestions(span, msg, sugg, Applicability::MaybeIncorrect);
+ err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect);
}
};
if accessible_sugg.is_empty() {
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 7b58453..c54f6cf 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -1,12 +1,8 @@
//! Code related to processing overloaded binary and unary operators.
-use super::method::MethodCallee;
-use super::FnCtxt;
-use crate::Expectation;
-use rustc_ast as ast;
use rustc_data_structures::packed::Pu128;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag};
-use rustc_hir as hir;
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, Diag};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
@@ -21,6 +17,11 @@
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{FulfillmentError, ObligationCtxt};
use rustc_type_ir::TyKind::*;
+use {rustc_ast as ast, rustc_hir as hir};
+
+use super::method::MethodCallee;
+use super::FnCtxt;
+use crate::Expectation;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Checks a `a <op>= b`
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 8afc6a4..c4f74ad 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1,9 +1,11 @@
-use crate::gather_locals::DeclOrigin;
-use crate::{errors, FnCtxt, LoweredTy};
+use std::cmp;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
+
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
+ pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
};
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -12,7 +14,8 @@
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
-use rustc_session::{lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS, parse::feature_err};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
+use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::Spanned;
@@ -23,10 +26,9 @@
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
use ty::VariantDef;
-use std::cmp;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-
use super::report_unexpected_variant_res;
+use crate::gather_locals::DeclOrigin;
+use crate::{errors, FnCtxt, LoweredTy};
const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\
This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 515e1b5..ad04b6b 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -1,16 +1,18 @@
-use crate::method::MethodCallee;
-use crate::{FnCtxt, PlaceOp};
-use rustc_ast as ast;
use rustc_errors::Applicability;
-use rustc_hir as hir;
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::infer::InferOk;
use rustc_middle::span_bug;
-use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCoercion};
-use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
+use rustc_middle::ty::adjustment::{
+ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, OverloadedDeref,
+ PointerCoercion,
+};
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
+use {rustc_ast as ast, rustc_hir as hir};
+
+use crate::method::MethodCallee;
+use crate::{FnCtxt, PlaceOp};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 805f36d..f22a13d 100644
--- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
@@ -1,4 +1,3 @@
-use super::FnCtxt;
use hir::def_id::DefId;
use hir::Node;
use rustc_hir as hir;
@@ -6,6 +5,8 @@
use rustc_middle::middle::region::{RvalueCandidateType, Scope, ScopeTree};
use rustc_middle::ty::RvalueScopes;
+use super::FnCtxt;
+
/// Applied to an expression `expr` if `expr` -- or something owned or partially owned by
/// `expr` -- is going to be indirectly referenced by a variable in a let statement. In that
/// case, the "temporary lifetime" or `expr` is extended to be the block enclosing the `let`
diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
index c99e8a7..a431645 100644
--- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
+++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs
@@ -1,4 +1,5 @@
-use super::callee::DeferredCallResolution;
+use std::cell::RefCell;
+use std::ops::Deref;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir as hir;
@@ -15,8 +16,7 @@
self, FulfillmentError, PredicateObligation, TraitEngine, TraitEngineExt as _,
};
-use std::cell::RefCell;
-use std::ops::Deref;
+use super::callee::DeferredCallResolution;
/// Data shared between a "typeck root" and its nested bodies,
/// e.g. closures defined within the function. For example:
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 4663978..55f0022 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -30,9 +30,9 @@
//! then mean that all later passes would have to check for these figments
//! and report an error, and it just seems like more mess in the end.)
-use super::FnCtxt;
+use std::iter;
-use crate::expr_use_visitor as euv;
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
use rustc_errors::{Applicability, MultiSpan};
use rustc_hir as hir;
@@ -49,14 +49,12 @@
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
-use rustc_span::sym;
-use rustc_span::{BytePos, Pos, Span, Symbol};
+use rustc_span::{sym, BytePos, Pos, Span, Symbol};
+use rustc_target::abi::FIRST_VARIANT;
use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_target::abi::FIRST_VARIANT;
-
-use std::iter;
+use super::FnCtxt;
+use crate::expr_use_visitor as euv;
/// Describe the relationship between the paths of two places
/// eg:
@@ -221,7 +219,8 @@ fn analyze_closure(
// `async-await/async-closures/force-move-due-to-inferred-kind.rs`.
//
// 2. If the coroutine-closure is forced to be `FnOnce` due to the way it
- // uses its upvars, but not *all* upvars would force the closure to `FnOnce`.
+ // uses its upvars (e.g. it consumes a non-copy value), but not *all* upvars
+ // would force the closure to `FnOnce`.
// See the test: `async-await/async-closures/force-move-due-to-actually-fnonce.rs`.
//
// This would lead to an impossible to satisfy situation, since `AsyncFnOnce`
@@ -229,11 +228,6 @@ fn analyze_closure(
// we force the inner coroutine to also be `move`. This only matters for
// coroutine-closures that are `move` since otherwise they themselves will
// be borrowing from the outer environment, so there's no self-borrows occuring.
- //
- // One *important* note is that we do a call to `process_collected_capture_information`
- // to eagerly test whether the coroutine would end up `FnOnce`, but we do this
- // *before* capturing all the closure args by-value below, since that would always
- // cause the analysis to return `FnOnce`.
if let UpvarArgs::Coroutine(..) = args
&& let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) =
self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind")
@@ -248,19 +242,16 @@ fn analyze_closure(
capture_clause = hir::CaptureBy::Value { move_kw };
}
// (2.) The way that the closure uses its upvars means it's `FnOnce`.
- else if let (_, ty::ClosureKind::FnOnce, _) = self
- .process_collected_capture_information(
- capture_clause,
- &delegate.capture_information,
- )
- {
+ else if self.coroutine_body_consumes_upvars(closure_def_id, body) {
capture_clause = hir::CaptureBy::Value { move_kw };
}
}
// As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode
// to `ByRef` for the `async {}` block internal to async fns/closure. This means
- // that we would *not* be moving all of the parameters into the async block by default.
+ // that we would *not* be moving all of the parameters into the async block in all cases.
+ // For example, when one of the arguments is `Copy`, we turn a consuming use into a copy of
+ // a reference, so for `async fn x(t: i32) {}`, we'd only take a reference to `t`.
//
// We force all of these arguments to be captured by move before we do expr use analysis.
//
@@ -537,6 +528,53 @@ fn analyze_closure(
}
}
+ /// Determines whether the body of the coroutine uses its upvars in a way that
+ /// consumes (i.e. moves) the value, which would force the coroutine to `FnOnce`.
+ /// In a more detailed comment above, we care whether this happens, since if
+ /// this happens, we want to force the coroutine to move all of the upvars it
+ /// would've borrowed from the parent coroutine-closure.
+ ///
+ /// This only really makes sense to be called on the child coroutine of a
+ /// coroutine-closure.
+ fn coroutine_body_consumes_upvars(
+ &self,
+ coroutine_def_id: LocalDefId,
+ body: &'tcx hir::Body<'tcx>,
+ ) -> bool {
+ // This block contains argument capturing details. Since arguments
+ // aren't upvars, we do not care about them for determining if the
+ // coroutine body actually consumes its upvars.
+ let hir::ExprKind::Block(&hir::Block { expr: Some(body), .. }, None) = body.value.kind
+ else {
+ bug!();
+ };
+ // Specifically, we only care about the *real* body of the coroutine.
+ // We skip out into the drop-temps within the block of the body in order
+ // to skip over the args of the desugaring.
+ let hir::ExprKind::DropTemps(body) = body.kind else {
+ bug!();
+ };
+
+ let mut delegate = InferBorrowKind {
+ closure_def_id: coroutine_def_id,
+ capture_information: Default::default(),
+ fake_reads: Default::default(),
+ };
+
+ let _ = euv::ExprUseVisitor::new(
+ &FnCtxt::new(self, self.tcx.param_env(coroutine_def_id), coroutine_def_id),
+ &mut delegate,
+ )
+ .consume_expr(body);
+
+ let (_, kind, _) = self.process_collected_capture_information(
+ hir::CaptureBy::Ref,
+ &delegate.capture_information,
+ );
+
+ matches!(kind, ty::ClosureKind::FnOnce)
+ }
+
// Returns a list of `Ty`s for each upvar.
fn final_upvar_tys(&self, closure_id: LocalDefId) -> Vec<Ty<'tcx>> {
self.typeck_results
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 4ef7f37..0327a30 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -2,7 +2,8 @@
// unresolved type variables and replaces "ty_var" types with their
// generic parameters.
-use crate::FnCtxt;
+use std::mem;
+
use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::{ErrorGuaranteed, StashKey};
use rustc_hir as hir;
@@ -13,14 +14,13 @@
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::TypeSuperFoldable;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
use rustc_trait_selection::solve;
-use std::mem;
+use crate::FnCtxt;
///////////////////////////////////////////////////////////////////////////
// Entry point
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 41caa5d..b29ba59 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -33,12 +33,12 @@
//! fn baz() { foo(); }
//! ```
-use crate::errors;
-use rustc_ast as ast;
+use std::env;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write};
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::graph::implementation::{Direction, NodeIndex, INCOMING, OUTGOING};
-use rustc_graphviz as dot;
-use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::dep_graph::{
@@ -49,10 +49,10 @@
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
-use std::env;
-use std::fs::{self, File};
-use std::io::{BufWriter, Write};
use tracing::debug;
+use {rustc_ast as ast, rustc_graphviz as dot, rustc_hir as hir};
+
+use crate::errors;
#[allow(missing_docs)]
pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs
index e94a7fb..f891003 100644
--- a/compiler/rustc_incremental/src/errors.rs
+++ b/compiler/rustc_incremental/src/errors.rs
@@ -1,7 +1,9 @@
-use rustc_macros::Diagnostic;
-use rustc_span::{symbol::Ident, Span, Symbol};
use std::path::{Path, PathBuf};
+use rustc_macros::Diagnostic;
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
+
#[derive(Diagnostic)]
#[diag(incremental_unrecognized_depnode)]
pub struct UnrecognizedDepNode {
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index 76e3c06..fcdcb08 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -12,14 +12,10 @@
mod errors;
mod persist;
-pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir;
-pub use persist::finalize_session_directory;
-pub use persist::in_incr_comp_dir;
-pub use persist::in_incr_comp_dir_sess;
-pub use persist::load_query_result_cache;
-pub use persist::save_dep_graph;
-pub use persist::save_work_product_index;
-pub use persist::setup_dep_graph;
-pub use persist::LoadResult;
+pub use persist::{
+ copy_cgu_workproduct_to_incr_comp_cache_dir, finalize_session_directory, in_incr_comp_dir,
+ in_incr_comp_dir_sess, load_query_result_cache, save_dep_graph, save_work_product_index,
+ setup_dep_graph, LoadResult,
+};
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 2a0d681..1e02324 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -19,14 +19,11 @@
//! Errors are reported if we are in the suitable configuration but
//! the required condition is not met.
-use crate::errors;
use rustc_ast::{self as ast, Attribute, NestedMetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit;
-use rustc_hir::Node as HirNode;
-use rustc_hir::{ImplItemKind, ItemKind as HirItem, TraitItemKind};
+use rustc_hir::{intravisit, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind};
use rustc_middle::dep_graph::{label_strs, DepNode, DepNodeExt};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt;
@@ -35,6 +32,8 @@
use thin_vec::ThinVec;
use tracing::debug;
+use crate::errors;
+
const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
const EXCEPT: Symbol = sym::except;
const CFG: Symbol = sym::cfg;
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index 303785b..174414d 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -9,18 +9,19 @@
//! compiler versions don't change frequently for the typical user, being
//! conservative here practically has no downside.
-use crate::errors;
+use std::borrow::Cow;
+use std::io::{self, Read};
+use std::path::{Path, PathBuf};
+use std::{env, fs};
+
use rustc_data_structures::memmap::Mmap;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encoder;
use rustc_session::Session;
-use std::borrow::Cow;
-use std::env;
-use std::fs;
-use std::io::{self, Read};
-use std::path::{Path, PathBuf};
use tracing::debug;
+use crate::errors;
+
/// The first few bytes of files generated by incremental compilation.
const FILE_MAGIC: &[u8] = b"RSIC";
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 9afea3d..5f85e62 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -103,30 +103,27 @@
//! unsupported file system and emit a warning in that case. This is not yet
//! implemented.
-use crate::errors;
-use rustc_data_structures::base_n;
-use rustc_data_structures::base_n::BaseNString;
-use rustc_data_structures::base_n::ToBaseN;
-use rustc_data_structures::base_n::CASE_INSENSITIVE;
-use rustc_data_structures::flock;
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_data_structures::svh::Svh;
-use rustc_data_structures::unord::{UnordMap, UnordSet};
-use rustc_errors::ErrorGuaranteed;
-use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy};
-use rustc_middle::bug;
-use rustc_session::config::CrateType;
-use rustc_session::output::{collect_crate_types, find_crate_name};
-use rustc_session::{Session, StableCrateId};
-
use std::fs as std_fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use rand::{thread_rng, RngCore};
+use rustc_data_structures::base_n::{BaseNString, ToBaseN, CASE_INSENSITIVE};
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_data_structures::svh::Svh;
+use rustc_data_structures::unord::{UnordMap, UnordSet};
+use rustc_data_structures::{base_n, flock};
+use rustc_errors::ErrorGuaranteed;
+use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy};
+use rustc_middle::bug;
+use rustc_session::config::CrateType;
+use rustc_session::output::{collect_crate_types, find_crate_name};
+use rustc_session::{Session, StableCrateId};
use tracing::debug;
+use crate::errors;
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index af667a5..18088a1 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -1,6 +1,8 @@
//! Code to load the dep-graph from files.
-use crate::errors;
+use std::path::{Path, PathBuf};
+use std::sync::Arc;
+
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::unord::UnordMap;
use rustc_middle::dep_graph::{DepGraph, DepsType, SerializedDepGraph, WorkProductMap};
@@ -10,15 +12,13 @@
use rustc_session::config::IncrementalStateAssertion;
use rustc_session::Session;
use rustc_span::ErrorGuaranteed;
-use std::path::{Path, PathBuf};
-use std::sync::Arc;
use tracing::{debug, warn};
use super::data::*;
-use super::file_format;
use super::fs::*;
use super::save::build_dep_graph;
-use super::work_product;
+use super::{file_format, work_product};
+use crate::errors;
#[derive(Debug)]
/// Represents the result of an attempt to load incremental compilation data.
diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs
index 94c05f4..a529b1d 100644
--- a/compiler/rustc_incremental/src/persist/mod.rs
+++ b/compiler/rustc_incremental/src/persist/mod.rs
@@ -10,12 +10,7 @@
mod save;
mod work_product;
-pub use fs::finalize_session_directory;
-pub use fs::in_incr_comp_dir;
-pub use fs::in_incr_comp_dir_sess;
-pub use load::load_query_result_cache;
-pub use load::setup_dep_graph;
-pub use load::LoadResult;
-pub use save::save_dep_graph;
-pub use save::save_work_product_index;
+pub use fs::{finalize_session_directory, in_incr_comp_dir, in_incr_comp_dir_sess};
+pub use load::{load_query_result_cache, setup_dep_graph, LoadResult};
+pub use save::{save_dep_graph, save_work_product_index};
pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir;
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 3bf582b..58a03cb 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -1,5 +1,6 @@
-use crate::assert_dep_graph::assert_dep_graph;
-use crate::errors;
+use std::fs;
+use std::sync::Arc;
+
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::join;
use rustc_middle::dep_graph::{
@@ -9,15 +10,13 @@
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encodable as RustcEncodable;
use rustc_session::Session;
-use std::fs;
-use std::sync::Arc;
use tracing::debug;
use super::data::*;
-use super::dirty_clean;
-use super::file_format;
use super::fs::*;
-use super::work_product;
+use super::{dirty_clean, file_format, work_product};
+use crate::assert_dep_graph::assert_dep_graph;
+use crate::errors;
/// Saves and writes the [`DepGraph`] to the file system.
///
diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs
index e230da9..048981f 100644
--- a/compiler/rustc_incremental/src/persist/work_product.rs
+++ b/compiler/rustc_incremental/src/persist/work_product.rs
@@ -2,16 +2,18 @@
//!
//! [work products]: WorkProduct
-use crate::errors;
-use crate::persist::fs::*;
+use std::fs as std_fs;
+use std::path::Path;
+
use rustc_data_structures::unord::UnordMap;
use rustc_fs_util::link_or_copy;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
-use std::fs as std_fs;
-use std::path::Path;
use tracing::debug;
+use crate::errors;
+use crate::persist::fs::*;
+
/// Copies a CGU work product to the incremental compilation directory, so next compilation can
/// find and reuse it.
pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index e37af66..506afba 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1,21 +1,16 @@
-use std::fmt;
-use std::iter;
use std::marker::PhantomData;
-use std::mem;
use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Bound, Not, Range, RangeBounds, Shl};
use std::rc::Rc;
-use std::slice;
+use std::{fmt, iter, mem, slice};
use arrayvec::ArrayVec;
-use smallvec::{smallvec, SmallVec};
-
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_Generic, Encodable_Generic};
+use smallvec::{smallvec, SmallVec};
+use Chunk::*;
use crate::{Idx, IndexVec};
-use Chunk::*;
-
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs
index 351d62f..066aa46 100644
--- a/compiler/rustc_index/src/bit_set/tests.rs
+++ b/compiler/rustc_index/src/bit_set/tests.rs
@@ -2,6 +2,7 @@
extern crate test;
use std::hint::black_box;
+
use test::Bencher;
#[test]
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index 0c1180b..be028fe 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -1,7 +1,6 @@
use std::iter::Step;
use std::marker::PhantomData;
-use std::ops::RangeBounds;
-use std::ops::{Bound, Range};
+use std::ops::{Bound, Range, RangeBounds};
use smallvec::SmallVec;
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index b775ae1..b5e4f02 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -12,9 +12,10 @@
mod slice;
mod vec;
-pub use {idx::Idx, slice::IndexSlice, vec::IndexVec};
-
+pub use idx::Idx;
pub use rustc_index_macros::newtype_index;
+pub use slice::IndexSlice;
+pub use vec::IndexVec;
/// Type size assertion. The first argument is a type and the second argument is its expected size.
///
diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs
index 0663c72..3205ca3 100644
--- a/compiler/rustc_index/src/slice.rs
+++ b/compiler/rustc_index/src/slice.rs
@@ -1,9 +1,6 @@
-use std::{
- fmt,
- marker::PhantomData,
- ops::{Index, IndexMut},
- slice,
-};
+use std::marker::PhantomData;
+use std::ops::{Index, IndexMut};
+use std::{fmt, slice};
use crate::{Idx, IndexVec};
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 346ce94..7438c97 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -1,13 +1,11 @@
-#[cfg(feature = "nightly")]
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-
use std::borrow::{Borrow, BorrowMut};
-use std::fmt;
use std::hash::Hash;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut, RangeBounds};
-use std::slice;
-use std::vec;
+use std::{fmt, slice, vec};
+
+#[cfg(feature = "nightly")]
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use crate::{Idx, IndexSlice};
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index fc7a228..9f6a176 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -25,12 +25,11 @@
//! sometimes useful when the types of `c` and `d` are not traceable
//! things. (That system should probably be refactored.)
-use super::*;
-
-use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
use rustc_middle::bug;
use rustc_middle::ty::{Const, ImplSubject};
+use super::*;
+use crate::infer::relate::{Relate, StructurallyRelateAliases, TypeRelation};
use crate::traits::Obligation;
/// Whether we should define opaque types or just treat them opaquely.
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 1659f3d..3bcb92d 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -5,18 +5,19 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
+use rustc_data_structures::fx::FxHashMap;
+use rustc_index::Idx;
+use rustc_middle::bug;
+use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::{
+ self, BoundVar, GenericArg, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt,
+};
+use smallvec::SmallVec;
+
use crate::infer::canonical::{
Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, OriginalQueryValues,
};
use crate::infer::InferCtxt;
-use rustc_middle::bug;
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::GenericArg;
-use rustc_middle::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_index::Idx;
-use smallvec::SmallVec;
impl<'tcx> InferCtxt<'tcx> {
/// Canonicalizes a query value `V`. When we canonicalize a query,
diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
index 153de3d..c10df2e 100644
--- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs
+++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs
@@ -6,12 +6,12 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-use crate::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
-use rustc_middle::ty::GenericArgKind;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, GenericArgKind, TyCtxt};
+
+use crate::infer::canonical::{Canonical, CanonicalVarValues};
/// FIXME(-Znext-solver): This or public because it is shared with the
/// new trait solver implementation. We should deduplicate canonicalization.
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 8ad4f79..8caedcd 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -21,16 +21,15 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-use crate::infer::{InferCtxt, RegionVariableOrigin};
+pub use instantiate::CanonicalExt;
use rustc_index::IndexVec;
+pub use rustc_middle::infer::canonical::*;
use rustc_middle::infer::unify_key::EffectVarValue;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::GenericArg;
-use rustc_middle::ty::{self, List, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt};
use rustc_span::Span;
-pub use instantiate::CanonicalExt;
-pub use rustc_middle::infer::canonical::*;
+use crate::infer::{InferCtxt, RegionVariableOrigin};
mod canonicalizer;
mod instantiate;
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index d7dd6a1..85e3cfb 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -7,6 +7,17 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
+use std::fmt::Debug;
+use std::iter;
+
+use rustc_data_structures::captures::Captures;
+use rustc_index::{Idx, IndexVec};
+use rustc_middle::arena::ArenaAllocatable;
+use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::ty::fold::TypeFoldable;
+use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
+
use crate::infer::canonical::instantiate::{instantiate_value, CanonicalExt};
use crate::infer::canonical::{
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
@@ -15,19 +26,9 @@
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
use crate::traits::query::NoSolution;
-use crate::traits::{Obligation, ObligationCause, PredicateObligation};
-use crate::traits::{ScrubbedTraitError, TraitEngine};
-use rustc_data_structures::captures::Captures;
-use rustc_index::Idx;
-use rustc_index::IndexVec;
-use rustc_middle::arena::ArenaAllocatable;
-use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, BoundVar, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
-use rustc_middle::{bug, span_bug};
-use std::fmt::Debug;
-use std::iter;
+use crate::traits::{
+ Obligation, ObligationCause, PredicateObligation, ScrubbedTraitError, TraitEngine,
+};
impl<'tcx> InferCtxt<'tcx> {
/// This method is meant to be invoked as the final step of a canonical query
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index de4267f..c429411 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -31,12 +31,14 @@
//! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
//! inferencer knows "so far".
-use super::InferCtxt;
+use std::collections::hash_map::Entry;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::bug;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt};
-use std::collections::hash_map::Entry;
+
+use super::InferCtxt;
pub struct TypeFreshener<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 72944c9c..c2c0c7a 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -1,13 +1,7 @@
//! Lexical region resolution.
-use crate::infer::region_constraints::Constraint;
-use crate::infer::region_constraints::GenericKind;
-use crate::infer::region_constraints::RegionConstraintData;
-use crate::infer::region_constraints::VarInfos;
-use crate::infer::region_constraints::VerifyBound;
-use crate::infer::RegionRelations;
-use crate::infer::RegionVariableOrigin;
-use crate::infer::SubregionOrigin;
+use std::fmt;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::implementation::{
Direction, Graph, NodeIndex, INCOMING, OUTGOING,
@@ -16,15 +10,18 @@
use rustc_data_structures::unord::UnordSet;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ReBound, RePlaceholder, ReVar};
-use rustc_middle::ty::{ReEarlyParam, ReErased, ReError, ReLateParam, ReStatic};
-use rustc_middle::ty::{Region, RegionVid};
+use rustc_middle::ty::{
+ self, ReBound, ReEarlyParam, ReErased, ReError, ReLateParam, RePlaceholder, ReStatic, ReVar,
+ Region, RegionVid, Ty, TyCtxt,
+};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
-use std::fmt;
use super::outlives::test_type_match;
+use crate::infer::region_constraints::{
+ Constraint, GenericKind, RegionConstraintData, VarInfos, VerifyBound,
+};
+use crate::infer::{RegionRelations, RegionVariableOrigin, SubregionOrigin};
/// This function performs lexical region resolution given a complete
/// set of constraints and variable origins. It performs a fixed-point
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 3cee0a6..f2fc25a 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -1,55 +1,56 @@
+use std::cell::{Cell, RefCell};
+use std::fmt;
+
pub use at::DefineOpaqueTypes;
+use free_regions::RegionRelations;
pub use freshen::TypeFreshener;
+use lexical_region_resolve::LexicalRegionResolutions;
pub use lexical_region_resolve::RegionResolutionError;
-pub use relate::combine::CombineFields;
-pub use relate::combine::PredicateEmittingRelation;
+use opaque_types::OpaqueTypeStorage;
+use region_constraints::{
+ GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
+};
+pub use relate::combine::{CombineFields, PredicateEmittingRelation};
pub use relate::StructurallyRelateAliases;
-use rustc_errors::DiagCtxtHandle;
+use rustc_data_structures::captures::Captures;
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::undo_log::Rollback;
+use rustc_data_structures::unify as ut;
+use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_macros::extension;
pub use rustc_macros::{TypeFoldable, TypeVisitable};
+use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
+use rustc_middle::infer::unify_key::{
+ ConstVariableOrigin, ConstVariableValue, ConstVidKey, EffectVarValue, EffectVidKey,
+};
+use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
+use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::traits::select;
+use rustc_middle::traits::solve::{Goal, NoSolution};
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::fold::{
+ BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable,
+};
+use rustc_middle::ty::visit::TypeVisitableExt;
pub use rustc_middle::ty::IntVarValue;
+use rustc_middle::ty::{
+ self, ConstVid, EffectVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef,
+ GenericParamDefKind, InferConst, IntVid, Ty, TyCtxt, TyVid,
+};
+use rustc_middle::{bug, span_bug};
+use rustc_span::symbol::Symbol;
+use rustc_span::Span;
+use snapshot::undo_log::InferCtxtUndoLogs;
+use type_variable::TypeVariableOrigin;
pub use BoundRegionConversionTime::*;
pub use RegionVariableOrigin::*;
pub use SubregionOrigin::*;
use crate::infer::relate::RelateResult;
use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
-use free_regions::RegionRelations;
-use lexical_region_resolve::LexicalRegionResolutions;
-use opaque_types::OpaqueTypeStorage;
-use region_constraints::{GenericKind, VarInfos, VerifyBound};
-use region_constraints::{RegionConstraintCollector, RegionConstraintStorage};
-use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::undo_log::Rollback;
-use rustc_data_structures::unify as ut;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_macros::extension;
-use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
-use rustc_middle::infer::unify_key::ConstVariableOrigin;
-use rustc_middle::infer::unify_key::ConstVariableValue;
-use rustc_middle::infer::unify_key::EffectVarValue;
-use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
-use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
-use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::traits::select;
-use rustc_middle::traits::solve::{Goal, NoSolution};
-use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::fold::BoundVarReplacerDelegate;
-use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
-use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
-use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
-use rustc_middle::{bug, span_bug};
-use rustc_span::symbol::Symbol;
-use rustc_span::Span;
-use snapshot::undo_log::InferCtxtUndoLogs;
-use std::cell::{Cell, RefCell};
-use std::fmt;
-use type_variable::TypeVariableOrigin;
pub mod at;
pub mod canonical;
@@ -1317,38 +1318,36 @@ pub fn instantiate_binder_with_fresh_vars<T>(
return inner;
}
- struct ToFreshVars<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
- span: Span,
- lbrct: BoundRegionConversionTime,
- map: FxHashMap<ty::BoundVar, ty::GenericArg<'tcx>>,
+ let bound_vars = value.bound_vars();
+ let mut args = Vec::with_capacity(bound_vars.len());
+
+ for bound_var_kind in bound_vars {
+ let arg: ty::GenericArg<'_> = match bound_var_kind {
+ ty::BoundVariableKind::Ty(_) => self.next_ty_var(span).into(),
+ ty::BoundVariableKind::Region(br) => {
+ self.next_region_var(BoundRegion(span, br, lbrct)).into()
+ }
+ ty::BoundVariableKind::Const => self.next_const_var(span).into(),
+ };
+ args.push(arg);
}
- impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'_, 'tcx> {
+ struct ToFreshVars<'tcx> {
+ args: Vec<ty::GenericArg<'tcx>>,
+ }
+
+ impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> {
fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
- self.map
- .entry(br.var)
- .or_insert_with(|| {
- self.infcx
- .next_region_var(BoundRegion(self.span, br.kind, self.lbrct))
- .into()
- })
- .expect_region()
+ self.args[br.var.index()].expect_region()
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
- self.map
- .entry(bt.var)
- .or_insert_with(|| self.infcx.next_ty_var(self.span).into())
- .expect_ty()
+ self.args[bt.var.index()].expect_ty()
}
fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
- self.map
- .entry(bv)
- .or_insert_with(|| self.infcx.next_const_var(self.span).into())
- .expect_const()
+ self.args[bv.index()].expect_const()
}
}
- let delegate = ToFreshVars { infcx: self, span, lbrct, map: Default::default() };
+ let delegate = ToFreshVars { args };
self.tcx.replace_bound_vars_uncached(value, delegate)
}
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 7c764cc..e9726ee 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -1,6 +1,3 @@
-use crate::errors::OpaqueHiddenTypeDiag;
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::{self, Obligation};
use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::Lrc;
@@ -9,13 +6,16 @@
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{
- self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitableExt, TypeVisitor,
+ self, GenericArgKind, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_span::Span;
+use crate::errors::OpaqueHiddenTypeDiag;
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::{self, Obligation};
+
mod table;
pub type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index e07d181..7b4e546 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -2,9 +2,8 @@
use rustc_middle::bug;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
-use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
-
use super::{OpaqueTypeDecl, OpaqueTypeMap};
+use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
#[derive(Default, Debug, Clone)]
pub struct OpaqueTypeStorage<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 5bcb4f2..cc76370 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -1,12 +1,12 @@
-use crate::infer::free_regions::FreeRegionMap;
-use crate::infer::GenericKind;
-use crate::traits::query::OutlivesBound;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
use rustc_middle::bug;
use rustc_middle::ty::{self, Region};
use super::explicit_outlives_bounds;
+use crate::infer::free_regions::FreeRegionMap;
+use crate::infer::GenericKind;
+use crate::traits::query::OutlivesBound;
/// The `OutlivesEnvironment` collects information about what outlives
/// what in a given type-checking setting. For example, if we have a
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 89ff460..e4eefbc 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -1,12 +1,13 @@
//! Various code related to computing outlives relations.
+use rustc_middle::traits::query::{NoSolution, OutlivesBound};
+use rustc_middle::ty;
+
use self::env::OutlivesEnvironment;
use super::region_constraints::RegionConstraintData;
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
use crate::infer::free_regions::RegionRelations;
use crate::infer::lexical_region_resolve;
-use rustc_middle::traits::query::{NoSolution, OutlivesBound};
-use rustc_middle::ty;
pub mod env;
pub mod for_liveness;
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index d82ae7b..88b004a 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -59,25 +59,25 @@
//! might later infer `?U` to something like `&'b u32`, which would
//! imply that `'b: 'a`.
+use rustc_data_structures::undo_log::UndoLogs;
+use rustc_middle::bug;
+use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::traits::query::NoSolution;
+use rustc_middle::ty::{
+ self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesPredicate, Region, Ty, TyCtxt,
+ TypeFoldable as _, TypeVisitableExt,
+};
+use rustc_span::DUMMY_SP;
+use rustc_type_ir::outlives::{push_outlives_components, Component};
+use smallvec::smallvec;
+
+use super::env::OutlivesEnvironment;
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::outlives::verify::VerifyBoundCx;
use crate::infer::resolve::OpportunisticRegionResolver;
use crate::infer::snapshot::undo_log::UndoLog;
use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
use crate::traits::{ObligationCause, ObligationCauseCode};
-use rustc_data_structures::undo_log::UndoLogs;
-use rustc_middle::bug;
-use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::{
- self, GenericArgsRef, Region, Ty, TyCtxt, TypeFoldable as _, TypeVisitableExt,
-};
-use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
-use rustc_span::DUMMY_SP;
-use rustc_type_ir::outlives::{push_outlives_components, Component};
-use smallvec::smallvec;
-
-use super::env::OutlivesEnvironment;
impl<'tcx> InferCtxt<'tcx> {
/// Registers that the given region obligation must be resolved
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index c63eeaf..835e34a 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -2,8 +2,7 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use crate::infer::region_constraints::VerifyIfEq;
use crate::infer::relate::{self as relate, Relate, RelateResult, TypeRelation};
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 2392a82..1908e1e 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,10 +1,12 @@
+use std::assert_matches::assert_matches;
+
+use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
+use rustc_type_ir::outlives::{compute_alias_components_recursive, Component};
+use smallvec::smallvec;
+
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::region_constraints::VerifyIfEq;
use crate::infer::{GenericKind, VerifyBound};
-use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
-use rustc_type_ir::outlives::{compute_alias_components_recursive, Component};
-
-use smallvec::smallvec;
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
/// obligation into a series of `'a: 'b` constraints and "verifys", as
@@ -181,7 +183,7 @@ fn declared_generic_bounds_from_env(
&self,
generic_ty: Ty<'tcx>,
) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
- assert!(matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_)));
+ assert_matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_));
self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
}
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index a1ba43e..b78f9d49 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -1,9 +1,8 @@
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};
-use crate::traits::{Obligation, PredicateObligation};
-
use super::InferCtxt;
+use crate::traits::{Obligation, PredicateObligation};
impl<'tcx> InferCtxt<'tcx> {
/// Instead of normalizing an associated type projection,
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 5b159d6..3d2a0a3 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -1,12 +1,14 @@
-use super::*;
-use crate::infer::relate::RelateResult;
-use crate::infer::snapshot::CombinedSnapshot;
use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::graph::{scc::Sccs, vec_graph::VecGraph};
+use rustc_data_structures::graph::scc::Sccs;
+use rustc_data_structures::graph::vec_graph::VecGraph;
use rustc_index::Idx;
use rustc_middle::span_bug;
use rustc_middle::ty::error::TypeError;
+use super::*;
+use crate::infer::relate::RelateResult;
+use crate::infer::snapshot::CombinedSnapshot;
+
impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
/// Searches new universes created during `snapshot`, looking for
/// placeholders that may "leak" out from the universes they are contained
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 6f755e0..6ee95c7 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -1,10 +1,7 @@
//! See `README.md`.
-use self::CombineMapType::*;
-use self::UndoLog::*;
-
-use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin};
-use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot};
+use std::ops::Range;
+use std::{cmp, fmt, mem};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
@@ -13,15 +10,14 @@
use rustc_index::IndexVec;
use rustc_macros::{TypeFoldable, TypeVisitable};
use rustc_middle::infer::unify_key::{RegionVariableValue, RegionVidKey};
-use rustc_middle::ty::ReStatic;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ReBound, ReVar};
-use rustc_middle::ty::{Region, RegionVid};
+use rustc_middle::ty::{self, ReBound, ReStatic, ReVar, Region, RegionVid, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
-use std::ops::Range;
-use std::{cmp, fmt, mem};
+use self::CombineMapType::*;
+use self::UndoLog::*;
+use super::{MiscVariable, RegionVariableOrigin, Rollback, SubregionOrigin};
+use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, Snapshot};
mod leak_check;
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 1dc03de..5751ce4 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -18,22 +18,19 @@
//! On success, the LUB/GLB operations return the appropriate bound. The
//! return value of `Equate` or `Sub` shouldn't really be used.
+use rustc_middle::bug;
+use rustc_middle::infer::unify_key::EffectVarValue;
+use rustc_middle::traits::solve::Goal;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::{self, InferConst, IntType, Ty, TyCtxt, TypeVisitableExt, UintType, Upcast};
pub use rustc_next_trait_solver::relate::combine::*;
use super::glb::Glb;
use super::lub::Lub;
use super::type_relating::TypeRelating;
-use super::RelateResult;
-use super::StructurallyRelateAliases;
-use crate::infer::relate;
-use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
+use super::{RelateResult, StructurallyRelateAliases};
+use crate::infer::{relate, DefineOpaqueTypes, InferCtxt, TypeTrace};
use crate::traits::{Obligation, PredicateObligation};
-use rustc_middle::bug;
-use rustc_middle::infer::unify_key::EffectVarValue;
-use rustc_middle::traits::solve::Goal;
-use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
-use rustc_middle::ty::{IntType, UintType};
#[derive(Clone)]
pub struct CombineFields<'infcx, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs
index 30cfbca..542104f 100644
--- a/compiler/rustc_infer/src/infer/relate/generalize.rs
+++ b/compiler/rustc_infer/src/infer/relate/generalize.rs
@@ -1,10 +1,5 @@
use std::mem;
-use super::StructurallyRelateAliases;
-use super::{PredicateEmittingRelation, Relate, RelateResult, TypeRelation};
-use crate::infer::relate;
-use crate::infer::type_variable::TypeVariableValue;
-use crate::infer::{InferCtxt, RegionVariableOrigin};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::DefId;
@@ -12,10 +7,17 @@
use rustc_middle::infer::unify_key::ConstVariableValue;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::visit::MaxUniverse;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{AliasRelationDirection, InferConst, Term, TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::{
+ self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
+};
use rustc_span::Span;
+use super::{
+ PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
+};
+use crate::infer::type_variable::TypeVariableValue;
+use crate::infer::{relate, InferCtxt, RegionVariableOrigin};
+
impl<'tcx> InferCtxt<'tcx> {
/// The idea is that we should ensure that the type variable `target_vid`
/// is equal to, a subtype of, or a supertype of `source_ty`.
diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
index cfce28a..c808ab5 100644
--- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
+++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs
@@ -1,11 +1,12 @@
//! Helper routines for higher-ranked things. See the `doc` module at
//! the end of the file for details.
+use rustc_middle::ty::fold::FnMutDelegate;
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+
use super::RelateResult;
use crate::infer::snapshot::CombinedSnapshot;
use crate::infer::InferCtxt;
-use rustc_middle::ty::fold::FnMutDelegate;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
impl<'tcx> InferCtxt<'tcx> {
/// Replaces all bound variables (lifetimes, types, and constants) bound by
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index d1d8707..f555fed 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -17,14 +17,13 @@
//!
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
+use rustc_middle::ty::relate::RelateResult;
+use rustc_middle::ty::{self, Ty, TyVar};
+
use super::combine::PredicateEmittingRelation;
use crate::infer::{DefineOpaqueTypes, InferCtxt};
use crate::traits::ObligationCause;
-use rustc_middle::ty::relate::RelateResult;
-use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, Ty};
-
/// Trait for returning data about a lattice, and for abstracting
/// over the "direction" of the lattice operation (LUB/GLB).
///
diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
index 2eb20f3..046e93b 100644
--- a/compiler/rustc_infer/src/infer/relate/lub.rs
+++ b/compiler/rustc_infer/src/infer/relate/lub.rs
@@ -1,16 +1,16 @@
//! Least upper bound. See [`lattice`].
+use rustc_middle::traits::solve::Goal;
+use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::Span;
+
use super::combine::{CombineFields, PredicateEmittingRelation};
use super::lattice::{self, LatticeDir};
use super::StructurallyRelateAliases;
use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use crate::traits::ObligationCause;
-use rustc_middle::traits::solve::Goal;
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::Span;
-
/// "Least upper bound" (common supertype)
pub struct Lub<'combine, 'infcx, 'tcx> {
fields: &'combine mut CombineFields<'infcx, 'tcx>,
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
index dd97dc0..183ea5b 100644
--- a/compiler/rustc_infer/src/infer/relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -5,8 +5,7 @@
pub use rustc_middle::ty::relate::RelateResult;
pub use rustc_next_trait_solver::relate::*;
-pub use self::combine::CombineFields;
-pub use self::combine::PredicateEmittingRelation;
+pub use self::combine::{CombineFields, PredicateEmittingRelation};
#[allow(hidden_glob_reexports)]
pub(super) mod combine;
diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs
index 3fe3535..ec600c6 100644
--- a/compiler/rustc_infer/src/infer/relate/type_relating.rs
+++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs
@@ -1,15 +1,15 @@
-use super::combine::CombineFields;
-use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
-use crate::infer::BoundRegionConversionTime::HigherRankedType;
-use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::relate::{
relate_args_invariantly, relate_args_with_variances, Relate, RelateResult, TypeRelation,
};
-use rustc_middle::ty::TyVar;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TyVar};
use rustc_span::Span;
+use super::combine::CombineFields;
+use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
+use crate::infer::BoundRegionConversionTime::HigherRankedType;
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
+
/// Enforce that `a` is equal to or a subtype of `b`.
pub struct TypeRelating<'combine, 'a, 'tcx> {
fields: &'combine mut CombineFields<'a, 'tcx>,
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index ed75fd1..34625ff 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -1,9 +1,10 @@
-use super::{FixupError, FixupResult, InferCtxt};
use rustc_middle::bug;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
+use super::{FixupError, FixupResult, InferCtxt};
+
///////////////////////////////////////////////////////////////////////////
// OPPORTUNISTIC VAR RESOLVER
diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
index f15bd0b..bc95405 100644
--- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs
@@ -1,16 +1,13 @@
+use std::ops::Range;
+
+use rustc_data_structures::{snapshot_vec as sv, unify as ut};
use rustc_middle::infer::unify_key::{ConstVariableValue, ConstVidKey};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid};
-
-use crate::infer::type_variable::TypeVariableOrigin;
-use crate::infer::InferCtxt;
-use crate::infer::{ConstVariableOrigin, RegionVariableOrigin, UnificationTable};
-
-use rustc_data_structures::snapshot_vec as sv;
-use rustc_data_structures::unify as ut;
use ut::UnifyKey;
-use std::ops::Range;
+use crate::infer::type_variable::TypeVariableOrigin;
+use crate::infer::{ConstVariableOrigin, InferCtxt, RegionVariableOrigin, UnificationTable};
fn vars_since_snapshot<'tcx, T>(
table: &UnificationTable<'_, 'tcx, T>,
diff --git a/compiler/rustc_infer/src/infer/snapshot/mod.rs b/compiler/rustc_infer/src/infer/snapshot/mod.rs
index 9eef147..d76b9b0 100644
--- a/compiler/rustc_infer/src/infer/snapshot/mod.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/mod.rs
@@ -1,8 +1,9 @@
-use super::region_constraints::RegionSnapshot;
-use super::InferCtxt;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::ty;
+use super::region_constraints::RegionSnapshot;
+use super::InferCtxt;
+
mod fudge;
pub(crate) mod undo_log;
diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
index 829b0a7..50a0d3b 100644
--- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
@@ -1,15 +1,12 @@
use std::marker::PhantomData;
-use rustc_data_structures::snapshot_vec as sv;
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
-use rustc_data_structures::unify as ut;
+use rustc_data_structures::{snapshot_vec as sv, unify as ut};
use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey, RegionVidKey};
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey};
-use crate::{
- infer::{region_constraints, type_variable, InferCtxtInner},
- traits,
-};
+use crate::infer::{region_constraints, type_variable, InferCtxtInner};
+use crate::traits;
pub struct Snapshot<'tcx> {
pub(crate) undo_len: usize,
diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs
index b56b39e..f022b8a 100644
--- a/compiler/rustc_infer/src/infer/type_variable.rs
+++ b/compiler/rustc_infer/src/infer/type_variable.rs
@@ -1,4 +1,9 @@
+use std::cmp;
+use std::marker::PhantomData;
+use std::ops::Range;
+
use rustc_data_structures::undo_log::Rollback;
+use rustc_data_structures::{snapshot_vec as sv, unify as ut};
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
use rustc_middle::bug;
@@ -7,12 +12,6 @@
use crate::infer::InferCtxtUndoLogs;
-use rustc_data_structures::snapshot_vec as sv;
-use rustc_data_structures::unify as ut;
-use std::cmp;
-use std::marker::PhantomData;
-use std::ops::Range;
-
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariableStorage<'tcx> {
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) {
self.eq_relations.reverse(undo)
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index b65ac85..25ac8ba 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -18,6 +18,7 @@
#![allow(rustc::untranslatable_diagnostic)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
+#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extend_one)]
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 026b2c1..fd38040 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -1,11 +1,11 @@
use std::fmt::Debug;
-use crate::infer::InferCtxt;
-use crate::traits::Obligation;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, Ty, Upcast};
use super::{ObligationCause, PredicateObligation};
+use crate::infer::InferCtxt;
+use crate::traits::Obligation;
/// A trait error with most of its information removed. This is the error
/// returned by an `ObligationCtxt` by default, and suitable if you just
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 7bc3af3..4f34c13 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -14,22 +14,20 @@
use rustc_hir as hir;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
+pub use rustc_middle::traits::*;
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
use rustc_span::Span;
+pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
+pub(crate) use self::project::UndoLog;
+pub use self::project::{
+ MismatchedProjectionTypes, Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry,
+ ProjectionCacheKey, ProjectionCacheStorage, Reveal,
+};
pub use self::ImplSource::*;
pub use self::SelectionError::*;
use crate::infer::InferCtxt;
-pub use self::engine::{FromSolverError, ScrubbedTraitError, TraitEngine};
-pub use self::project::MismatchedProjectionTypes;
-pub(crate) use self::project::UndoLog;
-pub use self::project::{
- Normalized, NormalizedTerm, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
- ProjectionCacheStorage, Reveal,
-};
-pub use rustc_middle::traits::*;
-
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
/// which the "impl_source" must be found. The process of finding an "impl_source" is
/// called "resolving" the `Obligation`. This process consists of
diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs
index b696264..9ed557e 100644
--- a/compiler/rustc_infer/src/traits/project.rs
+++ b/compiler/rustc_infer/src/traits/project.rs
@@ -1,16 +1,12 @@
//! Code for projecting associated types out of trait references.
-use super::PredicateObligation;
-
-use crate::infer::snapshot::undo_log::InferCtxtUndoLogs;
-
-use rustc_data_structures::{
- snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage},
- undo_log::Rollback,
-};
+use rustc_data_structures::snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage};
+use rustc_data_structures::undo_log::Rollback;
+pub use rustc_middle::traits::{EvaluationResult, Reveal};
use rustc_middle::ty;
-pub use rustc_middle::traits::{EvaluationResult, Reveal};
+use super::PredicateObligation;
+use crate::infer::snapshot::undo_log::InferCtxtUndoLogs;
pub(crate) type UndoLog<'tcx> =
snapshot_map::UndoLog<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>;
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index b26734a..31f585c 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -1,11 +1,12 @@
-use crate::traits;
-use crate::traits::project::Normalized;
+use std::fmt;
+
use rustc_ast_ir::try_visit;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
use rustc_middle::ty::{self, TyCtxt};
-use std::fmt;
+use crate::traits;
+use crate::traits::project::Normalized;
// Structural impls for the structs in `traits`.
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index f54d041..335c65d 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -1,11 +1,11 @@
-use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
use rustc_data_structures::fx::FxHashSet;
-use rustc_middle::ty::ToPolyTraitRef;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, ToPolyTraitRef, TyCtxt};
use rustc_span::symbol::Ident;
use rustc_span::Span;
pub use rustc_type_ir::elaborate::*;
+use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
+
pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
pred: ty::Predicate<'tcx>,
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs
index a27f737..786e2bb 100644
--- a/compiler/rustc_interface/src/callbacks.rs
+++ b/compiler/rustc_interface/src/callbacks.rs
@@ -9,12 +9,13 @@
//! The functions in this file should fall back to the default set in their
//! origin crate when the `TyCtxt` is not present in TLS.
+use std::fmt;
+
use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC};
use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef};
use rustc_middle::ty::tls;
use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug;
use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode};
-use std::fmt;
fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
tls::with_opt(|tcx| {
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index 2929400..939980a 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_macros::Diagnostic;
-use rustc_span::{Span, Symbol};
-
use std::io;
use std::path::Path;
+use rustc_macros::Diagnostic;
+use rustc_span::{Span, Symbol};
+
#[derive(Diagnostic)]
#[diag(interface_ferris_identifier)]
pub struct FerrisIdentifier {
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index dba20e4..04e2b7d 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -1,13 +1,13 @@
-use crate::util;
+use std::path::PathBuf;
+use std::result;
+use std::sync::Arc;
-use rustc_ast::token;
-use rustc_ast::{LitKind, MetaItemKind};
+use rustc_ast::{token, LitKind, MetaItemKind};
use rustc_codegen_ssa::traits::CodegenBackend;
-use rustc_data_structures::defer;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::jobserver;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::{defer, jobserver};
use rustc_errors::registry::Registry;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
use rustc_lint::LintStore;
@@ -15,6 +15,7 @@
use rustc_middle::ty::CurrentGcx;
use rustc_middle::util::Providers;
use rustc_parse::new_parser_from_source_str;
+use rustc_parse::parser::attr::AllowLeadingUnsafe;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::print_query_stack;
use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
@@ -24,11 +25,10 @@
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
use rustc_span::symbol::sym;
use rustc_span::FileName;
-use std::path::PathBuf;
-use std::result;
-use std::sync::Arc;
use tracing::trace;
+use crate::util;
+
pub type Result<T> = result::Result<T, ErrorGuaranteed>;
/// Represents a compiler session. Note that every `Compiler` contains a
@@ -68,7 +68,7 @@ macro_rules! error {
}
match new_parser_from_source_str(&psess, filename, s.to_string()) {
- Ok(mut parser) => match parser.parse_meta_item() {
+ Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(meta_item) if parser.token == token::Eof => {
if meta_item.path.segments.len() != 1 {
error!("argument key must be an identifier");
@@ -174,7 +174,7 @@ macro_rules! error {
}
};
- let meta_item = match parser.parse_meta_item() {
+ let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::Yes) {
Ok(meta_item) if parser.token == token::Eof => meta_item,
Ok(..) => expected_error(),
Err(err) => {
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 2951f50..96a6f52 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -1,7 +1,9 @@
-use crate::errors;
-use crate::interface::{Compiler, Result};
-use crate::proc_macro_decls;
-use crate::util;
+use std::any::Any;
+use std::ffi::OsString;
+use std::io::{self, BufWriter, Write};
+use std::path::{Path, PathBuf};
+use std::sync::{Arc, LazyLock};
+use std::{env, fs, iter};
use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::traits::CodegenBackend;
@@ -27,23 +29,18 @@
use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
-use rustc_session::output::filename_for_input;
-use rustc_session::output::{collect_crate_types, find_crate_name};
+use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name};
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::FileName;
use rustc_target::spec::PanicStrategy;
use rustc_trait_selection::traits;
-
-use std::any::Any;
-use std::ffi::OsString;
-use std::io::{self, BufWriter, Write};
-use std::path::{Path, PathBuf};
-use std::sync::{Arc, LazyLock};
-use std::{env, fs, iter};
use tracing::{info, instrument};
+use crate::interface::{Compiler, Result};
+use crate::{errors, proc_macro_decls, util};
+
pub(crate) fn parse<'a>(sess: &'a Session) -> Result<ast::Crate> {
let krate = sess
.time("parse_crate", || {
@@ -547,7 +544,13 @@ fn resolver_for_lowering_raw<'tcx>(
let arenas = Resolver::arenas();
let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
- let mut resolver = Resolver::new(tcx, &pre_configured_attrs, krate.spans.inner_span, &arenas);
+ let mut resolver = Resolver::new(
+ tcx,
+ &pre_configured_attrs,
+ krate.spans.inner_span,
+ krate.spans.inject_use_span,
+ &arenas,
+ );
let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);
// Make sure we don't mutate the cstore from here on.
@@ -815,6 +818,19 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
});
sess.time("layout_testing", || layout_test::test_layout(tcx));
sess.time("abi_testing", || abi_test::test_abi(tcx));
+
+ // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
+ // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
+ // in MIR optimizations that may only be reachable through codegen, or other codepaths
+ // that requires the optimized/ctfe MIR, such as polymorphization, coroutine bodies,
+ // or evaluating consts.
+ if tcx.sess.opts.unstable_opts.validate_mir {
+ sess.time("ensuring_final_MIR_is_computable", || {
+ tcx.hir().par_body_owners(|def_id| {
+ tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
+ });
+ });
+ }
}
/// Runs the type-checking, region checking and other miscellaneous analysis
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 821e8ee..c5d56c1 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -1,6 +1,6 @@
-use crate::errors::FailedWritingFile;
-use crate::interface::{Compiler, Result};
-use crate::{errors, passes};
+use std::any::Any;
+use std::cell::{RefCell, RefMut};
+use std::sync::Arc;
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
@@ -15,9 +15,10 @@
use rustc_serialize::opaque::FileEncodeResult;
use rustc_session::config::{self, OutputFilenames, OutputType};
use rustc_session::Session;
-use std::any::Any;
-use std::cell::{RefCell, RefMut};
-use std::sync::Arc;
+
+use crate::errors::FailedWritingFile;
+use crate::interface::{Compiler, Result};
+use crate::{errors, passes};
/// Represent the result of a query.
///
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 7d7a6a0..34f2dca 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -1,23 +1,20 @@
#![allow(rustc::bad_opt_access)]
-use crate::interface::{initialize_checked_jobserver, parse_cfg};
+use std::collections::{BTreeMap, BTreeSet};
+use std::num::NonZero;
+use std::path::{Path, PathBuf};
+use std::sync::Arc;
+
use rustc_data_structures::profiling::TimePassesFormat;
-use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
-use rustc_session::config::{build_configuration, build_session_options, rustc_optgroups};
+use rustc_errors::emitter::HumanReadableErrorType;
+use rustc_errors::{registry, ColorConfig};
use rustc_session::config::{
- BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions,
- DebugInfo, DumpMonoStatsFormat, ErrorOutputType,
-};
-use rustc_session::config::{
- ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input,
- InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto,
-};
-use rustc_session::config::{
- LocationDetail, LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType,
- OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry,
-};
-use rustc_session::config::{
- Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
- WasiExecModel,
+ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
+ CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat,
+ ErrorOutputType, ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold,
+ Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail,
+ LtoCli, NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey,
+ PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
+ SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
};
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
@@ -31,10 +28,8 @@
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, WasmCAbi,
};
-use std::collections::{BTreeMap, BTreeSet};
-use std::num::NonZero;
-use std::path::{Path, PathBuf};
-use std::sync::Arc;
+
+use crate::interface::{initialize_checked_jobserver, parse_cfg};
fn sess_and_cfg<F>(args: &[&'static str], f: F)
where
@@ -320,7 +315,8 @@ fn test_search_paths_tracking_hash_different_order() {
let early_dcx = EarlyDiagCtxt::new(JSON);
const JSON: ErrorOutputType = ErrorOutputType::Json {
pretty: false,
- json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
+ json_rendered: HumanReadableErrorType::Default,
+ color_config: ColorConfig::Never,
};
let push = |opts: &mut Options, search_path| {
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 8dac524..761d288 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -1,4 +1,9 @@
-use crate::errors;
+use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
+use std::path::{Path, PathBuf};
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::OnceLock;
+use std::{env, iter, thread};
+
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
#[cfg(parallel_compiler)]
@@ -16,14 +21,10 @@
use rustc_span::source_map::SourceMapInputs;
use rustc_span::symbol::sym;
use rustc_target::spec::Target;
-use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
-use std::path::{Path, PathBuf};
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::OnceLock;
-use std::thread;
-use std::{env, iter};
use tracing::info;
+use crate::errors;
+
/// Function pointer type that constructs a new CodegenBackend.
pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -136,11 +137,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce(CurrentGcx) -> R + Send,
sm_inputs: SourceMapInputs,
f: F,
) -> R {
- use rustc_data_structures::{defer, jobserver, sync::FromDyn};
+ use std::process;
+
+ use rustc_data_structures::sync::FromDyn;
+ use rustc_data_structures::{defer, jobserver};
use rustc_middle::ty::tls;
use rustc_query_impl::QueryCtxt;
use rustc_query_system::query::{break_query_cycles, QueryContext};
- use std::process;
let thread_stack_size = init_stack_size(thread_builder_diag);
@@ -383,7 +386,6 @@ fn get_codegen_sysroot(
}
}
-#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
pub(crate) fn check_attr_crate_type(
sess: &Session,
attrs: &[ast::Attribute],
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index d4efb41..2116ba6 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -31,12 +31,12 @@
#[cfg(test)]
mod tests;
-pub use crate::cursor::Cursor;
+use unicode_properties::UnicodeEmoji;
use self::LiteralKind::*;
use self::TokenKind::*;
+pub use crate::cursor::Cursor;
use crate::cursor::EOF_CHAR;
-use unicode_properties::UnicodeEmoji;
/// Parsed token.
/// It doesn't contain information about data that has been parsed,
diff --git a/compiler/rustc_lexer/src/tests.rs b/compiler/rustc_lexer/src/tests.rs
index e4c1787..493ec2b 100644
--- a/compiler/rustc_lexer/src/tests.rs
+++ b/compiler/rustc_lexer/src/tests.rs
@@ -1,7 +1,7 @@
-use super::*;
-
use expect_test::{expect, Expect};
+use super::*;
+
fn check_raw_str(s: &str, expected: Result<u8, RawStrError>) {
let s = &format!("r{}", s);
let mut cursor = Cursor::new(s);
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 987dbf6..7a394a6 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -518,8 +518,8 @@
lint_non_binding_let_on_drop_type =
non-binding let on a type that implements `Drop`
-lint_non_binding_let_on_sync_lock =
- non-binding let on a synchronization lock
+lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock
+ .label = this lock is not assigned to a binding and is immediately dropped
lint_non_binding_let_suggestion =
consider binding to an unused variable to avoid immediately dropping the value
@@ -700,10 +700,10 @@
lint_reason_must_come_last = reason in lint attribute must come last
lint_redundant_import = the item `{$ident}` is imported redundantly
- .label_imported_here = the item `{ident}` is already imported here
- .label_defined_here = the item `{ident}` is already defined here
- .label_imported_prelude = the item `{ident}` is already imported by the extern prelude
- .label_defined_prelude = the item `{ident}` is already defined by the extern prelude
+ .label_imported_here = the item `{$ident}` is already imported here
+ .label_defined_here = the item `{$ident}` is already defined here
+ .label_imported_prelude = the item `{$ident}` is already imported by the extern prelude
+ .label_defined_prelude = the item `{$ident}` is already defined by the extern prelude
lint_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough
.note = the most public imported item is `{$max_vis}`
@@ -775,6 +775,10 @@
.label = argument has type `{$arg_ty}`
.suggestion = use `std::mem::ManuallyDrop::into_inner` to get the inner value
+lint_unexpected_builtin_cfg = unexpected `--cfg {$cfg}` flag
+ .controlled_by = config `{$cfg_name}` is only supposed to be controlled by `{$controlled_by}`
+ .incoherent = manually setting a built-in cfg can and does create incoherent behaviors
+
lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_println}` to the top of the `build.rs`
lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead
lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}
diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs
index 6daee95..d904020 100644
--- a/compiler/rustc_lint/src/async_fn_in_trait.rs
+++ b/compiler/rustc_lint/src/async_fn_in_trait.rs
@@ -1,10 +1,10 @@
-use crate::lints::AsyncFnInTraitDiag;
-use crate::LateContext;
-use crate::LateLintPass;
use rustc_hir as hir;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_trait_selection::error_reporting::traits::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait;
+use crate::lints::AsyncFnInTraitDiag;
+use crate::{LateContext, LateLintPass};
+
declare_lint! {
/// The `async_fn_in_trait` lint detects use of `async fn` in the
/// definition of a publicly-reachable trait.
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index ab0b47d..6b36944 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -20,25 +20,8 @@
//! If you define a new `LateLintPass`, you will also need to add it to the
//! `late_lint_methods!` invocation in `lib.rs`.
-use crate::fluent_generated as fluent;
-use crate::{
- errors::BuiltinEllipsisInclusiveRangePatterns,
- lints::{
- BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
- BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr,
- BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
- BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
- BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
- BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc,
- BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns,
- BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds,
- BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit,
- BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe,
- BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
- BuiltinWhileTrue, InvalidAsmLabel,
- },
- EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
-};
+use std::fmt::Write;
+
use ast::token::TokenKind;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::visit::{FnCtxt, FnKind};
@@ -55,9 +38,9 @@
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::Upcast;
-use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
+// hardwired lints from rustc_lint_defs
+pub use rustc_session::lint::builtin::*;
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
use rustc_span::edition::Edition;
@@ -67,15 +50,29 @@
use rustc_target::abi::Abi;
use rustc_target::asm::InlineAsmArch;
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
+use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
+use rustc_trait_selection::traits::{self};
+use crate::errors::BuiltinEllipsisInclusiveRangePatterns;
+use crate::lints::{
+ BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink,
+ BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr,
+ BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives,
+ BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures,
+ BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents,
+ BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes,
+ BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed,
+ BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller,
+ BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub,
+ BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub,
+ BuiltinWhileTrue, InvalidAsmLabel,
+};
use crate::nonstandard_style::{method_context, MethodLateContext};
-
-use std::fmt::Write;
-
-// hardwired lints from rustc_lint_defs
-pub use rustc_session::lint::builtin::*;
+use crate::{
+ fluent_generated as fluent, EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level,
+ LintContext,
+};
declare_lint! {
/// The `while_true` lint detects `while true { }`.
@@ -1672,7 +1669,8 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat) {
return;
}
- use self::ast::{PatKind, RangeSyntax::DotDotDot};
+ use self::ast::PatKind;
+ use self::ast::RangeSyntax::DotDotDot;
/// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
/// corresponding to the ellipsis.
@@ -1926,14 +1924,13 @@ fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
impl ExplicitOutlivesRequirements {
fn lifetimes_outliving_lifetime<'tcx>(
tcx: TyCtxt<'tcx>,
- inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
+ inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
item: DefId,
lifetime: DefId,
) -> Vec<ty::Region<'tcx>> {
let item_generics = tcx.generics_of(item);
inferred_outlives
- .iter()
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
ty::ReEarlyParam(ebr)
@@ -1949,11 +1946,10 @@ fn lifetimes_outliving_lifetime<'tcx>(
}
fn lifetimes_outliving_type<'tcx>(
- inferred_outlives: &'tcx [(ty::Clause<'tcx>, Span)],
+ inferred_outlives: impl Iterator<Item = &'tcx (ty::Clause<'tcx>, Span)>,
index: u32,
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
- .iter()
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
a.is_param(index).then_some(b)
@@ -2096,7 +2092,11 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
(
Self::lifetimes_outliving_lifetime(
cx.tcx,
- inferred_outlives,
+ // don't warn if the inferred span actually came from the predicate we're looking at
+ // this happens if the type is recursively defined
+ inferred_outlives
+ .iter()
+ .filter(|(_, span)| !predicate.span.contains(*span)),
item.owner_id.to_def_id(),
region_def_id,
),
@@ -2118,7 +2118,14 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
};
let index = ty_generics.param_def_id_to_index[&def_id];
(
- Self::lifetimes_outliving_type(inferred_outlives, index),
+ Self::lifetimes_outliving_type(
+ // don't warn if the inferred span actually came from the predicate we're looking at
+ // this happens if the type is recursively defined
+ inferred_outlives.iter().filter(|(_, span)| {
+ !predicate.span.contains(*span)
+ }),
+ index,
+ ),
&predicate.bounds,
predicate.span,
predicate.origin == PredicateOrigin::WhereClause,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 9f0f116..c9e2eee 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -14,10 +14,9 @@
//! upon. As the ast is traversed, this keeps track of the current lint level
//! for all lint attributes.
-use self::TargetLint::*;
+use std::cell::Cell;
+use std::{iter, slice};
-use crate::levels::LintLevelsBuilder;
-use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync;
use rustc_data_structures::unord::UnordMap;
@@ -30,20 +29,22 @@
use rustc_middle::bug;
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError, PrintTraitRefExt as _};
-use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt};
-use rustc_session::lint::{BuiltinLintDiag, LintExpectationId};
-use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError, PrintTraitRefExt as _, Printer};
+use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt};
+use rustc_session::lint::{
+ BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
+};
use rustc_session::{LintStoreMarker, Session};
use rustc_span::edit_distance::find_best_match_for_names;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
use rustc_target::abi;
-use std::cell::Cell;
-use std::iter;
-use std::slice;
use tracing::debug;
+use self::TargetLint::*;
+use crate::levels::LintLevelsBuilder;
+use crate::passes::{EarlyLintPassObject, LateLintPassObject};
+
mod diagnostics;
type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync;
@@ -532,7 +533,7 @@ pub struct EarlyContext<'a> {
}
impl EarlyContext<'_> {
- /// Emit a lint at the appropriate level, with an optional associated span and an existing
+ /// Emit a lint at the appropriate level, with an associated span and an existing
/// diagnostic.
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
@@ -543,7 +544,21 @@ pub fn span_lint_with_diagnostics(
span: MultiSpan,
diagnostic: BuiltinLintDiag,
) {
- self.opt_span_lint(lint, Some(span), |diag| {
+ self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic);
+ }
+
+ /// Emit a lint at the appropriate level, with an optional associated span and an existing
+ /// diagnostic.
+ ///
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
+ #[rustc_lint_diagnostics]
+ pub fn opt_span_lint_with_diagnostics(
+ &self,
+ lint: &'static Lint,
+ span: Option<MultiSpan>,
+ diagnostic: BuiltinLintDiag,
+ ) {
+ self.opt_span_lint(lint, span, |diag| {
diagnostics::decorate_lint(self.sess(), diagnostic, diag);
});
}
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 05e0752..f289d4c 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -4,8 +4,9 @@
use std::borrow::Cow;
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
-use rustc_errors::elided_lifetime_in_path_suggestion;
-use rustc_errors::{Applicability, Diag, DiagArgValue, LintDiagnostic};
+use rustc_errors::{
+ elided_lifetime_in_path_suggestion, Applicability, Diag, DiagArgValue, LintDiagnostic,
+};
use rustc_middle::middle::stability;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::Session;
@@ -437,5 +438,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
BuiltinLintDiag::OutOfScopeMacroCalls { path } => {
lints::OutOfScopeMacroCalls { path }.decorate_lint(diag)
}
+ BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
+ lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
+ }
}
}
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index da36f68..fb3f40a 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -1,5 +1,6 @@
use rustc_middle::bug;
-use rustc_session::{config::ExpectedValues, Session};
+use rustc_session::config::ExpectedValues;
+use rustc_session::Session;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::{sym, Span, Symbol};
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index 911975f..f174470 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -1,8 +1,3 @@
-use crate::{
- lints::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel},
- LateContext, LateLintPass, LintContext,
-};
-
use rustc_hir::{self as hir, LangItem};
use rustc_middle::ty;
use rustc_session::lint::FutureIncompatibilityReason;
@@ -10,6 +5,9 @@
use rustc_span::sym;
use rustc_trait_selection::traits::supertraits;
+use crate::lints::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel};
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index eea0898..2060858 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -3,13 +3,11 @@
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;
-use crate::{
- lints::{
- DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag,
- UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion,
- },
- LateContext, LateLintPass, LintContext,
+use crate::lints::{
+ DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag,
+ UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion,
};
+use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `dropping_references` lint checks for calls to `std::mem::drop` with a reference
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 3292216..6fb0a62 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -14,8 +14,6 @@
//! upon. As the ast is traversed, this keeps track of the current lint level
//! for all lint attributes.
-use crate::context::{EarlyContext, LintStore};
-use crate::passes::{EarlyLintPass, EarlyLintPassObject};
use rustc_ast::ptr::P;
use rustc_ast::visit::{self as ast_visit, walk_list, Visitor};
use rustc_ast::{self as ast, HasAttrs};
@@ -28,6 +26,9 @@
use rustc_span::Span;
use tracing::debug;
+use crate::context::{EarlyContext, LintStore};
+use crate::passes::{EarlyLintPass, EarlyLintPassObject};
+
macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
$cx.pass.$f(&$cx.context, $($args),*);
}) }
@@ -46,7 +47,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
fn inlined_check_id(&mut self, id: ast::NodeId) {
for early_lint in self.context.buffered.take(id) {
let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint;
- self.context.span_lint_with_diagnostics(lint_id.lint, span, diagnostic);
+ self.context.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic);
}
}
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index 958da17..4e3eca4 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -1,12 +1,13 @@
-use crate::{
- context::LintContext,
- lints::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant},
- LateContext, LateLintPass,
-};
use rustc_hir as hir;
-use rustc_middle::ty::{visit::TypeVisitableExt, Ty};
+use rustc_middle::ty::visit::TypeVisitableExt;
+use rustc_middle::ty::Ty;
use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::{symbol::sym, Span};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+use crate::context::LintContext;
+use crate::lints::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant};
+use crate::{LateContext, LateLintPass};
declare_lint! {
/// The `enum_intrinsics_non_enums` lint detects calls to
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 46dfaf0..23e6b73 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,9 +1,11 @@
-use crate::fluent_generated as fluent;
-use rustc_errors::{codes::*, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::lint::Level;
use rustc_span::{Span, Symbol};
+use crate::fluent_generated as fluent;
+
#[derive(Diagnostic)]
#[diag(lint_overruled_attribute, code = E0453)]
pub struct OverruledAttribute<'a> {
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 04c2ebf..35af694 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -1,10 +1,11 @@
-use crate::lints::{Expectation, ExpectationNote};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS;
use rustc_session::lint::LintExpectationId;
use rustc_span::Symbol;
+use crate::lints::{Expectation, ExpectationNote};
+
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_expectations, ..*providers };
}
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index aa00fb4..6cb5263 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -1,19 +1,18 @@
-use crate::{
- lints::{
- ForLoopsOverFalliblesDiag, ForLoopsOverFalliblesLoopSub, ForLoopsOverFalliblesQuestionMark,
- ForLoopsOverFalliblesSuggestion,
- },
- LateContext, LateLintPass, LintContext,
-};
-
use hir::{Expr, Pat};
use rustc_hir as hir;
-use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::ObligationCause;
use rustc_middle::ty;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::{sym, Span};
use rustc_trait_selection::traits::ObligationCtxt;
+use crate::lints::{
+ ForLoopsOverFalliblesDiag, ForLoopsOverFalliblesLoopSub, ForLoopsOverFalliblesQuestionMark,
+ ForLoopsOverFalliblesSuggestion,
+};
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `for_loops_over_fallibles` lint checks for `for` loops over `Option` or `Result` values.
///
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index aa8ca17..ebd8bd5 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -1,15 +1,13 @@
-use crate::{
- lints::{
- HiddenUnicodeCodepointsDiag, HiddenUnicodeCodepointsDiagLabels,
- HiddenUnicodeCodepointsDiagSub,
- },
- EarlyContext, EarlyLintPass, LintContext,
-};
use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS};
use rustc_ast as ast;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::{BytePos, Span, Symbol};
+use crate::lints::{
+ HiddenUnicodeCodepointsDiag, HiddenUnicodeCodepointsDiagLabels, HiddenUnicodeCodepointsDiagSub,
+};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+
declare_lint! {
/// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the
/// visual representation of text on screen in a way that does not correspond to their on
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index 0860413..e914169 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -13,8 +13,7 @@
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::Span;
-use crate::fluent_generated as fluent;
-use crate::{LateContext, LateLintPass};
+use crate::{fluent_generated as fluent, LateContext, LateLintPass};
declare_lint! {
/// The `impl_trait_overcaptures` lint warns against cases where lifetime
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index e15eb90..044c941 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -1,16 +1,13 @@
//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
//! Clippy.
-use crate::lints::{
- BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
- NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
- TykindKind, UntranslatableDiag,
-};
-use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_hir::def::Res;
-use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
-use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{
+ BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind,
+ Path, PathSegment, QPath, Ty, TyKind,
+};
use rustc_middle::ty::{self, Ty as MiddleTy};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -18,6 +15,13 @@
use rustc_span::Span;
use tracing::debug;
+use crate::lints::{
+ BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
+ NonGlobImportTypeIrInherent, QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag,
+ TykindKind, UntranslatableDiag,
+};
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+
declare_tool_lint! {
/// The `default_hash_type` lint detects use of [`std::collections::HashMap`] and
/// [`std::collections::HashSet`], suggesting the use of `FxHashMap`/`FxHashSet`.
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index aa328fb..638b623 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -14,22 +14,24 @@
//! upon. As the ast is traversed, this keeps track of the current lint level
//! for all lint attributes.
-use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
+use std::any::Any;
+use std::cell::Cell;
+
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::{join, Lrc};
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
-use rustc_hir::intravisit as hir_visit;
-use rustc_hir::HirId;
+use rustc_hir::{intravisit as hir_visit, HirId};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::LintPass;
use rustc_session::Session;
use rustc_span::Span;
-use std::any::Any;
-use std::cell::Cell;
use tracing::debug;
+use crate::passes::LateLintPassObject;
+use crate::{LateContext, LateLintPass, LintStore};
+
/// Extract the [`LintStore`] from [`Session`].
///
/// This function exists because [`Session::lint_store`] is type-erased.
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index e6c274e..1368cc8 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -1,13 +1,12 @@
-use crate::{
- lints::{NonBindingLet, NonBindingLetSub},
- LateContext, LateLintPass, LintContext,
-};
use rustc_errors::MultiSpan;
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::{sym, Symbol};
+use crate::lints::{NonBindingLet, NonBindingLetSub};
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `let_underscore_drop` lint checks for statements which don't bind
/// an expression which has a non-trivial Drop implementation to anything,
@@ -105,7 +104,6 @@
];
impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::LetStmt<'_>) {
if matches!(local.source, rustc_hir::LocalSource::AsyncFn) {
return;
@@ -157,12 +155,12 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::LetStmt<'_>) {
is_assign_desugar: matches!(local.source, rustc_hir::LocalSource::AssignDesugar(_)),
};
if is_sync_lock {
- let mut span = MultiSpan::from_span(pat.span);
- span.push_span_label(
- pat.span,
- "this lock is not assigned to a binding and is immediately dropped".to_string(),
+ let span = MultiSpan::from_span(pat.span);
+ cx.emit_span_lint(
+ LET_UNDERSCORE_LOCK,
+ span,
+ NonBindingLet::SyncLock { sub, pat: pat.span },
);
- cx.emit_span_lint(LET_UNDERSCORE_LOCK, span, NonBindingLet::SyncLock { sub });
// Only emit let_underscore_drop for top-level `_` patterns.
} else if can_use_init.is_some() {
cx.emit_span_lint(LET_UNDERSCORE_DROP, local.span, NonBindingLet::DropType { sub });
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 0df34c3..44117e5 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,24 +1,7 @@
-use crate::errors::{CheckNameUnknownTool, RequestedLevel, UnsupportedGroup};
-use crate::lints::{
- DeprecatedLintNameFromCommandLine, RemovedLintFromCommandLine, RenamedLintFromCommandLine,
- UnknownLintFromCommandLine,
-};
-use crate::{
- builtin::MISSING_DOCS,
- context::{CheckLintNameResult, LintStore},
- fluent_generated as fluent,
- late::unerased_lint_store,
- lints::{
- DeprecatedLintName, IgnoredUnlessCrateSpecified, OverruledAttributeLint, RemovedLint,
- RenamedLint, RenamedLintSuggestion, UnknownLint, UnknownLintSuggestion,
- },
-};
-use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
use rustc_feature::{Features, GateIssue};
-use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirId;
use rustc_index::IndexVec;
@@ -30,21 +13,30 @@
};
use rustc_middle::query::Providers;
use rustc_middle::ty::{RegisteredTools, TyCtxt};
-use rustc_session::lint::{
- builtin::{
- self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES,
- UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES,
- },
- Level, Lint, LintExpectationId, LintId,
+use rustc_session::lint::builtin::{
+ self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES,
+ UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES,
};
+use rustc_session::lint::{Level, Lint, LintExpectationId, LintId};
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use tracing::{debug, instrument};
+use {rustc_ast as ast, rustc_hir as hir};
+use crate::builtin::MISSING_DOCS;
+use crate::context::{CheckLintNameResult, LintStore};
use crate::errors::{
- MalformedAttribute, MalformedAttributeSub, OverruledAttribute, OverruledAttributeSub,
- UnknownToolInScopedLint,
+ CheckNameUnknownTool, MalformedAttribute, MalformedAttributeSub, OverruledAttribute,
+ OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup,
+};
+use crate::fluent_generated as fluent;
+use crate::late::unerased_lint_store;
+use crate::lints::{
+ DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified,
+ OverruledAttributeLint, RemovedLint, RemovedLintFromCommandLine, RenamedLint,
+ RenamedLintFromCommandLine, RenamedLintSuggestion, UnknownLint, UnknownLintFromCommandLine,
+ UnknownLintSuggestion,
};
/// Collection of lint levels for the whole crate.
@@ -725,7 +717,6 @@ fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) {
};
}
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option<HirId>) {
let sess = self.sess;
for (attr_index, attr) in attrs.iter().enumerate() {
@@ -1047,7 +1038,6 @@ fn check_gated_lint(&self, lint_id: LintId, span: Span, lint_from_cli: bool) ->
let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS);
// FIXME: make this translatable
#[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)]
lint_level(self.sess, lint, level, src, Some(span.into()), |lint| {
lint.primary_message(fluent::lint_unknown_gated_lint);
lint.arg("name", lint_id.lint.name_lower());
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 7c44d16..4f3933d 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -83,12 +83,6 @@
mod unit_bindings;
mod unused;
-pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
-
-use rustc_hir::def_id::LocalModDefId;
-use rustc_middle::query::Providers;
-use rustc_middle::ty::TyCtxt;
-
use async_closures::AsyncClosureUsage;
use async_fn_in_trait::AsyncFnInTrait;
use builtin::*;
@@ -116,7 +110,11 @@
use ptr_nulls::*;
use redundant_semicolon::*;
use reference_casting::*;
+use rustc_hir::def_id::LocalModDefId;
+use rustc_middle::query::Providers;
+use rustc_middle::ty::TyCtxt;
use shadowed_into_iter::ShadowedIntoIter;
+pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
use traits::*;
use types::*;
use unit_bindings::*;
@@ -124,14 +122,16 @@
#[rustfmt::skip]
pub use builtin::{MissingDoc, SoftLints};
-pub use context::{CheckLintNameResult, FindLintError, LintStore};
-pub use context::{EarlyContext, LateContext, LintContext};
+pub use context::{
+ CheckLintNameResult, EarlyContext, FindLintError, LateContext, LintContext, LintStore,
+};
pub use early::{check_ast_node, EarlyCheckNode};
pub use late::{check_crate, late_lint_mod, unerased_lint_store};
pub use passes::{EarlyLintPass, LateLintPass};
pub use rustc_session::lint::Level::{self, *};
-pub use rustc_session::lint::{BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId};
-pub use rustc_session::lint::{LintPass, LintVec};
+pub use rustc_session::lint::{
+ BufferedEarlyLint, FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec,
+};
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
@@ -543,7 +543,7 @@ macro_rules! add_lint_group {
);
store.register_removed(
"suspicious_auto_trait_impls",
- "no longer needed, see #93367 \
+ "no longer needed, see issue #93367 \
<https://github.com/rust-lang/rust/issues/93367> for more information",
);
store.register_removed(
@@ -565,6 +565,11 @@ macro_rules! add_lint_group {
"box_pointers",
"it does not detect other kinds of allocations, and existed only for historical reasons",
);
+ store.register_removed(
+ "byte_slice_in_packed_struct_with_derive",
+ "converted into hard error, see issue #107457 \
+ <https://github.com/rust-lang/rust/issues/107457> for more information",
+ )
}
fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index b669a3c..03962d7 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2,27 +2,26 @@
#![allow(rustc::untranslatable_diagnostic)]
use std::num::NonZero;
+use rustc_errors::codes::*;
+use rustc_errors::{
+ Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag,
+ EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
+};
+use rustc_hir::def::Namespace;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir};
+use rustc_macros::{LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::inhabitedness::InhabitedPredicate;
+use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt};
+use rustc_session::lint::AmbiguityErrorDiag;
+use rustc_session::Session;
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
+use rustc_span::{sym, Span, Symbol};
+
use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds};
use crate::errors::{OverruledAttributeSub, RequestedLevel};
-use crate::fluent_generated as fluent;
-use crate::LateContext;
-use rustc_errors::{
- codes::*, Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString,
- ElidedLifetimeInPathSubdiag, EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp,
- Subdiagnostic, SuggestionStyle,
-};
-use rustc_hir::{self as hir, def::Namespace, def_id::DefId};
-use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{
- inhabitedness::InhabitedPredicate, Clause, PolyExistentialTraitRef, Ty, TyCtxt,
-};
-use rustc_session::{lint::AmbiguityErrorDiag, Session};
-use rustc_span::{
- edition::Edition,
- sym,
- symbol::{Ident, MacroRulesNormalizedIdent},
- Span, Symbol,
-};
+use crate::{fluent_generated as fluent, LateContext};
// array_into_iter.rs
#[derive(LintDiagnostic)]
@@ -958,6 +957,8 @@ pub struct BadOptAccessDiag<'a> {
pub enum NonBindingLet {
#[diag(lint_non_binding_let_on_sync_lock)]
SyncLock {
+ #[label]
+ pat: Span,
#[subdiagnostic]
sub: NonBindingLetSub,
},
@@ -2379,6 +2380,16 @@ pub enum CargoHelp {
}
#[derive(LintDiagnostic)]
+#[diag(lint_unexpected_builtin_cfg)]
+#[note(lint_controlled_by)]
+#[note(lint_incoherent)]
+pub struct UnexpectedBuiltinCfg {
+ pub(crate) cfg: String,
+ pub(crate) cfg_name: Symbol,
+ pub(crate) controlled_by: &'static str,
+}
+
+#[derive(LintDiagnostic)]
#[diag(lint_macro_use_deprecated)]
#[help]
pub struct MacroUseDeprecated;
diff --git a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs
index 867e132..e3b1967 100644
--- a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs
+++ b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs
@@ -1,16 +1,12 @@
-//! Migration code for the `expr_fragment_specifier_2024`
-//! rule.
-use tracing::debug;
+//! Migration code for the `expr_fragment_specifier_2024` rule.
-use rustc_ast::token::Token;
-use rustc_ast::token::TokenKind;
-use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::tokenstream::TokenTree;
-use rustc_session::declare_lint;
-use rustc_session::declare_lint_pass;
+use rustc_ast::token::{Token, TokenKind};
+use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
use rustc_span::sym;
+use tracing::debug;
use crate::lints::MacroExprFragment2024;
use crate::EarlyLintPass;
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs
index e355604..3b27e45 100644
--- a/compiler/rustc_lint/src/map_unit_fn.rs
+++ b/compiler/rustc_lint/src/map_unit_fn.rs
@@ -1,13 +1,11 @@
+use rustc_hir::{Expr, ExprKind, HirId, Stmt, StmtKind};
+use rustc_middle::query::Key;
+use rustc_middle::ty::{self, Ty};
+use rustc_session::{declare_lint, declare_lint_pass};
+
use crate::lints::MappingToUnit;
use crate::{LateContext, LateLintPass, LintContext};
-use rustc_hir::{Expr, ExprKind, HirId, Stmt, StmtKind};
-use rustc_middle::{
- query::Key,
- ty::{self, Ty},
-};
-use rustc_session::{declare_lint, declare_lint_pass};
-
declare_lint! {
/// The `map_unit_fn` lint checks for `Iterator::map` receive
/// a callable that returns `()`.
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index 7a71fec..dff72bb 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -1,11 +1,11 @@
-use crate::lints::CStringPtr;
-use crate::LateContext;
-use crate::LateLintPass;
-use crate::LintContext;
use rustc_hir::{Expr, ExprKind};
use rustc_middle::ty;
use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::{symbol::sym, Span};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+use crate::lints::CStringPtr;
+use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `temporary_cstring_as_ptr` lint detects getting the inner pointer of
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
index 93dd5e7..978109a 100644
--- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -1,8 +1,8 @@
-use crate::{LateContext, LateLintPass, LintContext};
-
use rustc_hir as hir;
use rustc_session::{declare_lint, declare_lint_pass};
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `multiple_supertrait_upcastable` lint detects when an object-safe trait has multiple
/// supertraits.
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index 9f298a6..08d054b 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -1,8 +1,3 @@
-use crate::lints::{
- ConfusableIdentifierPair, IdentifierNonAsciiChar, IdentifierUncommonCodepoints,
- MixedScriptConfusables,
-};
-use crate::{EarlyContext, EarlyLintPass, LintContext};
use rustc_ast as ast;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::UnordMap;
@@ -10,6 +5,12 @@
use rustc_span::symbol::Symbol;
use unicode_security::general_security_profile::IdentifierType;
+use crate::lints::{
+ ConfusableIdentifierPair, IdentifierNonAsciiChar, IdentifierUncommonCodepoints,
+ MixedScriptConfusables,
+};
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+
declare_lint! {
/// The `non_ascii_idents` lint detects non-ASCII identifiers.
///
@@ -152,9 +153,10 @@
impl EarlyLintPass for NonAsciiIdents {
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
+ use std::collections::BTreeMap;
+
use rustc_session::lint::Level;
use rustc_span::Span;
- use std::collections::BTreeMap;
use unicode_security::GeneralSecurityProfile;
let check_non_ascii_idents = cx.builder.lint_level(NON_ASCII_IDENTS).0 != Level::Allow;
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 2dc2a0e..10a517b 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -1,19 +1,20 @@
-use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
-use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::bug;
use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty;
+use rustc_middle::{bug, ty};
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
-use rustc_span::{hygiene, sym, symbol::kw, InnerSpan, Span, Symbol};
+use rustc_span::symbol::kw;
+use rustc_span::{hygiene, sym, InnerSpan, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
+use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
+use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `non_fmt_panics` lint detects `panic!(..)` invocations where the first
/// argument is not a formatting string.
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 93c606a..5ad6779 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -1,24 +1,23 @@
use rustc_errors::MultiSpan;
+use rustc_hir::def::DefKind;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::HirId;
-use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind};
-use rustc_hir::{Path, QPath};
+use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, QPath, TyKind};
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::{Obligation, ObligationCause};
-use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable, TypeFolder};
-use rustc_middle::ty::{EarlyBinder, TraitRef, TypeSuperFoldable};
+use rustc_middle::ty::{
+ self, Binder, EarlyBinder, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+};
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::def_id::{DefId, LOCAL_CRATE};
-use rustc_span::Span;
-use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind, Symbol};
+use rustc_span::symbol::kw;
+use rustc_span::{sym, ExpnKind, MacroKind, Span, Symbol};
use rustc_trait_selection::error_reporting::traits::ambiguity::{
compute_applicable_impls_for_diagnostics, CandidateSource,
};
use rustc_trait_selection::infer::TyCtxtInferExt;
-use crate::fluent_generated as fluent;
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
-use crate::{LateContext, LateLintPass, LintContext};
+use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `non_local_definitions` lint checks for `impl` blocks and `#[macro_export]`
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index d64f444..d7fd41c 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -1,11 +1,3 @@
-use crate::lints::{
- NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub,
- NonUpperCaseGlobal, NonUpperCaseGlobalSub,
-};
-use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_ast as ast;
-use rustc_attr as attr;
-use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{GenericParamKind, PatKind};
@@ -16,6 +8,13 @@
use rustc_span::symbol::{sym, Ident};
use rustc_span::{BytePos, Span};
use rustc_target::spec::abi::Abi;
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
+
+use crate::lints::{
+ NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub,
+ NonUpperCaseGlobal, NonUpperCaseGlobalSub,
+};
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
#[derive(PartialEq)]
pub enum MethodLateContext {
@@ -528,11 +527,11 @@ fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
// Lint for constants that look like binding identifiers (#7526)
if let PatKind::Path(hir::QPath::Resolved(None, path)) = p.kind {
if let Res::Def(DefKind::Const, _) = path.res {
- if path.segments.len() == 1 {
+ if let [segment] = path.segments {
NonUpperCaseGlobals::check_upper_case(
cx,
"constant in pattern",
- &path.segments[0].ident,
+ &segment.ident,
);
}
}
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index 307e4be..d08a959 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -1,9 +1,3 @@
-use crate::context::LintContext;
-use crate::lints::{
- NoopMethodCallDiag, SuspiciousDoubleRefCloneDiag, SuspiciousDoubleRefDerefDiag,
-};
-use crate::LateContext;
-use crate::LateLintPass;
use rustc_hir::def::DefKind;
use rustc_hir::{Expr, ExprKind};
use rustc_middle::ty;
@@ -11,6 +5,12 @@
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::symbol::sym;
+use crate::context::LintContext;
+use crate::lints::{
+ NoopMethodCallDiag, SuspiciousDoubleRefCloneDiag, SuspiciousDoubleRefDerefDiag,
+};
+use crate::{LateContext, LateLintPass};
+
declare_lint! {
/// The `noop_method_call` lint detects specific calls to noop methods
/// such as a calling `<&T as Clone>::clone` where `T: !Clone`.
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index fdb71ad..e0ba6a9 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -1,10 +1,12 @@
use rustc_hir as hir;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_macros::{LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath};
-use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_session::{declare_lint, declare_lint_pass};
-use rustc_span::{symbol::kw, Span};
+use rustc_span::symbol::kw;
+use rustc_span::Span;
use rustc_trait_selection::traits::{self, ObligationCtxt};
use crate::{LateContext, LateLintPass, LintContext};
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index fa23f12..23b2009 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -1,5 +1,3 @@
-use crate::lints::PassByValueDiag;
-use crate::{LateContext, LateLintPass, LintContext};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind};
@@ -7,6 +5,9 @@
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
+use crate::lints::PassByValueDiag;
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_tool_lint! {
/// The `rustc_pass_by_value` lint marks a type with `#[rustc_pass_by_value]` requiring it to
/// always be passed by value. This is usually used for types that are thin wrappers around
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 2a84397..bf16e3b 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -1,8 +1,8 @@
-use crate::context::{EarlyContext, LateContext};
-
use rustc_session::lint::builtin::HardwiredLints;
use rustc_session::lint::LintPass;
+use crate::context::{EarlyContext, LateContext};
+
#[macro_export]
macro_rules! late_lint_methods {
($macro:path, $args:tt) => (
diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs
index eb2ba39..52321e2 100644
--- a/compiler/rustc_lint/src/precedence.rs
+++ b/compiler/rustc_lint/src/precedence.rs
@@ -16,6 +16,7 @@
/// ### Example
///
/// ```rust,compile_fail
+ /// # #![deny(ambiguous_negative_literals)]
/// # #![allow(unused)]
/// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
/// ```
@@ -27,7 +28,7 @@
/// Method calls take precedence over unary precedence. Setting the
/// precedence explicitly makes the code clearer and avoid potential bugs.
pub AMBIGUOUS_NEGATIVE_LITERALS,
- Deny,
+ Allow,
"ambiguous negative literals operations",
report_in_external_macro
}
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 8038115..1489f9d 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -1,9 +1,11 @@
-use crate::{lints::PtrNullChecksDiag, LateContext, LateLintPass, LintContext};
use rustc_ast::LitKind;
use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;
+use crate::lints::PtrNullChecksDiag;
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `useless_ptr_null_checks` lint checks for useless null checks against pointers
/// obtained from non-null types.
diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs
index ef08e79..b43e493 100644
--- a/compiler/rustc_lint/src/redundant_semicolon.rs
+++ b/compiler/rustc_lint/src/redundant_semicolon.rs
@@ -1,8 +1,10 @@
-use crate::{lints::RedundantSemicolonsDiag, EarlyContext, EarlyLintPass, LintContext};
use rustc_ast::{Block, StmtKind};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::Span;
+use crate::lints::RedundantSemicolonsDiag;
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+
declare_lint! {
/// The `redundant_semicolons` lint detects unnecessary trailing
/// semicolons.
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 34153e3..5e8c39c 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -1,11 +1,12 @@
use rustc_ast::Mutability;
use rustc_hir::{Expr, ExprKind, UnOp};
-use rustc_middle::ty::layout::LayoutOf as _;
-use rustc_middle::ty::{self, layout::TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout};
+use rustc_middle::ty::{self};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym;
-use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext};
+use crate::lints::InvalidReferenceCastingDiag;
+use crate::{LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `invalid_reference_casting` lint checks for casts of `&T` to `&mut T`
diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs
index da2b5878..4fe35a6 100644
--- a/compiler/rustc_lint/src/shadowed_into_iter.rs
+++ b/compiler/rustc_lint/src/shadowed_into_iter.rs
@@ -1,11 +1,12 @@
-use crate::lints::{ShadowedIntoIterDiag, ShadowedIntoIterDiagSub};
-use crate::{LateContext, LateLintPass, LintContext};
use rustc_hir as hir;
use rustc_middle::ty::{self, Ty};
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::edition::Edition;
+use crate::lints::{ShadowedIntoIterDiag, ShadowedIntoIterDiagSub};
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `array_into_iter` lint detects calling `into_iter` on arrays.
///
diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs
index 4fd054c..988d164 100644
--- a/compiler/rustc_lint/src/tests.rs
+++ b/compiler/rustc_lint/src/tests.rs
@@ -1,6 +1,7 @@
-use crate::levels::parse_lint_and_tool_name;
use rustc_span::{create_default_session_globals_then, Symbol};
+use crate::levels::parse_lint_and_tool_name;
+
#[test]
fn parse_lint_no_tool() {
create_default_session_globals_then(|| {
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index 552245f..fea96b53 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -1,11 +1,10 @@
-use crate::lints::{DropGlue, DropTraitConstraintsDiag};
-use crate::LateContext;
-use crate::LateLintPass;
-use crate::LintContext;
use rustc_hir::{self as hir, LangItem};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::symbol::sym;
+use crate::lints::{DropGlue, DropTraitConstraintsDiag};
+use crate::{LateContext, LateLintPass, LintContext};
+
declare_lint! {
/// The `drop_bounds` lint checks for generics with `std::ops::Drop` as
/// bounds.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index c0364b3..51896da 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,39 +1,33 @@
-use crate::{
- fluent_generated as fluent,
- lints::{
- AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
- AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
- AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
- InvalidNanComparisonsSuggestion, OnlyCastu8ToChar, OverflowingBinHex,
- OverflowingBinHexSign, OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt,
- OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange,
- UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
- },
-};
-use crate::{LateContext, LateLintPass, LintContext};
-use rustc_ast as ast;
-use rustc_attr as attr;
+use std::iter;
+use std::ops::ControlFlow;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagMessage;
-use rustc_hir as hir;
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
use rustc_middle::bug;
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
-use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{
- self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
};
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
use rustc_span::def_id::LocalDefId;
-use rustc_span::source_map;
use rustc_span::symbol::sym;
-use rustc_span::{Span, Symbol};
-use rustc_target::abi::{Abi, Size, WrappingRange};
-use rustc_target::abi::{Integer, TagEncoding, Variants};
+use rustc_span::{source_map, Span, Symbol};
+use rustc_target::abi::{Abi, Integer, Size, TagEncoding, Variants, WrappingRange};
use rustc_target::spec::abi::Abi as SpecAbi;
-use std::iter;
-use std::ops::ControlFlow;
use tracing::debug;
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
+
+use crate::lints::{
+ AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
+ AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
+ AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
+ InvalidNanComparisonsSuggestion, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
+ OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp,
+ OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons,
+ UseInclusiveRange, VariantSizeDifferencesDiag,
+};
+use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
declare_lint! {
/// The `unused_comparisons` lint detects comparisons made useless by
@@ -217,15 +211,12 @@ fn lint_overflowing_range_endpoint<'tcx>(
if !is_range_literal(struct_expr) {
return false;
};
- let ExprKind::Struct(_, eps, _) = &struct_expr.kind else { return false };
- if eps.len() != 2 {
- return false;
- }
+ let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else { return false };
// We can suggest using an inclusive range
// (`..=`) instead only if it is the `end` that is
// overflowing and only by 1.
- if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) {
+ if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) {
return false;
};
@@ -238,7 +229,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
};
let sub_sugg = if expr.span.lo() == lit_span.lo() {
- let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false };
+ let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false };
UseInclusiveRange::WithoutParen {
sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
start,
@@ -315,11 +306,7 @@ fn report_bin_hex_error(
) {
let (t, actually) = match ty {
attr::IntType::SignedInt(t) => {
- let actually = if negative {
- -(size.sign_extend(val) as i128)
- } else {
- size.sign_extend(val) as i128
- };
+ let actually = if negative { -(size.sign_extend(val)) } else { size.sign_extend(val) };
(t.name_str(), actually.to_string())
}
attr::IntType::UnsignedInt(t) => {
@@ -468,8 +455,11 @@ fn lint_int_literal<'tcx>(
}
let span = if negative { type_limits.negated_expr_span.unwrap() } else { e.span };
- let lit =
- cx.sess().source_map().span_to_snippet(span).expect("must get snippet from literal");
+ let lit = cx
+ .sess()
+ .source_map()
+ .span_to_snippet(span)
+ .unwrap_or_else(|_| if negative { format!("-{v}") } else { v.to_string() });
let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
.map(|suggestion_ty| OverflowingIntHelp { suggestion_ty });
@@ -495,6 +485,7 @@ fn lint_uint_literal<'tcx>(
ast::LitKind::Int(v, _) => v.get(),
_ => bug!(),
};
+
if lit_val < min || lit_val > max {
if let Node::Expr(par_e) = cx.tcx.parent_hir_node(e.hir_id) {
match par_e.kind {
@@ -536,7 +527,7 @@ fn lint_uint_literal<'tcx>(
.sess()
.source_map()
.span_to_snippet(lit.span)
- .expect("must get snippet from literal"),
+ .unwrap_or_else(|_| lit_val.to_string()),
min,
max,
},
@@ -561,14 +552,14 @@ fn lint_literal<'tcx>(
}
ty::Uint(t) => lint_uint_literal(cx, e, lit, t),
ty::Float(t) => {
- let is_infinite = match lit.node {
+ let (is_infinite, sym) = match lit.node {
ast::LitKind::Float(v, _) => match t {
// FIXME(f16_f128): add this check once `is_infinite` is reliable (ABI
// issues resolved).
- ty::FloatTy::F16 => Ok(false),
- ty::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite),
- ty::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite),
- ty::FloatTy::F128 => Ok(false),
+ ty::FloatTy::F16 => (Ok(false), v),
+ ty::FloatTy::F32 => (v.as_str().parse().map(f32::is_infinite), v),
+ ty::FloatTy::F64 => (v.as_str().parse().map(f64::is_infinite), v),
+ ty::FloatTy::F128 => (Ok(false), v),
},
_ => bug!(),
};
@@ -582,7 +573,7 @@ fn lint_literal<'tcx>(
.sess()
.source_map()
.span_to_snippet(lit.span)
- .expect("must get snippet from literal"),
+ .unwrap_or_else(|_| sym.to_string()),
},
);
}
diff --git a/compiler/rustc_lint/src/unit_bindings.rs b/compiler/rustc_lint/src/unit_bindings.rs
index 8202bfa..ed01590 100644
--- a/compiler/rustc_lint/src/unit_bindings.rs
+++ b/compiler/rustc_lint/src/unit_bindings.rs
@@ -1,8 +1,9 @@
-use crate::lints::UnitBindingsDiag;
-use crate::{LateLintPass, LintContext};
use rustc_hir as hir;
use rustc_session::{declare_lint, declare_lint_pass};
+use crate::lints::UnitBindingsDiag;
+use crate::{LateLintPass, LintContext};
+
declare_lint! {
/// The `unit_bindings` lint detects cases where bindings are useless because they have
/// the unit type `()` as their inferred type. The lint is suppressed if the user explicitly
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 65d42ed..553d9db 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1,11 +1,6 @@
-use crate::lints::{
- PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
- UnusedAllocationMutDiag, UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion,
- UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
- UnusedResult,
-};
-use crate::Lint;
-use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use std::iter;
+use std::ops::ControlFlow;
+
use rustc_ast as ast;
use rustc_ast::util::{classify, parser};
use rustc_ast::{ExprKind, StmtKind};
@@ -14,16 +9,20 @@
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::traits::util::elaborate;
-use rustc_middle::ty::adjustment;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, adjustment, Ty};
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
-use rustc_span::symbol::Symbol;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{BytePos, Span};
-use std::iter;
-use std::ops::ControlFlow;
use tracing::instrument;
+use crate::lints::{
+ PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag,
+ UnusedAllocationMutDiag, UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion,
+ UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, UnusedOp, UnusedOpSuggestion,
+ UnusedResult,
+};
+use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Lint, LintContext};
+
declare_lint! {
/// The `unused_must_use` lint detects unused result of a type flagged as
/// `#[must_use]`.
@@ -676,6 +675,13 @@ fn is_expr_delims_necessary(
return true;
}
+ // Do not lint against parentheses around `&raw [const|mut] expr`.
+ // These parentheses will have to be added e.g. when calling a method on the result of this
+ // expression, and we want to avoid churn wrt adding and removing parentheses.
+ if matches!(inner.kind, ast::ExprKind::AddrOf(ast::BorrowKind::Raw, ..)) {
+ return true;
+ }
+
// Check if LHS needs parens to prevent false-positives in cases like
// `fn x() -> u8 { ({ 0 } + 1) }`.
//
@@ -802,7 +808,7 @@ fn visit_expr(&mut self, expr: &'ast ast::Expr) -> ControlFlow<()> {
return;
}
let spans = match value.kind {
- ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => block.stmts[0]
+ ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => stmt
.span
.find_ancestor_inside(value.span)
.map(|span| (value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))),
@@ -1205,7 +1211,8 @@ fn check_expr_post(&mut self, _cx: &EarlyContext<'_>, e: &ast::Expr) {
}
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
- use ast::{Mutability, PatKind::*};
+ use ast::Mutability;
+ use ast::PatKind::*;
let keep_space = (false, false);
match &p.kind {
// Do not lint on `(..)` as that will result in the other arms being useless.
@@ -1537,14 +1544,12 @@ fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &
}
// Trigger the lint only if there is one nested item
- if items.len() != 1 {
- return;
- }
+ let [(tree, _)] = items.as_slice() else { return };
// Trigger the lint if the nested item is a non-self single item
- let node_name = match items[0].0.kind {
+ let node_name = match tree.kind {
ast::UseTreeKind::Simple(rename) => {
- let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
+ let orig_ident = tree.prefix.segments.last().unwrap().ident;
if orig_ident.name == kw::SelfLower {
return;
}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index c4158cc..c731b03 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -7,9 +7,10 @@
//! When removing a lint, make sure to also add a call to `register_removed` in
//! compiler/rustc_lint/src/lib.rs.
-use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason};
use rustc_span::edition::Edition;
+use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason};
+
declare_lint_pass! {
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
@@ -25,7 +26,6 @@
BARE_TRAIT_OBJECTS,
BINDINGS_WITH_VARIANT_NAME,
BREAK_WITH_LABEL_AND_LOOP,
- BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
CENUM_IMPL_DROP_CAST,
COHERENCE_LEAK_CHECK,
CONFLICTING_REPR_HINTS,
@@ -42,6 +42,7 @@
DUPLICATE_MACRO_ATTRIBUTES,
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
ELIDED_LIFETIMES_IN_PATHS,
+ EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
EXPORTED_PRIVATE_DEPENDENCIES,
FFI_UNWIND_CALLS,
FORBIDDEN_LINT_GROUPS,
@@ -81,6 +82,7 @@
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
PTR_CAST_ADD_AUTO_TO_OBJECT,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+ REDUNDANT_IMPORTS,
REDUNDANT_LIFETIMES,
REFINING_IMPL_TRAIT_INTERNAL,
REFINING_IMPL_TRAIT_REACHABLE,
@@ -91,6 +93,7 @@
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
RUST_2021_PRELUDE_COLLISIONS,
RUST_2024_INCOMPATIBLE_PAT,
+ RUST_2024_PRELUDE_COLLISIONS,
SELF_CONSTRUCTOR_FROM_OUTER_ITEM,
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
SINGLE_USE_LIFETIMES,
@@ -425,6 +428,31 @@
}
declare_lint! {
+ /// The `redundant_imports` lint detects imports that are redundant due to being
+ /// imported already; either through a previous import, or being present in
+ /// the prelude.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// #![deny(redundant_imports)]
+ /// use std::option::Option::None;
+ /// fn foo() -> Option<i32> { None }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Redundant imports are unnecessary and can be removed to simplify code.
+ /// If you intended to re-export the item to make it available outside of the
+ /// module, add a visibility modifier like `pub`.
+ pub REDUNDANT_IMPORTS,
+ Allow,
+ "imports that are redundant due to being imported already"
+}
+
+declare_lint! {
/// The `must_not_suspend` lint guards against values that shouldn't be held across suspend points
/// (`.await`)
///
@@ -615,8 +643,6 @@
/// ### Example
///
/// ```rust
- /// #![cfg_attr(bootstrap, feature(lint_reasons))]
- ///
/// #[expect(unused_variables)]
/// let x = 10;
/// println!("{}", x);
@@ -1241,7 +1267,7 @@
Deny,
"type parameter default erroneously allowed in invalid location",
@future_incompatible = FutureIncompatibleInfo {
- reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+ reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
};
}
@@ -1834,8 +1860,7 @@
/// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions
pub ELIDED_LIFETIMES_IN_PATHS,
Allow,
- "hidden lifetime parameters in types are deprecated",
- crate_level_only
+ "hidden lifetime parameters in types are deprecated"
}
declare_lint! {
@@ -3265,6 +3290,39 @@
}
declare_lint! {
+ /// The `explicit_builtin_cfgs_in_flags` lint detects builtin cfgs set via the `--cfg` flag.
+ ///
+ /// ### Example
+ ///
+ /// ```text
+ /// rustc --cfg unix
+ /// ```
+ ///
+ /// ```rust,ignore (needs command line option)
+ /// fn main() {}
+ /// ```
+ ///
+ /// This will produce:
+ ///
+ /// ```text
+ /// error: unexpected `--cfg unix` flag
+ /// |
+ /// = note: config `unix` is only supposed to be controlled by `--target`
+ /// = note: manually setting a built-in cfg can and does create incoherent behaviors
+ /// = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+ /// ```
+ ///
+ /// ### Explanation
+ ///
+ /// Setting builtin cfgs can and does produce incoherent behavior, it's better to the use
+ /// the appropriate `rustc` flag that controls the config. For example setting the `windows`
+ /// cfg but on Linux based target.
+ pub EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
+ Deny,
+ "detects builtin cfgs set via the `--cfg`"
+}
+
+declare_lint! {
/// The `repr_transparent_external_private_fields` lint
/// detects types marked `#[repr(transparent)]` that (transitively)
/// contain an external ZST type marked `#[non_exhaustive]` or containing
@@ -3755,6 +3813,46 @@
}
declare_lint! {
+ /// The `rust_2024_prelude_collisions` lint detects the usage of trait methods which are ambiguous
+ /// with traits added to the prelude in future editions.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,edition2021,compile_fail
+ /// #![deny(rust_2024_prelude_collisions)]
+ /// trait Meow {
+ /// fn poll(&self) {}
+ /// }
+ /// impl<T> Meow for T {}
+ ///
+ /// fn main() {
+ /// core::pin::pin!(async {}).poll();
+ /// // ^^^^^^
+ /// // This call to try_into matches both Future::poll and Meow::poll as
+ /// // `Future` has been added to the Rust prelude in 2024 edition.
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Rust 2024, introduces two new additions to the standard library's prelude:
+ /// `Future` and `IntoFuture`. This results in an ambiguity as to which method/function
+ /// to call when an existing `poll`/`into_future` method is called via dot-call syntax or
+ /// a `poll`/`into_future` associated function is called directly on a type.
+ ///
+ pub RUST_2024_PRELUDE_COLLISIONS,
+ Allow,
+ "detects the usage of trait methods which are ambiguous with traits added to the \
+ prelude in future editions",
+ @future_incompatible = FutureIncompatibleInfo {
+ reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>",
+ };
+}
+
+declare_lint! {
/// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a
/// prefix instead in Rust 2021.
///
@@ -4251,39 +4349,6 @@
}
declare_lint! {
- /// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field
- /// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or
- /// more built-in traits.
- ///
- /// ### Example
- ///
- /// ```rust
- /// #[repr(packed)]
- /// #[derive(Hash)]
- /// struct FlexZeroSlice {
- /// width: u8,
- /// data: [u8],
- /// }
- /// ```
- ///
- /// {{produces}}
- ///
- /// ### Explanation
- ///
- /// This was previously accepted but is being phased out, because fields in packed structs are
- /// now required to implement `Copy` for `derive` to work. Byte slices and string slices are a
- /// temporary exception because certain crates depended on them.
- pub BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
- Warn,
- "`[u8]` or `str` used in a packed struct with `derive`",
- @future_incompatible = FutureIncompatibleInfo {
- reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
- reference: "issue #107457 <https://github.com/rust-lang/rust/issues/107457>",
- };
- report_in_external_macro
-}
-
-declare_lint! {
/// The `invalid_macro_export_arguments` lint detects cases where `#[macro_export]` is being used with invalid arguments.
///
/// ### Example
@@ -4869,7 +4934,6 @@
/// ### Example
///
/// ```rust
- /// #![feature(unsafe_extern_blocks)]
/// #![warn(missing_unsafe_on_extern)]
/// #![allow(dead_code)]
///
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index f87f19e..0f07de4 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -1,4 +1,3 @@
-pub use self::Level::*;
use rustc_ast::node_id::NodeId;
use rustc_ast::{AttrId, Attribute};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -7,16 +6,16 @@
};
use rustc_error_messages::{DiagMessage, MultiSpan};
use rustc_hir::def::Namespace;
-use rustc_hir::HashStableContext;
-use rustc_hir::HirId;
+use rustc_hir::{HashStableContext, HirId};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::Edition;
-use rustc_span::symbol::MacroRulesNormalizedIdent;
-use rustc_span::{sym, symbol::Ident, Span, Symbol};
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
+use rustc_span::{sym, Span, Symbol};
use rustc_target::spec::abi::Abi;
-
use serde::{Deserialize, Serialize};
+pub use self::Level::*;
+
pub mod builtin;
#[macro_export]
@@ -747,6 +746,11 @@ pub enum BuiltinLintDiag {
OutOfScopeMacroCalls {
path: String,
},
+ UnexpectedBuiltinCfg {
+ cfg: String,
+ cfg_name: Symbol,
+ controlled_by: &'static str,
+ },
}
/// Lints that are buffered up early on in the `Session` before the
@@ -754,7 +758,7 @@ pub enum BuiltinLintDiag {
#[derive(Debug)]
pub struct BufferedEarlyLint {
/// The span of code that we are linting on.
- pub span: MultiSpan,
+ pub span: Option<MultiSpan>,
/// The `NodeId` of the AST node that generated the lint.
pub node_id: NodeId,
@@ -792,7 +796,7 @@ pub fn buffer_lint(
self.add_early_lint(BufferedEarlyLint {
lint_id: LintId::of(lint),
node_id,
- span: span.into(),
+ span: Some(span.into()),
diagnostic,
});
}
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 4c1f78e..b2ff9ef 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -259,6 +259,7 @@ fn main() {
cmd.args(&components);
for lib in output(&mut cmd).split_whitespace() {
+ let mut is_static = false;
let name = if let Some(stripped) = lib.strip_prefix("-l") {
stripped
} else if let Some(stripped) = lib.strip_prefix('-') {
@@ -266,8 +267,24 @@ fn main() {
} else if Path::new(lib).exists() {
// On MSVC llvm-config will print the full name to libraries, but
// we're only interested in the name part
- let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
- name.trim_end_matches(".lib")
+ // On Unix when we get a static library llvm-config will print the
+ // full name and we *are* interested in the path, but we need to
+ // handle it separately. For example, when statically linking to
+ // libzstd llvm-config will output something like
+ // -lrt -ldl -lm -lz /usr/local/lib/libzstd.a -lxml2
+ // and we transform the zstd part into
+ // cargo:rustc-link-search-native=/usr/local/lib
+ // cargo:rustc-link-lib=static=zstd
+ let path = Path::new(lib);
+ if lib.ends_with(".a") {
+ is_static = true;
+ println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
+ let name = path.file_stem().unwrap().to_str().unwrap();
+ name.trim_start_matches("lib")
+ } else {
+ let name = path.file_name().unwrap().to_str().unwrap();
+ name.trim_end_matches(".lib")
+ }
} else if lib.ends_with(".lib") {
// Some MSVC libraries just come up with `.lib` tacked on, so chop
// that off
@@ -285,7 +302,13 @@ fn main() {
continue;
}
- let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" };
+ let kind = if name.starts_with("LLVM") {
+ llvm_kind
+ } else if is_static {
+ "static"
+ } else {
+ "dylib"
+ };
println!("cargo:rustc-link-lib={kind}={name}");
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 4cdd8af..79a68b2 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -397,6 +397,18 @@
std::nullopt));
}
+extern "C" LLVMAttributeRef
+LLVMRustCreateRangeAttribute(LLVMContextRef C, unsigned NumBits,
+ const uint64_t LowerWords[],
+ const uint64_t UpperWords[]) {
+#if LLVM_VERSION_GE(19, 0)
+ return LLVMCreateConstantRangeAttribute(C, Attribute::Range, NumBits,
+ LowerWords, UpperWords);
+#else
+ report_fatal_error("LLVM 19.0 is required for Range Attribute");
+#endif
+}
+
// These values **must** match ffi::AllocKindFlags.
// It _happens_ to match the LLVM values of llvm::AllocFnKind,
// but that's happenstance and we do explicit conversions before
@@ -1555,7 +1567,7 @@
extern "C" LLVMValueRef
LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) {
-#if LLVM_VERSION_GE(18, 0)
+#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0)
return wrap(llvm::Intrinsic::getDeclaration(
unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update));
#else
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index 1365afb..939e5e4 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -7,10 +7,11 @@
// NOTE: This crate only exists to allow linking on mingw targets.
-use libc::{c_char, size_t};
use std::cell::RefCell;
use std::slice;
+use libc::{c_char, size_t};
+
#[repr(C)]
pub struct RustString {
pub bytes: RefCell<Vec<u8>>,
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index 01b6e34..b6d8707 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -41,12 +41,11 @@
use std::env::{self, VarError};
use std::fmt::{self, Display};
use std::io::{self, IsTerminal};
+
use tracing_core::{Event, Subscriber};
use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter};
-use tracing_subscriber::fmt::{
- format::{self, FormatEvent, FormatFields},
- FmtContext,
-};
+use tracing_subscriber::fmt::format::{self, FormatEvent, FormatFields};
+use tracing_subscriber::fmt::FmtContext;
use tracing_subscriber::layer::SubscriberExt;
/// The values of all the environment variables that matter for configuring a logger.
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 2743660..52d892a 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -2,14 +2,15 @@
use std::cell::RefCell;
-use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind;
-use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
-use crate::diagnostics::utils::SetOnce;
use proc_macro2::TokenStream;
use quote::quote;
use syn::spanned::Spanned;
use synstructure::Structure;
+use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind;
+use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
+use crate::diagnostics::utils::SetOnce;
+
/// The central struct for constructing the `into_diag` method from an annotated struct.
pub(crate) struct DiagnosticDerive<'a> {
structure: Structure<'a>,
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index f93d89d..5c2a429 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -1,5 +1,12 @@
#![deny(unused_must_use)]
+use proc_macro2::{Ident, Span, TokenStream};
+use quote::{format_ident, quote, quote_spanned};
+use syn::spanned::Spanned;
+use syn::{parse_quote, Attribute, Meta, Path, Token, Type};
+use synstructure::{BindingInfo, Structure, VariantInfo};
+
+use super::utils::SubdiagnosticVariant;
use crate::diagnostics::error::{
span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
};
@@ -8,13 +15,6 @@
should_generate_arg, type_is_bool, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy,
FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
-use proc_macro2::{Ident, Span, TokenStream};
-use quote::{format_ident, quote, quote_spanned};
-use syn::Token;
-use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
-use synstructure::{BindingInfo, Structure, VariantInfo};
-
-use super::utils::SubdiagnosticVariant;
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
#[derive(Clone, Copy, PartialEq, Eq)]
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index 13138ee..9cdb9fb 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -1,7 +1,8 @@
use proc_macro::{Diagnostic, Level, MultiSpan};
use proc_macro2::TokenStream;
use quote::quote;
-use syn::{spanned::Spanned, Attribute, Error as SynError, Meta};
+use syn::spanned::Spanned;
+use syn::{Attribute, Error as SynError, Meta};
#[derive(Debug)]
pub(crate) enum DiagnosticDeriveError {
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 7f090f5..5d5d279 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -1,5 +1,12 @@
#![deny(unused_must_use)]
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote};
+use syn::spanned::Spanned;
+use syn::{Attribute, Meta, MetaList, Path};
+use synstructure::{BindingInfo, Structure, VariantInfo};
+
+use super::utils::SubdiagnosticVariant;
use crate::diagnostics::error::{
invalid_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
};
@@ -9,12 +16,6 @@
should_generate_arg, AllowMultipleAlternatives, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap,
SetOnce, SpannedOption, SubdiagnosticKind,
};
-use proc_macro2::TokenStream;
-use quote::{format_ident, quote};
-use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path};
-use synstructure::{BindingInfo, Structure, VariantInfo};
-
-use super::utils::SubdiagnosticVariant;
/// The central struct for constructing the `add_to_diag` method from an annotated struct.
pub(crate) struct SubdiagnosticDerive {
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 05a5a32..0d3b2f5 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -1,20 +1,21 @@
-use crate::diagnostics::error::{
- span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
-};
-use proc_macro::Span;
-use proc_macro2::{Ident, TokenStream};
-use quote::{format_ident, quote, ToTokens};
use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::str::FromStr;
+
+use proc_macro::Span;
+use proc_macro2::{Ident, TokenStream};
+use quote::{format_ident, quote, ToTokens};
use syn::meta::ParseNestedMeta;
use syn::punctuated::Punctuated;
-use syn::{parenthesized, LitStr, Path, Token};
-use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple};
+use syn::spanned::Spanned;
+use syn::{parenthesized, Attribute, Field, LitStr, Meta, Path, Token, Type, TypeTuple};
use synstructure::{BindingInfo, VariantInfo};
use super::error::invalid_attr;
+use crate::diagnostics::error::{
+ span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
+};
thread_local! {
pub(crate) static CODE_IDENT_COUNT: RefCell<u32> = RefCell::new(0);
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 9d7418c..c59f86b 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -10,9 +10,8 @@
#![feature(proc_macro_tracked_env)]
// tidy-alphabetical-end
-use synstructure::decl_derive;
-
use proc_macro::TokenStream;
+use synstructure::decl_derive;
mod current_version;
mod diagnostics;
diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs
index 488d450..6074c93 100644
--- a/compiler/rustc_macros/src/symbols.rs
+++ b/compiler/rustc_macros/src/symbols.rs
@@ -24,11 +24,13 @@
//! CFG_RELEASE="0.0.0" cargo +nightly expand > /tmp/rustc_span.rs
//! ```
+use std::collections::HashMap;
+
use proc_macro2::{Span, TokenStream};
use quote::quote;
-use std::collections::HashMap;
use syn::parse::{Parse, ParseStream, Result};
-use syn::{braced, punctuated::Punctuated, Expr, Ident, Lit, LitStr, Macro, Token};
+use syn::punctuated::Punctuated;
+use syn::{braced, Expr, Ident, Lit, LitStr, Macro, Token};
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 415399e..d80aa0c 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -41,6 +41,9 @@
metadata_crate_dep_not_static =
`{$crate_name}` was unavailable as a static crate, preventing fully static linking
+metadata_crate_dep_rustc_driver =
+ `feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library
+
metadata_crate_location_unknown_type =
extern location for {$crate_name} is of an unknown type: {$path}
@@ -131,12 +134,18 @@
metadata_lib_required =
crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
+metadata_link_arg_unstable =
+ link kind `link-arg` is unstable
+
metadata_link_cfg_form =
link cfg must be of the form `cfg(/* predicate */)`
metadata_link_cfg_single_predicate =
link cfg must have a single predicate argument
+metadata_link_cfg_unstable =
+ link cfg is unstable
+
metadata_link_framework_apple =
link kind `framework` is only supported on Apple targets
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 749495b..14a1a7f 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1,9 +1,13 @@
//! Validates all used crates and extern libraries and loads their metadata
-use crate::errors;
-use crate::locator::{CrateError, CrateLocator, CratePaths};
-use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
+use std::error::Error;
+use std::ops::Fn;
+use std::path::Path;
+use std::str::FromStr;
+use std::time::Duration;
+use std::{cmp, env, iter};
+use proc_macro::bridge::client::ProcMacro;
use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, AllocatorKind};
use rustc_ast::{self as ast, *};
use rustc_data_structures::fx::FxHashSet;
@@ -29,13 +33,9 @@
use rustc_target::spec::{PanicStrategy, Target, TargetTriple};
use tracing::{debug, info, trace};
-use proc_macro::bridge::client::ProcMacro;
-use std::error::Error;
-use std::ops::Fn;
-use std::path::Path;
-use std::str::FromStr;
-use std::time::Duration;
-use std::{cmp, env, iter};
+use crate::errors;
+use crate::locator::{CrateError, CrateLocator, CratePaths};
+use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
/// The backend's way to give the crate store access to the metadata in a library.
/// Note that it returns the raw metadata bytes stored in the library file, whether
@@ -949,7 +949,6 @@ fn inject_dependency_if(
}
}
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn report_unused_deps(&mut self, krate: &ast::Crate) {
// Make a point span rather than covering the whole file
let span = krate.spans.inner_span.shrink_to_lo();
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 9c69ab2..39fa237 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -51,13 +51,7 @@
//! Additionally, the algorithm is geared towards finding *any* solution rather
//! than finding a number of solutions (there are normally quite a few).
-use crate::creader::CStore;
-use crate::errors::{
- BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
- NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes,
-};
-
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::CrateNum;
use rustc_middle::bug;
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
@@ -65,8 +59,16 @@
use rustc_session::config::CrateType;
use rustc_session::cstore::CrateDepKind;
use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
+use rustc_span::sym;
use tracing::info;
+use crate::creader::CStore;
+use crate::errors::{
+ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
+ NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired,
+ TwoPanicRuntimes,
+};
+
pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
tcx.crate_types()
.iter()
@@ -160,25 +162,49 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
}
+ let all_dylibs = || {
+ tcx.crates(()).iter().filter(|&&cnum| {
+ !tcx.dep_kind(cnum).macros_only() && tcx.used_crate_source(cnum).dylib.is_some()
+ })
+ };
+
+ let mut upstream_in_dylibs = FxHashSet::default();
+
+ if tcx.features().rustc_private {
+ // We need this to prevent users of `rustc_driver` from linking dynamically to `std`
+ // which does not work as `std` is also statically linked into `rustc_driver`.
+
+ // Find all libraries statically linked to upstream dylibs.
+ for &cnum in all_dylibs() {
+ let deps = tcx.dylib_dependency_formats(cnum);
+ for &(depnum, style) in deps.iter() {
+ if let RequireStatic = style {
+ upstream_in_dylibs.insert(depnum);
+ }
+ }
+ }
+ }
+
let mut formats = FxHashMap::default();
// Sweep all crates for found dylibs. Add all dylibs, as well as their
// dependencies, ensuring there are no conflicts. The only valid case for a
// dependency to be relied upon twice is for both cases to rely on a dylib.
- for &cnum in tcx.crates(()).iter() {
- if tcx.dep_kind(cnum).macros_only() {
+ for &cnum in all_dylibs() {
+ if upstream_in_dylibs.contains(&cnum) {
+ info!("skipping dylib: {}", tcx.crate_name(cnum));
+ // If this dylib is also available statically linked to another dylib
+ // we try to use that instead.
continue;
}
+
let name = tcx.crate_name(cnum);
- let src = tcx.used_crate_source(cnum);
- if src.dylib.is_some() {
- info!("adding dylib: {}", name);
- add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static);
- let deps = tcx.dylib_dependency_formats(cnum);
- for &(depnum, style) in deps.iter() {
- info!("adding {:?}: {}", style, tcx.crate_name(depnum));
- add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static);
- }
+ info!("adding dylib: {}", name);
+ add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static);
+ let deps = tcx.dylib_dependency_formats(cnum);
+ for &(depnum, style) in deps.iter() {
+ info!("adding {:?}: {}", style, tcx.crate_name(depnum));
+ add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static);
}
}
@@ -268,12 +294,15 @@ fn add_library(
// This error is probably a little obscure, but I imagine that it
// can be refined over time.
if link2 != link || link == RequireStatic {
+ let linking_to_rustc_driver = tcx.sess.psess.unstable_features.is_nightly_build()
+ && tcx.crates(()).iter().any(|&cnum| tcx.crate_name(cnum) == sym::rustc_driver);
tcx.dcx().emit_err(CrateDepMultiple {
crate_name: tcx.crate_name(cnum),
non_static_deps: unavailable_as_static
.drain(..)
.map(|cnum| NonStaticCrateDep { crate_name: tcx.crate_name(cnum) })
.collect(),
+ rustc_driver_help: linking_to_rustc_driver.then_some(RustcDriverHelp),
});
}
}
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index b0d82a0..42dec97 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -1,9 +1,8 @@
-use std::{
- io::Error,
- path::{Path, PathBuf},
-};
+use std::io::Error;
+use std::path::{Path, PathBuf};
-use rustc_errors::{codes::*, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{sym, Span, Symbol};
use rustc_target::spec::{PanicStrategy, TargetTriple};
@@ -39,6 +38,8 @@ pub struct CrateDepMultiple {
pub crate_name: Symbol,
#[subdiagnostic]
pub non_static_deps: Vec<NonStaticCrateDep>,
+ #[subdiagnostic]
+ pub rustc_driver_help: Option<RustcDriverHelp>,
}
#[derive(Subdiagnostic)]
@@ -47,6 +48,10 @@ pub struct NonStaticCrateDep {
pub crate_name: Symbol,
}
+#[derive(Subdiagnostic)]
+#[help(metadata_crate_dep_rustc_driver)]
+pub struct RustcDriverHelp;
+
#[derive(Diagnostic)]
#[diag(metadata_two_panic_runtimes)]
pub struct TwoPanicRuntimes {
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index a0abda5..b2a979e 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -1,8 +1,5 @@
-use crate::errors::{
- BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile,
- FailedCreateTempdir, FailedWriteError,
-};
-use crate::{encode_metadata, EncodedMetadata};
+use std::path::{Path, PathBuf};
+use std::{fs, io};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_middle::ty::TyCtxt;
@@ -11,8 +8,11 @@
use rustc_session::{MetadataKind, Session};
use tempfile::Builder as TempFileBuilder;
-use std::path::{Path, PathBuf};
-use std::{fs, io};
+use crate::errors::{
+ BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile,
+ FailedCreateTempdir, FailedWriteError,
+};
+use crate::{encode_metadata, EncodedMetadata};
// FIXME(eddyb) maybe include the crate name in this?
pub const METADATA_FILENAME: &str = "lib.rmeta";
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 90fe52a..25ae7b2 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -212,9 +212,11 @@
//! no means all of the necessary details. Take a look at the rest of
//! metadata::locator or metadata::creader for all the juicy details!
-use crate::creader::{Library, MetadataLoader};
-use crate::errors;
-use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
+use std::borrow::Cow;
+use std::io::{Read, Result as IoResult, Write};
+use std::ops::Deref;
+use std::path::{Path, PathBuf};
+use std::{cmp, fmt};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::memmap::Mmap;
@@ -230,14 +232,12 @@
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_target::spec::{Target, TargetTriple};
+use snap::read::FrameDecoder;
use tracing::{debug, info};
-use snap::read::FrameDecoder;
-use std::borrow::Cow;
-use std::io::{Read, Result as IoResult, Write};
-use std::ops::Deref;
-use std::path::{Path, PathBuf};
-use std::{cmp, fmt};
+use crate::creader::{Library, MetadataLoader};
+use crate::errors;
+use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
#[derive(Clone)]
pub(crate) struct CrateLocator<'a> {
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 1254ebe..34497f5 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -1,3 +1,5 @@
+use std::path::PathBuf;
+
use rustc_ast::{NestedMetaItem, CRATE_NODE_ID};
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashSet;
@@ -15,9 +17,7 @@
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
-use crate::errors;
-
-use std::path::PathBuf;
+use crate::{errors, fluent_generated};
pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf {
let formats = if verbatim {
@@ -87,7 +87,6 @@ struct Collector<'tcx> {
}
impl<'tcx> Collector<'tcx> {
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn process_module(&mut self, module: &ForeignModule) {
let ForeignModule { def_id, abi, ref foreign_items } = *module;
let def_id = def_id.expect_local();
@@ -161,7 +160,7 @@ fn process_module(&mut self, module: &ForeignModule) {
sess,
sym::link_arg_attribute,
span,
- "link kind `link-arg` is unstable",
+ fluent_generated::metadata_link_arg_unstable,
)
.emit();
}
@@ -201,8 +200,13 @@ fn process_module(&mut self, module: &ForeignModule) {
continue;
};
if !features.link_cfg {
- feature_err(sess, sym::link_cfg, item.span(), "link cfg is unstable")
- .emit();
+ feature_err(
+ sess,
+ sym::link_cfg,
+ item.span(),
+ fluent_generated::metadata_link_cfg_unstable,
+ )
+ .emit();
}
cfg = Some(link_cfg.clone());
}
@@ -266,6 +270,8 @@ fn process_module(&mut self, module: &ForeignModule) {
macro report_unstable_modifier($feature: ident) {
if !features.$feature {
+ // FIXME: make this translatable
+ #[expect(rustc::untranslatable_diagnostic)]
feature_err(
sess,
sym::$feature,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 9874624..8c0ea3e 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1,9 +1,11 @@
// Decoding metadata from a single crate's metadata
-use crate::creader::CStore;
-use crate::rmeta::table::IsDefault;
-use crate::rmeta::*;
+use std::iter::TrustedLen;
+use std::path::Path;
+use std::{io, iter, mem};
+pub(super) use cstore_impl::provide;
+use proc_macro::bridge::client::ProcMacro;
use rustc_ast as ast;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
@@ -27,17 +29,14 @@
use rustc_serialize::{Decodable, Decoder};
use rustc_session::cstore::{CrateSource, ExternCrate};
use rustc_session::Session;
+use rustc_span::hygiene::HygieneDecodeContext;
use rustc_span::symbol::kw;
use rustc_span::{BytePos, Pos, SpanData, SpanDecoder, SyntaxContext, DUMMY_SP};
use tracing::debug;
-use proc_macro::bridge::client::ProcMacro;
-use std::iter::TrustedLen;
-use std::path::Path;
-use std::{io, iter, mem};
-
-pub(super) use cstore_impl::provide;
-use rustc_span::hygiene::HygieneDecodeContext;
+use crate::creader::CStore;
+use crate::rmeta::table::IsDefault;
+use crate::rmeta::*;
mod cstore_impl;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index bbd9ab5..46039f6 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -1,8 +1,5 @@
-use crate::creader::{CStore, LoadedMacro};
-use crate::foreign_modules;
-use crate::native_libs;
-use crate::rmeta::table::IsDefault;
-use crate::rmeta::AttrFlags;
+use std::any::Any;
+use std::mem;
use rustc_ast as ast;
use rustc_attr::Deprecation;
@@ -15,8 +12,7 @@
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::middle::stability::DeprecationEntry;
-use rustc_middle::query::ExternProviders;
-use rustc_middle::query::LocalCrate;
+use rustc_middle::query::{ExternProviders, LocalCrate};
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::util::Providers;
@@ -26,10 +22,11 @@
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
-use std::any::Any;
-use std::mem;
-
use super::{Decodable, DecodeContext, DecodeIterator};
+use crate::creader::{CStore, LoadedMacro};
+use crate::rmeta::table::IsDefault;
+use crate::rmeta::AttrFlags;
+use crate::{foreign_modules, native_libs};
trait ProcessQueryValue<'tcx, T> {
fn process_decoded(self, _tcx: TyCtxt<'tcx>, _err: impl Fn() -> !) -> T;
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 861bf6b..01fbf37 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -1,11 +1,11 @@
-use crate::rmeta::DecodeContext;
-use crate::rmeta::EncodeContext;
use rustc_data_structures::owned_slice::OwnedSlice;
use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
use rustc_middle::parameterized_over_tcx;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::def_id::{DefIndex, DefPathHash};
+use crate::rmeta::{DecodeContext, EncodeContext};
+
pub(crate) enum DefPathHashMapRef<'tcx> {
OwnedFromMetadata(odht::HashTable<HashMapConfig, OwnedSlice>),
BorrowedFromTcx(&'tcx DefPathHashMap),
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 6f31c0f..0d83f8c 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1,5 +1,8 @@
-use crate::errors::{FailCreateFileEncoder, FailWriteFile};
-use crate::rmeta::*;
+use std::borrow::Borrow;
+use std::collections::hash_map::Entry;
+use std::fs::File;
+use std::io::{Read, Seek, Write};
+use std::path::{Path, PathBuf};
use rustc_ast::Attribute;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
@@ -27,13 +30,11 @@
use rustc_span::{
ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId, SyntaxContext,
};
-use std::borrow::Borrow;
-use std::collections::hash_map::Entry;
-use std::fs::File;
-use std::io::{Read, Seek, Write};
-use std::path::{Path, PathBuf};
use tracing::{debug, instrument, trace};
+use crate::errors::{FailCreateFileEncoder, FailWriteFile};
+use crate::rmeta::*;
+
pub(super) struct EncodeContext<'a, 'tcx> {
opaque: opaque::FileEncoder,
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index e565c8c..c1b7717 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -1,35 +1,35 @@
-use crate::creader::CrateMetadataRef;
+use std::marker::PhantomData;
+use std::num::NonZero;
+
pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
use decoder::{DecodeContext, Metadata};
use def_path_hash_map::DefPathHashMapRef;
use encoder::EncodeContext;
pub use encoder::{encode_metadata, rendered_const, EncodedMetadata};
-use rustc_ast as ast;
use rustc_ast::expand::StrippedCfgItem;
-use rustc_attr as attr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh;
-use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId};
use rustc_hir::definitions::DefKey;
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
-use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable};
-use rustc_macros::{MetadataDecodable, MetadataEncodable};
+use rustc_macros::{
+ Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable, TyEncodable,
+};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::middle::lib_features::FeatureStability;
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
-use rustc_middle::mir;
-use rustc_middle::trivially_parameterized_over_tcx;
use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::{self, ReprOptions, Ty, UnusedGenericParams};
-use rustc_middle::ty::{DeducedParamAttrs, ParameterizedOverTcx, TyCtxt};
+use rustc_middle::ty::{
+ self, DeducedParamAttrs, ParameterizedOverTcx, ReprOptions, Ty, TyCtxt, UnusedGenericParams,
+};
use rustc_middle::util::Providers;
+use rustc_middle::{mir, trivially_parameterized_over_tcx};
use rustc_serialize::opaque::FileEncoder;
use rustc_session::config::SymbolManglingVersion;
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
@@ -39,9 +39,10 @@
use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Span};
use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_target::spec::{PanicStrategy, TargetTriple};
-use std::marker::PhantomData;
-use std::num::NonZero;
use table::TableBuilder;
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
+
+use crate::creader::CrateMetadataRef;
mod decoder;
mod def_path_hash_map;
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index dcbddad..617372a 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -1,9 +1,9 @@
-use crate::rmeta::*;
-
use rustc_hir::def::CtorOf;
use rustc_index::Idx;
use tracing::trace;
+use crate::rmeta::*;
+
pub(super) trait IsDefault: Default {
fn is_default(&self) -> bool;
}
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 84b47a6..9ebe4a5 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -56,18 +56,17 @@
//!
//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html
-use crate::mir::mono::MonoItem;
-use crate::ty::TyCtxt;
-
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_hir::{HirId, ItemLocalId, OwnerId};
+pub use rustc_query_system::dep_graph::dep_node::DepKind;
use rustc_query_system::dep_graph::FingerprintStyle;
+pub use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams};
use rustc_span::symbol::Symbol;
-pub use rustc_query_system::dep_graph::dep_node::DepKind;
-pub use rustc_query_system::dep_graph::{DepContext, DepNode, DepNodeParams};
+use crate::mir::mono::MonoItem;
+use crate::ty::TyCtxt;
macro_rules! define_dep_nodes {
(
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index dc0da16..b249545 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -1,20 +1,19 @@
-use crate::ty::{self, TyCtxt};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_query_system::ich::StableHashingContext;
use rustc_session::Session;
+use crate::ty::{self, TyCtxt};
+
#[macro_use]
mod dep_node;
-pub use rustc_query_system::dep_graph::debug::EdgeFilter;
-pub use rustc_query_system::dep_graph::{
- debug::DepNodeFilter, hash_result, DepContext, DepGraphQuery, DepNodeIndex, Deps,
- SerializedDepGraph, SerializedDepNodeIndex, TaskDepsRef, WorkProduct, WorkProductId,
- WorkProductMap,
-};
-
pub use dep_node::{dep_kinds, label_strs, DepKind, DepNode, DepNodeExt};
pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
+pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter};
+pub use rustc_query_system::dep_graph::{
+ hash_result, DepContext, DepGraphQuery, DepNodeIndex, Deps, SerializedDepGraph,
+ SerializedDepNodeIndex, TaskDepsRef, WorkProduct, WorkProductId, WorkProductMap,
+};
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepsType>;
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 711db4e..61348cd 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,7 +1,8 @@
use std::fmt;
use std::path::PathBuf;
-use rustc_errors::{codes::*, DiagArgName, DiagArgValue, DiagMessage};
+use rustc_errors::codes::*;
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index ad59bfa..edab6b5 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,8 +1,3 @@
-use crate::hir::ModuleItems;
-use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
-use crate::query::LocalCrate;
-use crate::ty::TyCtxt;
-use rustc_ast as ast;
use rustc_ast::visit::{walk_list, VisitorResult};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -13,12 +8,17 @@
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::intravisit::Visitor;
use rustc_hir::*;
-use rustc_hir_pretty as pprust_hir;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ErrorGuaranteed, Span};
use rustc_target::spec::abi::Abi;
+use {rustc_ast as ast, rustc_hir_pretty as pprust_hir};
+
+use crate::hir::ModuleItems;
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
+use crate::query::LocalCrate;
+use crate::ty::TyCtxt;
// FIXME: the structure was necessary in the past but now it
// only serves as "namespace" for HIR-related methods, and can be
@@ -746,6 +746,10 @@ pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> {
}
}
+ pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option<DefId> {
+ self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id()
+ }
+
#[inline]
fn opt_ident(self, id: HirId) -> Option<Ident> {
match self.tcx.hir_node(id) {
@@ -1161,17 +1165,23 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
}
Node::ImplItem(ii) => {
let kind = match ii.kind {
- ImplItemKind::Const(..) => "assoc const",
- ImplItemKind::Fn(..) => "method",
- ImplItemKind::Type(_) => "assoc type",
+ ImplItemKind::Const(..) => "associated constant",
+ ImplItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+ ImplicitSelfKind::None => "associated function",
+ _ => "method",
+ },
+ ImplItemKind::Type(_) => "associated type",
};
format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id))
}
Node::TraitItem(ti) => {
let kind = match ti.kind {
- TraitItemKind::Const(..) => "assoc constant",
- TraitItemKind::Fn(..) => "trait method",
- TraitItemKind::Type(..) => "assoc type",
+ TraitItemKind::Const(..) => "associated constant",
+ TraitItemKind::Fn(fn_sig, _) => match fn_sig.decl.implicit_self {
+ ImplicitSelfKind::None => "associated function",
+ _ => "trait method",
+ },
+ TraitItemKind::Type(..) => "associated type",
};
format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id))
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 57c8ba9..fa521ab 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -6,8 +6,6 @@
pub mod nested_filter;
pub mod place;
-use crate::query::Providers;
-use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -18,6 +16,9 @@
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::{ErrorGuaranteed, ExpnId};
+use crate::query::Providers;
+use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
+
/// Gather the LocalDefId for each item-like within a module, including items contained within
/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
#[derive(Debug, HashStable, Encodable, Decodable)]
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 1ac3531..4c7af0b 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -1,10 +1,10 @@
-use crate::ty;
-use crate::ty::Ty;
-
use rustc_hir::HirId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_target::abi::{FieldIdx, VariantIdx};
+use crate::ty;
+use crate::ty::Ty;
+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum PlaceBase {
diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs
index 75dc685..bde0521 100644
--- a/compiler/rustc_middle/src/hooks/mod.rs
+++ b/compiler/rustc_middle/src/hooks/mod.rs
@@ -3,15 +3,16 @@
//! queries come with a lot of machinery for caching and incremental compilation, whereas hooks are
//! just plain function pointers without any of the query magic.
-use crate::mir;
-use crate::query::TyCtxtAt;
-use crate::ty::{Ty, TyCtxt};
use rustc_hir::def_id::{DefId, DefPathHash};
use rustc_session::StableCrateId;
use rustc_span::def_id::{CrateNum, LocalDefId};
use rustc_span::{ExpnHash, ExpnId, DUMMY_SP};
use tracing::instrument;
+use crate::mir;
+use crate::query::TyCtxtAt;
+use crate::ty::{Ty, TyCtxt};
+
macro_rules! declare_hooks {
($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index dba71d8..d431497 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -21,18 +21,18 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
+use std::collections::hash_map::Entry;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
pub use rustc_type_ir as ir;
pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
use smallvec::SmallVec;
-use std::collections::hash_map::Entry;
use crate::infer::MemberConstraint;
use crate::mir::ConstraintCategory;
-use crate::ty::GenericArg;
-use crate::ty::{self, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
+use crate::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
pub type Canonical<'tcx, V> = ir::Canonical<TyCtxt<'tcx>, V>;
pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs
index f74f71b..19fe9e5 100644
--- a/compiler/rustc_middle/src/infer/mod.rs
+++ b/compiler/rustc_middle/src/infer/mod.rs
@@ -1,12 +1,12 @@
pub mod canonical;
pub mod unify_key;
-use crate::ty::Region;
-use crate::ty::{OpaqueTypeKey, Ty};
use rustc_data_structures::sync::Lrc;
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
use rustc_span::Span;
+use crate::ty::{OpaqueTypeKey, Region, Ty};
+
/// Requires that `region` must be equal to one of the regions in `choice_regions`.
/// We often denote this using the syntax:
///
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index a5da7e7..3fd4aba 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -1,9 +1,11 @@
-use crate::ty::{self, Ty, TyCtxt};
+use std::cmp;
+use std::marker::PhantomData;
+
use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue};
use rustc_span::def_id::DefId;
use rustc_span::Span;
-use std::cmp;
-use std::marker::PhantomData;
+
+use crate::ty::{self, Ty, TyCtxt};
pub trait ToType {
fn to_type<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>;
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index b499604..5bd7736 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -28,6 +28,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::potential_query_instability)]
#![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(allocator_api)]
@@ -48,7 +49,6 @@
#![feature(iter_from_coroutine)]
#![feature(let_chains)]
#![feature(macro_metavar_expr)]
-#![feature(min_exhaustive_patterns)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 4e655ca..8c27cac 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -5,10 +5,8 @@
use rustc_errors::{Diag, MultiSpan};
use rustc_hir::{HirId, ItemLocalId};
use rustc_macros::HashStable;
-use rustc_session::lint::{
- builtin::{self, FORBIDDEN_LINT_GROUPS},
- FutureIncompatibilityReason, Level, Lint, LintId,
-};
+use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS};
+use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintId};
use rustc_session::Session;
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{symbol, DesugaringKind, Span, Symbol, DUMMY_SP};
@@ -230,9 +228,11 @@ pub fn explain_lint_level_source(
err.note_once(format!(
"`{flag} {hyphen_case_lint_name}` implied by `{flag} {hyphen_case_flag_val}`"
));
- err.help_once(format!(
- "to override `{flag} {hyphen_case_flag_val}` add `#[allow({name})]`"
- ));
+ if matches!(orig_level, Level::Warn | Level::Deny) {
+ err.help_once(format!(
+ "to override `{flag} {hyphen_case_flag_val}` add `#[allow({name})]`"
+ ));
+ }
}
}
LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
diff --git a/compiler/rustc_middle/src/metadata.rs b/compiler/rustc_middle/src/metadata.rs
index 589f274..c3175c6 100644
--- a/compiler/rustc_middle/src/metadata.rs
+++ b/compiler/rustc_middle/src/metadata.rs
@@ -1,11 +1,11 @@
-use crate::ty;
-
use rustc_hir::def::Res;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::def_id::DefId;
use rustc_span::symbol::Ident;
use smallvec::SmallVec;
+use crate::ty;
+
/// A simplified version of `ImportKind` from resolve.
/// `DefId`s here correspond to `use` and `extern crate` items themselves, not their targets.
#[derive(Clone, Copy, Debug, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 3ddf889..b7d290e 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -1,10 +1,11 @@
-use crate::mir::mono::Linkage;
use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::symbol::Symbol;
use rustc_target::abi::Align;
use rustc_target::spec::SanitizerSet;
+use crate::mir::mono::Linkage;
+
#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
pub struct CodegenFnAttrs {
pub flags: CodegenFnAttrFlags,
@@ -27,7 +28,7 @@ pub struct CodegenFnAttrs {
pub link_ordinal: Option<u16>,
/// The `#[target_feature(enable = "...")]` attribute and the enabled
/// features (only enabled features are supported right now).
- pub target_features: Vec<Symbol>,
+ pub target_features: Vec<TargetFeature>,
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
pub linkage: Option<Linkage>,
/// The `#[linkage = "..."]` attribute on foreign items and the value we found.
@@ -51,6 +52,15 @@ pub struct CodegenFnAttrs {
}
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
+pub struct TargetFeature {
+ /// The name of the target feature (e.g. "avx")
+ pub name: Symbol,
+ /// The feature is implied by another feature, rather than explicitly added by the
+ /// `#[target_feature]` attribute
+ pub implied: bool,
+}
+
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct PatchableFunctionEntry {
/// Nops to prepend to the function
prefix: u8,
diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
index 74a5dfb..615a740 100644
--- a/compiler/rustc_middle/src/middle/debugger_visualizer.rs
+++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
@@ -1,6 +1,7 @@
+use std::path::PathBuf;
+
use rustc_data_structures::sync::Lrc;
use rustc_macros::{Decodable, Encodable, HashStable};
-use std::path::PathBuf;
#[derive(HashStable)]
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index b35cc83..0bfbd39 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -1,8 +1,8 @@
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, Ty, TyCtxt};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
+use crate::ty::{self, GenericArgsRef, Ty, TyCtxt};
+
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
/// kind of crate, including cdylibs which export very few things.
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index a0c9af4..f141af4 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -7,13 +7,13 @@
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
//! * Functions called by the compiler itself.
-use crate::ty::{self, TyCtxt};
-
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_span::Span;
use rustc_target::spec::PanicStrategy;
+use crate::ty::{self, TyCtxt};
+
impl<'tcx> TyCtxt<'tcx> {
/// Returns the `DefId` for a given `LangItem`.
/// If not found, fatally aborts compilation.
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index d0b4f36..70810f5 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -8,14 +8,14 @@
//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
//! just peeks and looks for that attribute.
-use crate::error::LimitInvalid;
-use crate::query::Providers;
+use std::num::IntErrorKind;
+
use rustc_ast::Attribute;
-use rustc_session::Session;
-use rustc_session::{Limit, Limits};
+use rustc_session::{Limit, Limits, Session};
use rustc_span::symbol::{sym, Symbol};
-use std::num::IntErrorKind;
+use crate::error::LimitInvalid;
+use crate::query::Providers;
pub fn provide(providers: &mut Providers) {
providers.limits = |tcx, ()| Limits {
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 5c395af..0c4f37a 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -6,7 +6,8 @@
pub mod lib_features {
use rustc_data_structures::unord::UnordMap;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
- use rustc_span::{symbol::Symbol, Span};
+ use rustc_span::symbol::Symbol;
+ use rustc_span::Span;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(HashStable, TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 4b47b01..db70f53 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -2,14 +2,16 @@
//! outside their scopes. This pass will also generate a set of exported items
//! which are available for use externally when compiled as a library.
-use crate::ty::{TyCtxt, Visibility};
+use std::hash::Hash;
+
use rustc_data_structures::fx::{FxIndexMap, IndexEntry};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def::DefKind;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
-use std::hash::Hash;
+
+use crate::ty::{TyCtxt, Visibility};
/// Represents the levels of effective visibility an item can have.
///
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 6e89dc4..6ef1801 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -6,7 +6,9 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
-use crate::ty::TyCtxt;
+use std::fmt;
+use std::ops::Deref;
+
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::UnordMap;
use rustc_hir as hir;
@@ -15,8 +17,7 @@
use rustc_span::{Span, DUMMY_SP};
use tracing::debug;
-use std::fmt;
-use std::ops::Deref;
+use crate::ty::TyCtxt;
/// Represents a statically-describable scope that can be used to
/// bound the lifetime/region for values.
diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
index d0103f6..a4f6d7a 100644
--- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
+++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs
@@ -1,13 +1,13 @@
//! Name resolution for lifetimes and late-bound type and const variables: type declarations.
-use crate::ty;
-
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_hir::{ItemLocalId, OwnerId};
use rustc_macros::{Decodable, Encodable, HashStable, TyDecodable, TyEncodable};
+use crate::ty;
+
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum ResolvedArg {
StaticLifetime,
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index b113e81..3b88613 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -1,9 +1,8 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-pub use self::StabilityLevel::*;
+use std::num::NonZero;
-use crate::ty::{self, TyCtxt};
use rustc_ast::NodeId;
use rustc_attr::{
self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
@@ -22,9 +21,11 @@
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
-use std::num::NonZero;
use tracing::debug;
+pub use self::StabilityLevel::*;
+use crate::ty::{self, TyCtxt};
+
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum StabilityLevel {
Unstable,
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index f9398b2..c08bfc1 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -1,6 +1,3 @@
-use crate::mir::traversal::Postorder;
-use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind, START_BLOCK};
-
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph;
use rustc_data_structures::graph::dominators::{dominators, Dominators};
@@ -11,6 +8,9 @@
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec;
+use crate::mir::traversal::Postorder;
+use crate::mir::{BasicBlock, BasicBlockData, Terminator, TerminatorKind, START_BLOCK};
+
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct BasicBlocks<'tcx> {
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 89f5aca..563647a 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -2,16 +2,15 @@
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+use rustc_session::config::RemapPathScopeComponents;
+use rustc_session::RemapFileNameExt;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{HasDataLayout, Size};
use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar};
use crate::mir::{pretty_print_const_value, Promoted};
-use crate::ty::print::with_no_trimmed_paths;
-use crate::ty::GenericArgsRef;
-use crate::ty::ScalarInt;
-use crate::ty::{self, print::pretty_print_const, Ty, TyCtxt};
+use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
+use crate::ty::{self, GenericArgsRef, ScalarInt, Ty, TyCtxt};
///////////////////////////////////////////////////////////////////////////
/// Evaluated Constants
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index 2a59334..b11c523 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -1,11 +1,11 @@
//! Metadata from source code coverage analysis and instrumentation.
+use std::fmt::{self, Debug, Formatter};
+
use rustc_index::IndexVec;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_span::{Span, Symbol};
-use std::fmt::{self, Debug, Formatter};
-
rustc_index::newtype_index! {
/// Used by [`CoverageKind::BlockMarker`] to mark blocks during THIR-to-MIR
/// lowering, so that those blocks can be identified later.
diff --git a/compiler/rustc_middle/src/mir/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs
index 809d4cd..e1c3d81 100644
--- a/compiler/rustc_middle/src/mir/generic_graphviz.rs
+++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs
@@ -1,7 +1,8 @@
+use std::io::{self, Write};
+
use rustc_data_structures::graph::{self, iterate};
use rustc_graphviz as dot;
use rustc_middle::ty::TyCtxt;
-use std::io::{self, Write};
pub struct GraphvizWriter<
'a,
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 2eadc4d..a3fe8f9 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -1,7 +1,8 @@
+use std::io::{self, Write};
+
use gsgdt::GraphvizSettings;
use rustc_graphviz as dot;
use rustc_middle::mir::*;
-use std::io::{self, Write};
use super::generic_graph::mir_fn_to_generic_graph;
use super::pretty::dump_mir_def_ids;
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index cac3bf9..665ab27 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -4,14 +4,14 @@
mod provenance_map;
use std::borrow::Cow;
-use std::fmt;
-use std::hash;
use std::hash::Hash;
use std::ops::{Deref, DerefMut, Range};
-use std::ptr;
+use std::{fmt, hash, ptr};
use either::{Left, Right};
-
+use init_mask::*;
+pub use init_mask::{InitChunk, InitChunkIter};
+use provenance_map::*;
use rustc_ast::Mutability;
use rustc_data_structures::intern::Interned;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
@@ -23,10 +23,6 @@
ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo,
};
use crate::ty;
-use init_mask::*;
-use provenance_map::*;
-
-pub use init_mask::{InitChunk, InitChunkIter};
/// Functionality required for the bytes of an `Allocation`.
pub trait AllocBytes: Clone + fmt::Debug + Deref<Target = [u8]> + DerefMut<Target = [u8]> {
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
index d60db77..1d2a82c 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs
@@ -1,9 +1,8 @@
#[cfg(test)]
mod tests;
-use std::hash;
-use std::iter;
use std::ops::Range;
+use std::{hash, iter};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_serialize::{Decodable, Encodable};
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index 4e37295..4fe2194 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -3,13 +3,14 @@
use std::cmp;
-use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
use rustc_data_structures::sorted_map::SortedMap;
use rustc_macros::HashStable;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::{HasDataLayout, Size};
use tracing::trace;
+use super::{alloc_range, AllocError, AllocRange, AllocResult, CtfeProvenance, Provenance};
+
/// Stores the provenance information of pointers stored in memory.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
#[derive(HashStable)]
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 9df1956..69ce3e0 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,19 +1,19 @@
+use std::any::Any;
+use std::backtrace::Backtrace;
use std::borrow::Cow;
-use std::{any::Any, backtrace::Backtrace, fmt};
+use std::fmt;
use either::Either;
-
use rustc_ast_ir::Mutability;
use rustc_data_structures::sync::Lock;
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_session::CtfeBacktrace;
-use rustc_span::Symbol;
-use rustc_span::{def_id::DefId, Span, DUMMY_SP};
+use rustc_span::def_id::DefId;
+use rustc_span::{Span, Symbol, DUMMY_SP};
use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange};
use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
-
use crate::error;
use crate::mir::{ConstAlloc, ConstValue};
use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
@@ -329,16 +329,22 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// Using a pointer after it got freed.
PointerUseAfterFree(AllocId, CheckInAllocMsg),
/// Used a pointer outside the bounds it is valid for.
- /// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
PointerOutOfBounds {
alloc_id: AllocId,
alloc_size: Size,
ptr_offset: i64,
- ptr_size: Size,
+ /// The size of the memory range that was expected to be in-bounds.
+ inbounds_size: i64,
msg: CheckInAllocMsg,
},
/// Using an integer as a pointer in the wrong way.
- DanglingIntPointer(u64, CheckInAllocMsg),
+ DanglingIntPointer {
+ addr: u64,
+ /// The size of the memory range that was expected to be in-bounds (or 0 if we need an
+ /// allocation but not any actual memory there, e.g. for function pointers).
+ inbounds_size: i64,
+ msg: CheckInAllocMsg,
+ },
/// Used a pointer with bad alignment.
AlignmentCheckFailed(Misalignment, CheckAlignMsg),
/// Writing to read-only memory.
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 15febfa..91e71c1 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -8,15 +8,11 @@
mod queries;
mod value;
-use std::fmt;
-use std::io;
use std::io::{Read, Write};
use std::num::NonZero;
-
-use tracing::{debug, trace};
+use std::{fmt, io};
use rustc_ast::LitKind;
-use rustc_attr::InlineAttr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
use rustc_errors::ErrorGuaranteed;
@@ -25,12 +21,18 @@
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_serialize::{Decodable, Encodable};
use rustc_target::abi::{AddressSpace, Endian, HasDataLayout};
+use tracing::{debug, trace};
+// Also make the error macros available from this module.
+pub use {
+ err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_custom, err_ub_format, err_unsup,
+ err_unsup_format, throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_custom,
+ throw_ub_format, throw_unsup, throw_unsup_format,
+};
-use crate::mir;
-use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::GenericArgKind;
-use crate::ty::{self, Instance, Ty, TyCtxt};
-
+pub use self::allocation::{
+ alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,
+ InitChunk, InitChunkIter,
+};
pub use self::error::{
BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult,
EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind,
@@ -39,21 +41,11 @@
ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
ValidationErrorKind,
};
-// Also make the error macros available from this module.
-pub use {
- err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_custom, err_ub_format, err_unsup,
- err_unsup_format, throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_custom,
- throw_ub_format, throw_unsup, throw_unsup_format,
-};
-
-pub use self::value::Scalar;
-
-pub use self::allocation::{
- alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,
- InitChunk, InitChunkIter,
-};
-
pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance};
+pub use self::value::Scalar;
+use crate::mir;
+use crate::ty::codec::{TyDecoder, TyEncoder};
+use crate::ty::{self, Instance, Ty, TyCtxt};
/// Uniquely identifies one of the following:
/// - A constant
@@ -133,11 +125,10 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>(
AllocDiscriminant::Alloc.encode(encoder);
alloc.encode(encoder);
}
- GlobalAlloc::Function { instance, unique } => {
+ GlobalAlloc::Function { instance } => {
trace!("encoding {:?} with {:#?}", alloc_id, instance);
AllocDiscriminant::Fn.encode(encoder);
instance.encode(encoder);
- unique.encode(encoder);
}
GlobalAlloc::VTable(ty, poly_trait_ref) => {
trace!("encoding {:?} with {ty:#?}, {poly_trait_ref:#?}", alloc_id);
@@ -226,38 +217,32 @@ pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> AllocId
}
// Now decode the actual data.
- let alloc_id = decoder.with_position(pos, |decoder| {
- match alloc_kind {
- AllocDiscriminant::Alloc => {
- trace!("creating memory alloc ID");
- let alloc = <ConstAllocation<'tcx> as Decodable<_>>::decode(decoder);
- trace!("decoded alloc {:?}", alloc);
- decoder.interner().reserve_and_set_memory_alloc(alloc)
- }
- AllocDiscriminant::Fn => {
- trace!("creating fn alloc ID");
- let instance = ty::Instance::decode(decoder);
- trace!("decoded fn alloc instance: {:?}", instance);
- let unique = bool::decode(decoder);
- // Here we cannot call `reserve_and_set_fn_alloc` as that would use a query, which
- // is not possible in this context. That's why the allocation stores
- // whether it is unique or not.
- decoder.interner().reserve_and_set_fn_alloc_internal(instance, unique)
- }
- AllocDiscriminant::VTable => {
- trace!("creating vtable alloc ID");
- let ty = <Ty<'_> as Decodable<D>>::decode(decoder);
- let poly_trait_ref =
- <Option<ty::PolyExistentialTraitRef<'_>> as Decodable<D>>::decode(decoder);
- trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}");
- decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref)
- }
- AllocDiscriminant::Static => {
- trace!("creating extern static alloc ID");
- let did = <DefId as Decodable<D>>::decode(decoder);
- trace!("decoded static def-ID: {:?}", did);
- decoder.interner().reserve_and_set_static_alloc(did)
- }
+ let alloc_id = decoder.with_position(pos, |decoder| match alloc_kind {
+ AllocDiscriminant::Alloc => {
+ trace!("creating memory alloc ID");
+ let alloc = <ConstAllocation<'tcx> as Decodable<_>>::decode(decoder);
+ trace!("decoded alloc {:?}", alloc);
+ decoder.interner().reserve_and_set_memory_alloc(alloc)
+ }
+ AllocDiscriminant::Fn => {
+ trace!("creating fn alloc ID");
+ let instance = ty::Instance::decode(decoder);
+ trace!("decoded fn alloc instance: {:?}", instance);
+ decoder.interner().reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT)
+ }
+ AllocDiscriminant::VTable => {
+ trace!("creating vtable alloc ID");
+ let ty = <Ty<'_> as Decodable<D>>::decode(decoder);
+ let poly_trait_ref =
+ <Option<ty::PolyExistentialTraitRef<'_>> as Decodable<D>>::decode(decoder);
+ trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}");
+ decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref, CTFE_ALLOC_SALT)
+ }
+ AllocDiscriminant::Static => {
+ trace!("creating extern static alloc ID");
+ let did = <DefId as Decodable<D>>::decode(decoder);
+ trace!("decoded static def-ID: {:?}", did);
+ decoder.interner().reserve_and_set_static_alloc(did)
}
});
@@ -272,12 +257,7 @@ pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> AllocId
#[derive(Debug, Clone, Eq, PartialEq, Hash, TyDecodable, TyEncodable, HashStable)]
pub enum GlobalAlloc<'tcx> {
/// The alloc ID is used as a function pointer.
- Function {
- instance: Instance<'tcx>,
- /// Stores whether this instance is unique, i.e. all pointers to this function use the same
- /// alloc ID.
- unique: bool,
- },
+ Function { instance: Instance<'tcx> },
/// This alloc ID points to a symbolic (not-reified) vtable.
VTable(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
@@ -330,14 +310,17 @@ pub fn address_space(&self, cx: &impl HasDataLayout) -> AddressSpace {
}
}
+pub const CTFE_ALLOC_SALT: usize = 0;
+
pub(crate) struct AllocMap<'tcx> {
/// Maps `AllocId`s to their corresponding allocations.
alloc_map: FxHashMap<AllocId, GlobalAlloc<'tcx>>,
- /// Used to ensure that statics and functions only get one associated `AllocId`.
- //
- // FIXME: Should we just have two separate dedup maps for statics and functions each?
- dedup: FxHashMap<GlobalAlloc<'tcx>, AllocId>,
+ /// Used to deduplicate global allocations: functions, vtables, string literals, ...
+ ///
+ /// The `usize` is a "salt" used by Miri to make deduplication imperfect, thus better emulating
+ /// the actual guarantees.
+ dedup: FxHashMap<(GlobalAlloc<'tcx>, usize), AllocId>,
/// The `AllocId` to assign to the next requested ID.
/// Always incremented; never gets smaller.
@@ -375,74 +358,40 @@ pub fn reserve_alloc_id(self) -> AllocId {
/// Reserves a new ID *if* this allocation has not been dedup-reserved before.
/// Should not be used for mutable memory.
- fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>) -> AllocId {
+ fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>, salt: usize) -> AllocId {
let mut alloc_map = self.alloc_map.lock();
if let GlobalAlloc::Memory(mem) = alloc {
if mem.inner().mutability.is_mut() {
bug!("trying to dedup-reserve mutable memory");
}
}
- if let Some(&alloc_id) = alloc_map.dedup.get(&alloc) {
+ let alloc_salt = (alloc, salt);
+ if let Some(&alloc_id) = alloc_map.dedup.get(&alloc_salt) {
return alloc_id;
}
let id = alloc_map.reserve();
- debug!("creating alloc {alloc:?} with id {id:?}");
- alloc_map.alloc_map.insert(id, alloc.clone());
- alloc_map.dedup.insert(alloc, id);
+ debug!("creating alloc {:?} with id {id:?}", alloc_salt.0);
+ alloc_map.alloc_map.insert(id, alloc_salt.0.clone());
+ alloc_map.dedup.insert(alloc_salt, id);
id
}
/// Generates an `AllocId` for a memory allocation. If the exact same memory has been
/// allocated before, this will return the same `AllocId`.
- pub fn reserve_and_set_memory_dedup(self, mem: ConstAllocation<'tcx>) -> AllocId {
- self.reserve_and_set_dedup(GlobalAlloc::Memory(mem))
+ pub fn reserve_and_set_memory_dedup(self, mem: ConstAllocation<'tcx>, salt: usize) -> AllocId {
+ self.reserve_and_set_dedup(GlobalAlloc::Memory(mem), salt)
}
/// Generates an `AllocId` for a static or return a cached one in case this function has been
/// called on the same static before.
pub fn reserve_and_set_static_alloc(self, static_id: DefId) -> AllocId {
- self.reserve_and_set_dedup(GlobalAlloc::Static(static_id))
+ let salt = 0; // Statics have a guaranteed unique address, no salt added.
+ self.reserve_and_set_dedup(GlobalAlloc::Static(static_id), salt)
}
- /// Generates an `AllocId` for a function. The caller must already have decided whether this
- /// function obtains a unique AllocId or gets de-duplicated via the cache.
- fn reserve_and_set_fn_alloc_internal(self, instance: Instance<'tcx>, unique: bool) -> AllocId {
- let alloc = GlobalAlloc::Function { instance, unique };
- if unique {
- // Deduplicate.
- self.reserve_and_set_dedup(alloc)
- } else {
- // Get a fresh ID.
- let mut alloc_map = self.alloc_map.lock();
- let id = alloc_map.reserve();
- alloc_map.alloc_map.insert(id, alloc);
- id
- }
- }
-
- /// Generates an `AllocId` for a function. Depending on the function type,
- /// this might get deduplicated or assigned a new ID each time.
- pub fn reserve_and_set_fn_alloc(self, instance: Instance<'tcx>) -> AllocId {
- // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
- // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
- // duplicated across crates. We thus generate a new `AllocId` for every mention of a
- // function. This means that `main as fn() == main as fn()` is false, while `let x = main as
- // fn(); x == x` is true. However, as a quality-of-life feature it can be useful to identify
- // certain functions uniquely, e.g. for backtraces. So we identify whether codegen will
- // actually emit duplicate functions. It does that when they have non-lifetime generics, or
- // when they can be inlined. All other functions are given a unique address.
- // This is not a stable guarantee! The `inline` attribute is a hint and cannot be relied
- // upon for anything. But if we don't do this, backtraces look terrible.
- let is_generic = instance
- .args
- .into_iter()
- .any(|kind| !matches!(kind.unpack(), GenericArgKind::Lifetime(_)));
- let can_be_inlined = match self.codegen_fn_attrs(instance.def_id()).inline {
- InlineAttr::Never => false,
- _ => true,
- };
- let unique = !is_generic && !can_be_inlined;
- self.reserve_and_set_fn_alloc_internal(instance, unique)
+ /// Generates an `AllocId` for a function. Will get deduplicated.
+ pub fn reserve_and_set_fn_alloc(self, instance: Instance<'tcx>, salt: usize) -> AllocId {
+ self.reserve_and_set_dedup(GlobalAlloc::Function { instance }, salt)
}
/// Generates an `AllocId` for a (symbolic, not-reified) vtable. Will get deduplicated.
@@ -450,8 +399,9 @@ pub fn reserve_and_set_vtable_alloc(
self,
ty: Ty<'tcx>,
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
+ salt: usize,
) -> AllocId {
- self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, poly_trait_ref))
+ self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, poly_trait_ref), salt)
}
/// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index a0acacc..6cfd07d 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -1,10 +1,11 @@
-use super::{AllocId, InterpResult};
+use std::fmt;
+use std::num::NonZero;
use rustc_data_structures::static_assert_size;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_target::abi::{HasDataLayout, Size};
-use std::{fmt, num::NonZero};
+use super::AllocId;
////////////////////////////////////////////////////////////////////////////////
// Pointer arithmetic
@@ -39,62 +40,13 @@ fn target_isize_max(&self) -> i64 {
}
#[inline]
- fn target_usize_to_isize(&self, val: u64) -> i64 {
- let val = val as i64;
- // Now wrap-around into the machine_isize range.
- if val > self.target_isize_max() {
- // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
- // i64.
- debug_assert!(self.pointer_size().bits() < 64);
- let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
- val - i64::try_from(max_usize_plus_1).unwrap()
- } else {
- val
- }
- }
-
- /// Helper function: truncate given value-"overflowed flag" pair to pointer size and
- /// update "overflowed flag" if there was an overflow.
- /// This should be called by all the other methods before returning!
- #[inline]
- fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) {
- let val = u128::from(val);
- let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
- (u64::try_from(val % max_ptr_plus_1).unwrap(), over || val >= max_ptr_plus_1)
+ fn truncate_to_target_usize(&self, val: u64) -> u64 {
+ self.pointer_size().truncate(val.into()).try_into().unwrap()
}
#[inline]
- fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
- // We do not need to check if i fits in a machine usize. If it doesn't,
- // either the wrapping_add will wrap or res will not fit in a pointer.
- let res = val.overflowing_add(i);
- self.truncate_to_ptr(res)
- }
-
- #[inline]
- fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
- // We need to make sure that i fits in a machine isize.
- let n = i.unsigned_abs();
- if i >= 0 {
- let (val, over) = self.overflowing_offset(val, n);
- (val, over || i > self.target_isize_max())
- } else {
- let res = val.overflowing_sub(n);
- let (val, over) = self.truncate_to_ptr(res);
- (val, over || i < self.target_isize_min())
- }
- }
-
- #[inline]
- fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> {
- let (res, over) = self.overflowing_offset(val, i);
- if over { throw_ub!(PointerArithOverflow) } else { Ok(res) }
- }
-
- #[inline]
- fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> {
- let (res, over) = self.overflowing_signed_offset(val, i);
- if over { throw_ub!(PointerArithOverflow) } else { Ok(res) }
+ fn sign_extend_to_target_isize(&self, val: u64) -> i64 {
+ self.pointer_size().sign_extend(val.into()).try_into().unwrap()
}
}
@@ -330,7 +282,7 @@ pub fn null() -> Self {
}
}
-impl<'tcx, Prov> Pointer<Prov> {
+impl<Prov> Pointer<Prov> {
#[inline(always)]
pub fn new(provenance: Prov, offset: Size) -> Self {
Pointer { provenance, offset }
@@ -348,43 +300,16 @@ pub fn map_provenance(self, f: impl FnOnce(Prov) -> Prov) -> Self {
Pointer { provenance: f(self.provenance), ..self }
}
- #[inline]
- pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
- Ok(Pointer {
- offset: Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
- ..self
- })
- }
-
- #[inline]
- pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) {
- let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
- let ptr = Pointer { offset: Size::from_bytes(res), ..self };
- (ptr, over)
- }
-
#[inline(always)]
pub fn wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
- self.overflowing_offset(i, cx).0
- }
-
- #[inline]
- pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> {
- Ok(Pointer {
- offset: Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
- ..self
- })
- }
-
- #[inline]
- pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) {
- let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
- let ptr = Pointer { offset: Size::from_bytes(res), ..self };
- (ptr, over)
+ let res =
+ cx.data_layout().truncate_to_target_usize(self.offset.bytes().wrapping_add(i.bytes()));
+ Pointer { offset: Size::from_bytes(res), ..self }
}
#[inline(always)]
pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
- self.overflowing_signed_offset(i, cx).0
+ // It's wrapping anyway, so we can just cast to `u64`.
+ self.wrapping_offset(Size::from_bytes(i as u64), cx)
}
}
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 9661359..675e786 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,18 +1,17 @@
-use super::{
- ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId,
-};
-
-use crate::mir;
-use crate::query::TyCtxtEnsure;
-use crate::ty::visit::TypeVisitableExt;
-use crate::ty::GenericArgs;
-use crate::ty::{self, TyCtxt};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_session::lint;
use rustc_span::{Span, DUMMY_SP};
use tracing::{debug, instrument};
+use super::{
+ ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId,
+};
+use crate::mir;
+use crate::query::TyCtxtEnsure;
+use crate::ty::visit::TypeVisitableExt;
+use crate::ty::{self, GenericArgs, TyCtxt};
+
impl<'tcx> TyCtxt<'tcx> {
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
/// that can't take any generic arguments like const items or enum discriminants. If a
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index a84a4c5..84c17b3 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -1,20 +1,16 @@
use std::fmt;
use either::{Either, Left, Right};
-
-use rustc_apfloat::{
- ieee::{Double, Half, Quad, Single},
- Float,
-};
+use rustc_apfloat::ieee::{Double, Half, Quad, Single};
+use rustc_apfloat::Float;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_target::abi::{HasDataLayout, Size};
-use crate::ty::ScalarInt;
-
use super::{
AllocId, CtfeProvenance, InterpResult, Pointer, PointerArithmetic, Provenance,
ScalarSizeMismatch,
};
+use crate::ty::ScalarInt;
/// A `Scalar` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of an `Allocation`, up to 16 bytes in
@@ -397,7 +393,7 @@ pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64>
#[inline]
pub fn to_int(self, size: Size) -> InterpResult<'tcx, i128> {
let b = self.to_bits(size)?;
- Ok(size.sign_extend(b) as i128)
+ Ok(size.sign_extend(b))
}
/// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer.
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 83e3898..46c4d58 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2,43 +2,6 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
-use crate::mir::interpret::{AllocRange, Scalar};
-use crate::mir::visit::MirVisitable;
-use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
-use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::visit::TypeVisitableExt;
-use crate::ty::{self, List, Ty, TyCtxt};
-use crate::ty::{AdtDef, Instance, InstanceKind, UserTypeAnnotationIndex};
-use crate::ty::{GenericArg, GenericArgsRef};
-
-use rustc_data_structures::captures::Captures;
-use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
-use rustc_hir::def::{CtorKind, Namespace};
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
-use rustc_hir::{
- self as hir, BindingMode, ByRef, CoroutineDesugaring, CoroutineKind, HirId, ImplicitSelfKind,
-};
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-use rustc_session::Session;
-use rustc_span::source_map::Spanned;
-use rustc_target::abi::{FieldIdx, VariantIdx};
-
-use polonius_engine::Atom;
-pub use rustc_ast::Mutability;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::graph::dominators::Dominators;
-use rustc_index::bit_set::BitSet;
-use rustc_index::{Idx, IndexSlice, IndexVec};
-use rustc_serialize::{Decodable, Encodable};
-use rustc_span::symbol::Symbol;
-use rustc_span::{Span, DUMMY_SP};
-
-use either::Either;
-use tracing::trace;
-
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::hash_map::Entry;
@@ -46,9 +9,42 @@
use std::ops::{Index, IndexMut};
use std::{iter, mem};
+pub use basic_blocks::BasicBlocks;
+use either::Either;
+use polonius_engine::Atom;
+pub use rustc_ast::Mutability;
+use rustc_data_structures::captures::Captures;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::graph::dominators::Dominators;
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
+use rustc_hir::def::{CtorKind, Namespace};
+use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_hir::{
+ self as hir, BindingMode, ByRef, CoroutineDesugaring, CoroutineKind, HirId, ImplicitSelfKind,
+};
+use rustc_index::bit_set::BitSet;
+use rustc_index::{Idx, IndexSlice, IndexVec};
+use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use rustc_serialize::{Decodable, Encodable};
+use rustc_session::Session;
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::Symbol;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi::{FieldIdx, VariantIdx};
+use tracing::trace;
+
pub use self::query::*;
use self::visit::TyContext;
-pub use basic_blocks::BasicBlocks;
+use crate::mir::interpret::{AllocRange, Scalar};
+use crate::mir::visit::MirVisitable;
+use crate::ty::codec::{TyDecoder, TyEncoder};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::ty::print::{pretty_print_const, with_no_trimmed_paths, FmtPrinter, Printer};
+use crate::ty::visit::TypeVisitableExt;
+use crate::ty::{
+ self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt,
+ UserTypeAnnotationIndex,
+};
mod basic_blocks;
mod consts;
@@ -70,17 +66,18 @@
mod type_foldable;
pub mod visit;
-pub use self::generic_graph::graphviz_safe_def_name;
-pub use self::graphviz::write_mir_graphviz;
-pub use self::pretty::{
- create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere,
-};
pub use consts::*;
use pretty::pretty_print_const_value;
pub use statement::*;
pub use syntax::*;
pub use terminator::*;
+pub use self::generic_graph::graphviz_safe_def_name;
+pub use self::graphviz::write_mir_graphviz;
+pub use self::pretty::{
+ create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere,
+};
+
/// Types for locals
pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>;
@@ -386,15 +383,17 @@ pub struct Body<'tcx> {
/// Constants that are required to evaluate successfully for this MIR to be well-formed.
/// We hold in this field all the constants we are not able to evaluate yet.
+ /// `None` indicates that the list has not been computed yet.
///
/// This is soundness-critical, we make a guarantee that all consts syntactically mentioned in a
/// function have successfully evaluated if the function ever gets executed at runtime.
- pub required_consts: Vec<ConstOperand<'tcx>>,
+ pub required_consts: Option<Vec<ConstOperand<'tcx>>>,
/// Further items that were mentioned in this function and hence *may* become monomorphized,
/// depending on optimizations. We use this to avoid optimization-dependent compile errors: the
/// collector recursively traverses all "mentioned" items and evaluates all their
/// `required_consts`.
+ /// `None` indicates that the list has not been computed yet.
///
/// This is *not* soundness-critical and the contents of this list are *not* a stable guarantee.
/// All that's relevant is that this set is optimization-level-independent, and that it includes
@@ -402,7 +401,7 @@ pub struct Body<'tcx> {
/// set after drop elaboration, so some drop calls that can never be reached are not considered
/// "mentioned".) See the documentation of `CollectionMode` in
/// `compiler/rustc_monomorphize/src/collector.rs` for more context.
- pub mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>,
+ pub mentioned_items: Option<Vec<Spanned<MentionedItem<'tcx>>>>,
/// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
///
@@ -480,8 +479,8 @@ pub fn new(
spread_arg: None,
var_debug_info,
span,
- required_consts: Vec::new(),
- mentioned_items: Vec::new(),
+ required_consts: None,
+ mentioned_items: None,
is_polymorphic: false,
injection_phase: None,
tainted_by_errors,
@@ -510,8 +509,8 @@ pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) ->
arg_count: 0,
spread_arg: None,
span: DUMMY_SP,
- required_consts: Vec::new(),
- mentioned_items: Vec::new(),
+ required_consts: None,
+ mentioned_items: None,
var_debug_info: Vec::new(),
is_polymorphic: false,
injection_phase: None,
@@ -788,6 +787,40 @@ pub fn caller_location_span<T>(
// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
caller_location.unwrap_or_else(|| from_span(source_info.span))
}
+
+ #[track_caller]
+ pub fn set_required_consts(&mut self, required_consts: Vec<ConstOperand<'tcx>>) {
+ assert!(
+ self.required_consts.is_none(),
+ "required_consts for {:?} have already been set",
+ self.source.def_id()
+ );
+ self.required_consts = Some(required_consts);
+ }
+ #[track_caller]
+ pub fn required_consts(&self) -> &[ConstOperand<'tcx>] {
+ match &self.required_consts {
+ Some(l) => l,
+ None => panic!("required_consts for {:?} have not yet been set", self.source.def_id()),
+ }
+ }
+
+ #[track_caller]
+ pub fn set_mentioned_items(&mut self, mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>) {
+ assert!(
+ self.mentioned_items.is_none(),
+ "mentioned_items for {:?} have already been set",
+ self.source.def_id()
+ );
+ self.mentioned_items = Some(mentioned_items);
+ }
+ #[track_caller]
+ pub fn mentioned_items(&self) -> &[Spanned<MentionedItem<'tcx>>] {
+ match &self.mentioned_items {
+ Some(l) => l,
+ None => panic!("mentioned_items for {:?} have not yet been set", self.source.def_id()),
+ }
+ }
}
impl<'tcx> Index<BasicBlock> for Body<'tcx> {
@@ -1815,8 +1848,9 @@ pub fn dominates(self, location: Location, dominators: &Dominators<BasicBlock>)
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(BasicBlockData<'_>, 128);
static_assert_size!(LocalDecl<'_>, 40);
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 146cd6d..336a938 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,9 +1,8 @@
-use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
-use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};
+use std::fmt;
+use std::hash::Hash;
+
use rustc_attr::InlineAttr;
-use rustc_data_structures::base_n::BaseNString;
-use rustc_data_structures::base_n::ToBaseN;
-use rustc_data_structures::base_n::CASE_INSENSITIVE;
+use rustc_data_structures::base_n::{BaseNString, ToBaseN, CASE_INSENSITIVE};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey};
@@ -16,10 +15,11 @@
use rustc_session::config::OptLevel;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
-use std::fmt;
-use std::hash::Hash;
use tracing::debug;
+use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
+use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};
+
/// Describes how a monomorphization will be instantiated in object files.
#[derive(PartialEq)]
pub enum InstantiationMode {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 2232499..f2d8781 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -4,9 +4,6 @@
use std::io::{self, Write as _};
use std::path::{Path, PathBuf};
-use crate::mir::interpret::ConstAllocation;
-
-use super::graphviz::write_mir_fn_graphviz;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_middle::mir::interpret::{
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
@@ -17,6 +14,9 @@
use rustc_target::abi::Size;
use tracing::trace;
+use super::graphviz::write_mir_fn_graphviz;
+use crate::mir::interpret::ConstAllocation;
+
const INDENT: &str = " ";
/// Alignment for lining up comments following MIR statements
pub(crate) const ALIGN: usize = 40;
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index acf4414..a36e49f 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -1,7 +1,8 @@
//! Values computed by queries that use MIR.
-use crate::mir;
-use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
+use std::cell::Cell;
+use std::fmt::{self, Debug};
+
use derive_where::derive_where;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
@@ -13,10 +14,10 @@
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
use smallvec::SmallVec;
-use std::cell::Cell;
-use std::fmt::{self, Debug};
use super::{ConstValue, SourceInfo};
+use crate::mir;
+use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt};
rustc_index::newtype_index! {
#[derive(HashStable)]
diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs
index ac3feb7..3009ca8 100644
--- a/compiler/rustc_middle/src/mir/statement.rs
+++ b/compiler/rustc_middle/src/mir/statement.rs
@@ -1,6 +1,7 @@
//! Functionality for statements, operands, places, and things that appear in them.
-use super::{interpret::GlobalAlloc, *};
+use super::interpret::GlobalAlloc;
+use super::*;
///////////////////////////////////////////////////////////////////////////
// Statements
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 620fa96..1119ff6 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -3,31 +3,26 @@
//! This is in a dedicated file so that changes to this file can be reviewed more carefully.
//! The intention is that this file only contains datatype declarations, no code.
-use super::{BasicBlock, Const, Local, UserTypeProjection};
-
-use crate::mir::coverage::CoverageKind;
-use crate::traits::Reveal;
-use crate::ty::adjustment::PointerCoercion;
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, List, Ty};
-use crate::ty::{Region, UserTypeAnnotationIndex};
-
-use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece, Mutability};
use rustc_data_structures::packed::Pu128;
use rustc_hir::def_id::DefId;
use rustc_hir::CoroutineKind;
use rustc_index::IndexVec;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-use rustc_span::source_map::Spanned;
-use rustc_target::abi::{FieldIdx, VariantIdx};
-
-use rustc_ast::Mutability;
use rustc_span::def_id::LocalDefId;
+use rustc_span::source_map::Spanned;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_target::asm::InlineAsmRegOrRegClass;
use smallvec::SmallVec;
+use super::{BasicBlock, Const, Local, UserTypeProjection};
+use crate::mir::coverage::CoverageKind;
+use crate::traits::Reveal;
+use crate::ty::adjustment::PointerCoercion;
+use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex};
+
/// Represents the "flavors" of MIR.
///
/// All flavors of MIR use the same data structure, but there are some important differences. These
@@ -1583,8 +1578,9 @@ pub enum BinOp {
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(AggregateKind<'_>, 32);
static_assert_size!(Operand<'_>, 24);
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 412cfc1..1075344 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -3,10 +3,11 @@
* building is complete.
*/
-use crate::mir::*;
use rustc_hir as hir;
use tracing::{debug, instrument};
+use crate::mir::*;
+
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct PlaceTy<'tcx> {
pub ty: Ty<'tcx>,
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 5b035d9..962b93a 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,14 +1,13 @@
//! Functionality for terminators and helper types that appear in terminators.
-use rustc_hir::LangItem;
-use smallvec::{smallvec, SmallVec};
-
-use super::TerminatorKind;
-use rustc_data_structures::packed::Pu128;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use std::slice;
-use super::*;
+use rustc_data_structures::packed::Pu128;
+use rustc_hir::LangItem;
+use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use smallvec::{smallvec, SmallVec};
+
+use super::{TerminatorKind, *};
impl SwitchTargets {
/// Creates switch targets from an iterator of values and target blocks.
@@ -295,9 +294,10 @@ pub fn fmt_assert_args<W: fmt::Write>(&self, f: &mut W) -> fmt::Result
/// Note that we deliberately show more details here than we do at runtime, such as the actual
/// numbers that overflowed -- it is much easier to do so here than at runtime.
pub fn diagnostic_message(&self) -> DiagMessage {
- use crate::fluent_generated::*;
use AssertKind::*;
+ use crate::fluent_generated::*;
+
match self {
BoundsCheck { .. } => middle_bounds_check,
Overflow(BinOp::Shl, _, _) => middle_assert_shl_overflow,
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 0031ded..3921176 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -1066,9 +1066,11 @@ macro_rules! type_annotations {
$self.visit_span($(& $mutability)? $body.span);
- for const_ in &$($mutability)? $body.required_consts {
- let location = Location::START;
- $self.visit_const_operand(const_, location);
+ if let Some(required_consts) = &$($mutability)? $body.required_consts {
+ for const_ in required_consts {
+ let location = Location::START;
+ $self.visit_const_operand(const_, location);
+ }
}
}
}
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index d9fa5b0..bd20e6a 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -1,11 +1,11 @@
-use crate::mir;
-use crate::query::CyclePlaceholder;
-use crate::traits;
-use crate::ty::adjustment::CoerceUnsizedInfo;
-use crate::ty::{self, Ty};
use std::intrinsics::transmute_unchecked;
use std::mem::MaybeUninit;
+use crate::query::CyclePlaceholder;
+use crate::ty::adjustment::CoerceUnsizedInfo;
+use crate::ty::{self, Ty};
+use crate::{mir, traits};
+
#[derive(Copy, Clone)]
pub struct Erased<T: Copy> {
// We use `MaybeUninit` here so we can store any value
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index add8849..6562d46 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -1,12 +1,5 @@
//! Defines the set of legal keys that can be used in queries.
-use crate::infer::canonical::Canonical;
-use crate::mir;
-use crate::traits;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::{TyAndLayout, ValidityRequirement};
-use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{GenericArg, GenericArgsRef};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, ModDefId, LOCAL_CRATE};
use rustc_hir::hir_id::{HirId, OwnerId};
use rustc_query_system::query::{DefIdCache, DefaultCache, SingleCache, VecCache};
@@ -14,6 +7,12 @@
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi;
+use crate::infer::canonical::Canonical;
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::{TyAndLayout, ValidityRequirement};
+use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
+use crate::{mir, traits};
+
/// Placeholder for `CrateNum`'s "local" counterpart
#[derive(Copy, Clone, Debug)]
pub struct LocalCrate;
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c7ea1d4..075eae0 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -6,58 +6,14 @@
#![allow(unused_parens)]
-use crate::dep_graph;
-use crate::infer::canonical::{self, Canonical};
-use crate::lint::LintExpectation;
-use crate::metadata::ModChild;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
-use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use crate::middle::lib_features::LibFeatures;
-use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
-use crate::middle::stability::{self, DeprecationEntry};
-use crate::mir;
-use crate::mir::interpret::GlobalId;
-use crate::mir::interpret::{
- EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
- EvalToValTreeResult,
-};
-use crate::mir::interpret::{LitToConstError, LitToConstInput};
-use crate::mir::mono::CodegenUnit;
-use crate::query::erase::{erase, restore, Erase};
-use crate::query::plumbing::{
- query_ensure, query_ensure_error_guaranteed, query_get_at, CyclePlaceholder, DynamicQuery,
-};
-use crate::thir;
-use crate::traits::query::{
- CanonicalAliasGoal, CanonicalPredicateGoal, CanonicalTyGoal,
- CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
- CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
-};
-use crate::traits::query::{
- DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
- OutlivesBound,
-};
-use crate::traits::specialization_graph;
-use crate::traits::{
- CodegenObligationError, EvaluationResult, ImplSource, ObjectSafetyViolation, ObligationCause,
- OverflowError, WellFormedLoc,
-};
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::ValidityRequirement;
-use crate::ty::print::PrintTraitRefExt;
-use crate::ty::util::AlwaysRequiresDrop;
-use crate::ty::TyCtxtFeed;
-use crate::ty::{
- self, print::describe_as_module, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt,
- UnusedGenericParams,
-};
-use crate::ty::{GenericArg, GenericArgsRef};
+use std::mem;
+use std::ops::Deref;
+use std::path::PathBuf;
+use std::sync::Arc;
+
use rustc_arena::TypedArena;
-use rustc_ast as ast;
-use rustc_ast::expand::{allocator::AllocatorKind, StrippedCfgItem};
-use rustc_attr as attr;
+use rustc_ast::expand::allocator::AllocatorKind;
+use rustc_ast::expand::StrippedCfgItem;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::steal::Steal;
@@ -65,7 +21,6 @@
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
use rustc_hir::def::{DefKind, DocLinkResMap};
use rustc_hir::def_id::{
CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId,
@@ -77,8 +32,9 @@
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{try_get_cached, QueryCache, QueryMode, QueryState};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use rustc_session::cstore::{CrateDepKind, CrateSource};
-use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
+use rustc_session::cstore::{
+ CrateDepKind, CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib,
+};
use rustc_session::lint::LintExpectationId;
use rustc_session::Limits;
use rustc_span::def_id::LOCAL_CRATE;
@@ -86,10 +42,47 @@
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi;
use rustc_target::spec::PanicStrategy;
-use std::mem;
-use std::ops::Deref;
-use std::path::PathBuf;
-use std::sync::Arc;
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
+
+use crate::infer::canonical::{self, Canonical};
+use crate::lint::LintExpectation;
+use crate::metadata::ModChild;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
+use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
+use crate::middle::lib_features::LibFeatures;
+use crate::middle::privacy::EffectiveVisibilities;
+use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
+use crate::middle::stability::{self, DeprecationEntry};
+use crate::mir::interpret::{
+ EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
+ EvalToValTreeResult, GlobalId, LitToConstError, LitToConstInput,
+};
+use crate::mir::mono::CodegenUnit;
+use crate::query::erase::{erase, restore, Erase};
+use crate::query::plumbing::{
+ query_ensure, query_ensure_error_guaranteed, query_get_at, CyclePlaceholder, DynamicQuery,
+};
+use crate::traits::query::{
+ CanonicalAliasGoal, CanonicalPredicateGoal, CanonicalTyGoal,
+ CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
+ CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, DropckConstraint,
+ DropckOutlivesResult, MethodAutoderefStepsResult, NoSolution, NormalizationResult,
+ OutlivesBound,
+};
+use crate::traits::{
+ specialization_graph, CodegenObligationError, EvaluationResult, ImplSource,
+ ObjectSafetyViolation, ObligationCause, OverflowError, WellFormedLoc,
+};
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::ValidityRequirement;
+use crate::ty::print::{describe_as_module, PrintTraitRefExt};
+use crate::ty::util::AlwaysRequiresDrop;
+use crate::ty::{
+ self, CrateInherentImpls, GenericArg, GenericArgsRef, ParamEnvAnd, Ty, TyCtxt, TyCtxtFeed,
+ UnusedGenericParams,
+};
+use crate::{dep_graph, mir, thir};
pub mod erase;
mod keys;
@@ -414,6 +407,10 @@
desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) }
}
+ query impl_super_outlives(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> {
+ desc { |tcx| "elaborating supertrait outlives for trait of `{}`", tcx.def_path_str(key) }
+ }
+
/// Look up all native libraries this crate depends on.
/// These are assembled from the following places:
/// - `extern` blocks (depending on their `link` attributes)
@@ -1729,6 +1726,10 @@
desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
}
+ query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] {
+ desc { "inheriting delegation signature" }
+ }
+
/// Does lifetime resolution on items. Importantly, we can't resolve
/// lifetimes directly on things like trait methods, because of trait params.
/// See `rustc_resolve::late::lifetimes` for details.
@@ -2186,6 +2187,12 @@
desc { "looking up supported target features" }
}
+ query implied_target_features(feature: Symbol) -> &'tcx Vec<Symbol> {
+ arena_cache
+ eval_always
+ desc { "looking up implied target features" }
+ }
+
query features_query(_: ()) -> &'tcx rustc_feature::Features {
feedable
desc { "looking up enabled feature gates" }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 924249b..ca52358 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -1,3 +1,6 @@
+use std::collections::hash_map::Entry;
+use std::mem;
+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
@@ -13,22 +16,17 @@
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::query::QuerySideEffects;
-use rustc_serialize::{
- opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder},
- Decodable, Decoder, Encodable, Encoder,
-};
+use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_session::Session;
use rustc_span::hygiene::{
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{
- BytePos, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span, SpanDecoder, SpanEncoder,
- StableSourceFileId,
+ BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span,
+ SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
};
-use rustc_span::{CachingSourceMapView, Symbol};
-use std::collections::hash_map::Entry;
-use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 8a4e3ab..c9bd702 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -1,25 +1,23 @@
-use crate::dep_graph;
-use crate::dep_graph::DepKind;
-use crate::query::on_disk_cache::CacheEncoder;
-use crate::query::on_disk_cache::EncodedDepNodeIndex;
-use crate::query::on_disk_cache::OnDiskCache;
-use crate::query::{
- DynamicQueries, ExternProviders, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
-};
-use crate::ty::TyCtxt;
+use std::ops::Deref;
+
use field_offset::FieldOffset;
-use rustc_data_structures::sync::AtomicU64;
-use rustc_data_structures::sync::WorkerLocal;
+use rustc_data_structures::sync::{AtomicU64, WorkerLocal};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_macros::HashStable;
-use rustc_query_system::dep_graph::DepNodeIndex;
-use rustc_query_system::dep_graph::SerializedDepNodeIndex;
+use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;
use rustc_query_system::HandleCycleError;
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
-use std::ops::Deref;
+
+use crate::dep_graph;
+use crate::dep_graph::DepKind;
+use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
+use crate::query::{
+ DynamicQueries, ExternProviders, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
+};
+use crate::ty::TyCtxt;
pub struct DynamicQuery<'tcx, C: QueryCache> {
pub name: &'static str,
@@ -574,9 +572,10 @@ pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) {
// as they will raise an fatal error on query cycles instead.
mod sealed {
- use super::{DefId, LocalDefId, OwnerId};
use rustc_hir::def_id::{LocalModDefId, ModDefId};
+ use super::{DefId, LocalDefId, OwnerId};
+
/// An analogue of the `Into` trait that's intended only for query parameters.
///
/// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index b80d007..f2ea322 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -8,13 +8,15 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
+use std::cmp::Ordering;
+use std::fmt;
+use std::ops::Index;
+
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
-use rustc_index::newtype_index;
-use rustc_index::IndexVec;
+use rustc_index::{newtype_index, IndexVec};
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::AllocId;
@@ -26,12 +28,9 @@
TyCtxt, UpvarArgs,
};
use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, ErrorGuaranteed, Span, Symbol, DUMMY_SP};
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx};
use rustc_target::asm::InlineAsmRegOrRegClass;
-use std::cmp::Ordering;
-use std::fmt;
-use std::ops::Index;
use tracing::instrument;
pub mod visit;
@@ -598,10 +597,6 @@ pub struct Pat<'tcx> {
}
impl<'tcx> Pat<'tcx> {
- pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
- Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
- }
-
pub fn simple_ident(&self) -> Option<Symbol> {
match self.kind {
PatKind::Binding {
@@ -702,12 +697,6 @@ pub fn is_never_pattern(&self) -> bool {
}
}
-impl<'tcx> IntoDiagArg for Pat<'tcx> {
- fn into_diag_arg(self) -> DiagArgValue {
- format!("{self}").into_diag_arg()
- }
-}
-
#[derive(Clone, Debug, HashStable, TypeVisitable)]
pub struct Ascription<'tcx> {
pub annotation: CanonicalUserTypeAnnotation<'tcx>,
@@ -1080,164 +1069,12 @@ pub fn compare_with(
}
}
-impl<'tcx> fmt::Display for Pat<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // Printing lists is a chore.
- let mut first = true;
- let mut start_or_continue = |s| {
- if first {
- first = false;
- ""
- } else {
- s
- }
- };
- let mut start_or_comma = || start_or_continue(", ");
-
- match self.kind {
- PatKind::Wild => write!(f, "_"),
- PatKind::Never => write!(f, "!"),
- PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"),
- PatKind::Binding { name, mode, ref subpattern, .. } => {
- f.write_str(mode.prefix_str())?;
- write!(f, "{name}")?;
- if let Some(ref subpattern) = *subpattern {
- write!(f, " @ {subpattern}")?;
- }
- Ok(())
- }
- PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
- let variant_and_name = match self.kind {
- PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
- let variant = adt_def.variant(variant_index);
- let adt_did = adt_def.did();
- let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
- || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
- {
- variant.name.to_string()
- } else {
- format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
- };
- Some((variant, name))
- }),
- _ => self.ty.ty_adt_def().and_then(|adt_def| {
- if !adt_def.is_enum() {
- ty::tls::with(|tcx| {
- Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
- })
- } else {
- None
- }
- }),
- };
-
- if let Some((variant, name)) = &variant_and_name {
- write!(f, "{name}")?;
-
- // Only for Adt we can have `S {...}`,
- // which we handle separately here.
- if variant.ctor.is_none() {
- write!(f, " {{ ")?;
-
- let mut printed = 0;
- for p in subpatterns {
- if let PatKind::Wild = p.pattern.kind {
- continue;
- }
- let name = variant.fields[p.field].name;
- write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
- printed += 1;
- }
-
- let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
- if printed < variant.fields.len() && (!is_union || printed == 0) {
- write!(f, "{}..", start_or_comma())?;
- }
-
- return write!(f, " }}");
- }
- }
-
- let num_fields =
- variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
- if num_fields != 0 || variant_and_name.is_none() {
- write!(f, "(")?;
- for i in 0..num_fields {
- write!(f, "{}", start_or_comma())?;
-
- // Common case: the field is where we expect it.
- if let Some(p) = subpatterns.get(i) {
- if p.field.index() == i {
- write!(f, "{}", p.pattern)?;
- continue;
- }
- }
-
- // Otherwise, we have to go looking for it.
- if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
- write!(f, "{}", p.pattern)?;
- } else {
- write!(f, "_")?;
- }
- }
- write!(f, ")")?;
- }
-
- Ok(())
- }
- PatKind::Deref { ref subpattern } => {
- match self.ty.kind() {
- ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
- ty::Ref(_, _, mutbl) => {
- write!(f, "&{}", mutbl.prefix_str())?;
- }
- _ => bug!("{} is a bad Deref pattern type", self.ty),
- }
- write!(f, "{subpattern}")
- }
- PatKind::DerefPattern { ref subpattern, .. } => {
- write!(f, "deref!({subpattern})")
- }
- PatKind::Constant { value } => write!(f, "{value}"),
- PatKind::InlineConstant { def: _, ref subpattern } => {
- write!(f, "{} (from inline const)", subpattern)
- }
- PatKind::Range(ref range) => write!(f, "{range}"),
- PatKind::Slice { ref prefix, ref slice, ref suffix }
- | PatKind::Array { ref prefix, ref slice, ref suffix } => {
- write!(f, "[")?;
- for p in prefix.iter() {
- write!(f, "{}{}", start_or_comma(), p)?;
- }
- if let Some(ref slice) = *slice {
- write!(f, "{}", start_or_comma())?;
- match slice.kind {
- PatKind::Wild => {}
- _ => write!(f, "{slice}")?,
- }
- write!(f, "..")?;
- }
- for p in suffix.iter() {
- write!(f, "{}{}", start_or_comma(), p)?;
- }
- write!(f, "]")
- }
- PatKind::Or { ref pats } => {
- for pat in pats.iter() {
- write!(f, "{}{}", start_or_continue(" | "), pat)?;
- }
- Ok(())
- }
- PatKind::Error(_) => write!(f, "<error>"),
- }
- }
-}
-
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(Block, 48);
static_assert_size!(Expr<'_>, 64);
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index b747751..d54e2ca 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -8,10 +8,8 @@
pub mod specialization_graph;
mod structural_impls;
-use crate::mir::ConstraintCategory;
-use crate::ty::abstract_const::NotConstEvaluatable;
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, AdtKind, Ty};
+use std::borrow::Cow;
+use std::hash::{Hash, Hasher};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
@@ -24,14 +22,14 @@
use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
-
-use std::borrow::Cow;
-use std::hash::{Hash, Hasher};
-
-pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
// FIXME: Remove this import and import via `solve::`
pub use rustc_type_ir::solve::{BuiltinImplSource, Reveal};
+use smallvec::{smallvec, SmallVec};
+
+pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache};
+use crate::mir::ConstraintCategory;
+use crate::ty::abstract_const::NotConstEvaluatable;
+use crate::ty::{self, AdtKind, GenericArgsRef, Ty};
/// The reason why we incurred this obligation; used for error reporting.
///
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 4fad721..81a543e 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -5,20 +5,22 @@
//! The providers for the queries defined here can be found in
//! `rustc_traits`.
-use crate::error::DropCheckOverflow;
-use crate::infer::canonical::{Canonical, QueryResponse};
-use crate::ty::GenericArg;
-use crate::ty::{self, Ty, TyCtxt};
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
use rustc_span::Span;
// FIXME: Remove this import and import via `traits::solve`.
pub use rustc_type_ir::solve::NoSolution;
+use crate::error::DropCheckOverflow;
+use crate::infer::canonical::{Canonical, QueryResponse};
+use crate::ty::{self, GenericArg, Ty, TyCtxt};
+
pub mod type_op {
+ use std::fmt;
+
+ use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
+
use crate::ty::fold::TypeFoldable;
use crate::ty::{Predicate, Ty, TyCtxt, UserType};
- use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
- use std::fmt;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
pub struct AscribeUserType<'tcx> {
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index c8caf22..6603546 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -2,17 +2,15 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
-use self::EvaluationResult::*;
-
-use super::{SelectionError, SelectionResult};
use rustc_errors::ErrorGuaranteed;
-
-use crate::ty;
-
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TypeVisitable};
use rustc_query_system::cache::Cache;
+use self::EvaluationResult::*;
+use super::{SelectionError, SelectionResult};
+use crate::ty;
+
pub type SelectionCache<'tcx> = Cache<
// This cache does not use `ParamEnvAnd` in its keys because `ParamEnv::and` can replace
// caller bounds with an empty list if the `TraitPredicate` looks global, which may happen
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index ff5d51b..26dcae0 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -1,13 +1,14 @@
-use crate::error::StrictCoherenceNeedsNegativeCoherence;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::visit::TypeVisitableExt;
-use crate::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::symbol::sym;
+use crate::error::StrictCoherenceNeedsNegativeCoherence;
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::visit::TypeVisitableExt;
+use crate::ty::{self, TyCtxt};
+
/// A per-trait graph of impls in specialization order. At the moment, this
/// graph forms a tree rooted with the trait itself, with all other nodes
/// representing impls, and parent-child relationships representing
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index ec450cf..d79a936 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -1,7 +1,7 @@
-use crate::traits;
-
use std::fmt;
+use crate::traits;
+
// Structural impls for the structs in `traits`.
impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 3aa01fb..002d381 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,11 +1,12 @@
//! A subset of a mir body used for const evaluability checking.
+use rustc_errors::ErrorGuaranteed;
+use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
+
use crate::ty::{
self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt,
};
-use rustc_errors::ErrorGuaranteed;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeVisitable};
#[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)]
#[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)]
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 6d7b625..1236c9e 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -1,10 +1,11 @@
-use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_span::Span;
use rustc_target::abi::FieldIdx;
+use crate::ty::{self, Ty, TyCtxt};
+
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
pub enum PointerCoercion {
/// Go from a fn-item type to a fn-pointer type.
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 88ee32e..204f61b 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -1,12 +1,13 @@
-use crate::mir::interpret::ErrorHandled;
-use crate::ty;
-use crate::ty::util::{Discr, IntTypeExt};
+use std::cell::RefCell;
+use std::hash::{Hash, Hasher};
+use std::ops::Range;
+use std::str;
+
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
-use rustc_data_structures::stable_hasher::HashingControls;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
@@ -19,14 +20,12 @@
use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
use tracing::{debug, info, trace};
-use std::cell::RefCell;
-use std::hash::{Hash, Hasher};
-use std::ops::Range;
-use std::str;
-
use super::{
AsyncDestructor, Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr,
};
+use crate::mir::interpret::ErrorHandled;
+use crate::ty;
+use crate::ty::util::{Discr, IntTypeExt};
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
pub struct AdtFlags(u16);
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 820f5e9..db56e00 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -1,4 +1,3 @@
-use crate::ty;
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace};
@@ -7,6 +6,7 @@
use rustc_span::symbol::{Ident, Symbol};
use super::{TyCtxt, Visibility};
+use crate::ty;
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
pub enum AssocItemContainer {
@@ -98,6 +98,15 @@ pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
}
}
+ pub fn descr(&self) -> &'static str {
+ match self.kind {
+ ty::AssocKind::Const => "const",
+ ty::AssocKind::Fn if self.fn_has_self_parameter => "method",
+ ty::AssocKind::Fn => "associated function",
+ ty::AssocKind::Type => "type",
+ }
+ }
+
pub fn is_impl_trait_in_trait(&self) -> bool {
self.opt_rpitit_info.is_some()
}
diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs
index 26c5a86..46f3765 100644
--- a/compiler/rustc_middle/src/ty/cast.rs
+++ b/compiler/rustc_middle/src/ty/cast.rs
@@ -1,10 +1,10 @@
// Helpers for handling cast expressions, used in both
// typeck and codegen.
-use crate::ty::{self, Ty};
+use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_middle::mir;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use crate::ty::{self, Ty};
/// Types that are represented as ints.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index bdd9a6b..8eb3c01 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -1,11 +1,5 @@
-use crate::hir::place::{
- Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
-};
-use crate::{mir, ty};
-
use std::fmt::Write;
-use crate::query::Providers;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
@@ -16,9 +10,13 @@
use rustc_span::symbol::Ident;
use rustc_span::{Span, Symbol};
-use super::TyCtxt;
-
use self::BorrowKind::*;
+use super::TyCtxt;
+use crate::hir::place::{
+ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
+};
+use crate::query::Providers;
+use crate::{mir, ty};
/// Captures are represented using fields inside a structure.
/// This represents accessing self in the closure structure
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 33f564e..401f6da 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -6,16 +6,10 @@
//! The functionality in here is shared between persisting to crate metadata and
//! persisting to incr. comp. caches.
-use crate::arena::ArenaAllocatable;
-use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
-use crate::mir::interpret::CtfeProvenance;
-use crate::mir::{
- self,
- interpret::{AllocId, ConstAllocation},
-};
-use crate::traits;
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, AdtDef, Ty};
+use std::hash::Hash;
+use std::intrinsics;
+use std::marker::DiscriminantKind;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;
@@ -23,9 +17,13 @@
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
pub use rustc_type_ir::{TyDecoder, TyEncoder};
-use std::hash::Hash;
-use std::intrinsics;
-use std::marker::DiscriminantKind;
+
+use crate::arena::ArenaAllocatable;
+use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
+use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
+use crate::mir::{self};
+use crate::traits;
+use crate::ty::{self, AdtDef, GenericArgsRef, Ty};
/// The shorthand encoding uses an enum's variant index `usize`
/// and is offset by this value so it never matches a real variant.
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 5cf1247..c380019 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,6 +1,3 @@
-use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
-use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use either::Either;
use rustc_data_structures::intern::Interned;
use rustc_error_messages::MultiSpan;
@@ -11,14 +8,17 @@
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
use tracing::{debug, instrument};
+use crate::middle::resolve_bound_vars as rbv;
+use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
+use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
+
mod int;
mod kind;
mod valtree;
pub use int::*;
pub use kind::*;
-use rustc_span::DUMMY_SP;
-use rustc_span::{ErrorGuaranteed, Span};
+use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
pub use valtree::*;
pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 13691b6..0024a2a 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -1,10 +1,11 @@
+use std::fmt;
+use std::num::NonZero;
+
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::Float;
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::Size;
-use std::fmt;
-use std::num::NonZero;
use crate::ty::TyCtxt;
@@ -233,7 +234,7 @@ pub fn truncate_from_int(i: impl Into<i128>, size: Size) -> (Self, bool) {
let data = i.into();
// `into` performed sign extension, we have to truncate
let r = Self::raw(size.truncate(data as u128), size);
- (r, size.sign_extend(r.data) as i128 != data)
+ (r, size.sign_extend(r.data) != data)
}
#[inline]
@@ -334,7 +335,7 @@ pub fn try_to_bool(self) -> Result<bool, ()> {
#[inline]
pub fn to_int(self, size: Size) -> i128 {
let b = self.to_bits(size);
- size.sign_extend(b) as i128
+ size.sign_extend(b)
}
/// Converts the `ScalarInt` to i8.
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 98f35b6..c7c2e8a 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,8 +1,12 @@
+use std::assert_matches::assert_matches;
+
+use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+
use super::Const;
use crate::mir;
use crate::ty::abstract_const::CastKind;
-use crate::ty::{self, visit::TypeVisitableExt as _, Ty, TyCtxt};
-use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use crate::ty::visit::TypeVisitableExt as _;
+use crate::ty::{self, Ty, TyCtxt};
#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
impl<'tcx> ty::UnevaluatedConst<'tcx> {
@@ -78,7 +82,7 @@ pub fn new_binop(
}
pub fn binop_args(self) -> (Ty<'tcx>, Ty<'tcx>, Const<'tcx>, Const<'tcx>) {
- assert!(matches!(self.kind, ExprKind::Binop(_)));
+ assert_matches!(self.kind, ExprKind::Binop(_));
match self.args().as_slice() {
[lhs_ty, rhs_ty, lhs_ct, rhs_ct] => (
@@ -99,7 +103,7 @@ pub fn new_unop(tcx: TyCtxt<'tcx>, unop: mir::UnOp, ty: Ty<'tcx>, ct: Const<'tcx
}
pub fn unop_args(self) -> (Ty<'tcx>, Const<'tcx>) {
- assert!(matches!(self.kind, ExprKind::UnOp(_)));
+ assert_matches!(self.kind, ExprKind::UnOp(_));
match self.args().as_slice() {
[ty, ct] => (ty.expect_ty(), ct.expect_const()),
@@ -123,7 +127,7 @@ pub fn new_call(
}
pub fn call_args(self) -> (Ty<'tcx>, Const<'tcx>, impl Iterator<Item = Const<'tcx>>) {
- assert!(matches!(self.kind, ExprKind::FunctionCall));
+ assert_matches!(self.kind, ExprKind::FunctionCall);
match self.args().as_slice() {
[func_ty, func, rest @ ..] => (
@@ -150,7 +154,7 @@ pub fn new_cast(
}
pub fn cast_args(self) -> (Ty<'tcx>, Const<'tcx>, Ty<'tcx>) {
- assert!(matches!(self.kind, ExprKind::Cast(_)));
+ assert_matches!(self.kind, ExprKind::Cast(_));
match self.args().as_slice() {
[value_ty, value, to_ty] => {
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index efc9135..9f9bf41 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -1,7 +1,8 @@
+use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+
use super::ScalarInt;
use crate::mir::interpret::Scalar;
use crate::ty::{self, Ty, TyCtxt};
-use rustc_macros::{HashStable, TyDecodable, TyEncodable};
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq)]
#[derive(HashStable)]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index fd41668..971e51b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -4,36 +4,14 @@
pub mod tls;
-pub use rustc_type_ir::lift::Lift;
+use std::assert_matches::assert_matches;
+use std::borrow::Borrow;
+use std::cmp::Ordering;
+use std::hash::{Hash, Hasher};
+use std::marker::PhantomData;
+use std::ops::{Bound, Deref};
+use std::{fmt, iter, mem};
-use crate::arena::Arena;
-use crate::dep_graph::{DepGraph, DepKindStruct};
-use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
-use crate::lint::lint_level;
-use crate::metadata::ModChild;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::resolve_bound_vars;
-use crate::middle::stability;
-use crate::mir::interpret::{self, Allocation, ConstAllocation};
-use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
-use crate::query::plumbing::QuerySystem;
-use crate::query::LocalCrate;
-use crate::query::Providers;
-use crate::query::{IntoQueryParam, TyCtxtAt};
-use crate::thir::Thir;
-use crate::traits;
-use crate::traits::solve;
-use crate::traits::solve::{
- ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
-};
-use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
-use crate::ty::{
- self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericParamDefKind,
- ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, PatternKind,
- PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region,
- RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
-};
-use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
use rustc_ast::{self as ast, attr};
use rustc_data_structures::defer;
use rustc_data_structures::fingerprint::Fingerprint;
@@ -74,20 +52,37 @@
use rustc_target::spec::abi;
use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::lang_items::TraitSolverLangItem;
+pub use rustc_type_ir::lift::Lift;
use rustc_type_ir::solve::SolverMode;
use rustc_type_ir::TyKind::*;
use rustc_type_ir::{search_graph, CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
use tracing::{debug, instrument};
-use std::assert_matches::assert_matches;
-use std::borrow::Borrow;
-use std::cmp::Ordering;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::iter;
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::{Bound, Deref};
+use crate::arena::Arena;
+use crate::dep_graph::{DepGraph, DepKindStruct};
+use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
+use crate::lint::lint_level;
+use crate::metadata::ModChild;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
+use crate::middle::{resolve_bound_vars, stability};
+use crate::mir::interpret::{self, Allocation, ConstAllocation};
+use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::query::plumbing::QuerySystem;
+use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt};
+use crate::thir::Thir;
+use crate::traits;
+use crate::traits::solve;
+use crate::traits::solve::{
+ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
+};
+use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
+use crate::ty::{
+ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs,
+ GenericArgsRef, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst,
+ ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind,
+ PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid,
+ Visibility,
+};
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
@@ -1443,11 +1438,11 @@ pub fn mk_adt_def(
/// Allocates a read-only byte or string literal for `mir::interpret`.
/// Returns the same `AllocId` if called again with the same bytes.
- pub fn allocate_bytes_dedup(self, bytes: &[u8]) -> interpret::AllocId {
+ pub fn allocate_bytes_dedup(self, bytes: &[u8], salt: usize) -> interpret::AllocId {
// Create an allocation that just contains these bytes.
let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes);
let alloc = self.mk_const_alloc(alloc);
- self.reserve_and_set_memory_dedup(alloc)
+ self.reserve_and_set_memory_dedup(alloc, salt)
}
/// Returns a range of the start/end indices specified with the
@@ -3181,6 +3176,12 @@ pub fn impl_trait_ref(
pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity {
self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity)
}
+
+ /// Whether this is a trait implementation that has `#[diagnostic::do_not_recommend]`
+ pub fn do_not_recommend_impl(self, def_id: DefId) -> bool {
+ matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true })
+ && self.impl_trait_header(def_id).is_some_and(|header| header.do_not_recommend)
+ }
}
/// Parameter attributes that can only be determined by examining the body of a function instead
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index 7b5ccae..6a5d303 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -1,15 +1,15 @@
-use super::{GlobalCtxt, TyCtxt};
-
-use crate::dep_graph::TaskDepsRef;
-use crate::query::plumbing::QueryJobId;
-use rustc_data_structures::sync::{self, Lock};
-use rustc_errors::DiagInner;
#[cfg(not(parallel_compiler))]
use std::cell::Cell;
-use std::mem;
-use std::ptr;
+use std::{mem, ptr};
+
+use rustc_data_structures::sync::{self, Lock};
+use rustc_errors::DiagInner;
use thin_vec::ThinVec;
+use super::{GlobalCtxt, TyCtxt};
+use crate::dep_graph::TaskDepsRef;
+use crate::query::plumbing::QueryJobId;
+
/// This is the implicit state of rustc. It contains the current
/// `TyCtxt` and query. It is updated when creating a local interner or
/// executing a new query. Whenever there's a `TyCtxt` value available
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index f2261f4..5acc0b7 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -4,12 +4,6 @@
use std::fmt::Write;
use std::ops::ControlFlow;
-use crate::ty::{
- self, AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque,
- PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
- TypeSuperVisitable, TypeVisitable, TypeVisitor,
-};
-
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{into_diag_arg_using_display, Applicability, Diag, DiagArgValue, IntoDiagArg};
use rustc_hir as hir;
@@ -19,6 +13,12 @@
use rustc_span::{BytePos, Span};
use rustc_type_ir::TyKind::*;
+use crate::ty::{
+ self, AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque,
+ PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitor,
+};
+
into_diag_arg_using_display! {
Ty<'_>,
ty::Region<'_>,
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 9d5481f..ecca1d4 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,7 +1,8 @@
+use tracing::debug;
+
use crate::query::Providers;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
-use tracing::debug;
pub(super) fn provide(providers: &mut Providers) {
*providers = Providers { erase_regions_ty, ..*providers };
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 32dc9fa..2f9bdb1 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,5 +1,6 @@
-use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
-use crate::ty::{self, Ty, TyCtxt};
+use std::borrow::Cow;
+use std::hash::{DefaultHasher, Hash, Hasher};
+use std::path::PathBuf;
use rustc_errors::pluralize;
use rustc_hir as hir;
@@ -7,9 +8,8 @@
use rustc_macros::extension;
pub use rustc_type_ir::error::ExpectedFound;
-use std::borrow::Cow;
-use std::hash::{DefaultHasher, Hash, Hasher};
-use std::path::PathBuf;
+use crate::ty::print::{with_forced_trimmed_paths, FmtPrinter, PrettyPrinter};
+use crate::ty::{self, Ty, TyCtxt};
pub type TypeError<'tcx> = rustc_type_ir::error::TypeError<TyCtxt<'tcx>>;
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 0413cfa..91344c4 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -1,9 +1,8 @@
use rustc_hir::def_id::DefId;
+pub use rustc_type_ir::fast_reject::*;
use super::TyCtxt;
-pub use rustc_type_ir::fast_reject::*;
-
pub type DeepRejectCtxt<'tcx> = rustc_type_ir::fast_reject::DeepRejectCtxt<TyCtxt<'tcx>>;
pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType<DefId>;
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 21c115c..c3430b5 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -1,7 +1,7 @@
-use crate::ty::{self, InferConst, Ty, TypeFlags};
-use crate::ty::{GenericArg, GenericArgKind};
use std::slice;
+use crate::ty::{self, GenericArg, GenericArgKind, InferConst, Ty, TypeFlags};
+
#[derive(Debug)]
pub struct FlagComputation {
pub flags: TypeFlags,
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 81ea873..7892ef8 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -1,11 +1,11 @@
-use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
-use tracing::{debug, instrument};
-
pub use rustc_type_ir::fold::{
shift_region, shift_vars, FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable,
};
+use tracing::{debug, instrument};
+
+use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt};
///////////////////////////////////////////////////////////////////////////
// Some sample folders
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 1091962..80c31e2 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -1,28 +1,27 @@
// Generic arguments.
-use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
-use crate::ty::visit::{TypeVisitable, TypeVisitor};
-use crate::ty::{
- self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt,
-};
+use core::intrinsics;
+use std::marker::PhantomData;
+use std::mem;
+use std::num::NonZero;
+use std::ptr::NonNull;
use rustc_ast_ir::visit::VisitorResult;
use rustc_ast_ir::walk_visitable_list;
use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_hir::def_id::DefId;
-use rustc_macros::extension;
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_serialize::{Decodable, Encodable};
use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec;
-use core::intrinsics;
-use std::marker::PhantomData;
-use std::mem;
-use std::num::NonZero;
-use std::ptr::NonNull;
+use crate::ty::codec::{TyDecoder, TyEncoder};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::ty::visit::{TypeVisitable, TypeVisitor};
+use crate::ty::{
+ self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt,
+};
pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>;
pub type TermKind<'tcx> = rustc_type_ir::TermKind<TyCtxt<'tcx>>;
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 11ed0bd..8cb8e9a 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -1,5 +1,3 @@
-use crate::ty;
-use crate::ty::{EarlyBinder, GenericArgsRef};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
@@ -9,6 +7,8 @@
use tracing::instrument;
use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
+use crate::ty;
+use crate::ty::{EarlyBinder, GenericArgsRef};
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
@@ -376,7 +376,7 @@ pub struct GenericPredicates<'tcx> {
impl<'tcx> GenericPredicates<'tcx> {
pub fn instantiate(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
) -> InstantiatedPredicates<'tcx> {
@@ -386,20 +386,20 @@ pub fn instantiate(
}
pub fn instantiate_own(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args)
}
- pub fn instantiate_own_identity(&self) -> impl Iterator<Item = (Clause<'tcx>, Span)> {
+ pub fn instantiate_own_identity(self) -> impl Iterator<Item = (Clause<'tcx>, Span)> {
EarlyBinder::bind(self.predicates).iter_identity_copied()
}
#[instrument(level = "debug", skip(self, tcx))]
fn instantiate_into(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
instantiated: &mut InstantiatedPredicates<'tcx>,
args: GenericArgsRef<'tcx>,
@@ -413,14 +413,14 @@ fn instantiate_into(
instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
}
- pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> {
+ pub fn instantiate_identity(self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> {
let mut instantiated = InstantiatedPredicates::empty();
self.instantiate_identity_into(tcx, &mut instantiated);
instantiated
}
fn instantiate_identity_into(
- &self,
+ self,
tcx: TyCtxt<'tcx>,
instantiated: &mut InstantiatedPredicates<'tcx>,
) {
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 9be7370..b5b7b8b 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -1,18 +1,20 @@
//! This module contains `HashStable` implementations for various data types
//! from `rustc_middle::ty` in no particular order.
-use crate::middle::region;
-use crate::mir;
-use crate::ty;
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::HashingControls;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_query_system::ich::StableHashingContext;
use std::cell::RefCell;
use std::ptr;
+
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{
+ HashStable, HashingControls, StableHasher, ToStableHashKey,
+};
+use rustc_query_system::ich::StableHashingContext;
use tracing::trace;
+use crate::middle::region;
+use crate::{mir, ty};
+
impl<'a, 'tcx, H, T> HashStable<StableHashingContext<'a>> for &'tcx ty::list::RawList<H, T>
where
T: HashStable<StableHashingContext<'a>>,
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index afdf2cb..698104b 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -43,13 +43,13 @@
//! This code should only compile in modules where the uninhabitedness of `Foo`
//! is visible.
+use rustc_type_ir::TyKind::*;
+use tracing::instrument;
+
use crate::query::Providers;
use crate::ty::context::TyCtxt;
use crate::ty::{self, DefId, Ty, TypeVisitableExt, VariantDef, Visibility};
-use rustc_type_ir::TyKind::*;
-use tracing::instrument;
-
pub mod inhabited_predicate;
pub use inhabited_predicate::InhabitedPredicate;
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 6e64e9b..0496c57 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -1,10 +1,7 @@
-use crate::error;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::ty::print::{shrunk_instance_name, FmtPrinter, Printer};
-use crate::ty::{
- self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
- TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
-};
+use std::assert_matches::assert_matches;
+use std::fmt;
+use std::path::PathBuf;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
@@ -18,9 +15,13 @@
use rustc_span::{Span, Symbol, DUMMY_SP};
use tracing::{debug, instrument};
-use std::assert_matches::assert_matches;
-use std::fmt;
-use std::path::PathBuf;
+use crate::error;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::ty::print::{shrunk_instance_name, FmtPrinter, Printer};
+use crate::ty::{
+ self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
+ TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
/// An `InstanceKind` along with the args that are needed to substitute the instance.
///
diff --git a/compiler/rustc_middle/src/ty/intrinsic.rs b/compiler/rustc_middle/src/ty/intrinsic.rs
index 68c1d8c..41a966d 100644
--- a/compiler/rustc_middle/src/ty/intrinsic.rs
+++ b/compiler/rustc_middle/src/ty/intrinsic.rs
@@ -1,5 +1,6 @@
use rustc_macros::{Decodable, Encodable, HashStable};
-use rustc_span::{def_id::DefId, Symbol};
+use rustc_span::def_id::DefId;
+use rustc_span::Symbol;
use super::TyCtxt;
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 22a6786..6845748 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,8 +1,8 @@
-use crate::error::UnsupportedFnAbi;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::query::TyCtxtAt;
-use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt};
+use std::borrow::Cow;
+use std::num::NonZero;
+use std::ops::Bound;
+use std::{cmp, fmt};
+
use rustc_error_messages::DiagMessage;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
@@ -17,16 +17,15 @@
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::*;
-use rustc_target::spec::{
- abi::Abi as SpecAbi, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi,
-};
+use rustc_target::spec::abi::Abi as SpecAbi;
+use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi};
use tracing::debug;
-use std::borrow::Cow;
-use std::cmp;
-use std::fmt;
-use std::num::NonZero;
-use std::ops::Bound;
+use crate::error::UnsupportedFnAbi;
+use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::query::TyCtxtAt;
+use crate::ty::normalize_erasing_regions::NormalizationError;
+use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt};
#[extension(pub trait IntegerExt)]
impl Integer {
@@ -231,8 +230,9 @@ pub enum LayoutError<'tcx> {
impl<'tcx> LayoutError<'tcx> {
pub fn diagnostic_message(&self) -> DiagMessage {
- use crate::fluent_generated::*;
use LayoutError::*;
+
+ use crate::fluent_generated::*;
match self {
Unknown(_) => middle_unknown_layout,
SizeOverflow(_) => middle_values_too_big,
@@ -243,8 +243,9 @@ pub fn diagnostic_message(&self) -> DiagMessage {
}
pub fn into_diagnostic(self) -> crate::error::LayoutError<'tcx> {
- use crate::error::LayoutError as E;
use LayoutError::*;
+
+ use crate::error::LayoutError as E;
match self {
Unknown(ty) => E::Unknown { ty },
SizeOverflow(ty) => E::Overflow { ty },
@@ -361,7 +362,7 @@ pub fn compute(
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
let non_zero = !ty.is_unsafe_ptr();
- let tail = tcx.struct_tail_with_normalize(
+ let tail = tcx.struct_tail_raw(
pointee,
|ty| match tcx.try_normalize_erasing_regions(param_env, ty) {
Ok(ty) => ty,
@@ -868,7 +869,7 @@ fn field_ty_or_layout<'tcx>(
metadata
}
} else {
- match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
+ match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() {
ty::Slice(_) | ty::Str => tcx.types.usize,
ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()),
_ => bug!("TyAndLayout::field({:?}): not applicable", this),
@@ -1347,7 +1348,7 @@ pub fn offset_of_subfield<I>(
layout = layout.field(&cx, index);
if !layout.is_sized() {
// If it is not sized, then the tail must still have at least a known static alignment.
- let tail = self.struct_tail_erasing_lifetimes(layout.ty, param_env);
+ let tail = self.struct_tail_for_codegen(layout.ty, param_env);
if !matches!(tail.kind(), ty::Slice(..)) {
bug!(
"offset of not-statically-aligned field (type {:?}) cannot be computed statically",
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 73eba93..1a1acf3 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -1,20 +1,17 @@
+use std::alloc::Layout;
+use std::cmp::Ordering;
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+use std::{fmt, iter, mem, ptr, slice};
+
+use rustc_data_structures::aligned::{align_of, Aligned};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::sync::DynSync;
+use rustc_serialize::{Encodable, Encoder};
+
use super::flags::FlagComputation;
use super::{DebruijnIndex, TypeFlags};
use crate::arena::Arena;
-use rustc_data_structures::aligned::{align_of, Aligned};
-use rustc_serialize::{Encodable, Encoder};
-use std::alloc::Layout;
-use std::cmp::Ordering;
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::iter;
-use std::mem;
-use std::ops::Deref;
-use std::ptr;
-use std::slice;
-
-#[cfg(parallel_compiler)]
-use rustc_data_structures::sync::DynSync;
/// `List<T>` is a bit like `&[T]`, but with some critical differences.
/// - IMPORTANT: Every `List<T>` is *required* to have unique contents. The
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 558590a..69b1940 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -11,37 +11,28 @@
#![allow(rustc::usage_of_ty_tykind)]
-pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
-pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-pub use self::AssocItemContainer::*;
-pub use self::BorrowKind::*;
-pub use self::IntVarValue::*;
-use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
-use crate::metadata::ModChild;
-use crate::middle::privacy::EffectiveVisibilities;
-use crate::mir::{Body, CoroutineLayout};
-use crate::query::Providers;
-use crate::traits::{self, Reveal};
-use crate::ty;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::util::Discr;
+use std::assert_matches::assert_matches;
+use std::fmt::Debug;
+use std::hash::{Hash, Hasher};
+use std::marker::PhantomData;
+use std::num::NonZero;
+use std::ptr::NonNull;
+use std::{fmt, mem, str};
+
pub use adt::*;
pub use assoc::*;
pub use generic_args::{GenericArgKind, TermKind, *};
pub use generics::*;
pub use intrinsic::IntrinsicDef;
-use rustc_ast as ast;
use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::node_id::NodeMap;
pub use rustc_ast_ir::{try_visit, Movability, Mutability};
-use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
-use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_index::IndexVec;
@@ -59,24 +50,14 @@
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
pub use rustc_type_ir::relate::VarianceDiagInfo;
-use tracing::{debug, instrument};
-pub use vtable::*;
-
-use std::assert_matches::assert_matches;
-use std::fmt::Debug;
-use std::hash::{Hash, Hasher};
-use std::marker::PhantomData;
-use std::mem;
-use std::num::NonZero;
-use std::ptr::NonNull;
-use std::{fmt, str};
-
-pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::ConstKind::{
Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
Placeholder as PlaceholderCt, Unevaluated, Value,
};
pub use rustc_type_ir::*;
+use tracing::{debug, instrument};
+pub use vtable::*;
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
pub use self::closure::{
analyze_coroutine_closure_captures, is_ancestor_or_same_capture, place_to_string_for_capture,
@@ -91,6 +72,7 @@
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
TyCtxt, TyCtxtFeed,
};
+pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
pub use self::instance::{Instance, InstanceKind, ReifyReason, ShortInstance, UnusedGenericParams};
pub use self::list::{List, ListWithCachedTypeInfo};
pub use self::opaque_types::OpaqueTypeKey;
@@ -105,9 +87,9 @@
PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
TraitPredicate, TraitRef, TypeOutlivesPredicate,
};
+pub use self::region::BoundRegionKind::*;
pub use self::region::{
- BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region,
- RegionKind, RegionVid,
+ BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, Region, RegionKind, RegionVid,
};
pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::{
@@ -120,6 +102,20 @@
CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity,
TypeckResults, UserType, UserTypeAnnotationIndex,
};
+pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+pub use self::AssocItemContainer::*;
+pub use self::BorrowKind::*;
+pub use self::IntVarValue::*;
+use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
+use crate::metadata::ModChild;
+use crate::middle::privacy::EffectiveVisibilities;
+use crate::mir::{Body, CoroutineLayout};
+use crate::query::Providers;
+use crate::traits::{self, Reveal};
+use crate::ty;
+pub use crate::ty::diagnostics::*;
+use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::util::Discr;
pub mod abstract_const;
pub mod adjustment;
@@ -266,6 +262,7 @@ pub struct ImplTraitHeader<'tcx> {
pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>,
pub polarity: ImplPolarity,
pub safety: hir::Safety,
+ pub do_not_recommend: bool,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
@@ -2148,8 +2145,9 @@ pub struct DestructuredConst<'tcx> {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(PredicateKind<'_>, 32);
static_assert_size!(WithCachedTypeInfo<TyKind<'_>>, 56);
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 96f00e1d..e51d220 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -7,11 +7,12 @@
//! `normalize_generic_arg_after_erasing_regions` query for each type
//! or constant found within. (This underlying query is what is cached.)
+use rustc_macros::{HashStable, TyDecodable, TyEncodable};
+use tracing::{debug, instrument};
+
use crate::traits::query::NoSolution;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
-use rustc_macros::{HashStable, TyDecodable, TyEncodable};
-use tracing::{debug, instrument};
#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
pub enum NormalizationError<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 70a54e9..d3f4432 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -1,12 +1,12 @@
-use crate::error::ConstNotUsedTraitAlias;
-use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
-use crate::ty::{GenericArg, GenericArgKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_span::def_id::DefId;
use rustc_span::Span;
use tracing::{debug, instrument, trace};
+use crate::error::ConstNotUsedTraitAlias;
+use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
+use crate::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable};
+
pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey<TyCtxt<'tcx>>;
/// Converts generic params of a TypeFoldable from one
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index f394b3c..7e1255f 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -1,7 +1,8 @@
+use std::hash::Hash;
+
use rustc_data_structures::unord::UnordMap;
use rustc_hir::def_id::DefIndex;
use rustc_index::{Idx, IndexVec};
-use std::hash::Hash;
use crate::ty;
diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs
index d1875fb..e604aed 100644
--- a/compiler/rustc_middle/src/ty/pattern.rs
+++ b/compiler/rustc_middle/src/ty/pattern.rs
@@ -1,9 +1,10 @@
use std::fmt;
-use crate::ty;
use rustc_data_structures::intern::Interned;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
+use crate::ty;
+
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>);
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 5d6352c..8e72505 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -1,9 +1,10 @@
+use std::cmp::Ordering;
+
use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::Interned;
use rustc_hir::def_id::DefId;
use rustc_macros::{extension, HashStable};
use rustc_type_ir as ir;
-use std::cmp::Ordering;
use tracing::instrument;
use crate::ty::{
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index c165790..6cce79d 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,8 +1,5 @@
use std::path::PathBuf;
-use crate::ty::GenericArg;
-use crate::ty::{self, ShortInstance, Ty, TyCtxt};
-
use hir::def::Namespace;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
@@ -11,10 +8,11 @@
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use tracing::{debug, instrument, trace};
+use crate::ty::{self, GenericArg, ShortInstance, Ty, TyCtxt};
+
// `pretty` is a separate module only for organization.
mod pretty;
pub use self::pretty::*;
-
use super::Lift;
pub type PrintError = std::fmt::Error;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 0e24166..29d7218 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,11 +1,8 @@
-use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
-use crate::query::IntoQueryParam;
-use crate::query::Providers;
-use crate::ty::GenericArgKind;
-use crate::ty::{
- ConstInt, Expr, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
- TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
-};
+use std::cell::Cell;
+use std::fmt::{self, Write as _};
+use std::iter;
+use std::ops::{Deref, DerefMut};
+
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::Float;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@@ -25,13 +22,14 @@
use rustc_type_ir::{elaborate, Upcast as _};
use smallvec::SmallVec;
-use std::cell::Cell;
-use std::fmt::{self, Write as _};
-use std::iter;
-use std::ops::{Deref, DerefMut};
-
// `pretty` is a separate module only for organization.
use super::*;
+use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
+use crate::query::{IntoQueryParam, Providers};
+use crate::ty::{
+ ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TypeFoldable,
+ TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+};
macro_rules! p {
(@$lit:literal) => {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 4e85af9..a2a9610 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -1,13 +1,13 @@
+use std::ops::Deref;
+
use rustc_data_structures::intern::Interned;
use rustc_errors::MultiSpan;
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
-use rustc_span::symbol::sym;
-use rustc_span::symbol::{kw, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
use rustc_type_ir::RegionKind as IrRegionKind;
pub use rustc_type_ir::RegionVid;
-use std::ops::Deref;
use tracing::debug;
use crate::ty::{self, BoundVar, TyCtxt, TypeFlags};
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index 8ec7946..bcab54c 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -1,9 +1,10 @@
-use crate::middle::region::{Scope, ScopeData, ScopeTree};
use rustc_hir as hir;
use rustc_hir::ItemLocalMap;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use tracing::debug;
+use crate::middle::region::{Scope, ScopeData, ScopeTree};
+
/// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
/// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
#[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7cdc0e3..8fb44a5 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -3,11 +3,8 @@
//! written by hand, though we've recently added some macros and proc-macros
//! to help with the tedium.
-use crate::mir::interpret;
-use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
-use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
-use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
+use std::fmt::{self, Debug};
+
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use rustc_hir::def::Namespace;
@@ -15,12 +12,13 @@
use rustc_target::abi::TyAndLayout;
use rustc_type_ir::ConstKind;
-use std::fmt::{self, Debug};
-
use super::print::PrettyPrinter;
-use super::{GenericArg, GenericArgKind, Region};
-
-use super::Pattern;
+use super::{GenericArg, GenericArgKind, Pattern, Region};
+use crate::mir::interpret;
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
+use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
+use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
impl fmt::Debug for ty::TraitDef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index da98e3b..8781a67 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2,14 +2,11 @@
#![allow(rustc::usage_of_ty_tykind)]
-use crate::infer::canonical::Canonical;
-use crate::ty::InferTy::*;
-use crate::ty::{
- self, AdtDef, BoundRegionKind, Discr, Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable,
- TypeVisitable, TypeVisitor,
-};
-use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
-use crate::ty::{List, ParamEnv};
+use std::assert_matches::debug_assert_matches;
+use std::borrow::Cow;
+use std::iter;
+use std::ops::{ControlFlow, Range};
+
use hir::def::{CtorKind, DefKind};
use rustc_data_structures::captures::Captures;
use rustc_errors::{ErrorGuaranteed, MultiSpan};
@@ -22,16 +19,17 @@
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_target::spec::abi;
use rustc_type_ir::visit::TypeVisitableExt;
-use std::assert_matches::debug_assert_matches;
-use std::borrow::Cow;
-use std::iter;
-use std::ops::{ControlFlow, Range};
-use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
-
use rustc_type_ir::TyKind::*;
use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
+use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
use super::GenericParamDefKind;
+use crate::infer::canonical::Canonical;
+use crate::ty::InferTy::*;
+use crate::ty::{
+ self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
+ Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor,
+};
// Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here
#[rustc_diagnostic_item = "TyKind"]
@@ -1592,7 +1590,7 @@ pub fn ptr_metadata_ty_or_tail(
tcx: TyCtxt<'tcx>,
normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
) -> Result<Ty<'tcx>, Ty<'tcx>> {
- let tail = tcx.struct_tail_with_normalize(self, normalize, || {});
+ let tail = tcx.struct_tail_raw(self, normalize, || {});
match tail.kind() {
// Sized types
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
@@ -1616,10 +1614,10 @@ pub fn ptr_metadata_ty_or_tail(
| ty::Foreign(..)
// `dyn*` has metadata = ().
| ty::Dynamic(_, _, ty::DynStar)
- // If returned by `struct_tail_with_normalize` this is a unit struct
+ // If returned by `struct_tail_raw` this is a unit struct
// without any fields, or not a struct, and therefore is Sized.
| ty::Adt(..)
- // If returned by `struct_tail_with_normalize` this is the empty tuple,
+ // If returned by `struct_tail_raw` this is the empty tuple,
// a.k.a. unit type, which is Sized
| ty::Tuple(..) => Ok(tcx.types.unit),
@@ -1966,8 +1964,9 @@ fn split_inputs_and_output(self) -> (&'tcx [Ty<'tcx>], Ty<'tcx>) {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(ty::RegionKind<'_>, 24);
static_assert_size!(ty::TyKind<'_>, 32);
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 3bd9f6a..dfb137f 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,13 +1,12 @@
use std::iter;
-use tracing::debug;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::DefId;
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_macros::{Decodable, Encodable, HashStable};
+use tracing::debug;
use crate::query::LocalCrate;
use crate::traits::specialization_graph;
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index a6dec66..a92bdb2 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -1,21 +1,15 @@
-use crate::{
- hir::place::Place as HirPlace,
- infer::canonical::Canonical,
- traits::ObligationCause,
- ty::{
- self, tls, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind,
- GenericArgs, GenericArgsRef, Ty, UserArgs,
- },
-};
+use std::collections::hash_map::Entry;
+use std::hash::Hash;
+use std::iter;
+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
+use rustc_hir::hir_id::OwnerId;
use rustc_hir::{
- self as hir,
- def::{DefKind, Res},
- def_id::{DefId, LocalDefId, LocalDefIdMap},
- hir_id::OwnerId,
- BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
+ self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
};
use rustc_index::IndexVec;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
@@ -23,9 +17,15 @@
use rustc_session::Session;
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
-use std::{collections::hash_map::Entry, hash::Hash, iter};
use super::RvalueScopes;
+use crate::hir::place::Place as HirPlace;
+use crate::infer::canonical::Canonical;
+use crate::traits::ObligationCause;
+use crate::ty::{
+ self, tls, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs,
+ GenericArgsRef, Ty, UserArgs,
+};
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
pub struct TypeckResults<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 4335d96..6be3dc4 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1,13 +1,7 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
-use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::query::{IntoQueryParam, Providers};
-use crate::ty::layout::{FloatExt, IntegerExt};
-use crate::ty::{
- self, Asyncness, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
- TypeVisitableExt, Upcast,
-};
-use crate::ty::{GenericArgKind, GenericArgsRef};
+use std::{fmt, iter};
+
use rustc_apfloat::Float as _;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
@@ -23,9 +17,16 @@
use rustc_target::abi::{Float, Integer, IntegerType, Size};
use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec};
-use std::{fmt, iter};
use tracing::{debug, instrument, trace};
+use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::query::{IntoQueryParam, Providers};
+use crate::ty::layout::{FloatExt, IntegerExt};
+use crate::ty::{
+ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable,
+ TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast,
+};
+
#[derive(Copy, Clone, Debug)]
pub struct Discr<'tcx> {
/// Bit representation of the discriminant (e.g., `-128i8` is `0xFF_u128`).
@@ -78,7 +79,7 @@ pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
let (val, oflo) = if signed {
let min = size.signed_int_min();
let max = size.signed_int_max();
- let val = size.sign_extend(self.val) as i128;
+ let val = size.sign_extend(self.val);
assert!(n < (i128::MAX as u128));
let n = n as i128;
let oflo = val > max - n;
@@ -170,14 +171,6 @@ pub fn res_generics_def_id(self, res: Res) -> Option<DefId> {
}
}
- /// Attempts to returns the deeply last field of nested structures, but
- /// does not apply any normalization in its search. Returns the same type
- /// if input `ty` is not a structure at all.
- pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- let tcx = self;
- tcx.struct_tail_with_normalize(ty, |ty| ty, || {})
- }
-
/// Returns the deeply last field of nested structures, or the same type if
/// not a structure at all. Corresponds to the only possible unsized field,
/// and its type can be used to determine unsizing strategy.
@@ -185,13 +178,9 @@ pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx> {
/// Should only be called if `ty` has no inference variables and does not
/// need its lifetimes preserved (e.g. as part of codegen); otherwise
/// normalization attempt may cause compiler bugs.
- pub fn struct_tail_erasing_lifetimes(
- self,
- ty: Ty<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ) -> Ty<'tcx> {
+ pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let tcx = self;
- tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
+ tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {})
}
/// Returns the deeply last field of nested structures, or the same type if
@@ -199,12 +188,14 @@ pub fn struct_tail_erasing_lifetimes(
/// and its type can be used to determine unsizing strategy.
///
/// This is parameterized over the normalization strategy (i.e. how to
- /// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
- /// function to indicate no normalization should take place.
+ /// handle `<T as Trait>::Assoc` and `impl Trait`). You almost certainly do
+ /// **NOT** want to pass the identity function here, unless you know what
+ /// you're doing, or you're within normalization code itself and will handle
+ /// an unnormalized tail recursively.
///
- /// See also `struct_tail_erasing_lifetimes`, which is suitable for use
+ /// See also `struct_tail_for_codegen`, which is suitable for use
/// during codegen.
- pub fn struct_tail_with_normalize(
+ pub fn struct_tail_raw(
self,
mut ty: Ty<'tcx>,
mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
@@ -271,20 +262,20 @@ pub fn struct_tail_with_normalize(
/// Same as applying `struct_tail` on `source` and `target`, but only
/// keeps going as long as the two types are instances of the same
/// structure definitions.
- /// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
+ /// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, dyn Trait)`,
/// whereas struct_tail produces `T`, and `Trait`, respectively.
///
/// Should only be called if the types have no inference variables and do
/// not need their lifetimes preserved (e.g., as part of codegen); otherwise,
/// normalization attempt may cause compiler bugs.
- pub fn struct_lockstep_tails_erasing_lifetimes(
+ pub fn struct_lockstep_tails_for_codegen(
self,
source: Ty<'tcx>,
target: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> (Ty<'tcx>, Ty<'tcx>) {
let tcx = self;
- tcx.struct_lockstep_tails_with_normalize(source, target, |ty| {
+ tcx.struct_lockstep_tails_raw(source, target, |ty| {
tcx.normalize_erasing_regions(param_env, ty)
})
}
@@ -295,9 +286,9 @@ pub fn struct_lockstep_tails_erasing_lifetimes(
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
/// whereas struct_tail produces `T`, and `Trait`, respectively.
///
- /// See also `struct_lockstep_tails_erasing_lifetimes`, which is suitable for use
+ /// See also `struct_lockstep_tails_for_codegen`, which is suitable for use
/// during codegen.
- pub fn struct_lockstep_tails_with_normalize(
+ pub fn struct_lockstep_tails_raw(
self,
source: Ty<'tcx>,
target: Ty<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index b1bbfd4..78d8300 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -1,11 +1,11 @@
-use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
+use std::ops::ControlFlow;
use rustc_data_structures::fx::FxHashSet;
use rustc_type_ir::fold::TypeFoldable;
-use std::ops::ControlFlow;
-
pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
+
///////////////////////////////////////////////////////////////////////////
// Region folder
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 466c3b9..951112d 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -1,10 +1,11 @@
use std::fmt;
-use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar};
-use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
use rustc_ast::Mutability;
use rustc_macros::HashStable;
+use crate::mir::interpret::{alloc_range, AllocId, Allocation, Pointer, Scalar, CTFE_ALLOC_SALT};
+use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
+
#[derive(Clone, Copy, PartialEq, HashStable)]
pub enum VtblEntry<'tcx> {
/// destructor of this type (used in vtable header)
@@ -72,6 +73,11 @@ pub(crate) fn vtable_min_entries<'tcx>(
/// Retrieves an allocation that represents the contents of a vtable.
/// Since this is a query, allocations are cached and not duplicated.
+///
+/// This is an "internal" `AllocId` that should never be used as a value in the interpreted program.
+/// The interpreter should use `AllocId` that refer to a `GlobalAlloc::VTable` instead.
+/// (This is similar to statics, which also have a similar "internal" `AllocId` storing their
+/// initial contents.)
pub(super) fn vtable_allocation_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
@@ -113,7 +119,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
VtblEntry::MetadataDropInPlace => {
if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) {
let instance = ty::Instance::resolve_drop_in_place(tcx, ty);
- let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance);
+ let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
let fn_ptr = Pointer::from(fn_alloc_id);
Scalar::from_pointer(fn_ptr, &tcx)
} else {
@@ -126,7 +132,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
VtblEntry::Method(instance) => {
// Prepare the fn ptr we write into the vtable.
let instance = instance.polymorphize(tcx);
- let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance);
+ let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT);
let fn_ptr = Pointer::from(fn_alloc_id);
Scalar::from_pointer(fn_ptr, &tcx)
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index efcaf89..2dd7a96 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -1,12 +1,12 @@
//! An iterator over the type substructure.
//! WARNING: this does not keep track of the region depth.
-use crate::ty::{self, Ty};
-use crate::ty::{GenericArg, GenericArgKind};
use rustc_data_structures::sso::SsoHashSet;
use smallvec::{smallvec, SmallVec};
use tracing::debug;
+use crate::ty::{self, GenericArg, GenericArgKind, Ty};
+
// The TypeWalker's stack is hot enough that it's worth going to some effort to
// avoid heap allocations.
type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs
index 43853a1..32f5251 100644
--- a/compiler/rustc_middle/src/util/bug.rs
+++ b/compiler/rustc_middle/src/util/bug.rs
@@ -1,11 +1,13 @@
// These functions are used by macro expansion for bug! and span_bug!
-use crate::ty::{tls, TyCtxt};
-use rustc_errors::MultiSpan;
-use rustc_span::Span;
use std::fmt;
use std::panic::{panic_any, Location};
+use rustc_errors::MultiSpan;
+use rustc_span::Span;
+
+use crate::ty::{tls, TyCtxt};
+
#[cold]
#[inline(never)]
#[track_caller]
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index 0815c29..75ae4e1 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -2,14 +2,14 @@
//! as well as errors when attempting to call a non-const function in a const
//! context.
-use crate::ty::GenericArgsRef;
-use crate::ty::{AssocItemContainer, Instance, ParamEnv, Ty, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_hir::{lang_items, LangItem};
use rustc_span::symbol::Ident;
use rustc_span::{sym, DesugaringKind, Span};
use tracing::debug;
+use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, ParamEnv, Ty, TyCtxt};
+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum CallDesugaringKind {
/// for _ in x {} calls x.into_iter()
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index 831853b..ec6051d 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -1,10 +1,10 @@
-use crate::mir::*;
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::source_map::Spanned;
use tracing::debug;
+use crate::mir::*;
+use crate::ty::{self, GenericArgsRef, TyCtxt};
+
/// Checks if the specified `local` is used as the `self` parameter of a method call
/// in the provided `BasicBlock`. If it is, then the `DefId` of the called method is
/// returned.
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 8c32318..9e429f5 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,19 +1,20 @@
-use crate::dep_graph::dep_kinds;
-use crate::query::plumbing::CyclePlaceholder;
+use std::collections::VecDeque;
+use std::fmt::Write;
+use std::ops::ControlFlow;
+
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
+use rustc_errors::codes::*;
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
-use rustc_middle::ty::Representability;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
use rustc_query_system::query::{report_cycle, CycleError};
use rustc_query_system::Value;
use rustc_span::def_id::LocalDefId;
use rustc_span::{ErrorGuaranteed, Span};
-use std::collections::VecDeque;
-use std::fmt::Write;
-use std::ops::ControlFlow;
+use crate::dep_graph::dep_kinds;
+use crate::query::plumbing::CyclePlaceholder;
impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self {
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index c608e5c..7afa628 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -1,12 +1,13 @@
+use rustc_middle::middle::region::Scope;
+use rustc_middle::mir::*;
+use rustc_middle::thir::*;
+use rustc_middle::{span_bug, ty};
+use rustc_span::Span;
+use tracing::debug;
+
use crate::build::matches::{DeclareLetBindings, EmitStorageLive, ScheduleDrops};
use crate::build::ForGuard::OutsideGuard;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
-use rustc_middle::middle::region::Scope;
-use rustc_middle::span_bug;
-use rustc_middle::thir::*;
-use rustc_middle::{mir::*, ty};
-use rustc_span::Span;
-use tracing::debug;
impl<'a, 'tcx> Builder<'a, 'tcx> {
pub(crate) fn ast_block(
diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs
index 6034c8f..e80b654 100644
--- a/compiler/rustc_mir_build/src/build/cfg.rs
+++ b/compiler/rustc_mir_build/src/build/cfg.rs
@@ -1,10 +1,11 @@
//! Routines for manipulating the control-flow graph.
-use crate::build::CFG;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::debug;
+use crate::build::CFG;
+
impl<'tcx> CFG<'tcx> {
pub(crate) fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
&self.basic_blocks[blk]
diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs
index f6ebcbc..28477e5 100644
--- a/compiler/rustc_mir_build/src/build/custom/mod.rs
+++ b/compiler/rustc_mir_build/src/build/custom/mod.rs
@@ -22,12 +22,10 @@
use rustc_hir::def_id::DefId;
use rustc_hir::HirId;
use rustc_index::{IndexSlice, IndexVec};
-use rustc_middle::{
- mir::*,
- span_bug,
- thir::*,
- ty::{ParamEnv, Ty, TyCtxt},
-};
+use rustc_middle::mir::*;
+use rustc_middle::span_bug;
+use rustc_middle::thir::*;
+use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_span::Span;
mod parse;
@@ -56,8 +54,8 @@ pub(super) fn build_custom_mir<'tcx>(
spread_arg: None,
var_debug_info: Vec::new(),
span,
- required_consts: Vec::new(),
- mentioned_items: Vec::new(),
+ required_consts: None,
+ mentioned_items: None,
is_polymorphic: false,
tainted_by_errors: None,
injection_phase: None,
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs
index 9607022..646aefa 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse.rs
@@ -1,6 +1,7 @@
use rustc_index::IndexSlice;
+use rustc_middle::mir::*;
+use rustc_middle::thir::*;
use rustc_middle::ty::{self, Ty};
-use rustc_middle::{mir::*, thir::*};
use rustc_span::Span;
use super::{PResult, ParseCtxt, ParseError};
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 94ab2fb..56896d9 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -1,16 +1,17 @@
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::tcx::PlaceTy;
+use rustc_middle::mir::*;
+use rustc_middle::thir::*;
+use rustc_middle::ty;
use rustc_middle::ty::cast::mir_cast_kind;
-use rustc_middle::{mir::*, thir::*, ty};
use rustc_span::source_map::Spanned;
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
+use super::{parse_by_kind, PResult, ParseCtxt};
use crate::build::custom::ParseError;
use crate::build::expr::as_constant::as_constant_inner;
-use super::{parse_by_kind, PResult, ParseCtxt};
-
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
pub(crate) fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
parse_by_kind!(self, expr_id, _, "statement",
@@ -74,6 +75,9 @@ pub(crate) fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind
@call(mir_call, args) => {
self.parse_call(args)
},
+ @call(mir_tail_call, args) => {
+ self.parse_tail_call(args)
+ },
ExprKind::Match { scrutinee, arms, .. } => {
let discr = self.parse_operand(*scrutinee)?;
self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t })
@@ -186,6 +190,25 @@ fn parse_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
)
}
+ fn parse_tail_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
+ parse_by_kind!(self, args[0], _, "tail call",
+ ExprKind::Call { fun, args, fn_span, .. } => {
+ let fun = self.parse_operand(*fun)?;
+ let args = args
+ .iter()
+ .map(|arg|
+ Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } )
+ )
+ .collect::<PResult<Box<[_]>>>()?;
+ Ok(TerminatorKind::TailCall {
+ func: fun,
+ args,
+ fn_span: *fn_span,
+ })
+ },
+ )
+ }
+
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
parse_by_kind!(self, expr_id, expr, "rvalue",
@call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant),
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index be62a3d..4430aab7 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -1,19 +1,21 @@
//! See docs in build/expr/mod.rs
-use crate::build::{parse_float_into_constval, Builder};
use rustc_ast as ast;
use rustc_hir::LangItem;
-use rustc_middle::mir;
-use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput, Scalar};
+use rustc_middle::mir::interpret::{
+ Allocation, LitToConstError, LitToConstInput, Scalar, CTFE_ALLOC_SALT,
+};
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::{
self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex,
};
-use rustc_middle::{bug, span_bug};
+use rustc_middle::{bug, mir, span_bug};
use rustc_target::abi::Size;
use tracing::{instrument, trace};
+use crate::build::{parse_float_into_constval, Builder};
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant!
@@ -140,7 +142,7 @@ fn lit_to_mir_constant<'tcx>(
ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
}
(ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
- let id = tcx.allocate_bytes_dedup(data);
+ let id = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT);
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
}
(ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index 09ce134..1e67e75 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -1,12 +1,13 @@
//! See docs in build/expr/mod.rs
-use crate::build::expr::category::Category;
-use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use tracing::{debug, instrument};
+use crate::build::expr::category::Category;
+use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Returns an operand suitable for use until the end of the current
/// scope expression.
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 91a3b53..b80d9de 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -1,24 +1,23 @@
//! See docs in build/expr/mod.rs
-use crate::build::expr::category::Category;
-use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
-use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap};
+use std::assert_matches::assert_matches;
+use std::iter;
+
use rustc_hir::def_id::LocalDefId;
-use rustc_middle::hir::place::Projection as HirProjection;
-use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
+use rustc_middle::hir::place::{Projection as HirProjection, ProjectionKind as HirProjectionKind};
use rustc_middle::middle::region;
use rustc_middle::mir::AssertKind::BoundsCheck;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
-use rustc_middle::ty::AdtDef;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
+use rustc_middle::ty::{self, AdtDef, CanonicalUserTypeAnnotation, Ty, Variance};
use rustc_middle::{bug, span_bug};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use tracing::{debug, instrument, trace};
-use std::assert_matches::assert_matches;
-use std::iter;
+use crate::build::expr::category::Category;
+use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
+use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap};
/// The "outermost" place that holds this value.
#[derive(Copy, Clone, Debug, PartialEq)]
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 40cfe56..379d214 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -1,14 +1,7 @@
//! See docs in `build/expr/mod.rs`.
-use rustc_index::{Idx, IndexVec};
-use rustc_middle::ty::util::IntTypeExt;
-use rustc_span::source_map::Spanned;
-use rustc_target::abi::{Abi, FieldIdx, Primitive};
-
-use crate::build::expr::as_place::PlaceBase;
-use crate::build::expr::category::{Category, RvalueFunc};
-use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
use rustc_hir::lang_items::LangItem;
+use rustc_index::{Idx, IndexVec};
use rustc_middle::bug;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::Scalar;
@@ -16,10 +9,17 @@
use rustc_middle::thir::*;
use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
use rustc_middle::ty::layout::IntegerExt;
+use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, Ty, UpvarArgs};
+use rustc_span::source_map::Spanned;
use rustc_span::{Span, DUMMY_SP};
+use rustc_target::abi::{Abi, FieldIdx, Primitive};
use tracing::debug;
+use crate::build::expr::as_place::PlaceBase;
+use crate::build::expr::category::{Category, RvalueFunc};
+use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Returns an rvalue suitable for use until the end of the current
/// scope expression.
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 8267358..af5940f 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -1,13 +1,14 @@
//! See docs in build/expr/mod.rs
-use crate::build::scope::DropKind;
-use crate::build::{BlockAnd, BlockAndExtension, Builder};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use tracing::{debug, instrument};
+use crate::build::scope::DropKind;
+use crate::build::{BlockAnd, BlockAndExtension, Builder};
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr` into a fresh temporary. This is used when building
/// up rvalues so as to freeze the value that will be consumed.
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 9cd958a..01b32b8 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -1,8 +1,7 @@
//! See docs in build/expr/mod.rs
-use crate::build::expr::category::{Category, RvalueFunc};
-use crate::build::matches::DeclareLetBindings;
-use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary};
+use std::iter;
+
use rustc_ast::InlineAsmOptions;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -12,9 +11,12 @@
use rustc_middle::thir::*;
use rustc_middle::ty::CanonicalUserTypeAnnotation;
use rustc_span::source_map::Spanned;
-use std::iter;
use tracing::{debug, instrument};
+use crate::build::expr::category::{Category, RvalueFunc};
+use crate::build::matches::DeclareLetBindings;
+use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary};
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized.
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 8e13edb..b38f0a4 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -1,5 +1,3 @@
-use crate::build::scope::BreakableTarget;
-use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
@@ -7,6 +5,9 @@
use rustc_span::source_map::Spanned;
use tracing::debug;
+use crate::build::scope::BreakableTarget;
+use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Builds a block of MIR statements to evaluate the THIR `expr`.
///
diff --git a/compiler/rustc_mir_build/src/build/matches/match_pair.rs b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
index 95fec15..ab2bfcb 100644
--- a/compiler/rustc_mir_build/src/build/matches/match_pair.rs
+++ b/compiler/rustc_mir_build/src/build/matches/match_pair.rs
@@ -208,14 +208,11 @@ pub(in crate::build) fn for_pattern(
subpairs = cx.field_match_pairs(downcast_place, subpatterns);
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
- i == variant_index || {
- (cx.tcx.features().exhaustive_patterns
- || cx.tcx.features().min_exhaustive_patterns)
- && !v
- .inhabited_predicate(cx.tcx, adt_def)
- .instantiate(cx.tcx, args)
- .apply_ignore_module(cx.tcx, cx.param_env)
- }
+ i == variant_index
+ || !v
+ .inhabited_predicate(cx.tcx, adt_def)
+ .instantiate(cx.tcx, args)
+ .apply_ignore_module(cx.tcx, cx.param_env)
}) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 6ac8f0d..cae4aa7 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -5,12 +5,8 @@
//! This also includes code for pattern bindings in `let` statements and
//! function parameters.
-use crate::build::expr::as_place::PlaceBuilder;
-use crate::build::scope::DropKind;
-use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
-use crate::build::{BlockAnd, BlockAndExtension, Builder};
-use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
-use rustc_data_structures::{fx::FxIndexMap, stack::ensure_sufficient_stack};
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::{BindingMode, ByRef};
use rustc_middle::bug;
use rustc_middle::middle::region;
@@ -21,7 +17,13 @@
use rustc_span::{BytePos, Pos, Span};
use rustc_target::abi::VariantIdx;
use tracing::{debug, instrument};
-use util::visit_bindings;
+
+use crate::build::expr::as_place::PlaceBuilder;
+use crate::build::scope::DropKind;
+use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
+use crate::build::{
+ BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode,
+};
// helper functions, broken out by category:
mod match_pair;
@@ -363,28 +365,22 @@ pub(crate) fn match_expr(
let scrutinee_place =
unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
- let mut arm_candidates = self.create_match_candidates(&scrutinee_place, arms);
-
- let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
- let mut candidates =
- arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
-
+ let arms = arms.iter().map(|arm| &self.thir[*arm]);
let match_start_span = span.shrink_to_lo().to(scrutinee_span);
-
- // The set of places that we are creating fake borrows of. If there are no match guards then
- // we don't need any fake borrows, so don't track them.
- let fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)> = if match_has_guard {
- util::collect_fake_borrows(self, &candidates, scrutinee_span, scrutinee_place.base())
- } else {
- Vec::new()
- };
-
- self.lower_match_tree(
+ let patterns = arms
+ .clone()
+ .map(|arm| {
+ let has_match_guard =
+ if arm.guard.is_some() { HasMatchGuard::Yes } else { HasMatchGuard::No };
+ (&*arm.pattern, has_match_guard)
+ })
+ .collect();
+ let built_tree = self.lower_match_tree(
block,
scrutinee_span,
&scrutinee_place,
match_start_span,
- &mut candidates,
+ patterns,
false,
);
@@ -392,9 +388,9 @@ pub(crate) fn match_expr(
destination,
scrutinee_place,
scrutinee_span,
- arm_candidates,
+ arms,
+ built_tree,
self.source_info(span),
- fake_borrow_temps,
)
}
@@ -414,51 +410,29 @@ fn lower_scrutinee(
block.and(scrutinee_place_builder)
}
- /// Create the initial `Candidate`s for a `match` expression.
- fn create_match_candidates<'pat>(
- &mut self,
- scrutinee: &PlaceBuilder<'tcx>,
- arms: &'pat [ArmId],
- ) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)>
- where
- 'a: 'pat,
- {
- // Assemble the initial list of candidates. These top-level candidates
- // are 1:1 with the original match arms, but other parts of match
- // lowering also introduce subcandidates (for subpatterns), and will
- // also flatten candidates in some cases. So in general a list of
- // candidates does _not_ necessarily correspond to a list of arms.
- arms.iter()
- .copied()
- .map(|arm| {
- let arm = &self.thir[arm];
- let arm_has_guard = arm.guard.is_some();
- let arm_candidate =
- Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard, self);
- (arm, arm_candidate)
- })
- .collect()
- }
-
/// Lower the bindings, guards and arm bodies of a `match` expression.
///
/// The decision tree should have already been created
/// (by [Builder::lower_match_tree]).
///
/// `outer_source_info` is the SourceInfo for the whole match.
- fn lower_match_arms(
+ fn lower_match_arms<'pat>(
&mut self,
destination: Place<'tcx>,
scrutinee_place_builder: PlaceBuilder<'tcx>,
scrutinee_span: Span,
- arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>,
+ arms: impl IntoIterator<Item = &'pat Arm<'tcx>>,
+ built_match_tree: BuiltMatchTree<'tcx>,
outer_source_info: SourceInfo,
- fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
- ) -> BlockAnd<()> {
- let arm_end_blocks: Vec<BasicBlock> = arm_candidates
+ ) -> BlockAnd<()>
+ where
+ 'tcx: 'pat,
+ {
+ let arm_end_blocks: Vec<BasicBlock> = arms
.into_iter()
- .map(|(arm, candidate)| {
- debug!("lowering arm {:?}\ncandidate = {:?}", arm, candidate);
+ .zip(built_match_tree.branches)
+ .map(|(arm, branch)| {
+ debug!("lowering arm {:?}\ncorresponding branch = {:?}", arm, branch);
let arm_source_info = self.source_info(arm.span);
let arm_scope = (arm.scope, arm_source_info);
@@ -491,8 +465,8 @@ fn lower_match_arms(
let arm_block = this.bind_pattern(
outer_source_info,
- candidate,
- &fake_borrow_temps,
+ branch,
+ &built_match_tree.fake_borrow_temps,
scrutinee_span,
Some((arm, match_scope)),
EmitStorageLive::Yes,
@@ -545,18 +519,17 @@ fn lower_match_arms(
fn bind_pattern(
&mut self,
outer_source_info: SourceInfo,
- candidate: Candidate<'_, 'tcx>,
+ branch: MatchTreeBranch<'tcx>,
fake_borrow_temps: &[(Place<'tcx>, Local, FakeBorrowKind)],
scrutinee_span: Span,
arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
emit_storage_live: EmitStorageLive,
) -> BasicBlock {
- if candidate.subcandidates.is_empty() {
- // Avoid generating another `BasicBlock` when we only have one
- // candidate.
+ if branch.sub_branches.len() == 1 {
+ let [sub_branch] = branch.sub_branches.try_into().unwrap();
+ // Avoid generating another `BasicBlock` when we only have one sub branch.
self.bind_and_guard_matched_candidate(
- candidate,
- &[],
+ sub_branch,
fake_borrow_temps,
scrutinee_span,
arm_match_scope,
@@ -584,35 +557,23 @@ fn bind_pattern(
// We keep a stack of all of the bindings and type ascriptions
// from the parent candidates that we visit, that also need to
// be bound for each candidate.
- traverse_candidate(
- candidate,
- &mut Vec::new(),
- &mut |leaf_candidate, parent_data| {
- if let Some(arm) = arm {
- self.clear_top_scope(arm.scope);
- }
- let binding_end = self.bind_and_guard_matched_candidate(
- leaf_candidate,
- parent_data,
- fake_borrow_temps,
- scrutinee_span,
- arm_match_scope,
- schedule_drops,
- emit_storage_live,
- );
- if arm.is_none() {
- schedule_drops = ScheduleDrops::No;
- }
- self.cfg.goto(binding_end, outer_source_info, target_block);
- },
- |inner_candidate, parent_data| {
- parent_data.push(inner_candidate.extra_data);
- inner_candidate.subcandidates.into_iter()
- },
- |parent_data| {
- parent_data.pop();
- },
- );
+ for sub_branch in branch.sub_branches {
+ if let Some(arm) = arm {
+ self.clear_top_scope(arm.scope);
+ }
+ let binding_end = self.bind_and_guard_matched_candidate(
+ sub_branch,
+ fake_borrow_temps,
+ scrutinee_span,
+ arm_match_scope,
+ schedule_drops,
+ emit_storage_live,
+ );
+ if arm.is_none() {
+ schedule_drops = ScheduleDrops::No;
+ }
+ self.cfg.goto(binding_end, outer_source_info, target_block);
+ }
target_block
}
@@ -722,7 +683,15 @@ pub(crate) fn place_into_pattern(
initializer: PlaceBuilder<'tcx>,
set_match_place: bool,
) -> BlockAnd<()> {
- let mut candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self);
+ let built_tree = self.lower_match_tree(
+ block,
+ irrefutable_pat.span,
+ &initializer,
+ irrefutable_pat.span,
+ vec![(irrefutable_pat, HasMatchGuard::No)],
+ false,
+ );
+ let [branch] = built_tree.branches.try_into().unwrap();
// For matches and function arguments, the place that is being matched
// can be set when creating the variables. But the place for
@@ -743,7 +712,9 @@ pub(crate) fn place_into_pattern(
// };
// ```
if let Some(place) = initializer.try_to_place(self) {
- visit_bindings(&[&mut candidate], |binding: &Binding<'_>| {
+ // Because or-alternatives bind the same variables, we only explore the first one.
+ let first_sub_branch = branch.sub_branches.first().unwrap();
+ for binding in &first_sub_branch.bindings {
let local = self.var_local_id(binding.var_id, OutsideGuard);
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
opt_match_place: Some((ref mut match_place, _)),
@@ -754,21 +725,13 @@ pub(crate) fn place_into_pattern(
} else {
bug!("Let binding to non-user variable.")
};
- });
+ }
}
}
- self.lower_match_tree(
- block,
- irrefutable_pat.span,
- &initializer,
- irrefutable_pat.span,
- &mut [&mut candidate],
- false,
- );
self.bind_pattern(
self.source_info(irrefutable_pat.span),
- candidate,
+ branch,
&[],
irrefutable_pat.span,
None,
@@ -1149,20 +1112,21 @@ struct Candidate<'pat, 'tcx> {
/// The earliest block that has only candidates >= this one as descendents. Used for false
/// edges, see the doc for [`Builder::match_expr`].
false_edge_start_block: Option<BasicBlock>,
- /// The `false_edge_start_block` of the next candidate.
- next_candidate_start_block: Option<BasicBlock>,
}
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
fn new(
place: PlaceBuilder<'tcx>,
pattern: &'pat Pat<'tcx>,
- has_guard: bool,
+ has_guard: HasMatchGuard,
cx: &mut Builder<'_, 'tcx>,
) -> Self {
// Use `FlatPat` to build simplified match pairs, then immediately
// incorporate them into a new candidate.
- Self::from_flat_pat(FlatPat::new(place, pattern, cx), has_guard)
+ Self::from_flat_pat(
+ FlatPat::new(place, pattern, cx),
+ matches!(has_guard, HasMatchGuard::Yes),
+ )
}
/// Incorporates an already-simplified [`FlatPat`] into a new candidate.
@@ -1176,7 +1140,6 @@ fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
otherwise_block: None,
pre_binding_block: None,
false_edge_start_block: None,
- next_candidate_start_block: None,
}
}
@@ -1196,6 +1159,17 @@ fn visit_leaves<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) {
|_| {},
);
}
+
+ /// Visit the leaf candidates in reverse order.
+ fn visit_leaves_rev<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) {
+ traverse_candidate(
+ self,
+ &mut (),
+ &mut move |c, _| visit_leaf(c),
+ move |c, _| c.subcandidates.iter_mut().rev(),
+ |_| {},
+ );
+ }
}
/// A depth-first traversal of the `Candidate` and all of its recursive
@@ -1406,12 +1380,114 @@ fn as_constant(&self) -> Option<&Const<'tcx>> {
///////////////////////////////////////////////////////////////////////////
// Main matching algorithm
+/// A sub-branch in the output of match lowering. Match lowering has generated MIR code that will
+/// branch to `success_block` when the matched value matches the corresponding pattern. If there is
+/// a guard, its failure must continue to `otherwise_block`, which will resume testing patterns.
+#[derive(Debug)]
+struct MatchTreeSubBranch<'tcx> {
+ span: Span,
+ /// The block that is branched to if the corresponding subpattern matches.
+ success_block: BasicBlock,
+ /// The block to branch to if this arm had a guard and the guard fails.
+ otherwise_block: BasicBlock,
+ /// The bindings to set up in this sub-branch.
+ bindings: Vec<Binding<'tcx>>,
+ /// The ascriptions to set up in this sub-branch.
+ ascriptions: Vec<Ascription<'tcx>>,
+ /// Whether the sub-branch corresponds to a never pattern.
+ is_never: bool,
+}
+
+/// A branch in the output of match lowering.
+#[derive(Debug)]
+struct MatchTreeBranch<'tcx> {
+ sub_branches: Vec<MatchTreeSubBranch<'tcx>>,
+}
+
+/// The result of generating MIR for a pattern-matching expression. Each input branch/arm/pattern
+/// gives rise to an output `MatchTreeBranch`. If one of the patterns matches, we branch to the
+/// corresponding `success_block`. If none of the patterns matches, we branch to `otherwise_block`.
+///
+/// Each branch is made of one of more sub-branches, corresponding to or-patterns. E.g.
+/// ```ignore(illustrative)
+/// match foo {
+/// (x, false) | (false, x) => {}
+/// (true, true) => {}
+/// }
+/// ```
+/// Here the first arm gives the first `MatchTreeBranch`, which has two sub-branches, one for each
+/// alternative of the or-pattern. They are kept separate because each needs to bind `x` to a
+/// different place.
+#[derive(Debug)]
+struct BuiltMatchTree<'tcx> {
+ branches: Vec<MatchTreeBranch<'tcx>>,
+ otherwise_block: BasicBlock,
+ /// If any of the branches had a guard, we collect here the places and locals to fakely borrow
+ /// to ensure match guards can't modify the values as we match them. For more details, see
+ /// [`util::collect_fake_borrows`].
+ fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
+}
+
+impl<'tcx> MatchTreeSubBranch<'tcx> {
+ fn from_sub_candidate(
+ candidate: Candidate<'_, 'tcx>,
+ parent_data: &Vec<PatternExtraData<'tcx>>,
+ ) -> Self {
+ debug_assert!(candidate.match_pairs.is_empty());
+ MatchTreeSubBranch {
+ span: candidate.extra_data.span,
+ success_block: candidate.pre_binding_block.unwrap(),
+ otherwise_block: candidate.otherwise_block.unwrap(),
+ bindings: parent_data
+ .iter()
+ .flat_map(|d| &d.bindings)
+ .chain(&candidate.extra_data.bindings)
+ .cloned()
+ .collect(),
+ ascriptions: parent_data
+ .iter()
+ .flat_map(|d| &d.ascriptions)
+ .cloned()
+ .chain(candidate.extra_data.ascriptions)
+ .collect(),
+ is_never: candidate.extra_data.is_never,
+ }
+ }
+}
+
+impl<'tcx> MatchTreeBranch<'tcx> {
+ fn from_candidate(candidate: Candidate<'_, 'tcx>) -> Self {
+ let mut sub_branches = Vec::new();
+ traverse_candidate(
+ candidate,
+ &mut Vec::new(),
+ &mut |candidate: Candidate<'_, '_>, parent_data: &mut Vec<PatternExtraData<'_>>| {
+ sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data));
+ },
+ |inner_candidate, parent_data| {
+ parent_data.push(inner_candidate.extra_data);
+ inner_candidate.subcandidates.into_iter()
+ },
+ |parent_data| {
+ parent_data.pop();
+ },
+ );
+ MatchTreeBranch { sub_branches }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum HasMatchGuard {
+ Yes,
+ No,
+}
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// The entrypoint of the matching algorithm. Create the decision tree for the match expression,
/// starting from `block`.
///
- /// Modifies `candidates` to store the bindings and type ascriptions for
- /// that candidate.
+ /// `patterns` is a list of patterns, one for each arm. The associated boolean indicates whether
+ /// the arm has a guard.
///
/// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
/// or not (for `let` and `match`). In the refutable case we return the block to which we branch
@@ -1422,31 +1498,76 @@ fn lower_match_tree<'pat>(
scrutinee_span: Span,
scrutinee_place_builder: &PlaceBuilder<'tcx>,
match_start_span: Span,
- candidates: &mut [&mut Candidate<'pat, 'tcx>],
+ patterns: Vec<(&'pat Pat<'tcx>, HasMatchGuard)>,
refutable: bool,
- ) -> BasicBlock {
- // This will generate code to test scrutinee_place and branch to the appropriate arm block.
- // See the doc comment on `match_candidates` for why we have an otherwise block.
- let otherwise_block =
- self.match_candidates(match_start_span, scrutinee_span, block, candidates);
+ ) -> BuiltMatchTree<'tcx>
+ where
+ 'tcx: 'pat,
+ {
+ // Assemble the initial list of candidates. These top-level candidates are 1:1 with the
+ // input patterns, but other parts of match lowering also introduce subcandidates (for
+ // sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
+ // match arms directly.
+ let mut candidates: Vec<Candidate<'_, '_>> = patterns
+ .into_iter()
+ .map(|(pat, has_guard)| {
+ Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self)
+ })
+ .collect();
- // Link each leaf candidate to the `false_edge_start_block` of the next one.
- let mut previous_candidate: Option<&mut Candidate<'_, '_>> = None;
- for candidate in candidates {
- candidate.visit_leaves(|leaf_candidate| {
- if let Some(ref mut prev) = previous_candidate {
- assert!(leaf_candidate.false_edge_start_block.is_some());
- prev.next_candidate_start_block = leaf_candidate.false_edge_start_block;
+ let fake_borrow_temps = util::collect_fake_borrows(
+ self,
+ &candidates,
+ scrutinee_span,
+ scrutinee_place_builder.base(),
+ );
+
+ // This will generate code to test scrutinee_place and branch to the appropriate arm block.
+ // If none of the arms match, we branch to `otherwise_block`. When lowering a `match`
+ // expression, exhaustiveness checking ensures that this block is unreachable.
+ let mut candidate_refs = candidates.iter_mut().collect::<Vec<_>>();
+ let otherwise_block =
+ self.match_candidates(match_start_span, scrutinee_span, block, &mut candidate_refs);
+
+ // Set up false edges so that the borrow-checker cannot make use of the specific CFG we
+ // generated. We falsely branch from each candidate to the one below it to make it as if we
+ // were testing match branches one by one in order. In the refutable case we also want a
+ // false edge to the final failure block.
+ let mut next_candidate_start_block = if refutable { Some(otherwise_block) } else { None };
+ for candidate in candidates.iter_mut().rev() {
+ let has_guard = candidate.has_guard;
+ candidate.visit_leaves_rev(|leaf_candidate| {
+ if let Some(next_candidate_start_block) = next_candidate_start_block {
+ let source_info = self.source_info(leaf_candidate.extra_data.span);
+ // Falsely branch to `next_candidate_start_block` before reaching pre_binding.
+ let old_pre_binding = leaf_candidate.pre_binding_block.unwrap();
+ let new_pre_binding = self.cfg.start_new_block();
+ self.false_edges(
+ old_pre_binding,
+ new_pre_binding,
+ next_candidate_start_block,
+ source_info,
+ );
+ leaf_candidate.pre_binding_block = Some(new_pre_binding);
+ if has_guard {
+ // Falsely branch to `next_candidate_start_block` also if the guard fails.
+ let new_otherwise = self.cfg.start_new_block();
+ let old_otherwise = leaf_candidate.otherwise_block.unwrap();
+ self.false_edges(
+ new_otherwise,
+ old_otherwise,
+ next_candidate_start_block,
+ source_info,
+ );
+ leaf_candidate.otherwise_block = Some(new_otherwise);
+ }
}
- previous_candidate = Some(leaf_candidate);
+ assert!(leaf_candidate.false_edge_start_block.is_some());
+ next_candidate_start_block = leaf_candidate.false_edge_start_block;
});
}
- if refutable {
- // In refutable cases there's always at least one candidate, and we want a false edge to
- // the failure block.
- previous_candidate.as_mut().unwrap().next_candidate_start_block = Some(otherwise_block)
- } else {
+ if !refutable {
// Match checking ensures `otherwise_block` is actually unreachable in irrefutable
// cases.
let source_info = self.source_info(scrutinee_span);
@@ -1476,7 +1597,11 @@ fn lower_match_tree<'pat>(
self.cfg.terminate(otherwise_block, source_info, TerminatorKind::Unreachable);
}
- otherwise_block
+ BuiltMatchTree {
+ branches: candidates.into_iter().map(MatchTreeBranch::from_candidate).collect(),
+ otherwise_block,
+ fake_borrow_temps,
+ }
}
/// The main match algorithm. It begins with a set of candidates `candidates` and has the job of
@@ -2226,17 +2351,17 @@ pub(crate) fn lower_let_expr(
) -> BlockAnd<()> {
let expr_span = self.thir[expr_id].span;
let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
- let mut candidate = Candidate::new(scrutinee.clone(), pat, false, self);
- let otherwise_block = self.lower_match_tree(
+ let built_tree = self.lower_match_tree(
block,
expr_span,
&scrutinee,
pat.span,
- &mut [&mut candidate],
+ vec![(pat, HasMatchGuard::No)],
true,
);
+ let [branch] = built_tree.branches.try_into().unwrap();
- self.break_for_else(otherwise_block, self.source_info(expr_span));
+ self.break_for_else(built_tree.otherwise_block, self.source_info(expr_span));
match declare_let_bindings {
DeclareLetBindings::Yes => {
@@ -2258,7 +2383,7 @@ pub(crate) fn lower_let_expr(
let success = self.bind_pattern(
self.source_info(pat.span),
- candidate,
+ branch,
&[],
expr_span,
None,
@@ -2266,7 +2391,7 @@ pub(crate) fn lower_let_expr(
);
// If branch coverage is enabled, record this branch.
- self.visit_coverage_conditional_let(pat, success, otherwise_block);
+ self.visit_coverage_conditional_let(pat, success, built_tree.otherwise_block);
success.unit()
}
@@ -2279,52 +2404,28 @@ pub(crate) fn lower_let_expr(
/// Note: we do not check earlier that if there is a guard,
/// there cannot be move bindings. We avoid a use-after-move by only
/// moving the binding once the guard has evaluated to true (see below).
- fn bind_and_guard_matched_candidate<'pat>(
+ fn bind_and_guard_matched_candidate(
&mut self,
- candidate: Candidate<'pat, 'tcx>,
- parent_data: &[PatternExtraData<'tcx>],
+ sub_branch: MatchTreeSubBranch<'tcx>,
fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)],
scrutinee_span: Span,
arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
schedule_drops: ScheduleDrops,
emit_storage_live: EmitStorageLive,
) -> BasicBlock {
- debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
+ debug!("bind_and_guard_matched_candidate(subbranch={:?})", sub_branch);
- debug_assert!(candidate.match_pairs.is_empty());
+ let block = sub_branch.success_block;
- let candidate_source_info = self.source_info(candidate.extra_data.span);
-
- let mut block = candidate.pre_binding_block.unwrap();
-
- if candidate.next_candidate_start_block.is_some() {
- let fresh_block = self.cfg.start_new_block();
- self.false_edges(
- block,
- fresh_block,
- candidate.next_candidate_start_block,
- candidate_source_info,
- );
- block = fresh_block;
- }
-
- if candidate.extra_data.is_never {
+ if sub_branch.is_never {
// This arm has a dummy body, we don't need to generate code for it. `block` is already
// unreachable (except via false edge).
- let source_info = self.source_info(candidate.extra_data.span);
+ let source_info = self.source_info(sub_branch.span);
self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
return self.cfg.start_new_block();
}
- let ascriptions = parent_data
- .iter()
- .flat_map(|d| &d.ascriptions)
- .cloned()
- .chain(candidate.extra_data.ascriptions);
- let bindings =
- parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings);
-
- self.ascribe_types(block, ascriptions);
+ self.ascribe_types(block, sub_branch.ascriptions);
// Lower an instance of the arm guard (if present) for this candidate,
// and then perform bindings for the arm body.
@@ -2335,9 +2436,17 @@ fn bind_and_guard_matched_candidate<'pat>(
// Bindings for guards require some extra handling to automatically
// insert implicit references/dereferences.
- self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
+ self.bind_matched_candidate_for_guard(
+ block,
+ schedule_drops,
+ sub_branch.bindings.iter(),
+ );
let guard_frame = GuardFrame {
- locals: bindings.clone().map(|b| GuardFrameLocal::new(b.var_id)).collect(),
+ locals: sub_branch
+ .bindings
+ .iter()
+ .map(|b| GuardFrameLocal::new(b.var_id))
+ .collect(),
};
debug!("entering guard building context: {:?}", guard_frame);
self.guard_context.push(guard_frame);
@@ -2373,17 +2482,7 @@ fn bind_and_guard_matched_candidate<'pat>(
self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(temp));
}
- let otherwise_block = candidate.otherwise_block.unwrap_or_else(|| {
- let unreachable = self.cfg.start_new_block();
- self.cfg.terminate(unreachable, source_info, TerminatorKind::Unreachable);
- unreachable
- });
- self.false_edges(
- otherwise_post_guard_block,
- otherwise_block,
- candidate.next_candidate_start_block,
- source_info,
- );
+ self.cfg.goto(otherwise_post_guard_block, source_info, sub_branch.otherwise_block);
// We want to ensure that the matched candidates are bound
// after we have confirmed this candidate *and* any
@@ -2411,8 +2510,10 @@ fn bind_and_guard_matched_candidate<'pat>(
// ```
//
// and that is clearly not correct.
- let by_value_bindings =
- bindings.filter(|binding| matches!(binding.binding_mode.0, ByRef::No));
+ let by_value_bindings = sub_branch
+ .bindings
+ .iter()
+ .filter(|binding| matches!(binding.binding_mode.0, ByRef::No));
// Read all of the by reference bindings to ensure that the
// place they refer to can't be modified by the guard.
for binding in by_value_bindings.clone() {
@@ -2440,7 +2541,7 @@ fn bind_and_guard_matched_candidate<'pat>(
self.bind_matched_candidate_for_arm_body(
block,
schedule_drops,
- bindings,
+ sub_branch.bindings.iter(),
emit_storage_live,
);
block
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 20310f6..04cf81d 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -12,11 +12,12 @@
//! sort of test: for example, testing which variant an enum is, or
//! testing a value against a constant.
-use crate::build::matches::{MatchPairTree, PatternExtraData, TestCase};
-use crate::build::Builder;
+use std::mem;
+
use tracing::{debug, instrument};
-use std::mem;
+use crate::build::matches::{MatchPairTree, PatternExtraData, TestCase};
+use crate::build::Builder;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 802193b..7af1ede 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -5,14 +5,14 @@
// identify what tests are needed, perform the tests, and then filter
// the candidates based on the result.
-use crate::build::matches::{Candidate, MatchPairTree, Test, TestBranch, TestCase, TestKind};
-use crate::build::Builder;
+use std::cmp::Ordering;
+
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::{LangItem, RangeEnd};
use rustc_middle::mir::*;
+use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::GenericArg;
-use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::source_map::Spanned;
@@ -20,7 +20,8 @@
use rustc_span::{Span, DUMMY_SP};
use tracing::{debug, instrument};
-use std::cmp::Ordering;
+use crate::build::matches::{Candidate, MatchPairTree, Test, TestBranch, TestCase, TestKind};
+use crate::build::Builder;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Identifies what test is needed to decide if `match_pair` is applicable.
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 8fe8069..8491b5f 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -1,14 +1,13 @@
-use std::marker::PhantomData;
-
-use crate::build::expr::as_place::PlaceBase;
-use crate::build::matches::{Binding, Candidate, FlatPat, MatchPairTree, TestCase};
-use crate::build::Builder;
use rustc_data_structures::fx::FxIndexMap;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;
use rustc_span::Span;
use tracing::debug;
+use crate::build::expr::as_place::PlaceBase;
+use crate::build::matches::{Binding, Candidate, FlatPat, MatchPairTree, TestCase};
+use crate::build::Builder;
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Creates a false edge to `imaginary_target` and a real edge to
/// real_target. If `imaginary_target` is none, or is the same as the real
@@ -17,18 +16,17 @@ pub(crate) fn false_edges(
&mut self,
from_block: BasicBlock,
real_target: BasicBlock,
- imaginary_target: Option<BasicBlock>,
+ imaginary_target: BasicBlock,
source_info: SourceInfo,
) {
- match imaginary_target {
- Some(target) if target != real_target => {
- self.cfg.terminate(
- from_block,
- source_info,
- TerminatorKind::FalseEdge { real_target, imaginary_target: target },
- );
- }
- _ => self.cfg.goto(from_block, source_info, real_target),
+ if imaginary_target != real_target {
+ self.cfg.terminate(
+ from_block,
+ source_info,
+ TerminatorKind::FalseEdge { real_target, imaginary_target },
+ );
+ } else {
+ self.cfg.goto(from_block, source_info, real_target)
}
}
}
@@ -70,10 +68,14 @@ pub(crate) fn false_edges(
/// a MIR pass run after borrow checking.
pub(super) fn collect_fake_borrows<'tcx>(
cx: &mut Builder<'_, 'tcx>,
- candidates: &[&mut Candidate<'_, 'tcx>],
+ candidates: &[Candidate<'_, 'tcx>],
temp_span: Span,
scrutinee_base: PlaceBase,
) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
+ if candidates.iter().all(|candidate| !candidate.has_guard) {
+ // Fake borrows are only used when there is a guard.
+ return Vec::new();
+ }
let mut collector =
FakeBorrowCollector { cx, scrutinee_base, fake_borrows: FxIndexMap::default() };
for candidate in candidates.iter() {
@@ -221,57 +223,6 @@ fn visit_binding(&mut self, Binding { source, .. }: &Binding<'tcx>) {
}
}
-/// Visit all the bindings of these candidates. Because or-alternatives bind the same variables, we
-/// only explore the first one of each or-pattern.
-pub(super) fn visit_bindings<'tcx>(
- candidates: &[&mut Candidate<'_, 'tcx>],
- f: impl FnMut(&Binding<'tcx>),
-) {
- let mut visitor = BindingsVisitor { f, phantom: PhantomData };
- for candidate in candidates.iter() {
- visitor.visit_candidate(candidate);
- }
-}
-
-pub(super) struct BindingsVisitor<'tcx, F> {
- f: F,
- phantom: PhantomData<&'tcx ()>,
-}
-
-impl<'tcx, F> BindingsVisitor<'tcx, F>
-where
- F: FnMut(&Binding<'tcx>),
-{
- fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
- for binding in &candidate.extra_data.bindings {
- (self.f)(binding)
- }
- for match_pair in &candidate.match_pairs {
- self.visit_match_pair(match_pair);
- }
- }
-
- fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
- for binding in &flat_pat.extra_data.bindings {
- (self.f)(binding)
- }
- for match_pair in &flat_pat.match_pairs {
- self.visit_match_pair(match_pair);
- }
- }
-
- fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
- if let TestCase::Or { pats, .. } = &match_pair.test_case {
- // All the or-alternatives should bind the same locals, so we only visit the first one.
- self.visit_flat_pat(&pats[0])
- } else {
- for subpair in &match_pair.subpairs {
- self.visit_match_pair(subpair);
- }
- }
- }
-}
-
#[must_use]
pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
match ref_mutability {
diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs
index 04e6d24..2690697 100644
--- a/compiler/rustc_mir_build/src/build/misc.rs
+++ b/compiler/rustc_mir_build/src/build/misc.rs
@@ -1,14 +1,14 @@
//! Miscellaneous builder routines that are not specific to building any particular
//! kind of thing.
-use crate::build::Builder;
-
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
use tracing::debug;
+use crate::build::Builder;
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Adds a new temporary value of type `ty` storing the result of
/// evaluating `expr`.
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 2793a7d..b98deda 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,5 +1,3 @@
-use crate::build::expr::as_place::PlaceBuilder;
-use crate::build::scope::DropKind;
use itertools::Itertools;
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_apfloat::Float;
@@ -21,12 +19,13 @@
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::sym;
-use rustc_span::Span;
-use rustc_span::Symbol;
+use rustc_span::{Span, Symbol};
use rustc_target::abi::FieldIdx;
use rustc_target::spec::abi::Abi;
use super::lints;
+use crate::build::expr::as_place::PlaceBuilder;
+use crate::build::scope::DropKind;
pub(crate) fn closure_saved_names_of_captured_variables<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index b630c74..8546a25 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -83,7 +83,6 @@
use std::mem;
-use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::HirId;
use rustc_index::{IndexSlice, IndexVec};
@@ -96,6 +95,8 @@
use rustc_span::{Span, DUMMY_SP};
use tracing::{debug, instrument};
+use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
+
#[derive(Debug)]
pub(crate) struct Scopes<'tcx> {
scopes: Vec<Scope>,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 6309f2a..54a4204 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -1,9 +1,11 @@
-use crate::build::ExprCategory;
-use crate::errors::*;
+use std::borrow::Cow;
+use std::mem;
+use std::ops::Bound;
use rustc_errors::DiagArgValue;
use rustc_hir::def::DefKind;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
+use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
use rustc_middle::mir::BorrowKind;
use rustc_middle::span_bug;
use rustc_middle::thir::visit::Visitor;
@@ -16,9 +18,8 @@
use rustc_span::symbol::Symbol;
use rustc_span::{sym, Span};
-use std::borrow::Cow;
-use std::mem;
-use std::ops::Bound;
+use crate::build::ExprCategory;
+use crate::errors::*;
struct UnsafetyVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@@ -31,7 +32,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
safety_context: SafetyContext,
/// The `#[target_feature]` attributes of the body. Used for checking
/// calls to functions with `#[target_feature]` (RFC 2396).
- body_target_features: &'tcx [Symbol],
+ body_target_features: &'tcx [TargetFeature],
/// When inside the LHS of an assignment to a field, this is the type
/// of the LHS and the span of the assignment expression.
assignment_info: Option<Ty<'tcx>>,
@@ -442,14 +443,21 @@ fn visit_expr(&mut self, expr: &'a Expr<'tcx>) {
// is_like_wasm check in hir_analysis/src/collect.rs
let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
if !self.tcx.sess.target.options.is_like_wasm
- && !callee_features
- .iter()
- .all(|feature| self.body_target_features.contains(feature))
+ && !callee_features.iter().all(|feature| {
+ self.body_target_features.iter().any(|f| f.name == feature.name)
+ })
{
let missing: Vec<_> = callee_features
.iter()
.copied()
- .filter(|feature| !self.body_target_features.contains(feature))
+ .filter(|feature| {
+ !feature.implied
+ && !self
+ .body_target_features
+ .iter()
+ .any(|body_feature| body_feature.name == feature.name)
+ })
+ .map(|feature| feature.name)
.collect();
let build_enabled = self
.tcx
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index bdc4b0e..42eca71 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,15 +1,17 @@
-use crate::fluent_generated as fluent;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Applicability, Diag, Diagnostic, EmissionGuarantee, Level, MultiSpan,
- SubdiagMessageOp, Subdiagnostic,
+ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
+ MultiSpan, SubdiagMessageOp, Subdiagnostic,
};
-use rustc_errors::{DiagArgValue, DiagCtxtHandle};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, Ty};
-use rustc_pattern_analysis::{errors::Uncovered, rustc::RustcPatCtxt};
+use rustc_pattern_analysis::errors::Uncovered;
+use rustc_pattern_analysis::rustc::RustcPatCtxt;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
+use crate::fluent_generated as fluent;
+
#[derive(LintDiagnostic)]
#[diag(mir_build_unconditional_recursion)]
#[help]
@@ -856,7 +858,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
pub(crate) span: Span,
pub(crate) origin: &'s str,
#[subdiagnostic]
- pub(crate) uncovered: Uncovered<'tcx>,
+ pub(crate) uncovered: Uncovered,
#[subdiagnostic]
pub(crate) inform: Option<Inform>,
#[subdiagnostic]
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 263e777..80e9181 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -1,14 +1,15 @@
-use crate::errors::UnconditionalRecursion;
+use std::ops::ControlFlow;
+
use rustc_data_structures::graph::iterate::{
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
};
use rustc_hir::def::DefKind;
use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind};
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArg, GenericArgs};
+use rustc_middle::ty::{self, GenericArg, GenericArgs, Instance, Ty, TyCtxt};
use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
use rustc_span::Span;
-use std::ops::ControlFlow;
+
+use crate::errors::UnconditionalRecursion;
pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
check_call_recursion(tcx, body);
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 95cd703..069c2e7 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -1,5 +1,3 @@
-use crate::thir::cx::Cx;
-
use rustc_hir as hir;
use rustc_index::Idx;
use rustc_middle::middle::region;
@@ -8,6 +6,8 @@
use rustc_middle::ty::CanonicalUserTypeAnnotation;
use tracing::debug;
+use crate::thir::cx::Cx;
+
impl<'tcx> Cx<'tcx> {
pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId {
// We have to eagerly lower the "spine" of the statements
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 5f13b32..d4de5fa 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1,30 +1,31 @@
-use crate::errors;
-use crate::thir::cx::region::Scope;
-use crate::thir::cx::Cx;
-use crate::thir::util::UserAnnotatedTyHelpers;
use itertools::Itertools;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_index::Idx;
-use rustc_middle::hir::place::Place as HirPlace;
-use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
-use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
+use rustc_middle::hir::place::{
+ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
+};
use rustc_middle::middle::region;
use rustc_middle::mir::{self, BinOp, BorrowKind, UnOp};
use rustc_middle::thir::*;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion,
};
-use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{
- self, AdtKind, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, UserType,
+ self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs,
+ UserType,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{sym, Span};
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use tracing::{debug, info, instrument, trace};
+use crate::errors;
+use crate::thir::cx::region::Scope;
+use crate::thir::cx::Cx;
+use crate::thir::util::UserAnnotatedTyHelpers;
+
impl<'tcx> Cx<'tcx> {
pub(crate) fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId {
// `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow.
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 244ac40..6120b14 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -2,23 +2,22 @@
//! structures into the THIR. The `builder` is generally ignorant of the tcx,
//! etc., and instead goes through the `Cx` for most of its work.
-use crate::thir::pattern::pat_from_hir;
-use crate::thir::util::UserAnnotatedTyHelpers;
-
use rustc_data_structures::steal::Steal;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
-use rustc_hir::HirId;
-use rustc_hir::Node;
+use rustc_hir::{HirId, Node};
use rustc_middle::bug;
use rustc_middle::middle::region;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
use tracing::instrument;
+use crate::thir::pattern::pat_from_hir;
+use crate::thir::util::UserAnnotatedTyHelpers;
+
pub(crate) fn thir_body(
tcx: TyCtxt<'_>,
owner_def: LocalDefId,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 5e90405..07bf222 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1,11 +1,9 @@
-use crate::errors::*;
-use crate::fluent_generated as fluent;
-
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::Mutability;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, ErrorGuaranteed, MultiSpan};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, ErrorGuaranteed, MultiSpan};
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
@@ -27,6 +25,9 @@
use rustc_span::{sym, Span};
use tracing::instrument;
+use crate::errors::*;
+use crate::fluent_generated as fluent;
+
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
let typeck_results = tcx.typeck(def_id);
let (thir, expr) = tcx.thir_body(def_id)?;
@@ -482,9 +483,11 @@ fn check_match(
// Check if the match is exhaustive.
let witnesses = report.non_exhaustiveness_witnesses;
if !witnesses.is_empty() {
- if source == hir::MatchSource::ForLoopDesugar && arms.len() == 2 {
+ if source == hir::MatchSource::ForLoopDesugar
+ && let [_, snd_arm] = *arms
+ {
// the for loop pattern is not irrefutable
- let pat = &self.thir[arms[1]].pattern;
+ let pat = &self.thir[snd_arm].pattern;
// `pat` should be `Some(<pat_field>)` from a desugared for loop.
debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop));
let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() };
@@ -694,9 +697,7 @@ fn check_binding_is_irrefutable(
// Emit an extra note if the first uncovered witness would be uninhabited
// if we disregard visibility.
- let witness_1_is_privately_uninhabited = if (self.tcx.features().exhaustive_patterns
- || self.tcx.features().min_exhaustive_patterns)
- && let Some(witness_1) = witnesses.get(0)
+ let witness_1_is_privately_uninhabited = if let Some(witness_1) = witnesses.get(0)
&& let ty::Adt(adt, args) = witness_1.ty().kind()
&& adt.is_enum()
&& let Constructor::Variant(variant_index) = witness_1.ctor()
@@ -1058,7 +1059,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
err.note("`&str` cannot be matched exhaustively, so a wildcard `_` is necessary");
} else if cx.is_foreign_non_exhaustive_enum(ty) {
err.note(format!("`{ty}` is marked as non-exhaustive, so a wildcard `_` is necessary to match exhaustively"));
- } else if cx.is_uninhabited(ty.inner()) && cx.tcx.features().min_exhaustive_patterns {
+ } else if cx.is_uninhabited(ty.inner()) {
// The type is uninhabited yet there is a witness: we must be in the `MaybeInvalid`
// case.
err.note(format!("`{ty}` is uninhabited but is not being matched by value, so a wildcard `_` is required"));
@@ -1077,7 +1078,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
let suggested_arm = if suggest_the_witnesses {
let pattern = witnesses
.iter()
- .map(|witness| cx.hoist_witness_pat(witness).to_string())
+ .map(|witness| cx.print_witness_pat(witness))
.collect::<Vec<String>>()
.join(" | ");
if witnesses.iter().all(|p| p.is_never_pattern()) && cx.tcx.features().never_patterns {
@@ -1195,13 +1196,13 @@ fn joined_uncovered_patterns<'p, 'tcx>(
witnesses: &[WitnessPat<'p, 'tcx>],
) -> String {
const LIMIT: usize = 3;
- let pat_to_str = |pat: &WitnessPat<'p, 'tcx>| cx.hoist_witness_pat(pat).to_string();
+ let pat_to_str = |pat: &WitnessPat<'p, 'tcx>| cx.print_witness_pat(pat);
match witnesses {
[] => bug!(),
- [witness] => format!("`{}`", cx.hoist_witness_pat(witness)),
+ [witness] => format!("`{}`", cx.print_witness_pat(witness)),
[head @ .., tail] if head.len() < LIMIT => {
let head: Vec<_> = head.iter().map(pat_to_str).collect();
- format!("`{}` and `{}`", head.join("`, `"), cx.hoist_witness_pat(tail))
+ format!("`{}` and `{}`", head.join("`, `"), cx.print_witness_pat(tail))
}
_ => {
let (head, tail) = witnesses.split_at(LIMIT);
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 0d54f33..6f8d17b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -7,8 +7,7 @@
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::{FieldPat, Pat, PatKind};
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, Ty, TyCtxt, ValTree};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 6226518..6150700 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -3,10 +3,7 @@
mod check_match;
mod const_to_pat;
-pub(crate) use self::check_match::check_match;
-
-use crate::errors::*;
-use crate::thir::util::UserAnnotatedTyHelpers;
+use std::cmp::Ordering;
use rustc_errors::codes::*;
use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -26,7 +23,9 @@
use rustc_target::abi::{FieldIdx, Integer};
use tracing::{debug, instrument};
-use std::cmp::Ordering;
+pub(crate) use self::check_match::check_match;
+use crate::errors::*;
+use crate::thir::util::UserAnnotatedTyHelpers;
struct PatCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 619bfbc..2d4b39e 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -1,8 +1,9 @@
+use std::fmt::{self, Write};
+
use rustc_middle::query::TyCtxtAt;
use rustc_middle::thir::*;
use rustc_middle::ty;
use rustc_span::def_id::LocalDefId;
-use std::fmt::{self, Write};
pub(crate) fn thir_tree(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(*tcx, owner_def) {
diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index 82c59d7..bb53eaf 100644
--- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -1,10 +1,9 @@
-use crate::elaborate_drops::DropFlagState;
use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
use rustc_target::abi::VariantIdx;
use tracing::debug;
use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
-use super::MoveDataParamEnv;
+use crate::elaborate_drops::DropFlagState;
pub fn move_path_children_matching<'tcx, F>(
move_data: &MoveData<'tcx>,
@@ -70,12 +69,11 @@ fn on_all_children_bits<'tcx, F>(
pub fn drop_flag_effects_for_function_entry<'tcx, F>(
body: &Body<'tcx>,
- ctxt: &MoveDataParamEnv<'tcx>,
+ move_data: &MoveData<'tcx>,
mut callback: F,
) where
F: FnMut(MovePathIndex, DropFlagState),
{
- let move_data = &ctxt.move_data;
for arg in body.args_iter() {
let place = mir::Place::from(arg);
let lookup_result = move_data.rev_lookup.find(place.as_ref());
@@ -87,13 +85,12 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>(
pub fn drop_flag_effects_for_location<'tcx, F>(
body: &Body<'tcx>,
- ctxt: &MoveDataParamEnv<'tcx>,
+ move_data: &MoveData<'tcx>,
loc: Location,
mut callback: F,
) where
F: FnMut(MovePathIndex, DropFlagState),
{
- let move_data = &ctxt.move_data;
debug!("drop_flag_effects_for_location({:?})", loc);
// first, move out of the RHS
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index e0da960..2ec3b53 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -1,3 +1,5 @@
+use std::{fmt, iter};
+
use rustc_hir::lang_items::LangItem;
use rustc_index::Idx;
use rustc_middle::mir::patch::MirPatch;
@@ -5,12 +7,10 @@
use rustc_middle::span_bug;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt};
use rustc_span::source_map::Spanned;
use rustc_span::DUMMY_SP;
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
-use std::{fmt, iter};
use tracing::{debug, instrument};
/// The value of an inserted drop flag.
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index 1bd9167..7cfaef2 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -1,7 +1,5 @@
//! Random access inspection of the results of a dataflow analysis.
-use crate::framework::BitSetExt;
-
use std::cmp::Ordering;
#[cfg(debug_assertions)]
@@ -9,6 +7,7 @@
use rustc_middle::mir::{self, BasicBlock, Location};
use super::{Analysis, Direction, Effect, EffectIndex, Results};
+use crate::framework::BitSetExt;
/// Allows random access inspection of the results of a dataflow analysis.
///
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index f57e8b8..ba4a7d7 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,7 +1,8 @@
+use std::ops::RangeInclusive;
+
use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges,
};
-use std::ops::RangeInclusive;
use super::visitor::{ResultsVisitable, ResultsVisitor};
use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget};
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index 564a99e..364a416 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -1,32 +1,28 @@
//! A solver for dataflow problems.
-use crate::errors::{
- DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
-};
-use crate::framework::BitSetExt;
-
use std::ffi::OsString;
use std::path::PathBuf;
-use rustc_ast as ast;
use rustc_data_structures::work_queue::WorkQueue;
-use rustc_graphviz as dot;
use rustc_hir::def_id::DefId;
use rustc_index::{Idx, IndexVec};
use rustc_middle::bug;
-use rustc_middle::mir::{self, traversal, BasicBlock};
-use rustc_middle::mir::{create_dump_file, dump_enabled};
+use rustc_middle::mir::{self, create_dump_file, dump_enabled, traversal, BasicBlock};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{sym, Symbol};
use tracing::{debug, error};
+use {rustc_ast as ast, rustc_graphviz as dot};
use super::fmt::DebugWithContext;
-use super::graphviz;
use super::{
- visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis, GenKillSet,
- JoinSemiLattice, ResultsCursor, ResultsVisitor,
+ graphviz, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis,
+ GenKillSet, JoinSemiLattice, ResultsCursor, ResultsVisitor,
};
+use crate::errors::{
+ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter,
+};
+use crate::framework::BitSetExt;
pub type EntrySets<'tcx, A> = IndexVec<BasicBlock, <A as AnalysisDomain<'tcx>>::Domain>;
diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
index e3a66bd..5e4f36e 100644
--- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
@@ -1,10 +1,12 @@
//! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
//! analysis.
-use super::lattice::MaybeReachable;
+use std::fmt;
+
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
use rustc_index::Idx;
-use std::fmt;
+
+use super::lattice::MaybeReachable;
/// An extension to `fmt::Debug` for data that can be better printed with some auxiliary data `C`.
pub trait DebugWithContext<C>: Eq + fmt::Debug {
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index a827f6a..2e860e2 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -8,8 +8,7 @@
use regex::Regex;
use rustc_graphviz as dot;
use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::graphviz_safe_def_name;
-use rustc_middle::mir::{self, BasicBlock, Body, Location};
+use rustc_middle::mir::{self, graphviz_safe_def_name, BasicBlock, Body, Location};
use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor};
diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
index 23738f7..4d03ee5 100644
--- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
@@ -38,10 +38,12 @@
//! [Hasse diagram]: https://en.wikipedia.org/wiki/Hasse_diagram
//! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
-use crate::framework::BitSetExt;
+use std::iter;
+
use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
use rustc_index::{Idx, IndexVec};
-use std::iter;
+
+use crate::framework::BitSetExt;
/// A [partially ordered set][poset] that has a [least upper bound][lub] for any pair of elements
/// in the set.
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
index d44da42..7822fb1 100644
--- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -1,3 +1,5 @@
+use std::assert_matches::assert_matches;
+
use rustc_index::bit_set::{BitSet, ChunkedBitSet};
use rustc_index::Idx;
use rustc_middle::bug;
@@ -5,15 +7,14 @@
use rustc_middle::ty::{self, TyCtxt};
use tracing::{debug, instrument};
-use crate::drop_flag_effects_for_function_entry;
-use crate::drop_flag_effects_for_location;
use crate::elaborate_drops::DropFlagState;
use crate::framework::SwitchIntEdgeEffects;
use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
-use crate::on_lookup_result_bits;
-use crate::MoveDataParamEnv;
-use crate::{drop_flag_effects, on_all_children_bits};
-use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis, MaybeReachable};
+use crate::{
+ drop_flag_effects, drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
+ lattice, on_all_children_bits, on_lookup_result_bits, AnalysisDomain, GenKill, GenKillAnalysis,
+ MaybeReachable,
+};
/// `MaybeInitializedPlaces` tracks all places that might be
/// initialized upon reaching a particular point in the control flow
@@ -53,17 +54,13 @@
pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'mir Body<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ move_data: &'a MoveData<'tcx>,
skip_unreachable_unwind: bool,
}
impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> {
- pub fn new(
- tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
- ) -> Self {
- MaybeInitializedPlaces { tcx, body, mdpe, skip_unreachable_unwind: false }
+ pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+ MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false }
}
pub fn skipping_unreachable_unwind(mut self) -> Self {
@@ -90,7 +87,7 @@ pub fn is_unwind_dead(
impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
- &self.mdpe.move_data
+ self.move_data
}
}
@@ -132,22 +129,18 @@ fn move_data(&self) -> &MoveData<'tcx> {
pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'mir Body<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ move_data: &'a MoveData<'tcx>,
mark_inactive_variants_as_uninit: bool,
skip_unreachable_unwind: BitSet<mir::BasicBlock>,
}
impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> {
- pub fn new(
- tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
- ) -> Self {
+ pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
MaybeUninitializedPlaces {
tcx,
body,
- mdpe,
+ move_data,
mark_inactive_variants_as_uninit: false,
skip_unreachable_unwind: BitSet::new_empty(body.basic_blocks.len()),
}
@@ -174,7 +167,7 @@ pub fn skipping_unreachable_unwind(
impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
- &self.mdpe.move_data
+ self.move_data
}
}
@@ -214,18 +207,18 @@ fn move_data(&self) -> &MoveData<'tcx> {
/// that would require a dynamic drop-flag at that statement.
pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
body: &'a Body<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ move_data: &'a MoveData<'tcx>,
}
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
- pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
- DefinitelyInitializedPlaces { body, mdpe }
+ pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+ DefinitelyInitializedPlaces { body, move_data }
}
}
impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
- &self.mdpe.move_data
+ self.move_data
}
}
@@ -260,18 +253,18 @@ fn move_data(&self) -> &MoveData<'tcx> {
/// ```
pub struct EverInitializedPlaces<'a, 'mir, 'tcx> {
body: &'mir Body<'tcx>,
- mdpe: &'a MoveDataParamEnv<'tcx>,
+ move_data: &'a MoveData<'tcx>,
}
impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> {
- pub fn new(body: &'mir Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
- EverInitializedPlaces { body, mdpe }
+ pub fn new(body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self {
+ EverInitializedPlaces { body, move_data }
}
}
impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> {
fn move_data(&self) -> &MoveData<'tcx> {
- &self.mdpe.move_data
+ self.move_data
}
}
@@ -329,7 +322,7 @@ fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
*state =
MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len()));
- drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
+ drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| {
assert!(s == DropFlagState::Present);
state.gen_(path);
});
@@ -349,7 +342,7 @@ fn statement_effect(
statement: &mir::Statement<'tcx>,
location: Location,
) {
- drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
+ drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
Self::update_bits(trans, path, s)
});
@@ -381,7 +374,7 @@ fn terminator_effect<'mir>(
{
edges = TerminatorEdges::Single(target);
}
- drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
+ drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
Self::update_bits(state, path, s)
});
edges
@@ -466,7 +459,7 @@ fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain)
// set all bits to 1 (uninit) before gathering counter-evidence
state.insert_all();
- drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
+ drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| {
assert!(s == DropFlagState::Present);
state.remove(path);
});
@@ -486,7 +479,7 @@ fn statement_effect(
_statement: &mir::Statement<'tcx>,
location: Location,
) {
- drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
+ drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
Self::update_bits(trans, path, s)
});
@@ -500,12 +493,12 @@ fn terminator_effect<'mir>(
terminator: &'mir mir::Terminator<'tcx>,
location: Location,
) -> TerminatorEdges<'mir, 'tcx> {
- drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
+ drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
Self::update_bits(trans, path, s)
});
if self.skip_unreachable_unwind.contains(location.block) {
let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() };
- assert!(matches!(unwind, mir::UnwindAction::Cleanup(_)));
+ assert_matches!(unwind, mir::UnwindAction::Cleanup(_));
TerminatorEdges::Single(target)
} else {
terminator.edges()
@@ -593,7 +586,7 @@ fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
state.0.clear();
- drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
+ drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| {
assert!(s == DropFlagState::Present);
state.0.insert(path);
});
@@ -613,7 +606,7 @@ fn statement_effect(
_statement: &mir::Statement<'tcx>,
location: Location,
) {
- drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
+ drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
Self::update_bits(trans, path, s)
})
}
@@ -624,7 +617,7 @@ fn terminator_effect<'mir>(
terminator: &'mir mir::Terminator<'tcx>,
location: Location,
) -> TerminatorEdges<'mir, 'tcx> {
- drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
+ drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| {
Self::update_bits(trans, path, s)
});
terminator.edges()
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index f8db18f..f283660 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -7,13 +7,12 @@
mod liveness;
mod storage_liveness;
-pub use self::borrowed_locals::borrowed_locals;
-pub use self::borrowed_locals::MaybeBorrowedLocals;
+pub use self::borrowed_locals::{borrowed_locals, MaybeBorrowedLocals};
pub use self::initialized::{
DefinitelyInitializedPlaces, EverInitializedPlaces, MaybeInitializedPlaces,
MaybeUninitializedPlaces,
};
-pub use self::liveness::MaybeLiveLocals;
-pub use self::liveness::MaybeTransitiveLiveLocals;
-pub use self::liveness::TransferFunction as LivenessTransferFunction;
+pub use self::liveness::{
+ MaybeLiveLocals, MaybeTransitiveLiveLocals, TransferFunction as LivenessTransferFunction,
+};
pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive};
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 682cec1..9f2f018 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -1,9 +1,9 @@
+use std::borrow::Cow;
+
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use std::borrow::Cow;
-
use super::MaybeBorrowedLocals;
use crate::{GenKill, ResultsCursor};
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index b0808ba..8708beb 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,4 +1,5 @@
// tidy-alphabetical-start
+#![feature(assert_matches)]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 7b39db8..c26a72e 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -1,3 +1,5 @@
+use std::mem;
+
use rustc_index::IndexVec;
use rustc_middle::mir::tcx::{PlaceTy, RvalueInitializationState};
use rustc_middle::mir::*;
@@ -6,12 +8,10 @@
use smallvec::{smallvec, SmallVec};
use tracing::debug;
-use std::mem;
-
use super::abs_domain::Lift;
-use super::{Init, InitIndex, InitKind, InitLocation, LookupResult};
use super::{
- LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
+ Init, InitIndex, InitKind, InitLocation, LocationMap, LookupResult, MoveData, MoveOut,
+ MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
};
struct MoveDataBuilder<'a, 'tcx, F> {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 830f44d..bc11779 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -1,4 +1,6 @@
-use crate::un_derefer::UnDerefer;
+use std::fmt;
+use std::ops::{Index, IndexMut};
+
use rustc_data_structures::fx::FxHashMap;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::*;
@@ -6,10 +8,8 @@
use rustc_span::Span;
use smallvec::SmallVec;
-use std::fmt;
-use std::ops::{Index, IndexMut};
-
use self::abs_domain::{AbstractElem, Lift};
+use crate::un_derefer::UnDerefer;
mod abs_domain;
diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs
index bbfb37d..4be7492 100644
--- a/compiler/rustc_mir_dataflow/src/points.rs
+++ b/compiler/rustc_mir_dataflow/src/points.rs
@@ -1,10 +1,10 @@
-use crate::framework::{visit_results, ResultsVisitable, ResultsVisitor};
use rustc_index::bit_set::BitSet;
use rustc_index::interval::SparseIntervalMatrix;
-use rustc_index::Idx;
-use rustc_index::IndexVec;
+use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::{self, BasicBlock, Body, Location};
+use crate::framework::{visit_results, ResultsVisitable, ResultsVisitor};
+
/// Maps between a `Location` and a `PointIndex` (and vice versa).
pub struct DenseLocationMap {
/// For each basic block, how many points are contained within?
diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index 1de9055..0171cc8 100644
--- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -1,3 +1,12 @@
+use rustc_ast::MetaItem;
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::{self, Body, Local, Location, MirPass};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::Span;
+use tracing::{debug, info};
+
use crate::errors::{
PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary,
PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation,
@@ -6,19 +15,8 @@
use crate::impls::{
DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
};
-use crate::move_paths::{HasMoveData, MoveData};
-use crate::move_paths::{LookupResult, MovePathIndex};
-use crate::MoveDataParamEnv;
+use crate::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex};
use crate::{Analysis, JoinSemiLattice, ResultsCursor};
-use rustc_ast::MetaItem;
-use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::MirPass;
-use rustc_middle::mir::{self, Body, Local, Location};
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::Span;
-use tracing::{debug, info};
pub struct SanityCheck;
@@ -48,10 +46,9 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let param_env = tcx.param_env(def_id);
let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
- let mdpe = MoveDataParamEnv { move_data, param_env };
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
- let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe)
+ let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
.into_engine(tcx, body)
.iterate_to_fixpoint();
@@ -59,7 +56,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() {
- let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe)
+ let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data)
.into_engine(tcx, body)
.iterate_to_fixpoint();
@@ -67,7 +64,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
}
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() {
- let flow_def_inits = DefinitelyInitializedPlaces::new(body, &mdpe)
+ let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data)
.into_engine(tcx, body)
.iterate_to_fixpoint();
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index c9f5d38..139fd59 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -32,6 +32,7 @@
//! Because of that, we can assume that the only way to change the value behind a tracked place is
//! by direct assignment.
+use std::assert_matches::assert_matches;
use std::fmt::{Debug, Formatter};
use std::ops::Range;
@@ -48,14 +49,13 @@
use rustc_target::abi::{FieldIdx, VariantIdx};
use tracing::debug;
+use crate::fmt::DebugWithContext;
use crate::lattice::{HasBottom, HasTop};
-use crate::{
- fmt::DebugWithContext, Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects,
-};
+use crate::{Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects};
pub trait ValueAnalysis<'tcx> {
/// For each place of interest, the analysis tracks a value of the given type.
- type Value: Clone + JoinSemiLattice + HasBottom + HasTop;
+ type Value: Clone + JoinSemiLattice + HasBottom + HasTop + Debug;
const NAME: &'static str;
@@ -345,7 +345,7 @@ fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
// The initial state maps all tracked places of argument projections to ⊤ and the rest to ⊥.
- assert!(matches!(state, State::Unreachable));
+ assert_matches!(state, State::Unreachable);
*state = State::new_reachable();
for arg in body.args_iter() {
state.flood(PlaceRef { local: arg, projection: &[] }, self.0.map());
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index f864a13..07ca51a 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -25,6 +25,7 @@
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
# tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index d43fca3..f52a452 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -1,8 +1,7 @@
use rustc_ast::InlineAsmOptions;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
-use rustc_middle::ty::layout;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, layout, TyCtxt};
use rustc_target::spec::abi::Abi;
use rustc_target::spec::PanicStrategy;
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index de6d20a..cd850e2 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -1,8 +1,8 @@
+use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::util;
-use rustc_middle::mir::patch::MirPatch;
/// This pass moves values being dropped that are within a packed
/// struct to a separate local before dropping them, to ensure that
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 5199c41..a1dbd7d 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,10 +1,8 @@
use rustc_hir::lang_items::LangItem;
use rustc_index::IndexVec;
+use rustc_middle::mir::interpret::Scalar;
+use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::mir::{
- interpret::Scalar,
- visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor},
-};
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
use rustc_session::Session;
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 5f67bd7..9902002 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -3,8 +3,7 @@
use rustc_middle::span_bug;
use rustc_middle::ty::{self, TyCtxt};
-use crate::MirLint;
-use crate::{errors, util};
+use crate::{errors, util, MirLint};
pub struct CheckPackedRef;
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 264d8a1..08c9f9f 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -16,12 +16,13 @@
//! [`BlockMarker`]: rustc_middle::mir::coverage::CoverageKind::BlockMarker
//! [`SpanMarker`]: rustc_middle::mir::coverage::CoverageKind::SpanMarker
-use crate::MirPass;
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, TerminatorKind};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::TyCtxt;
+use crate::MirPass;
+
pub struct CleanupPostBorrowck;
impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 658cc4c..8252810 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -51,13 +51,9 @@
//! Otherwise it drops all the values in scope at the last suspension point.
mod by_move_body;
-pub use by_move_body::ByMoveBody;
+use std::{iter, ops};
-use crate::abort_unwinding_calls;
-use crate::deref_separator::deref_finder;
-use crate::errors;
-use crate::pass_manager as pm;
-use crate::simplify;
+pub use by_move_body::ByMoveBody;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::pluralize;
use rustc_hir as hir;
@@ -67,9 +63,7 @@
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::ty::CoroutineArgs;
-use rustc_middle::ty::InstanceKind;
-use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TyCtxt};
+use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, InstanceKind, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::impls::{
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
@@ -83,9 +77,10 @@
use rustc_target::spec::PanicStrategy;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::TyCtxtInferExt as _;
-use rustc_trait_selection::traits::ObligationCtxt;
-use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
-use std::{iter, ops};
+use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
+
+use crate::deref_separator::deref_finder;
+use crate::{abort_unwinding_calls, errors, pass_manager as pm, simplify};
pub struct StateTransform;
@@ -1167,10 +1162,11 @@ fn insert_switch<'tcx>(
}
fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- use crate::shim::DropShimElaborator;
use rustc_middle::mir::patch::MirPatch;
use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, Unwind};
+ use crate::shim::DropShimElaborator;
+
// Note that `elaborate_drops` only drops the upvars of a coroutine, and
// this is ok because `open_drop` can only be reached within that own
// coroutine's resume function.
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 83fb9ff..31b2077 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -1,3 +1,7 @@
+use std::cmp::Ordering;
+use std::collections::VecDeque;
+use std::ops::{Index, IndexMut};
+
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::dominators::{self, Dominators};
@@ -7,10 +11,6 @@
use rustc_middle::bug;
use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind};
-use std::cmp::Ordering;
-use std::collections::VecDeque;
-use std::ops::{Index, IndexMut};
-
/// A coverage-specific simplification of the MIR control flow graph (CFG). The `CoverageGraph`s
/// nodes are `BasicCoverageBlock`s, which encompass one or more MIR `BasicBlock`s.
#[derive(Debug)]
@@ -350,8 +350,8 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
// An inline asm terminator can normally be chained, except when it diverges or uses asm
// goto.
InlineAsm { ref targets, .. } => {
- if targets.len() == 1 {
- CoverageSuccessors::Chainable(targets[0])
+ if let [target] = targets[..] {
+ CoverageSuccessors::Chainable(target)
} else {
CoverageSuccessors::NotChainable(targets)
}
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 3772a8f..96ca3b4 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -147,7 +147,8 @@ fn create_mappings<'tcx>(
let source_file = source_map.lookup_source_file(body_span.lo());
- use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+ use rustc_session::config::RemapPathScopeComponents;
+ use rustc_session::RemapFileNameExt;
let file_name = Symbol::intern(
&source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(),
);
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index dbc26a2..092ec1e 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -6,11 +6,10 @@
use rustc_span::Span;
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
-use crate::coverage::mappings;
use crate::coverage::spans::from_mir::{
extract_covspans_from_mir, ExtractedCovspans, Hole, SpanFromMir,
};
-use crate::coverage::ExtractedHirInfo;
+use crate::coverage::{mappings, ExtractedHirInfo};
mod from_mir;
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 63a9f30..a4db11b 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -24,16 +24,15 @@
//! globals is comparatively simpler. The easiest way is to wrap the test in a closure argument
//! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
-use super::graph::{self, BasicCoverageBlock};
-
use itertools::Itertools;
use rustc_data_structures::graph::{DirectedGraph, Successors};
use rustc_index::{Idx, IndexVec};
-use rustc_middle::bug;
use rustc_middle::mir::*;
-use rustc_middle::ty;
+use rustc_middle::{bug, ty};
use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
+use super::graph::{self, BasicCoverageBlock};
+
fn bcb(index: u32) -> BasicCoverageBlock {
BasicCoverageBlock::from_u32(index)
}
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 483fd75..50aaed0 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -1,5 +1,3 @@
-use crate::inline;
-use crate::pass_manager as pm;
use rustc_attr::InlineAttr;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -7,10 +5,11 @@
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::InliningThreshold;
-use rustc_session::config::OptLevel;
+use rustc_session::config::{InliningThreshold, OptLevel};
use rustc_span::sym;
+use crate::{inline, pass_manager as pm};
+
pub fn provide(providers: &mut Providers) {
providers.cross_crate_inlinable = cross_crate_inlinable;
}
diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs
index a0dddec..ff9fc77 100644
--- a/compiler/rustc_mir_transform/src/ctfe_limit.rs
+++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs
@@ -1,14 +1,14 @@
//! A pass that inserts the `ConstEvalCounter` instruction into any blocks that have a back edge
//! (thus indicating there is a loop in the CFG), or whose terminator is a function call.
-use crate::MirPass;
-
use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::mir::{
BasicBlock, BasicBlockData, Body, Statement, StatementKind, TerminatorKind,
};
use rustc_middle::ty::TyCtxt;
+use crate::MirPass;
+
pub struct CtfeLimit;
impl<'tcx> MirPass<'tcx> for CtfeLimit {
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 8303ef0..0fc4d6b 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -12,10 +12,11 @@
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_mir_dataflow::lattice::FlatSet;
use rustc_mir_dataflow::value_analysis::{
Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
};
-use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
+use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 60230be..f473073 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -12,7 +12,6 @@
//! will still not cause any further changes.
//!
-use crate::util::is_within_packed;
use rustc_middle::bug;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
@@ -23,6 +22,8 @@
};
use rustc_mir_dataflow::Analysis;
+use crate::util::is_within_packed;
+
/// Performs the optimization on the body
///
/// The `borrowed` set must be a `BitSet` of all the locals that are ever borrowed in this body. It
diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
index 8249749..4a94c3e 100644
--- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
+++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
@@ -1,7 +1,9 @@
//! This pass finds basic blocks that are completely equal,
//! and replaces all uses with just one of them.
-use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter};
+use std::collections::hash_map::Entry;
+use std::hash::{Hash, Hasher};
+use std::iter;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::visit::MutVisitor;
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index ab73a8a..054cdbc 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -131,23 +131,22 @@
//! [attempt 2]: https://github.com/rust-lang/rust/pull/71003
//! [attempt 3]: https://github.com/rust-lang/rust/pull/72632
-use crate::MirPass;
use rustc_data_structures::fx::{FxIndexMap, IndexEntry, IndexOccupiedEntry};
use rustc_index::bit_set::BitSet;
use rustc_index::interval::SparseIntervalMatrix;
use rustc_middle::bug;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
-use rustc_middle::mir::HasLocalDecls;
-use rustc_middle::mir::{dump_mir, PassWhere};
use rustc_middle::mir::{
- traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, Rvalue,
- Statement, StatementKind, TerminatorKind,
+ dump_mir, traversal, Body, HasLocalDecls, InlineAsmOperand, Local, LocalKind, Location,
+ Operand, PassWhere, Place, Rvalue, Statement, StatementKind, TerminatorKind,
};
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::MaybeLiveLocals;
use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex};
use rustc_mir_dataflow::Analysis;
+use crate::MirPass;
+
pub struct DestinationPropagation;
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 3b71cf02..29db45f 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -3,12 +3,12 @@
use std::fs::File;
use std::io;
-use crate::MirPass;
-use rustc_middle::mir::write_mir_pretty;
-use rustc_middle::mir::Body;
+use rustc_middle::mir::{write_mir_pretty, Body};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{OutFileName, OutputType};
+use crate::MirPass;
+
pub struct Marker(pub &'static str);
impl<'tcx> MirPass<'tcx> for Marker {
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 40c0c72..49e41c3 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -1,7 +1,8 @@
+use std::fmt::Debug;
+
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
-use std::fmt::Debug;
use super::simplify::simplify_cfg;
@@ -308,11 +309,11 @@ fn verify_candidate_branch<'tcx>(
) -> bool {
// In order for the optimization to be correct, the branch must...
// ...have exactly one statement
- if branch.statements.len() != 1 {
+ let [statement] = branch.statements.as_slice() else {
return false;
- }
+ };
// ...assign the discriminant of `place` in that statement
- let StatementKind::Assign(boxed) = &branch.statements[0].kind else { return false };
+ let StatementKind::Assign(boxed) = &statement.kind else { return false };
let (discr_place, Rvalue::Discriminant(from_place)) = &**boxed else { return false };
if *from_place != place {
return false;
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index d955b96..e5778f8 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -116,29 +116,30 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
for debug_info in body.var_debug_info.iter_mut() {
if let VarDebugInfoContents::Place(place) = &mut debug_info.value {
let mut new_projections: Option<Vec<_>> = None;
- let mut last_deref = 0;
- for (i, (base, elem)) in place.iter_projections().enumerate() {
+ for (base, elem) in place.iter_projections() {
let base_ty = base.ty(&body.local_decls, tcx).ty;
if elem == PlaceElem::Deref && base_ty.is_box() {
- let new_projections = new_projections.get_or_insert_default();
+ // Clone the projections before us, since now we need to mutate them.
+ let new_projections =
+ new_projections.get_or_insert_with(|| base.projection.to_vec());
let (unique_ty, nonnull_ty, ptr_ty) =
build_ptr_tys(tcx, base_ty.boxed_ty(), unique_did, nonnull_did);
- new_projections.extend_from_slice(&base.projection[last_deref..]);
new_projections.extend_from_slice(&build_projection(
unique_ty, nonnull_ty, ptr_ty,
));
new_projections.push(PlaceElem::Deref);
-
- last_deref = i;
+ } else if let Some(new_projections) = new_projections.as_mut() {
+ // Keep building up our projections list once we've started it.
+ new_projections.push(elem);
}
}
- if let Some(mut new_projections) = new_projections {
- new_projections.extend_from_slice(&place.projection[last_deref..]);
+ // Store the mutated projections if we actually changed something.
+ if let Some(new_projections) = new_projections {
place.projection = tcx.mk_place_elems(&new_projections);
}
}
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 25bebb0..5a22ef7 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -1,20 +1,22 @@
-use crate::deref_separator::deref_finder;
+use std::fmt;
+
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, DropFlagState, Unwind};
-use rustc_mir_dataflow::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle};
+use rustc_mir_dataflow::elaborate_drops::{
+ elaborate_drop, DropElaborator, DropFlagMode, DropFlagState, DropStyle, Unwind,
+};
use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
-use rustc_mir_dataflow::on_all_children_bits;
-use rustc_mir_dataflow::on_lookup_result_bits;
-use rustc_mir_dataflow::MoveDataParamEnv;
-use rustc_mir_dataflow::{Analysis, ResultsCursor};
+use rustc_mir_dataflow::{
+ on_all_children_bits, on_lookup_result_bits, Analysis, MoveDataParamEnv, ResultsCursor,
+};
use rustc_span::Span;
use rustc_target::abi::{FieldIdx, VariantIdx};
-use std::fmt;
+
+use crate::deref_separator::deref_finder;
/// During MIR building, Drop terminators are inserted in every place where a drop may occur.
/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run,
@@ -60,7 +62,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let elaborate_patch = {
let env = MoveDataParamEnv { move_data, param_env };
- let mut inits = MaybeInitializedPlaces::new(tcx, body, &env)
+ let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
.skipping_unreachable_unwind()
.into_engine(tcx, body)
.pass_name("elaborate_drops")
@@ -68,7 +70,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
.into_results_cursor(body);
let dead_unwinds = compute_dead_unwinds(body, &mut inits);
- let uninits = MaybeUninitializedPlaces::new(tcx, body, &env)
+ let uninits = MaybeUninitializedPlaces::new(tcx, body, &env.move_data)
.mark_inactive_variants_as_uninit()
.skipping_unreachable_unwind(dead_unwinds)
.into_engine(tcx, body)
@@ -441,9 +443,13 @@ fn drop_flags_for_fn_rets(&mut self) {
fn drop_flags_for_args(&mut self) {
let loc = Location::START;
- rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body, self.env, |path, ds| {
- self.set_drop_flag(loc, path, ds);
- })
+ rustc_mir_dataflow::drop_flag_effects_for_function_entry(
+ self.body,
+ &self.env.move_data,
+ |path, ds| {
+ self.set_drop_flag(loc, path, ds);
+ },
+ )
}
fn drop_flags_for_locs(&mut self) {
@@ -476,7 +482,7 @@ fn drop_flags_for_locs(&mut self) {
let loc = Location { block: bb, statement_index: i };
rustc_mir_dataflow::drop_flag_effects_for_location(
self.body,
- self.env,
+ &self.env.move_data,
loc,
|path, ds| self.set_drop_flag(loc, path, ds),
)
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index dc7648d..2703dc5 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -1,4 +1,5 @@
-use rustc_errors::{codes::*, Diag, LintDiagnostic};
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, LintDiagnostic};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::mir::AssertKind;
use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 0cb304d..4132e60 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -1,9 +1,7 @@
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_middle::mir::*;
-use rustc_middle::query::LocalCrate;
-use rustc_middle::query::Providers;
-use rustc_middle::ty::layout;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::query::{LocalCrate, Providers};
+use rustc_middle::ty::{self, layout, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::FFI_UNWIND_CALLS;
use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 434529c..b7873e7 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -5,7 +5,8 @@
use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::source_map::Spanned;
-use rustc_span::{symbol::sym, Span};
+use rustc_span::symbol::sym;
+use rustc_span::Span;
use rustc_target::spec::abi::Abi;
use crate::{errors, MirLint};
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 1002746..e16911d 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -82,15 +82,19 @@
//! Second, when writing constants in MIR, we do not write `Const::Slice` or `Const`
//! that contain `AllocId`s.
+use std::borrow::Cow;
+
+use either::Either;
use rustc_const_eval::const_eval::DummyMachine;
-use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemPlaceMeta, MemoryKind};
-use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable, Scalar};
+use rustc_const_eval::interpret::{
+ intern_const_alloc_for_constprop, ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy,
+ Projectable, Scalar,
+};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_hir::def::DefKind;
use rustc_index::bit_set::BitSet;
-use rustc_index::newtype_index;
-use rustc_index::IndexVec;
+use rustc_index::{newtype_index, IndexVec};
use rustc_middle::bug;
use rustc_middle::mir::interpret::GlobalAlloc;
use rustc_middle::mir::visit::*;
@@ -101,10 +105,8 @@
use rustc_span::DUMMY_SP;
use rustc_target::abi::{self, Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
use smallvec::SmallVec;
-use std::borrow::Cow;
use crate::ssa::{AssignedValue, SsaLocals};
-use either::Either;
pub struct GVN;
@@ -126,7 +128,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Clone dominators as we need them while mutating the body.
let dominators = body.basic_blocks.dominators().clone();
- let mut state = VnState::new(tcx, param_env, &ssa, &dominators, &body.local_decls);
+ let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls);
ssa.for_each_assignment_mut(
body.basic_blocks.as_mut_preserves_cfg(),
|local, value, location| {
@@ -202,6 +204,7 @@ enum Value<'tcx> {
value: Const<'tcx>,
/// Some constants do not have a deterministic value. To avoid merging two instances of the
/// same `Const`, we assign them an additional integer index.
+ // `disambiguator` is 0 iff the constant is deterministic.
disambiguator: usize,
},
/// An aggregate value, either tuple/closure/struct/enum.
@@ -264,21 +267,29 @@ struct VnState<'body, 'tcx> {
impl<'body, 'tcx> VnState<'body, 'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
+ body: &Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ssa: &'body SsaLocals,
dominators: &'body Dominators<BasicBlock>,
local_decls: &'body LocalDecls<'tcx>,
) -> Self {
+ // Compute a rough estimate of the number of values in the body from the number of
+ // statements. This is meant to reduce the number of allocations, but it's all right if
+ // we miss the exact amount. We estimate based on 2 values per statement (one in LHS and
+ // one in RHS) and 4 values per terminator (for call operands).
+ let num_values =
+ 2 * body.basic_blocks.iter().map(|bbdata| bbdata.statements.len()).sum::<usize>()
+ + 4 * body.basic_blocks.len();
VnState {
tcx,
ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
param_env,
local_decls,
locals: IndexVec::from_elem(None, local_decls),
- rev_locals: IndexVec::default(),
- values: FxIndexSet::default(),
- evaluated: IndexVec::new(),
- next_opaque: Some(0),
+ rev_locals: IndexVec::with_capacity(num_values),
+ values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()),
+ evaluated: IndexVec::with_capacity(num_values),
+ next_opaque: Some(1),
feature_unsized_locals: tcx.features().unsized_locals,
ssa,
dominators,
@@ -291,9 +302,15 @@ fn insert(&mut self, value: Value<'tcx>) -> VnIndex {
let (index, new) = self.values.insert_full(value);
let index = VnIndex::from_usize(index);
if new {
+ // Grow `evaluated` and `rev_locals` here to amortize the allocations.
let evaluated = self.eval_to_const(index);
let _index = self.evaluated.push(evaluated);
debug_assert_eq!(index, _index);
+ // No need to push to `rev_locals` if we finished listing assignments.
+ if self.next_opaque.is_some() {
+ let _index = self.rev_locals.push(SmallVec::new());
+ debug_assert_eq!(index, _index);
+ }
}
index
}
@@ -330,7 +347,7 @@ fn assign(&mut self, local: Local, value: VnIndex) {
let is_sized = !self.feature_unsized_locals
|| self.local_decls[local].ty.is_sized(self.tcx, self.param_env);
if is_sized {
- self.rev_locals.ensure_contains_elem(value, SmallVec::new).push(local);
+ self.rev_locals[value].push(local);
}
}
@@ -344,6 +361,8 @@ fn insert_constant(&mut self, value: Const<'tcx>) -> Option<VnIndex> {
let next_opaque = self.next_opaque.as_mut()?;
let disambiguator = *next_opaque;
*next_opaque += 1;
+ // `disambiguator: 0` means deterministic.
+ debug_assert_ne!(disambiguator, 0);
disambiguator
};
Some(self.insert(Value::Constant { value, disambiguator }))
@@ -351,12 +370,16 @@ fn insert_constant(&mut self, value: Const<'tcx>) -> Option<VnIndex> {
fn insert_bool(&mut self, flag: bool) -> VnIndex {
// Booleans are deterministic.
- self.insert(Value::Constant { value: Const::from_bool(self.tcx, flag), disambiguator: 0 })
+ let value = Const::from_bool(self.tcx, flag);
+ debug_assert!(value.is_deterministic());
+ self.insert(Value::Constant { value, disambiguator: 0 })
}
fn insert_scalar(&mut self, scalar: Scalar, ty: Ty<'tcx>) -> VnIndex {
- self.insert_constant(Const::from_scalar(self.tcx, scalar, ty))
- .expect("scalars are deterministic")
+ // Scalars are deterministic.
+ let value = Const::from_scalar(self.tcx, scalar, ty);
+ debug_assert!(value.is_deterministic());
+ self.insert(Value::Constant { value, disambiguator: 0 })
}
fn insert_tuple(&mut self, values: Vec<VnIndex>) -> VnIndex {
@@ -669,7 +692,7 @@ fn project(
fn simplify_place_projection(&mut self, place: &mut Place<'tcx>, location: Location) {
// If the projection is indirect, we treat the local as a value, so can replace it with
// another local.
- if place.is_indirect()
+ if place.is_indirect_first_projection()
&& let Some(base) = self.locals[place.local]
&& let Some(new_local) = self.try_as_local(base, location)
&& place.local != new_local
@@ -771,10 +794,7 @@ fn simplify_operand(
location: Location,
) -> Option<VnIndex> {
match *operand {
- Operand::Constant(ref mut constant) => {
- let const_ = constant.const_.normalize(self.tcx, self.param_env);
- self.insert_constant(const_)
- }
+ Operand::Constant(ref constant) => self.insert_constant(constant.const_),
Operand::Copy(ref mut place) | Operand::Move(ref mut place) => {
let value = self.simplify_place_value(place, location)?;
if let Some(const_) = self.try_as_constant(value) {
@@ -1369,8 +1389,13 @@ fn op_to_prop_const<'tcx>(
// If this constant has scalar ABI, return it as a `ConstValue::Scalar`.
if let Abi::Scalar(abi::Scalar::Initialized { .. }) = op.layout.abi
&& let Ok(scalar) = ecx.read_scalar(op)
- && scalar.try_to_scalar_int().is_ok()
{
+ if !scalar.try_to_scalar_int().is_ok() {
+ // Check that we do not leak a pointer.
+ // Those pointers may lose part of their identity in codegen.
+ // FIXME: remove this hack once https://github.com/rust-lang/rust/issues/79738 is fixed.
+ return None;
+ }
return Some(ConstValue::Scalar(scalar));
}
@@ -1434,12 +1459,11 @@ fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option<Opera
/// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR.
fn try_as_constant(&mut self, index: VnIndex) -> Option<ConstOperand<'tcx>> {
- // This was already constant in MIR, do not change it.
- if let Value::Constant { value, disambiguator: _ } = *self.get(index)
- // If the constant is not deterministic, adding an additional mention of it in MIR will
- // not give the same value as the former mention.
- && value.is_deterministic()
- {
+ // This was already constant in MIR, do not change it. If the constant is not
+ // deterministic, adding an additional mention of it in MIR will not give the same value as
+ // the former mention.
+ if let Value::Constant { value, disambiguator: 0 } = *self.get(index) {
+ debug_assert!(value.is_deterministic());
return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value });
}
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index fd9f0fe..324ddc5 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -1,6 +1,8 @@
//! Inlining pass for MIR functions.
-use crate::deref_separator::deref_finder;
+use std::iter;
+use std::ops::{Range, RangeFrom};
+
use rustc_attr::InlineAttr;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@@ -10,8 +12,9 @@
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags};
+use rustc_middle::ty::{
+ self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt,
+};
use rustc_session::config::{DebugInfo, OptLevel};
use rustc_span::source_map::Spanned;
use rustc_span::sym;
@@ -19,11 +22,10 @@
use rustc_target::spec::abi::Abi;
use crate::cost_checker::CostChecker;
+use crate::deref_separator::deref_finder;
use crate::simplify::simplify_cfg;
use crate::util;
use crate::validate::validate_types;
-use std::iter;
-use std::ops::{Range, RangeFrom};
pub(crate) mod cycle;
@@ -477,7 +479,9 @@ fn check_codegen_attributes(
return Err("incompatible instruction set");
}
- if callee_attrs.target_features != self.codegen_fn_attrs.target_features {
+ let callee_feature_names = callee_attrs.target_features.iter().map(|f| f.name);
+ let this_feature_names = self.codegen_fn_attrs.target_features.iter().map(|f| f.name);
+ if callee_feature_names.ne(this_feature_names) {
// In general it is not correct to inline a callee with target features that are a
// subset of the caller. This is because the callee might contain calls, and the ABI of
// those calls depends on the target features of the surrounding function. By moving a
@@ -501,6 +505,10 @@ fn check_mir_body(
) -> Result<(), &'static str> {
let tcx = self.tcx;
+ if let Some(_) = callee_body.tainted_by_errors {
+ return Err("Body is tainted");
+ }
+
let mut threshold = if self.caller_is_inline_forwarder {
self.tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30)
} else if cross_crate_inlinable {
@@ -742,8 +750,8 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
// Copy required constants from the callee_body into the caller_body. Although we are only
// pushing unevaluated consts to `required_consts`, here they may have been evaluated
// because we are calling `instantiate_and_normalize_erasing_regions` -- so we filter again.
- caller_body.required_consts.extend(
- callee_body.required_consts.into_iter().filter(|ct| ct.const_.is_required_const()),
+ caller_body.required_consts.as_mut().unwrap().extend(
+ callee_body.required_consts().into_iter().filter(|ct| ct.const_.is_required_const()),
);
// Now that we incorporated the callee's `required_consts`, we can remove the callee from
// `mentioned_items` -- but we have to take their `mentioned_items` in return. This does
@@ -753,12 +761,11 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
// We need to reconstruct the `required_item` for the callee so that we can find and
// remove it.
let callee_item = MentionedItem::Fn(func.ty(caller_body, self.tcx));
- if let Some(idx) =
- caller_body.mentioned_items.iter().position(|item| item.node == callee_item)
- {
+ let caller_mentioned_items = caller_body.mentioned_items.as_mut().unwrap();
+ if let Some(idx) = caller_mentioned_items.iter().position(|item| item.node == callee_item) {
// We found the callee, so remove it and add its items instead.
- caller_body.mentioned_items.remove(idx);
- caller_body.mentioned_items.extend(callee_body.mentioned_items);
+ caller_mentioned_items.remove(idx);
+ caller_mentioned_items.extend(callee_body.mentioned_items());
} else {
// If we can't find the callee, there's no point in adding its items. Probably it
// already got removed by being inlined elsewhere in the same function, so we already
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index d447756..f5274c6 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -2,8 +2,7 @@
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir::TerminatorKind;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt};
+use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt, TypeVisitableExt};
use rustc_session::Limit;
use rustc_span::sym;
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 58fdc2d..1589653 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -1,21 +1,37 @@
//! Performs various peephole optimizations.
-use crate::simplify::simplify_duplicate_switch_targets;
-use crate::take_array;
use rustc_ast::attr;
use rustc_hir::LangItem;
use rustc_middle::bug;
use rustc_middle::mir::*;
-use rustc_middle::ty::layout;
use rustc_middle::ty::layout::ValidityRequirement;
-use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
+use rustc_middle::ty::{self, layout, GenericArgsRef, ParamEnv, Ty, TyCtxt};
use rustc_span::sym;
use rustc_span::symbol::Symbol;
use rustc_target::spec::abi::Abi;
-pub struct InstSimplify;
+use crate::simplify::simplify_duplicate_switch_targets;
+use crate::take_array;
+
+pub enum InstSimplify {
+ BeforeInline,
+ AfterSimplifyCfg,
+}
+
+impl InstSimplify {
+ pub fn name(&self) -> &'static str {
+ match self {
+ InstSimplify::BeforeInline => "InstSimplify-before-inline",
+ InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
+ }
+ }
+}
impl<'tcx> MirPass<'tcx> for InstSimplify {
+ fn name(&self) -> &'static str {
+ self.name()
+ }
+
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
sess.mir_opt_level() > 0
}
@@ -248,9 +264,7 @@ fn simplify_primitive_clone(
};
// It's definitely not a clone if there are multiple arguments
- if args.len() != 1 {
- return;
- }
+ let [arg] = &args[..] else { return };
let Some(destination_block) = *target else { return };
@@ -264,7 +278,7 @@ fn simplify_primitive_clone(
// These types are easily available from locals, so check that before
// doing DefId lookups to figure out what we're actually calling.
- let arg_ty = args[0].node.ty(self.local_decls, self.tcx);
+ let arg_ty = arg.node.ty(self.local_decls, self.tcx);
let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return };
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 82ad887..7202cc2 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -13,7 +13,8 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
use rustc_hir::HirId;
-use rustc_index::{bit_set::BitSet, IndexVec};
+use rustc_index::bit_set::BitSet;
+use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 243c9c6..1f214bc 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -28,17 +28,16 @@
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_index::IndexVec;
-use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{
- traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs,
- LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue,
- SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK,
+ AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl,
+ MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo,
+ Statement, StatementKind, TerminatorKind, START_BLOCK,
};
-use rustc_middle::query;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_middle::util::Providers;
-use rustc_middle::{bug, span_bug};
-use rustc_span::{source_map::Spanned, sym, DUMMY_SP};
+use rustc_middle::{bug, query, span_bug};
+use rustc_span::source_map::Spanned;
+use rustc_span::{sym, DUMMY_SP};
use rustc_trait_selection::traits;
#[macro_use]
@@ -339,12 +338,15 @@ fn mir_promoted(
// Collect `required_consts` *before* promotion, so if there are any consts being promoted
// we still add them to the list in the outer MIR body.
- let mut required_consts = Vec::new();
- let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
- for (bb, bb_data) in traversal::reverse_postorder(&body) {
- required_consts_visitor.visit_basic_block_data(bb, bb_data);
+ RequiredConstsVisitor::compute_required_consts(&mut body);
+ // If this has an associated by-move async closure body, that doesn't get run through these
+ // passes itself, it gets "tagged along" by the pass manager. `RequiredConstsVisitor` is not
+ // a regular pass so we have to also apply it manually to the other body.
+ if let Some(coroutine) = body.coroutine.as_mut() {
+ if let Some(by_move_body) = coroutine.by_move_body.as_mut() {
+ RequiredConstsVisitor::compute_required_consts(by_move_body);
+ }
}
- body.required_consts = required_consts;
// What we need to run borrowck etc.
let promote_pass = promote_consts::PromoteTemps::default();
@@ -561,9 +563,6 @@ fn o1<T>(x: T) -> WithMinOptLevel<T> {
tcx,
body,
&[
- // Before doing anything, remember which items are being mentioned so that the set of items
- // visited does not depend on the optimization level.
- &mentioned_items::MentionedItems,
// Add some UB checks before any UB gets optimized away.
&check_alignment::CheckAlignment,
// Before inlining: trim down MIR with passes to reduce inlining work.
@@ -571,6 +570,8 @@ fn o1<T>(x: T) -> WithMinOptLevel<T> {
// Has to be done before inlining, otherwise actual call will be almost always inlined.
// Also simple, so can just do first
&lower_slice_len::LowerSliceLenCalls,
+ // Perform instsimplify before inline to eliminate some trivial calls (like clone shims).
+ &instsimplify::InstSimplify::BeforeInline,
// Perform inlining, which may add a lot of code.
&inline::Inline,
// Code from other crates may have storage markers, so this needs to happen after inlining.
@@ -590,7 +591,8 @@ fn o1<T>(x: T) -> WithMinOptLevel<T> {
&match_branches::MatchBranchSimplification,
// inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
&multiple_return_terminators::MultipleReturnTerminators,
- &instsimplify::InstSimplify,
+ // After simplifycfg, it allows us to discover new opportunities for peephole optimizations.
+ &instsimplify::InstSimplify::AfterSimplifyCfg,
&simplify::SimplifyLocals::BeforeConstProp,
&dead_store_elimination::DeadStoreElimination::Initial,
&gvn::GVN,
@@ -654,6 +656,19 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
return body;
}
+ // Before doing anything, remember which items are being mentioned so that the set of items
+ // visited does not depend on the optimization level.
+ // We do not use `run_passes` for this as that might skip the pass if `injection_phase` is set.
+ mentioned_items::MentionedItems.run_pass(tcx, &mut body);
+ // If this has an associated by-move async closure body, that doesn't get run through these
+ // passes itself, it gets "tagged along" by the pass manager. Since we're not using the pass
+ // manager we have to do this by hand.
+ if let Some(coroutine) = body.coroutine.as_mut() {
+ if let Some(by_move_body) = coroutine.by_move_body.as_mut() {
+ mentioned_items::MentionedItems.run_pass(tcx, by_move_body);
+ }
+ }
+
// If `mir_drops_elaborated_and_const_checked` found that the current body has unsatisfiable
// predicates, it will shrink the MIR to a single `unreachable` terminator.
// More generally, if MIR is a lone `unreachable`, there is nothing to optimize.
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index 3d1e1e4..7460680 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -2,6 +2,8 @@
//! It can be used to locate problems in MIR building or optimizations. It assumes that all code
//! can be executed, so it has false positives.
+use std::borrow::Cow;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
@@ -10,7 +12,6 @@
use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
-use std::borrow::Cow;
pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
let always_live_locals = &always_storage_live_locals(body);
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 6aa9039..a9bdff9 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -1,11 +1,12 @@
//! Lowers intrinsic calls
-use crate::take_array;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::sym;
+use crate::take_array;
+
pub struct LowerIntrinsics;
impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 6ab4ec6..47758b5 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -1,9 +1,12 @@
+use std::iter;
+
use rustc_index::IndexSlice;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
+use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
-use rustc_target::abi::Size;
-use std::iter;
+use rustc_target::abi::Integer;
+use rustc_type_ir::TyKind::*;
use super::simplify::simplify_cfg;
@@ -41,10 +44,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
should_cleanup = true;
continue;
}
- // unsound: https://github.com/rust-lang/rust/issues/124150
- if tcx.sess.opts.unstable_opts.unsound_mir_opts
- && SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some()
- {
+ if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() {
should_cleanup = true;
continue;
}
@@ -263,33 +263,56 @@ fn new_stmts(
}
}
+/// Check if the cast constant using `IntToInt` is equal to the target constant.
+fn can_cast(
+ tcx: TyCtxt<'_>,
+ src_val: impl Into<u128>,
+ src_layout: TyAndLayout<'_>,
+ cast_ty: Ty<'_>,
+ target_scalar: ScalarInt,
+) -> bool {
+ let from_scalar = ScalarInt::try_from_uint(src_val.into(), src_layout.size).unwrap();
+ let v = match src_layout.ty.kind() {
+ Uint(_) => from_scalar.to_uint(src_layout.size),
+ Int(_) => from_scalar.to_int(src_layout.size) as u128,
+ _ => unreachable!("invalid int"),
+ };
+ let size = match *cast_ty.kind() {
+ Int(t) => Integer::from_int_ty(&tcx, t).size(),
+ Uint(t) => Integer::from_uint_ty(&tcx, t).size(),
+ _ => unreachable!("invalid int"),
+ };
+ let v = size.truncate(v);
+ let cast_scalar = ScalarInt::try_from_uint(v, size).unwrap();
+ cast_scalar == target_scalar
+}
+
#[derive(Default)]
struct SimplifyToExp {
- transfrom_types: Vec<TransfromType>,
+ transfrom_kinds: Vec<TransfromKind>,
}
#[derive(Clone, Copy)]
-enum CompareType<'tcx, 'a> {
+enum ExpectedTransformKind<'tcx, 'a> {
/// Identical statements.
Same(&'a StatementKind<'tcx>),
/// Assignment statements have the same value.
- Eq(&'a Place<'tcx>, Ty<'tcx>, ScalarInt),
+ SameByEq { place: &'a Place<'tcx>, ty: Ty<'tcx>, scalar: ScalarInt },
/// Enum variant comparison type.
- Discr { place: &'a Place<'tcx>, ty: Ty<'tcx>, is_signed: bool },
+ Cast { place: &'a Place<'tcx>, ty: Ty<'tcx> },
}
-enum TransfromType {
+enum TransfromKind {
Same,
- Eq,
- Discr,
+ Cast,
}
-impl From<CompareType<'_, '_>> for TransfromType {
- fn from(compare_type: CompareType<'_, '_>) -> Self {
+impl From<ExpectedTransformKind<'_, '_>> for TransfromKind {
+ fn from(compare_type: ExpectedTransformKind<'_, '_>) -> Self {
match compare_type {
- CompareType::Same(_) => TransfromType::Same,
- CompareType::Eq(_, _, _) => TransfromType::Eq,
- CompareType::Discr { .. } => TransfromType::Discr,
+ ExpectedTransformKind::Same(_) => TransfromKind::Same,
+ ExpectedTransformKind::SameByEq { .. } => TransfromKind::Same,
+ ExpectedTransformKind::Cast { .. } => TransfromKind::Cast,
}
}
}
@@ -353,7 +376,7 @@ fn can_simplify(
return None;
}
let mut target_iter = targets.iter();
- let (first_val, first_target) = target_iter.next().unwrap();
+ let (first_case_val, first_target) = target_iter.next().unwrap();
let first_terminator_kind = &bbs[first_target].terminator().kind;
// Check that destinations are identical, and if not, then don't optimize this block
if !targets
@@ -363,24 +386,20 @@ fn can_simplify(
return None;
}
- let discr_size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
+ let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap();
let first_stmts = &bbs[first_target].statements;
- let (second_val, second_target) = target_iter.next().unwrap();
+ let (second_case_val, second_target) = target_iter.next().unwrap();
let second_stmts = &bbs[second_target].statements;
if first_stmts.len() != second_stmts.len() {
return None;
}
- fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool {
- l.to_bits_unchecked() == ScalarInt::try_from_uint(r, size).unwrap().to_bits_unchecked()
- }
-
// We first compare the two branches, and then the other branches need to fulfill the same conditions.
- let mut compare_types = Vec::new();
+ let mut expected_transform_kinds = Vec::new();
for (f, s) in iter::zip(first_stmts, second_stmts) {
let compare_type = match (&f.kind, &s.kind) {
// If two statements are exactly the same, we can optimize.
- (f_s, s_s) if f_s == s_s => CompareType::Same(f_s),
+ (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s),
// If two statements are assignments with the match values to the same place, we can optimize.
(
@@ -394,22 +413,29 @@ fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool {
f_c.const_.try_eval_scalar_int(tcx, param_env),
s_c.const_.try_eval_scalar_int(tcx, param_env),
) {
- (Some(f), Some(s)) if f == s => CompareType::Eq(lhs_f, f_c.const_.ty(), f),
- // Enum variants can also be simplified to an assignment statement if their values are equal.
- // We need to consider both unsigned and signed scenarios here.
+ (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq {
+ place: lhs_f,
+ ty: f_c.const_.ty(),
+ scalar: f,
+ },
+ // Enum variants can also be simplified to an assignment statement,
+ // if we can use `IntToInt` cast to get an equal value.
(Some(f), Some(s))
- if ((f_c.const_.ty().is_signed() || discr_ty.is_signed())
- && int_equal(f, first_val, discr_size)
- && int_equal(s, second_val, discr_size))
- || (Some(f) == ScalarInt::try_from_uint(first_val, f.size())
- && Some(s)
- == ScalarInt::try_from_uint(second_val, s.size())) =>
+ if (can_cast(
+ tcx,
+ first_case_val,
+ discr_layout,
+ f_c.const_.ty(),
+ f,
+ ) && can_cast(
+ tcx,
+ second_case_val,
+ discr_layout,
+ f_c.const_.ty(),
+ s,
+ )) =>
{
- CompareType::Discr {
- place: lhs_f,
- ty: f_c.const_.ty(),
- is_signed: f_c.const_.ty().is_signed() || discr_ty.is_signed(),
- }
+ ExpectedTransformKind::Cast { place: lhs_f, ty: f_c.const_.ty() }
}
_ => {
return None;
@@ -420,47 +446,36 @@ fn int_equal(l: ScalarInt, r: impl Into<u128>, size: Size) -> bool {
// Otherwise we cannot optimize. Try another block.
_ => return None,
};
- compare_types.push(compare_type);
+ expected_transform_kinds.push(compare_type);
}
// All remaining BBs need to fulfill the same pattern as the two BBs from the previous step.
for (other_val, other_target) in target_iter {
let other_stmts = &bbs[other_target].statements;
- if compare_types.len() != other_stmts.len() {
+ if expected_transform_kinds.len() != other_stmts.len() {
return None;
}
- for (f, s) in iter::zip(&compare_types, other_stmts) {
+ for (f, s) in iter::zip(&expected_transform_kinds, other_stmts) {
match (*f, &s.kind) {
- (CompareType::Same(f_s), s_s) if f_s == s_s => {}
+ (ExpectedTransformKind::Same(f_s), s_s) if f_s == s_s => {}
(
- CompareType::Eq(lhs_f, f_ty, val),
+ ExpectedTransformKind::SameByEq { place: lhs_f, ty: f_ty, scalar },
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
) if lhs_f == lhs_s
&& s_c.const_.ty() == f_ty
- && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(val) => {}
+ && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {}
(
- CompareType::Discr { place: lhs_f, ty: f_ty, is_signed },
+ ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty },
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
- ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty => {
- let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) else {
- return None;
- };
- if is_signed
- && s_c.const_.ty().is_signed()
- && int_equal(f, other_val, discr_size)
- {
- continue;
- }
- if Some(f) == ScalarInt::try_from_uint(other_val, f.size()) {
- continue;
- }
- return None;
- }
+ ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env)
+ && lhs_f == lhs_s
+ && s_c.const_.ty() == f_ty
+ && can_cast(tcx, other_val, discr_layout, f_ty, f) => {}
_ => return None,
}
}
}
- self.transfrom_types = compare_types.into_iter().map(|c| c.into()).collect();
+ self.transfrom_kinds = expected_transform_kinds.into_iter().map(|c| c.into()).collect();
Some(())
}
@@ -478,13 +493,13 @@ fn new_stmts(
let (_, first) = targets.iter().next().unwrap();
let first = &bbs[first];
- for (t, s) in iter::zip(&self.transfrom_types, &first.statements) {
+ for (t, s) in iter::zip(&self.transfrom_kinds, &first.statements) {
match (t, &s.kind) {
- (TransfromType::Same, _) | (TransfromType::Eq, _) => {
+ (TransfromKind::Same, _) => {
patch.add_statement(parent_end, s.kind.clone());
}
(
- TransfromType::Discr,
+ TransfromKind::Cast,
StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))),
) => {
let operand = Operand::Copy(Place::from(discr_local));
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index d928d7c..32c8064 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -1,6 +1,7 @@
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, Location, MentionedItem, MirPass};
-use rustc_middle::ty::{self, adjustment::PointerCoercion, TyCtxt};
+use rustc_middle::ty::adjustment::PointerCoercion;
+use rustc_middle::ty::{self, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::Spanned;
@@ -22,10 +23,9 @@ fn is_enabled(&self, _sess: &Session) -> bool {
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
- debug_assert!(body.mentioned_items.is_empty());
let mut mentioned_items = Vec::new();
MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body);
- body.mentioned_items = mentioned_items;
+ body.set_mentioned_items(mentioned_items);
}
}
diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index 64749a4..1e87a0e 100644
--- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -1,11 +1,12 @@
//! This pass removes jumps to basic blocks containing only a return, and replaces them with a
//! return instead.
-use crate::simplify;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
+use crate::simplify;
+
pub struct MultipleReturnTerminators;
impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 17a1c3c..824a4b2 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -2,7 +2,8 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
-use crate::{lint::lint_body, validate, MirPass};
+use crate::lint::lint_body;
+use crate::{validate, MirPass};
/// Just like `MirPass`, except it cannot mutate `Body`.
pub trait MirLint<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
index 7b77d03..14dd0c6 100644
--- a/compiler/rustc_mir_transform/src/prettify.rs
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -4,7 +4,8 @@
//! (`-Zmir-enable-passes=+ReorderBasicBlocks,+ReorderLocals`)
//! to make the MIR easier to read for humans.
-use rustc_index::{bit_set::BitSet, IndexSlice, IndexVec};
+use rustc_index::bit_set::BitSet;
+use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 736647f..48a3266 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -12,25 +12,21 @@
//! initialization and can otherwise silence errors, if
//! move analysis runs after promotion on broken MIR.
-use either::{Left, Right};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_middle::mir;
-use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::*;
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::{bug, span_bug};
-use rustc_span::Span;
-
-use rustc_index::{Idx, IndexSlice, IndexVec};
-use rustc_span::source_map::Spanned;
-
use std::assert_matches::assert_matches;
use std::cell::Cell;
use std::{cmp, iter, mem};
+use either::{Left, Right};
use rustc_const_eval::check_consts::{qualifs, ConstCx};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir as hir;
+use rustc_index::{Idx, IndexSlice, IndexVec};
+use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::*;
+use rustc_middle::ty::{self, GenericArgs, List, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::{bug, mir, span_bug};
+use rustc_span::source_map::Spanned;
+use rustc_span::Span;
/// A `MirPass` for promotion.
///
@@ -472,7 +468,7 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
if let ty::RawPtr(_, _) | ty::FnPtr(..) = lhs_ty.kind() {
// Raw and fn pointer operations are not allowed inside consts and thus not promotable.
- assert!(matches!(
+ assert_matches!(
op,
BinOp::Eq
| BinOp::Ne
@@ -481,7 +477,7 @@ fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable>
| BinOp::Ge
| BinOp::Gt
| BinOp::Offset
- ));
+ );
return Err(Unpromotable);
}
@@ -706,6 +702,9 @@ struct Promoter<'a, 'tcx> {
temps: &'a mut IndexVec<Local, TempState>,
extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>,
+ /// Used to assemble the required_consts list while building the promoted.
+ required_consts: Vec<ConstOperand<'tcx>>,
+
/// If true, all nested temps are also kept in the
/// source MIR, not moved to the promoted MIR.
keep_original: bool,
@@ -928,11 +927,14 @@ fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) ->
let span = self.promoted.span;
self.assign(RETURN_PLACE, rvalue, span);
- // Now that we did promotion, we know whether we'll want to add this to `required_consts`.
+ // Now that we did promotion, we know whether we'll want to add this to `required_consts` of
+ // the surrounding MIR body.
if self.add_to_required {
- self.source.required_consts.push(promoted_op);
+ self.source.required_consts.as_mut().unwrap().push(promoted_op);
}
+ self.promoted.set_required_consts(self.required_consts);
+
self.promoted
}
}
@@ -951,7 +953,7 @@ fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) {
fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) {
if constant.const_.is_required_const() {
- self.promoted.required_consts.push(*constant);
+ self.required_consts.push(*constant);
}
// Skipping `super_constant` as the visitor is otherwise only looking for locals.
@@ -1015,9 +1017,9 @@ fn promote_candidates<'tcx>(
extra_statements: &mut extra_statements,
keep_original: false,
add_to_required: false,
+ required_consts: Vec::new(),
};
- // `required_consts` of the promoted itself gets filled while building the MIR body.
let mut promoted = promoter.promote_candidate(candidate, promotions.len());
promoted.source.promoted = Some(promotions.next_index());
promotions.push(promoted);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 801ef14..76e6509 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -1,3 +1,5 @@
+use std::borrow::Cow;
+
use rustc_data_structures::fx::FxHashSet;
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
@@ -8,7 +10,6 @@
use rustc_mir_dataflow::impls::MaybeStorageDead;
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::Analysis;
-use std::borrow::Cow;
use crate::ssa::{SsaLocals, StorageLiveLocals};
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 7d12bcf2..fae1cb5 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -1,10 +1,9 @@
use rustc_index::bit_set::ChunkedBitSet;
use rustc_middle::mir::{Body, TerminatorKind};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
+use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
-use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable, MoveDataParamEnv};
+use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable};
use rustc_target::abi::FieldIdx;
use crate::MirPass;
@@ -25,8 +24,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let move_data =
MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env));
- let mdpe = MoveDataParamEnv { move_data, param_env };
- let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe)
+ let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
.into_engine(tcx, body)
.pass_name("remove_uninit_drops")
.iterate_to_fixpoint()
@@ -41,7 +39,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let MaybeReachable::Reachable(maybe_inits) = maybe_inits.get() else { continue };
// If there's no move path for the dropped place, it's probably a `Deref`. Let it alone.
- let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {
+ let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) else {
continue;
};
@@ -49,7 +47,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
tcx,
param_env,
maybe_inits,
- &mdpe.move_data,
+ &move_data,
place.ty(body, tcx).ty,
mpi,
);
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 00bfb5e..50637e2 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,14 +1,23 @@
use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{ConstOperand, Location};
+use rustc_middle::mir::{traversal, Body, ConstOperand, Location};
pub struct RequiredConstsVisitor<'a, 'tcx> {
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
}
impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
- pub fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
+ fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
RequiredConstsVisitor { required_consts }
}
+
+ pub fn compute_required_consts(body: &mut Body<'tcx>) {
+ let mut required_consts = Vec::new();
+ let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
+ for (bb, bb_data) in traversal::reverse_postorder(&body) {
+ required_consts_visitor.visit_basic_block_data(bb, bb_data);
+ }
+ body.set_required_consts(required_consts);
+ }
}
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index d2f5004..29185e7 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -1,26 +1,27 @@
+use std::assert_matches::assert_matches;
+use std::{fmt, iter};
+
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_index::{Idx, IndexVec};
+use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, Ty, TyCtxt};
+use rustc_middle::ty::{
+ self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt,
+};
use rustc_middle::{bug, span_bug};
-use rustc_span::{source_map::Spanned, Span, DUMMY_SP};
+use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
+use rustc_span::source_map::Spanned;
+use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_target::spec::abi::Abi;
-use std::assert_matches::assert_matches;
-use std::fmt;
-use std::iter;
-
use crate::{
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
instsimplify, mentioned_items, pass_manager as pm, remove_noop_landing_pads, simplify,
};
-use rustc_middle::mir::patch::MirPatch;
-use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
mod async_destructor_ctor;
@@ -154,7 +155,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
&deref_separator::Derefer,
&remove_noop_landing_pads::RemoveNoopLandingPads,
&simplify::SimplifyCfg::MakeShim,
- &instsimplify::InstSimplify,
+ &instsimplify::InstSimplify::BeforeInline,
&abort_unwinding_calls::AbortUnwindingCalls,
&add_call_guards::CriticalCallEdges,
],
@@ -304,7 +305,7 @@ fn new_body<'tcx>(
arg_count: usize,
span: Span,
) -> Body<'tcx> {
- Body::new(
+ let mut body = Body::new(
source,
basic_blocks,
IndexVec::from_elem_n(
@@ -325,7 +326,10 @@ fn new_body<'tcx>(
None,
// FIXME(compiler-errors): is this correct?
None,
- )
+ );
+ // Shims do not directly mention any consts.
+ body.set_required_consts(Vec::new());
+ body
}
pub struct DropShimElaborator<'a, 'tcx> {
@@ -968,13 +972,16 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
};
let source = MirSource::item(ctor_id);
- let body = new_body(
+ let mut body = new_body(
source,
IndexVec::from_elem_n(start_block, 1),
local_decls,
sig.inputs().len(),
span,
);
+ // A constructor doesn't mention any other items (and we don't run the usual optimization passes
+ // so this would otherwise not get filled).
+ body.set_mentioned_items(Vec::new());
crate::pass_manager::dump_mir_for_phase_change(tcx, &body);
@@ -989,7 +996,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
/// }
/// ```
fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
- assert!(matches!(self_ty.kind(), ty::FnPtr(..)), "expected fn ptr, found {self_ty}");
+ assert_matches!(self_ty.kind(), ty::FnPtr(..), "expected fn ptr, found {self_ty}");
let span = tcx.def_span(def_id);
let Some(sig) = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).no_bound_vars() else {
span_bug!(span, "FnPtr::addr with bound vars for `{self_ty}`");
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index e174ccc..59f67d8 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -1,14 +1,14 @@
use std::iter;
-use super::MirPass;
-use rustc_middle::{
- bug,
- mir::{
- interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement,
- StatementKind, SwitchTargets, TerminatorKind,
- },
- ty::{Ty, TyCtxt},
+use rustc_middle::bug;
+use rustc_middle::mir::interpret::Scalar;
+use rustc_middle::mir::{
+ BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, StatementKind, SwitchTargets,
+ TerminatorKind,
};
+use rustc_middle::ty::{Ty, TyCtxt};
+
+use super::MirPass;
/// Pass to convert `if` conditions on integrals into switches on the integral.
/// For an example, it turns something like
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index 93736e5..35cb687 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -1,4 +1,5 @@
-use rustc_index::{bit_set::BitSet, IndexVec};
+use rustc_index::bit_set::BitSet;
+use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 1404a45..81baf58 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -1,6 +1,5 @@
//! A pass that eliminates branches on uninhabited or unreachable enum variants.
-use crate::MirPass;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
use rustc_middle::mir::patch::MirPatch;
@@ -12,6 +11,8 @@
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_target::abi::{Abi, Variants};
+use crate::MirPass;
+
pub struct UnreachableEnumBranching;
fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option<Local> {
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index ab5c25c..491ae1c 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -17,9 +17,7 @@
use rustc_target::abi::{Size, FIRST_VARIANT};
use rustc_target::spec::abi::Abi;
-use crate::util::is_within_packed;
-
-use crate::util::relate_types;
+use crate::util::{is_within_packed, relate_types};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum EdgeKind {
@@ -900,8 +898,8 @@ macro_rules! check_kinds {
self.param_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
);
- if fields.len() == 1 {
- let src_ty = fields.raw[0].ty(self.body, self.tcx);
+ if let [field] = fields.raw.as_slice() {
+ let src_ty = field.ty(self.body, self.tcx);
if !self.mir_assign_valid_types(src_ty, dest_ty) {
self.fail(location, "union field has the wrong type");
}
@@ -969,11 +967,9 @@ macro_rules! check_kinds {
self.fail(location, "RawPtr should be in runtime MIR only");
}
- if fields.len() != 2 {
- self.fail(location, "raw pointer aggregate must have 2 fields");
- } else {
- let data_ptr_ty = fields.raw[0].ty(self.body, self.tcx);
- let metadata_ty = fields.raw[1].ty(self.body, self.tcx);
+ if let [data_ptr, metadata] = fields.raw.as_slice() {
+ let data_ptr_ty = data_ptr.ty(self.body, self.tcx);
+ let metadata_ty = metadata.ty(self.body, self.tcx);
if let ty::RawPtr(in_pointee, in_mut) = data_ptr_ty.kind() {
if *in_mut != mutability {
self.fail(location, "input and output mutability must match");
@@ -1000,6 +996,8 @@ macro_rules! check_kinds {
self.fail(location, "metadata for pointer-to-thin must be unit");
}
}
+ } else {
+ self.fail(location, "raw pointer aggregate must have 2 fields");
}
}
},
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 3655a67..0ae635f 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -207,6 +207,9 @@
mod move_check;
+use std::path::PathBuf;
+
+use move_check::MoveCheckState;
use rustc_data_structures::sync::{par_for_each_in, LRef, MTLock};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir as hir;
@@ -216,17 +219,15 @@
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
-use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::Visitor as MirVisitor;
-use rustc_middle::mir::{self, Location, MentionedItem};
+use rustc_middle::mir::{self, traversal, Location, MentionedItem};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::print::{shrunk_instance_name, with_no_trimmed_paths};
-use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{
- self, AssocKind, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
- TypeVisitableExt, VtblEntry,
+ self, AssocKind, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt,
+ TypeFoldable, TypeVisitableExt, VtblEntry,
};
use rustc_middle::util::Providers;
use rustc_middle::{bug, span_bug};
@@ -236,11 +237,9 @@
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::Size;
-use std::path::PathBuf;
use tracing::{debug, instrument, trace};
use crate::errors::{self, EncounteredErrorWhileInstantiating, NoOptimizedMir, RecursionLimit};
-use move_check::MoveCheckState;
#[derive(PartialEq)]
pub enum MonoItemCollectionStrategy {
@@ -1020,7 +1019,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
if ty.is_sized(tcx.tcx, param_env) {
return false;
}
- let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);
+ let tail = tcx.struct_tail_for_codegen(ty, param_env);
match tail.kind() {
ty::Foreign(..) => false,
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
@@ -1030,7 +1029,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
if type_has_metadata(inner_source) {
(inner_source, inner_target)
} else {
- tcx.struct_lockstep_tails_erasing_lifetimes(inner_source, inner_target, param_env)
+ tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, param_env)
}
};
@@ -1230,7 +1229,7 @@ fn collect_items_of_instance<'tcx>(
// Always visit all `required_consts`, so that we evaluate them and abort compilation if any of
// them errors.
- for const_op in &body.required_consts {
+ for const_op in body.required_consts() {
if let Some(val) = collector.eval_constant(const_op) {
collect_const_value(tcx, val, mentioned_items);
}
@@ -1238,7 +1237,7 @@ fn collect_items_of_instance<'tcx>(
// Always gather mentioned items. We try to avoid processing items that we have already added to
// `used_items` above.
- for item in &body.mentioned_items {
+ for item in body.mentioned_items() {
if !collector.used_mentioned_items.contains(&item.node) {
let item_mono = collector.monomorphize(item.node);
visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items);
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 9548c46..88286cb 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -1,10 +1,11 @@
use std::path::PathBuf;
-use crate::fluent_generated as fluent;
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
use rustc_macros::{Diagnostic, LintDiagnostic};
use rustc_span::{Span, Symbol};
+use crate::fluent_generated as fluent;
+
#[derive(Diagnostic)]
#[diag(monomorphize_recursion_limit)]
pub struct RecursionLimit {
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 3b8f0a9..d6b0f9c 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -3,12 +3,11 @@
// tidy-alphabetical-end
use rustc_hir::lang_items::LangItem;
-use rustc_middle::bug;
use rustc_middle::query::TyCtxtAt;
-use rustc_middle::traits;
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
use rustc_middle::ty::{self, Ty};
use rustc_middle::util::Providers;
+use rustc_middle::{bug, traits};
use rustc_span::ErrorGuaranteed;
mod collector;
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 8c7c5e0..65a3d8d 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -113,15 +113,15 @@
Visibility,
};
use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};
-use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceKind, TyCtxt};
+use rustc_middle::ty::visit::TypeVisitableExt;
+use rustc_middle::ty::{self, InstanceKind, TyCtxt};
use rustc_middle::util::Providers;
use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
use rustc_session::CodegenUnits;
use rustc_span::symbol::Symbol;
use tracing::debug;
-use crate::collector::UsageMap;
-use crate::collector::{self, MonoItemCollectionStrategy};
+use crate::collector::{self, MonoItemCollectionStrategy, UsageMap};
use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode};
struct PartitioningCx<'a, 'tcx> {
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 2d69bfa..5a24202 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -5,18 +5,14 @@
//! generic parameters are unused (and eventually, in what ways generic parameters are used - only
//! for their size, offset of a field, etc.).
-use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
-use rustc_middle::mir::{
- self,
- visit::{TyContext, Visitor},
- Local, LocalDecl, Location,
-};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_hir::ConstContext;
+use rustc_middle::mir::visit::{TyContext, Visitor};
+use rustc_middle::mir::{self, Local, LocalDecl, Location};
use rustc_middle::query::Providers;
-use rustc_middle::ty::{
- self,
- visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
- GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
-};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams};
use rustc_span::symbol::sym;
use tracing::{debug, instrument};
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index e25c5c9..093a697 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -1,7 +1,8 @@
-use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt};
use std::fs::OpenOptions;
use std::io::prelude::*;
+use rustc_middle::ty::{self, ClosureSizeProfileData, Instance, TyCtxt};
+
/// For a given closure, writes out the data for the profiling the impact of RFC 2229 on
/// closure size into a CSV.
///
diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs
index 254ee51..132b740 100644
--- a/compiler/rustc_next_trait_solver/src/resolve.rs
+++ b/compiler/rustc_next_trait_solver/src/resolve.rs
@@ -1,9 +1,10 @@
-use crate::delegate::SolverDelegate;
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_type_ir::inherent::*;
use rustc_type_ir::visit::TypeVisitableExt;
use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
+use crate::delegate::SolverDelegate;
+
///////////////////////////////////////////////////////////////////////////
// EAGER RESOLUTION
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
index f74597f..84921e8 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs
@@ -3,12 +3,11 @@
pub(super) mod structural_traits;
use derive_where::derive_where;
-use rustc_type_ir::elaborate;
use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::visit::TypeVisitableExt as _;
-use rustc_type_ir::{self as ty, Interner, Upcast as _};
+use rustc_type_ir::{self as ty, elaborate, Interner, Upcast as _};
use tracing::{debug, instrument};
use crate::delegate::SolverDelegate;
@@ -699,6 +698,18 @@ fn assemble_coherence_unknowable_candidates<G: GoalKind<D>>(
if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? {
Err(NoSolution)
} else {
+ // While the trait bound itself may be unknowable, we may be able to
+ // prove that a super trait is not implemented. For this, we recursively
+ // prove the super trait bounds of the current goal.
+ //
+ // We skip the goal itself as that one would cycle.
+ let predicate: I::Predicate = trait_ref.upcast(cx);
+ ecx.add_goals(
+ GoalSource::Misc,
+ elaborate::elaborate(cx, [predicate])
+ .skip(1)
+ .map(|predicate| goal.with(cx, predicate)),
+ );
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
},
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index 60beaa0..00837f7 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -7,7 +7,7 @@
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::{self as ty, Interner, Upcast as _};
+use rustc_type_ir::{self as ty, elaborate, Interner, Upcast as _};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use tracing::instrument;
@@ -458,28 +458,23 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
))
}
- ty::FnDef(..) | ty::FnPtr(..) => {
- let bound_sig = self_ty.fn_sig(cx);
- let sig = bound_sig.skip_binder();
- let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
- // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
- // return type implements `Future`.
- let nested = vec![
- bound_sig
- .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
- .upcast(cx),
- ];
- let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
- let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
- Ok((
- bound_sig.rebind(AsyncCallableRelevantTypes {
- tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
- output_coroutine_ty: sig.output(),
- coroutine_return_ty: future_output_ty,
- }),
- nested,
- ))
+ ty::FnDef(def_id, _) => {
+ let sig = self_ty.fn_sig(cx);
+ if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
+ fn_item_to_async_callable(cx, sig)
+ } else {
+ Err(NoSolution)
+ }
}
+ ty::FnPtr(..) => {
+ let sig = self_ty.fn_sig(cx);
+ if sig.skip_binder().is_fn_trait_compatible() {
+ fn_item_to_async_callable(cx, sig)
+ } else {
+ Err(NoSolution)
+ }
+ }
+
ty::Closure(_, args) => {
let args = args.as_closure();
let bound_sig = args.sig();
@@ -563,6 +558,29 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
}
}
+fn fn_item_to_async_callable<I: Interner>(
+ cx: I,
+ bound_sig: ty::Binder<I, ty::FnSig<I>>,
+) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
+ let sig = bound_sig.skip_binder();
+ let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
+ // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
+ // return type implements `Future`.
+ let nested = vec![
+ bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
+ ];
+ let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
+ let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
+ Ok((
+ bound_sig.rebind(AsyncCallableRelevantTypes {
+ tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
+ output_coroutine_ty: sig.output(),
+ coroutine_return_ty: future_output_ty,
+ }),
+ nested,
+ ))
+}
+
/// Given a coroutine-closure, project to its returned coroutine when we are *certain*
/// that the closure's kind is compatible with the goal.
fn coroutine_closure_to_certain_coroutine<I: Interner>(
@@ -671,11 +689,19 @@ pub(in crate::solve) fn predicates_for_object_candidate<D, I>(
{
let cx = ecx.cx();
let mut requirements = vec![];
- requirements.extend(
+ // Elaborating all supertrait outlives obligations here is not soundness critical,
+ // since if we just used the unelaborated set, then the transitive supertraits would
+ // be reachable when proving the former. However, since we elaborate all supertrait
+ // outlives obligations when confirming impls, we would end up with a different set
+ // of outlives obligations here if we didn't do the same, leading to ambiguity.
+ // FIXME(-Znext-solver=coinductive): Adding supertraits here can be removed once we
+ // make impls coinductive always, since they'll always need to prove their supertraits.
+ requirements.extend(elaborate::elaborate(
+ cx,
cx.explicit_super_predicates_of(trait_ref.def_id)
.iter_instantiated(cx, trait_ref.args)
.map(|(pred, _)| pred),
- );
+ ));
// FIXME(associated_const_equality): Also add associated consts to
// the requirements here.
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 9474d50..2e521dd 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -21,9 +21,8 @@
use crate::delegate::SolverDelegate;
use crate::resolve::EagerResolver;
use crate::solve::eval_ctxt::NestedGoals;
-use crate::solve::inspect;
use crate::solve::{
- response_no_constraints_raw, CanonicalInput, CanonicalResponse, Certainty, EvalCtxt,
+ inspect, response_no_constraints_raw, CanonicalInput, CanonicalResponse, Certainty, EvalCtxt,
ExternalConstraintsData, Goal, MaybeCause, NestedNormalizationGoals, NoSolution,
PredefinedOpaquesData, QueryInput, QueryResult, Response,
};
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs
index 4258dd9..e459d5c 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/probe.rs
@@ -5,8 +5,9 @@
use crate::delegate::SolverDelegate;
use crate::solve::assembly::Candidate;
-use crate::solve::inspect;
-use crate::solve::{BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult};
+use crate::solve::{
+ inspect, BuiltinImplSource, CandidateSource, EvalCtxt, NoSolution, QueryResult,
+};
pub(in crate::solve) struct ProbeCtxt<'me, 'a, D, I, F, T>
where
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index 36e13cc..a3c2166 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -13,10 +13,9 @@
use crate::delegate::SolverDelegate;
use crate::solve::eval_ctxt::canonical;
-use crate::solve::inspect;
use crate::solve::{
- CanonicalInput, Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, QueryInput,
- QueryResult,
+ inspect, CanonicalInput, Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource,
+ QueryInput, QueryResult,
};
/// The core data structure when building proof trees.
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index a83bd68..5738173 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -6,8 +6,7 @@
use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
-use rustc_type_ir::Upcast as _;
-use rustc_type_ir::{self as ty, Interner, NormalizesTo};
+use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
use tracing::instrument;
use crate::delegate::SolverDelegate;
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 4474bbc..b1dba71 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -87,6 +87,19 @@ fn consider_impl_candidate(
.map(|pred| goal.with(cx, pred));
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds);
+ // We currently elaborate all supertrait outlives obligations from impls.
+ // This can be removed when we actually do coinduction correctly, and prove
+ // all supertrait obligations unconditionally.
+ let goal_clause: I::Clause = goal.predicate.upcast(cx);
+ for clause in elaborate::elaborate(cx, [goal_clause]) {
+ if matches!(
+ clause.kind().skip_binder(),
+ ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..)
+ ) {
+ ecx.add_goal(GoalSource::Misc, goal.with(cx, clause));
+ }
+ }
+
ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty)
})
}
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 391a579..8e8d91c 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -66,7 +66,7 @@
.suggestion = escape `box` to use it as an identifier
parse_box_syntax_removed = `box_syntax` has been removed
- .suggestion = use `Box::new()` instead
+parse_box_syntax_removed_suggestion = use `Box::new()` instead
parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier
@@ -365,6 +365,7 @@
.sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
+ .label = this is not an unsafe attribute
.suggestion = remove the `unsafe(...)`
.note = extraneous unsafe is not allowed in attributes
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 2e81d2a..0d4512b 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2,9 +2,10 @@
use rustc_ast::token::Token;
use rustc_ast::{Path, Visibility};
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
- SubdiagMessageOp, Subdiagnostic,
+ Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, SubdiagMessageOp,
+ Subdiagnostic,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_session::errors::ExprParenthesesNeeded;
@@ -554,12 +555,7 @@ pub(crate) enum MissingInInForLoopSub {
code = "in"
)]
InNotOf(#[primary_span] Span),
- #[suggestion(
- parse_add_in,
- style = "verbose",
- applicability = "maybe-incorrect",
- code = " in "
- )]
+ #[suggestion(parse_add_in, style = "verbose", applicability = "maybe-incorrect", code = " in ")]
AddIn(#[primary_span] Span),
}
@@ -2729,15 +2725,24 @@ pub fn new() -> Self {
#[derive(Diagnostic)]
#[diag(parse_box_syntax_removed)]
-pub struct BoxSyntaxRemoved<'a> {
+pub struct BoxSyntaxRemoved {
#[primary_span]
- #[suggestion(
- code = "Box::new({code})",
- applicability = "machine-applicable",
- style = "verbose"
- )]
pub span: Span,
- pub code: &'a str,
+ #[subdiagnostic]
+ pub sugg: AddBoxNew,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+ parse_box_syntax_removed_suggestion,
+ applicability = "machine-applicable",
+ style = "verbose"
+)]
+pub struct AddBoxNew {
+ #[suggestion_part(code = "Box::new(")]
+ pub box_kw_and_lo: Span,
+ #[suggestion_part(code = ")")]
+ pub hi: Span,
}
#[derive(Diagnostic)]
@@ -3187,6 +3192,7 @@ pub(crate) struct DotDotRangeAttribute {
#[note]
pub struct InvalidAttrUnsafe {
#[primary_span]
+ #[label]
pub span: Span,
pub name: Path,
}
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
index 1247e2e..4d5d1ce 100644
--- a/compiler/rustc_parse/src/lexer/diagnostics.rs
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -1,9 +1,10 @@
-use super::UnmatchedDelim;
use rustc_ast::token::Delimiter;
use rustc_errors::Diag;
use rustc_span::source_map::SourceMap;
use rustc_span::Span;
+use super::UnmatchedDelim;
+
#[derive(Default)]
pub(super) struct TokenTreeDiagInfo {
/// Stack of open delimiters and their spans. Used for error message.
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 511805c..f309390 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,25 +1,26 @@
use std::ops::Range;
-use crate::errors;
-use crate::lexer::unicode_chars::UNICODE_ARRAY;
-use crate::make_unclosed_delims_error;
use rustc_ast::ast::{self, AttrStyle};
use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{codes::*, Applicability, Diag, DiagCtxtHandle, StashKey};
+use rustc_errors::codes::*;
+use rustc_errors::{Applicability, Diag, DiagCtxtHandle, StashKey};
use rustc_lexer::unescape::{self, EscapeError, Mode};
-use rustc_lexer::{Base, DocStyle, RawStrError};
-use rustc_lexer::{Cursor, LiteralKind};
+use rustc_lexer::{Base, Cursor, DocStyle, LiteralKind, RawStrError};
use rustc_session::lint::builtin::{
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::ParseSess;
+use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol;
-use rustc_span::{edition::Edition, BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos, Span};
use tracing::debug;
+use crate::lexer::unicode_chars::UNICODE_ARRAY;
+use crate::{errors, make_unclosed_delims_error};
+
mod diagnostics;
mod tokentrees;
mod unescape_error_reporting;
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 8e54345..fb4ed5b 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,14 +1,15 @@
-use super::diagnostics::report_suspicious_mismatch_block;
-use super::diagnostics::same_indentation_level;
-use super::diagnostics::TokenTreeDiagInfo;
-use super::{StringReader, UnmatchedDelim};
-use crate::Parser;
use rustc_ast::token::{self, Delimiter, Token};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_ast_pretty::pprust::token_to_string;
use rustc_errors::{Applicability, PErr};
use rustc_span::symbol::kw;
+use super::diagnostics::{
+ report_suspicious_mismatch_block, same_indentation_level, TokenTreeDiagInfo,
+};
+use super::{StringReader, UnmatchedDelim};
+use crate::Parser;
+
pub(super) struct TokenTreesReader<'psess, 'src> {
string_reader: StringReader<'psess, 'src>,
/// The "next" token, which has been obtained from the `StringReader` but
@@ -72,16 +73,31 @@ fn lex_token_trees(
fn eof_err(&mut self) -> PErr<'psess> {
let msg = "this file contains an unclosed delimiter";
let mut err = self.string_reader.dcx().struct_span_err(self.token.span, msg);
- for &(_, sp) in &self.diag_info.open_braces {
- err.span_label(sp, "unclosed delimiter");
+
+ let unclosed_delimiter_show_limit = 5;
+ let len = usize::min(unclosed_delimiter_show_limit, self.diag_info.open_braces.len());
+ for &(_, span) in &self.diag_info.open_braces[..len] {
+ err.span_label(span, "unclosed delimiter");
self.diag_info.unmatched_delims.push(UnmatchedDelim {
found_delim: None,
found_span: self.token.span,
- unclosed_span: Some(sp),
+ unclosed_span: Some(span),
candidate_span: None,
});
}
+ if let Some((_, span)) = self.diag_info.open_braces.get(unclosed_delimiter_show_limit)
+ && self.diag_info.open_braces.len() >= unclosed_delimiter_show_limit + 2
+ {
+ err.span_label(
+ *span,
+ format!(
+ "another {} unclosed delimiters begin from here",
+ self.diag_info.open_braces.len() - unclosed_delimiter_show_limit
+ ),
+ );
+ }
+
if let Some((delim, _)) = self.diag_info.open_braces.last() {
report_suspicious_mismatch_block(
&mut err,
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index b7a790f..efa53f0 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -40,7 +40,8 @@ pub(crate) fn emit_unescape_error(
dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false })
}
EscapeError::MoreThanOneChar => {
- use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
+ use unicode_normalization::char::is_combining_mark;
+ use unicode_normalization::UnicodeNormalization;
let mut sugg = None;
let mut note = None;
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index 0a82ede..d78b366 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -1,12 +1,12 @@
//! Characters and their corresponding confusables were collected from
//! <https://www.unicode.org/Public/security/10.0.0/confusables.txt>
+use rustc_span::symbol::kw;
+use rustc_span::{BytePos, Pos, Span};
+
use super::StringReader;
-use crate::{
- errors::TokenSubstitution,
- token::{self, Delimiter},
-};
-use rustc_span::{symbol::kw, BytePos, Pos, Span};
+use crate::errors::TokenSubstitution;
+use crate::token::{self, Delimiter};
#[rustfmt::skip] // for line breaks
pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 4454747..3707927 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -5,6 +5,7 @@
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![feature(array_windows)]
+#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(debug_closure_helpers)]
#![feature(if_let_guard)]
@@ -12,18 +13,17 @@
#![feature(let_chains)]
// tidy-alphabetical-end
+use std::path::Path;
+
use rustc_ast as ast;
-use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{AttrItem, Attribute, MetaItem};
+use rustc_ast::{token, AttrItem, Attribute, MetaItem};
use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Diag, FatalError, PResult};
use rustc_session::parse::ParseSess;
use rustc_span::{FileName, SourceFile, Span};
-use std::path::Path;
-
pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments");
#[macro_use]
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 535b53a..8fdfbce 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -1,16 +1,16 @@
-use crate::errors;
-use crate::fluent_generated as fluent;
-use crate::maybe_whole;
-
-use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle};
use rustc_ast as ast;
use rustc_ast::attr;
use rustc_ast::token::{self, Delimiter};
-use rustc_errors::{codes::*, Diag, PResult};
-use rustc_span::{sym, symbol::kw, BytePos, Span};
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, PResult};
+use rustc_span::symbol::kw;
+use rustc_span::{sym, BytePos, Span};
use thin_vec::ThinVec;
use tracing::debug;
+use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle};
+use crate::{errors, fluent_generated as fluent, maybe_whole};
+
// Public for rustfmt usage
#[derive(Debug)]
pub enum InnerAttrPolicy {
@@ -31,6 +31,12 @@ enum OuterAttributeType {
Attribute,
}
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum AllowLeadingUnsafe {
+ Yes,
+ No,
+}
+
impl<'a> Parser<'a> {
/// Parses attributes that appear before an item.
pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
@@ -307,8 +313,8 @@ pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
// inner attribute, for possible later processing in a `LazyAttrTokenStream`.
if let Capturing::Yes = self.capture_state.capturing {
let end_pos = self.num_bump_calls;
- let range = start_pos..end_pos;
- self.capture_state.inner_attr_ranges.insert(attr.id, range);
+ let parser_range = ParserRange(start_pos..end_pos);
+ self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range);
}
attrs.push(attr);
} else {
@@ -332,7 +338,7 @@ pub(crate) fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'a, ast::Meta
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
- let cfg_predicate = self.parse_meta_item()?;
+ let cfg_predicate = self.parse_meta_item(AllowLeadingUnsafe::No)?;
self.expect(&token::Comma)?;
// Presumably, the majority of the time there will only be one attr.
@@ -368,7 +374,10 @@ pub(crate) fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::NestedMe
/// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
/// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
/// ```
- pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
+ pub fn parse_meta_item(
+ &mut self,
+ unsafe_allowed: AllowLeadingUnsafe,
+ ) -> PResult<'a, ast::MetaItem> {
// We can't use `maybe_whole` here because it would bump in the `None`
// case, which we don't want.
if let token::Interpolated(nt) = &self.token.kind
@@ -384,7 +393,11 @@ pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
}
let lo = self.token.span;
- let is_unsafe = self.eat_keyword(kw::Unsafe);
+ let is_unsafe = if unsafe_allowed == AllowLeadingUnsafe::Yes {
+ self.eat_keyword(kw::Unsafe)
+ } else {
+ false
+ };
let unsafety = if is_unsafe {
let unsafe_span = self.prev_token.span;
self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
@@ -427,7 +440,7 @@ fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
Err(err) => err.cancel(), // we provide a better error below
}
- match self.parse_meta_item() {
+ match self.parse_meta_item(AllowLeadingUnsafe::No) {
Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)),
Err(err) => err.cancel(), // we provide a better error below
}
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 5dc49ea..abf6103 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,14 +1,19 @@
-use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor};
+use std::{iter, mem};
+
use rustc_ast::token::{Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, AttrsTarget, DelimSpacing};
-use rustc_ast::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, ToAttrTokenStream};
-use rustc_ast::{self as ast};
-use rustc_ast::{AttrVec, Attribute, HasAttrs, HasTokens};
+use rustc_ast::tokenstream::{
+ AttrTokenStream, AttrTokenTree, AttrsTarget, DelimSpacing, DelimSpan, LazyAttrTokenStream,
+ Spacing, ToAttrTokenStream,
+};
+use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, HasTokens};
use rustc_errors::PResult;
use rustc_session::parse::ParseSess;
use rustc_span::{sym, Span, DUMMY_SP};
-use std::{iter, mem};
+use super::{
+ Capturing, FlatToken, ForceCollect, NodeRange, NodeReplacement, Parser, ParserRange,
+ TokenCursor,
+};
/// A wrapper type to ensure that the parser handles outer attributes correctly.
/// When we parse outer attributes, we need to ensure that we capture tokens
@@ -26,8 +31,8 @@
#[derive(Debug, Clone)]
pub struct AttrWrapper {
attrs: AttrVec,
- // The start of the outer attributes in the token cursor.
- // This allows us to create a `ReplaceRange` for the entire attribute
+ // The start of the outer attributes in the parser's token stream.
+ // This lets us create a `NodeReplacement` for the entire attribute
// target, including outer attributes.
start_pos: u32,
}
@@ -51,10 +56,9 @@ pub(crate) fn take_for_recovery(self, psess: &ParseSess) -> AttrVec {
/// Prepend `self.attrs` to `attrs`.
// FIXME: require passing an NT to prevent misuse of this method
- pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
- let mut self_attrs = self.attrs;
- mem::swap(attrs, &mut self_attrs);
- attrs.extend(self_attrs);
+ pub(crate) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) {
+ mem::swap(attrs, &mut self.attrs);
+ attrs.extend(self.attrs);
}
pub fn is_empty(&self) -> bool {
@@ -87,7 +91,7 @@ struct LazyAttrTokenStreamImpl {
cursor_snapshot: TokenCursor,
num_calls: u32,
break_last_token: bool,
- replace_ranges: Box<[ReplaceRange]>,
+ node_replacements: Box<[NodeReplacement]>,
}
impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
@@ -102,21 +106,24 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
.chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next())))
.take(self.num_calls as usize);
- if self.replace_ranges.is_empty() {
+ if self.node_replacements.is_empty() {
make_attr_token_stream(tokens, self.break_last_token)
} else {
let mut tokens: Vec<_> = tokens.collect();
- let mut replace_ranges = self.replace_ranges.to_vec();
- replace_ranges.sort_by_key(|(range, _)| range.start);
+ let mut node_replacements = self.node_replacements.to_vec();
+ node_replacements.sort_by_key(|(range, _)| range.0.start);
#[cfg(debug_assertions)]
- for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() {
+ for [(node_range, tokens), (next_node_range, next_tokens)] in
+ node_replacements.array_windows()
+ {
assert!(
- range.end <= next_range.start || range.end >= next_range.end,
- "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
- range,
+ node_range.0.end <= next_node_range.0.start
+ || node_range.0.end >= next_node_range.0.end,
+ "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
+ node_range,
tokens,
- next_range,
+ next_node_range,
next_tokens,
);
}
@@ -134,20 +141,23 @@ fn to_attr_token_stream(&self) -> AttrTokenStream {
// start position, we ensure that any (outer) replace range which
// encloses another (inner) replace range will fully overwrite the
// inner range's replacement.
- for (range, target) in replace_ranges.into_iter().rev() {
- assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}");
+ for (node_range, target) in node_replacements.into_iter().rev() {
+ assert!(
+ !node_range.0.is_empty(),
+ "Cannot replace an empty node range: {:?}",
+ node_range.0
+ );
// Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus
// enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the
// total length of `tokens` constant throughout the replacement process, allowing
- // us to use all of the `ReplaceRanges` entries without adjusting indices.
+ // us to do all replacements without adjusting indices.
let target_len = target.is_some() as usize;
tokens.splice(
- (range.start as usize)..(range.end as usize),
- target
- .into_iter()
- .map(|target| FlatToken::AttrsTarget(target))
- .chain(iter::repeat(FlatToken::Empty).take(range.len() - target_len)),
+ (node_range.0.start as usize)..(node_range.0.end as usize),
+ target.into_iter().map(|target| FlatToken::AttrsTarget(target)).chain(
+ iter::repeat(FlatToken::Empty).take(node_range.0.len() - target_len),
+ ),
);
}
make_attr_token_stream(tokens.into_iter(), self.break_last_token)
@@ -214,7 +224,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
let cursor_snapshot = self.token_cursor.clone();
let start_pos = self.num_bump_calls;
let has_outer_attrs = !attrs.attrs.is_empty();
- let replace_ranges_start = self.capture_state.replace_ranges.len();
+ let parser_replacements_start = self.capture_state.parser_replacements.len();
// We set and restore `Capturing::Yes` on either side of the call to
// `f`, so we can distinguish the outermost call to
@@ -269,7 +279,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
return Ok(ret);
}
- let replace_ranges_end = self.capture_state.replace_ranges.len();
+ let parser_replacements_end = self.capture_state.parser_replacements.len();
assert!(
!(self.break_last_token && capture_trailing),
@@ -286,15 +296,16 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
let num_calls = end_pos - start_pos;
- // Take the captured ranges for any inner attributes that we parsed in
- // `Parser::parse_inner_attributes`, and pair them in a `ReplaceRange`
- // with `None`, which means the relevant tokens will be removed. (More
- // details below.)
- let mut inner_attr_replace_ranges = Vec::new();
+ // Take the captured `ParserRange`s for any inner attributes that we parsed in
+ // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
+ // which means the relevant tokens will be removed. (More details below.)
+ let mut inner_attr_parser_replacements = Vec::new();
for attr in ret.attrs() {
if attr.style == ast::AttrStyle::Inner {
- if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&attr.id) {
- inner_attr_replace_ranges.push((attr_range, None));
+ if let Some(inner_attr_parser_range) =
+ self.capture_state.inner_attr_parser_ranges.remove(&attr.id)
+ {
+ inner_attr_parser_replacements.push((inner_attr_parser_range, None));
} else {
self.dcx().span_delayed_bug(attr.span, "Missing token range for attribute");
}
@@ -303,37 +314,41 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
// This is hot enough for `deep-vector` that checking the conditions for an empty iterator
// is measurably faster than actually executing the iterator.
- let replace_ranges: Box<[ReplaceRange]> =
- if replace_ranges_start == replace_ranges_end && inner_attr_replace_ranges.is_empty() {
- Box::new([])
- } else {
- // Grab any replace ranges that occur *inside* the current AST node. We will
- // perform the actual replacement only when we convert the `LazyAttrTokenStream` to
- // an `AttrTokenStream`.
- self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end]
- .iter()
- .cloned()
- .chain(inner_attr_replace_ranges.iter().cloned())
- .map(|(range, data)| ((range.start - start_pos)..(range.end - start_pos), data))
- .collect()
- };
+ let node_replacements: Box<[_]> = if parser_replacements_start == parser_replacements_end
+ && inner_attr_parser_replacements.is_empty()
+ {
+ Box::new([])
+ } else {
+ // Grab any replace ranges that occur *inside* the current AST node. Convert them
+ // from `ParserRange` form to `NodeRange` form. We will perform the actual
+ // replacement only when we convert the `LazyAttrTokenStream` to an
+ // `AttrTokenStream`.
+ self.capture_state.parser_replacements
+ [parser_replacements_start..parser_replacements_end]
+ .iter()
+ .cloned()
+ .chain(inner_attr_parser_replacements.iter().cloned())
+ .map(|(parser_range, data)| (NodeRange::new(parser_range, start_pos), data))
+ .collect()
+ };
// What is the status here when parsing the example code at the top of this method?
//
// When parsing `g`:
// - `start_pos..end_pos` is `12..33` (`fn g { ... }`, excluding the outer attr).
- // - `inner_attr_replace_ranges` has one entry (`5..15`, when counting from `fn`), to
+ // - `inner_attr_parser_replacements` has one entry (`ParserRange(17..27)`), to
// delete the inner attr's tokens.
- // - This entry is put into the lazy tokens for `g`, i.e. deleting the inner attr from
- // those tokens (if they get evaluated).
+ // - This entry is converted to `NodeRange(5..15)` (relative to the `fn`) and put into
+ // the lazy tokens for `g`, i.e. deleting the inner attr from those tokens (if they get
+ // evaluated).
// - Those lazy tokens are also put into an `AttrsTarget` that is appended to `self`'s
// replace ranges at the bottom of this function, for processing when parsing `m`.
- // - `replace_ranges_start..replace_ranges_end` is empty.
+ // - `parser_replacements_start..parser_replacements_end` is empty.
//
// When parsing `m`:
// - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute).
- // - `inner_attr_replace_ranges` is empty.
- // - `replace_range_start..replace_ranges_end` has one entry.
+ // - `inner_attr_parser_replacements` is empty.
+ // - `parser_replacements_start..parser_replacements_end` has one entry.
// - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`,
// including its outer attribute), with:
// - `attrs`: includes the outer and the inner attr.
@@ -344,7 +359,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
num_calls,
cursor_snapshot,
break_last_token: self.break_last_token,
- replace_ranges,
+ node_replacements,
});
// If we support tokens and don't already have them, store the newly captured tokens.
@@ -365,7 +380,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
// What is the status here when parsing the example code at the top of this method?
//
// When parsing `g`, we add one entry:
- // - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with:
+ // - The pushed entry (`ParserRange(3..33)`) has a new `AttrsTarget` with:
// - `attrs`: includes the outer and the inner attr.
// - `tokens`: lazy tokens for `g` (with its inner attr deleted).
//
@@ -376,12 +391,14 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
// cfg-expand this AST node.
let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos };
let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
- self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target)));
+ self.capture_state
+ .parser_replacements
+ .push((ParserRange(start_pos..end_pos), Some(target)));
} else if matches!(self.capture_state.capturing, Capturing::No) {
// Only clear the ranges once we've finished capturing entirely, i.e. we've finished
// the outermost call to this method.
- self.capture_state.replace_ranges.clear();
- self.capture_state.inner_attr_ranges.clear();
+ self.capture_state.parser_replacements.clear();
+ self.capture_state.inner_attr_parser_ranges.clear();
}
Ok(ret)
}
@@ -469,8 +486,9 @@ fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(AttrWrapper, 16);
static_assert_size!(LazyAttrTokenStreamImpl, 96);
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 1a0d9aa..47ca85b 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1,25 +1,6 @@
-use super::pat::Expected;
-use super::{
- BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenType,
-};
-use crate::errors::{
- AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, AwaitSuggestion,
- BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained,
- ComparisonOperatorsCannotBeChainedSugg, ConstGenericWithoutBraces,
- ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, DocCommentOnParamType,
- DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
- GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
- HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
- IncorrectSemicolon, IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType,
- QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
- StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
- SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
- UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
- UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
-};
-use crate::fluent_generated as fluent;
-use crate::parser;
-use crate::parser::attr::InnerAttrPolicy;
+use std::mem::take;
+use std::ops::{Deref, DerefMut};
+
use ast::token::IdentIsRaw;
use rustc_ast as ast;
use rustc_ast::ptr::P;
@@ -41,11 +22,31 @@
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP};
-use std::mem::take;
-use std::ops::{Deref, DerefMut};
use thin_vec::{thin_vec, ThinVec};
use tracing::{debug, trace};
+use super::pat::Expected;
+use super::{
+ BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenType,
+};
+use crate::errors::{
+ AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AttributeOnParamType, AwaitSuggestion,
+ BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi, ComparisonOperatorsCannotBeChained,
+ ComparisonOperatorsCannotBeChainedSugg, ConstGenericWithoutBraces,
+ ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, DocCommentOnParamType,
+ DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
+ GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
+ HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
+ IncorrectSemicolon, IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType,
+ QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
+ StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg,
+ SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator,
+ UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
+ UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
+};
+use crate::parser::attr::InnerAttrPolicy;
+use crate::{fluent_generated as fluent, parser};
+
/// Creates a placeholder argument.
pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
let pat = P(Pat {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 389a6d1..cf5d657 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,30 +1,22 @@
// ignore-tidy-filelength
-use super::diagnostics::SnapshotParser;
-use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
-use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{
- AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
- SemiColonMode, SeqSep, TokenType, Trailing,
-};
+use core::mem;
+use core::ops::ControlFlow;
-use crate::errors;
-use crate::maybe_recover_from_interpolated_ty_qpath;
use ast::mut_visit::{self, MutVisitor};
use ast::token::IdentIsRaw;
use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
-use core::mem;
-use core::ops::ControlFlow;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::util::classify;
use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity};
use rustc_ast::visit::{walk_expr, Visitor};
-use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, UnOp, DUMMY_NODE_ID};
-use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
-use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
-use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
+use rustc_ast::{
+ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy,
+ ClosureBinder, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, MetaItemLit,
+ Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, DUMMY_NODE_ID,
+};
use rustc_ast_pretty::pprust;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
@@ -39,13 +31,14 @@
use thin_vec::{thin_vec, ThinVec};
use tracing::instrument;
-#[derive(Debug)]
-pub(super) enum LhsExpr {
- // Already parsed just the outer attributes.
- Unparsed { attrs: AttrWrapper },
- // Already parsed the expression.
- Parsed { expr: P<Expr>, starts_statement: bool },
-}
+use super::diagnostics::SnapshotParser;
+use super::pat::{CommaRecoveryMode, Expected, RecoverColon, RecoverComma};
+use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
+use super::{
+ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
+ SemiColonMode, SeqSep, TokenType, Trailing,
+};
+use crate::{errors, maybe_recover_from_interpolated_ty_qpath};
#[derive(Debug)]
enum DestructuredFloat {
@@ -112,30 +105,31 @@ pub(super) fn parse_expr_res(
r: Restrictions,
attrs: AttrWrapper,
) -> PResult<'a, P<Expr>> {
- self.with_res(r, |this| this.parse_expr_assoc_with(0, LhsExpr::Unparsed { attrs }))
+ self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs))
}
/// Parses an associative expression with operators of at least `min_prec` precedence.
pub(super) fn parse_expr_assoc_with(
&mut self,
min_prec: usize,
- lhs: LhsExpr,
+ attrs: AttrWrapper,
) -> PResult<'a, P<Expr>> {
- let mut starts_stmt = false;
- let mut lhs = match lhs {
- LhsExpr::Parsed { expr, starts_statement } => {
- starts_stmt = starts_statement;
- expr
- }
- LhsExpr::Unparsed { attrs } => {
- if self.token.is_range_separator() {
- return self.parse_expr_prefix_range(attrs);
- } else {
- self.parse_expr_prefix(attrs)?
- }
- }
+ let lhs = if self.token.is_range_separator() {
+ return self.parse_expr_prefix_range(attrs);
+ } else {
+ self.parse_expr_prefix(attrs)?
};
+ self.parse_expr_assoc_rest_with(min_prec, false, lhs)
+ }
+ /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators
+ /// of at least `min_prec` precedence.
+ pub(super) fn parse_expr_assoc_rest_with(
+ &mut self,
+ min_prec: usize,
+ starts_stmt: bool,
+ mut lhs: P<Expr>,
+ ) -> PResult<'a, P<Expr>> {
if !self.should_continue_as_assoc_expr(&lhs) {
return Ok(lhs);
}
@@ -271,7 +265,7 @@ pub(super) fn parse_expr_assoc_with(
};
let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| {
let attrs = this.parse_outer_attributes()?;
- this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::Unparsed { attrs })
+ this.parse_expr_assoc_with(prec + prec_adjustment, attrs)
})?;
let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span);
@@ -446,7 +440,7 @@ fn parse_expr_range(
let maybe_lt = self.token.clone();
let attrs = self.parse_outer_attributes()?;
Some(
- self.parse_expr_assoc_with(prec + 1, LhsExpr::Unparsed { attrs })
+ self.parse_expr_assoc_with(prec + 1, attrs)
.map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
)
} else {
@@ -503,12 +497,9 @@ fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>
let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
// RHS must be parsed with more associativity than the dots.
let attrs = this.parse_outer_attributes()?;
- this.parse_expr_assoc_with(
- op.unwrap().precedence() + 1,
- LhsExpr::Unparsed { attrs },
- )
- .map(|x| (lo.to(x.span), Some(x)))
- .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
+ this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs)
+ .map(|x| (lo.to(x.span), Some(x)))
+ .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
} else {
(lo, None)
};
@@ -617,10 +608,12 @@ fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
/// Parse `box expr` - this syntax has been removed, but we still parse this
/// for now to provide a more useful error
fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
- let (span, _) = self.parse_expr_prefix_common(box_kw)?;
- let inner_span = span.with_lo(box_kw.hi());
- let code = self.psess.source_map().span_to_snippet(inner_span).unwrap();
- let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() });
+ let (span, expr) = self.parse_expr_prefix_common(box_kw)?;
+ // Make a multipart suggestion instead of `span_to_snippet` in case source isn't available
+ let box_kw_and_lo = box_kw.until(self.interpolated_or_expr_span(&expr));
+ let hi = span.shrink_to_hi();
+ let sugg = errors::AddBoxNew { box_kw_and_lo, hi };
+ let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span, sugg });
Ok((span, ExprKind::Err(guar)))
}
@@ -701,12 +694,12 @@ fn parse_assoc_op_cast(
// `foo: `
ExprKind::Path(None, ast::Path { segments, .. }),
token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No),
- ) if segments.len() == 1 => {
+ ) if let [segment] = segments.as_slice() => {
let snapshot = self.create_snapshot_for_diagnostic();
let label = Label {
ident: Ident::from_str_and_span(
- &format!("'{}", segments[0].ident),
- segments[0].ident.span,
+ &format!("'{}", segment.ident),
+ segment.ident.span,
),
};
match self.parse_expr_labeled(label, false) {
@@ -886,7 +879,7 @@ pub(super) fn parse_expr_dot_or_call_with(
mut e: P<Expr>,
lo: Span,
) -> PResult<'a, P<Expr>> {
- let res = ensure_sufficient_stack(|| {
+ let mut res = ensure_sufficient_stack(|| {
loop {
let has_question =
if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) {
@@ -933,17 +926,13 @@ pub(super) fn parse_expr_dot_or_call_with(
// Stitch the list of outer attributes onto the return value. A little
// bit ugly, but the best way given the current code structure.
- if attrs.is_empty() {
- res
- } else {
- res.map(|expr| {
- expr.map(|mut expr| {
- attrs.extend(expr.attrs);
- expr.attrs = attrs;
- expr
- })
- })
+ if !attrs.is_empty()
+ && let Ok(expr) = &mut res
+ {
+ mem::swap(&mut expr.attrs, &mut attrs);
+ expr.attrs.extend(attrs)
}
+ res
}
pub(super) fn parse_dot_suffix_expr(
@@ -2644,10 +2633,7 @@ fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>>
self.expect(&token::Eq)?;
}
let attrs = self.parse_outer_attributes()?;
- let expr = self.parse_expr_assoc_with(
- 1 + prec_let_scrutinee_needs_par(),
- LhsExpr::Unparsed { attrs },
- )?;
+ let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?;
let span = lo.to(expr.span);
Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered)))
}
@@ -3152,7 +3138,8 @@ pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
if !require_comma {
arm_body = Some(expr);
- this.eat(&token::Comma);
+ // Eat a comma if it exists, though.
+ let _ = this.eat(&token::Comma);
Ok(Recovered::No)
} else if let Some((span, guar)) =
this.parse_arm_body_missing_braces(&expr, arrow_span)
@@ -3653,7 +3640,7 @@ pub(super) fn parse_struct_fields(
fields.push(f);
}
self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore);
- self.eat(&token::Comma);
+ let _ = self.eat(&token::Comma);
}
}
}
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 523538e..9124c15 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -1,21 +1,19 @@
-use crate::errors::{
- self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
- UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
- WhereClauseBeforeTupleStructBodySugg,
-};
-
-use super::{ForceCollect, Parser};
-
use ast::token::Delimiter;
-use rustc_ast::token;
use rustc_ast::{
- self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause,
+ self as ast, token, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause,
};
use rustc_errors::{Applicability, PResult};
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
use thin_vec::ThinVec;
+use super::{ForceCollect, Parser};
+use crate::errors::{
+ self, MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
+ UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
+ WhereClauseBeforeTupleStructBodySugg,
+};
+
enum PredicateOrStructBody {
Predicate(ast::WherePredicate),
StructBody(ThinVec<ast::FieldDef>),
@@ -180,7 +178,8 @@ pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec<ast::Generi
span: this.prev_token.span,
});
- this.eat(&token::Comma);
+ // Eat a trailing comma, if it exists.
+ let _ = this.eat(&token::Comma);
}
let param = if this.check_lifetime() {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 112855e..8775d79 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1,9 +1,6 @@
-use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
-use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing};
-use crate::errors::{self, MacroExpandsToAdtField};
-use crate::fluent_generated as fluent;
-use crate::maybe_whole;
+use std::fmt::Write;
+use std::mem;
+
use ast::token::IdentIsRaw;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
@@ -12,18 +9,21 @@
use rustc_ast::util::case::Case;
use rustc_ast::{self as ast};
use rustc_ast_pretty::pprust;
-use rustc_errors::{codes::*, struct_span_code_err, Applicability, PResult, StashKey};
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, Applicability, PResult, StashKey};
use rustc_span::edit_distance::edit_distance;
use rustc_span::edition::Edition;
-use rustc_span::source_map;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::ErrorGuaranteed;
-use rustc_span::{Span, DUMMY_SP};
-use std::fmt::Write;
-use std::mem;
+use rustc_span::{source_map, ErrorGuaranteed, Span, DUMMY_SP};
use thin_vec::{thin_vec, ThinVec};
use tracing::debug;
+use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
+use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
+use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, Trailing};
+use crate::errors::{self, MacroExpandsToAdtField};
+use crate::{fluent_generated as fluent, maybe_whole};
+
impl<'a> Parser<'a> {
/// Parses a source module as a crate. This is the main entry point for the parser.
pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
@@ -471,9 +471,8 @@ fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> {
Err(mut err) => {
// Maybe the user misspelled `macro_rules` (issue #91227)
if self.token.is_ident()
- && path.segments.len() == 1
- && edit_distance("macro_rules", &path.segments[0].ident.to_string(), 2)
- .is_some()
+ && let [segment] = path.segments.as_slice()
+ && edit_distance("macro_rules", &segment.ident.to_string(), 2).is_some()
{
err.span_suggestion(
path.span,
@@ -1192,13 +1191,14 @@ fn parse_item_foreign_mod(
mut safety: Safety,
) -> PResult<'a, ItemInfo> {
let abi = self.parse_abi(); // ABI?
+ // FIXME: This recovery should be tested better.
if safety == Safety::Default
&& self.token.is_keyword(kw::Unsafe)
&& self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace))
{
self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit();
safety = Safety::Unsafe(self.token.span);
- self.eat_keyword(kw::Unsafe);
+ let _ = self.eat_keyword(kw::Unsafe);
}
let module = ast::ForeignMod {
safety,
@@ -1759,7 +1759,7 @@ pub(crate) fn parse_record_struct_body(
}
}
}
- self.eat(&token::CloseDelim(Delimiter::Brace));
+ self.expect(&token::CloseDelim(Delimiter::Brace))?;
} else {
let token_str = super::token_descr(&self.token);
let where_str = if parsed_where { "" } else { "`where`, or " };
@@ -1902,7 +1902,7 @@ fn parse_single_struct_field(
if let Some(_guar) = guar {
// Handle a case like `Vec<u8>>,` where we can continue parsing fields
// after the comma
- self.eat(&token::Comma);
+ let _ = self.eat(&token::Comma);
// `check_trailing_angle_brackets` already emitted a nicer error, as
// proven by the presence of `_guar`. We can continue parsing.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index e724086..9b3b6d5 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -10,18 +10,21 @@
mod stmt;
mod ty;
-use crate::lexer::UnmatchedDelim;
+use std::assert_matches::debug_assert_matches;
+use std::ops::Range;
+use std::{fmt, mem, slice};
+
use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
pub(crate) use expr::ForbiddenLetReason;
pub(crate) use item::FnParseMode;
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
use path::PathStyle;
-
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{AttrsTarget, DelimSpacing, DelimSpan, Spacing};
-use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
+use rustc_ast::tokenstream::{
+ AttrsTarget, DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree, TokenTreeCursor,
+};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, AnonConst, AttrArgs, AttrArgsEq, AttrId, ByRef, Const, CoroutineKind, DelimArgs,
@@ -35,14 +38,13 @@
use rustc_session::parse::ParseSess;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use std::ops::Range;
-use std::{fmt, mem, slice};
use thin_vec::ThinVec;
use tracing::debug;
use crate::errors::{
self, IncorrectVisibilityRestriction, MismatchedClosingDelimiter, NonStringAbiLiteral,
};
+use crate::lexer::UnmatchedDelim;
#[cfg(test)]
mod tests;
@@ -191,24 +193,54 @@ struct ClosureSpans {
body: Span,
}
-/// Indicates a range of tokens that should be replaced by
-/// the tokens in the provided `AttrsTarget`. This is used in two
-/// places during token collection:
+/// A token range within a `Parser`'s full token stream.
+#[derive(Clone, Debug)]
+struct ParserRange(Range<u32>);
+
+/// A token range within an individual AST node's (lazy) token stream, i.e.
+/// relative to that node's first token. Distinct from `ParserRange` so the two
+/// kinds of range can't be mixed up.
+#[derive(Clone, Debug)]
+struct NodeRange(Range<u32>);
+
+/// Indicates a range of tokens that should be replaced by an `AttrsTarget`
+/// (replacement) or be replaced by nothing (deletion). This is used in two
+/// places during token collection.
///
-/// 1. During the parsing of an AST node that may have a `#[derive]`
-/// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]`
-/// In this case, we use a `ReplaceRange` to replace the entire inner AST node
-/// with `FlatToken::AttrsTarget`, allowing us to perform eager cfg-expansion
-/// on an `AttrTokenStream`.
+/// 1. Replacement. During the parsing of an AST node that may have a
+/// `#[derive]` attribute, when we parse a nested AST node that has `#[cfg]`
+/// or `#[cfg_attr]`, we replace the entire inner AST node with
+/// `FlatToken::AttrsTarget`. This lets us perform eager cfg-expansion on an
+/// `AttrTokenStream`.
///
-/// 2. When we parse an inner attribute while collecting tokens. We
-/// remove inner attributes from the token stream entirely, and
-/// instead track them through the `attrs` field on the AST node.
-/// This allows us to easily manipulate them (for example, removing
-/// the first macro inner attribute to invoke a proc-macro).
-/// When create a `TokenStream`, the inner attributes get inserted
-/// into the proper place in the token stream.
-type ReplaceRange = (Range<u32>, Option<AttrsTarget>);
+/// 2. Deletion. We delete inner attributes from all collected token streams,
+/// and instead track them through the `attrs` field on the AST node. This
+/// lets us manipulate them similarly to outer attributes. When we create a
+/// `TokenStream`, the inner attributes are inserted into the proper place
+/// in the token stream.
+///
+/// Each replacement starts off in `ParserReplacement` form but is converted to
+/// `NodeReplacement` form when it is attached to a single AST node, via
+/// `LazyAttrTokenStreamImpl`.
+type ParserReplacement = (ParserRange, Option<AttrsTarget>);
+
+/// See the comment on `ParserReplacement`.
+type NodeReplacement = (NodeRange, Option<AttrsTarget>);
+
+impl NodeRange {
+ // Converts a range within a parser's tokens to a range within a
+ // node's tokens beginning at `start_pos`.
+ //
+ // For example, imagine a parser with 50 tokens in its token stream, a
+ // function that spans `ParserRange(20..40)` and an inner attribute within
+ // that function that spans `ParserRange(30..35)`. We would find the inner
+ // attribute's range within the function's tokens by subtracting 20, which
+ // is the position of the function's start token. This gives
+ // `NodeRange(10..15)`.
+ fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange {
+ NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos))
+ }
+}
/// Controls how we capture tokens. Capturing can be expensive,
/// so we try to avoid performing capturing in cases where
@@ -225,8 +257,8 @@ enum Capturing {
#[derive(Clone, Debug)]
struct CaptureState {
capturing: Capturing,
- replace_ranges: Vec<ReplaceRange>,
- inner_attr_ranges: FxHashMap<AttrId, Range<u32>>,
+ parser_replacements: Vec<ParserReplacement>,
+ inner_attr_parser_ranges: FxHashMap<AttrId, ParserRange>,
}
/// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
@@ -416,8 +448,8 @@ pub fn new(
subparser_name,
capture_state: CaptureState {
capturing: Capturing::No,
- replace_ranges: Vec::new(),
- inner_attr_ranges: Default::default(),
+ parser_replacements: Vec::new(),
+ inner_attr_parser_ranges: Default::default(),
},
current_closure: None,
recovery: Recovery::Allowed,
@@ -546,6 +578,7 @@ fn check(&mut self, tok: &TokenKind) -> bool {
}
#[inline]
+ #[must_use]
fn check_noexpect(&self, tok: &TokenKind) -> bool {
self.token == *tok
}
@@ -555,6 +588,7 @@ fn check_noexpect(&self, tok: &TokenKind) -> bool {
/// the main purpose of this function is to reduce the cluttering of the suggestions list
/// which using the normal eat method could introduce in some cases.
#[inline]
+ #[must_use]
fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
let is_present = self.check_noexpect(tok);
if is_present {
@@ -565,6 +599,7 @@ fn eat_noexpect(&mut self, tok: &TokenKind) -> bool {
/// Consumes a token 'tok' if it exists. Returns whether the given token was present.
#[inline]
+ #[must_use]
pub fn eat(&mut self, tok: &TokenKind) -> bool {
let is_present = self.check(tok);
if is_present {
@@ -576,12 +611,14 @@ pub fn eat(&mut self, tok: &TokenKind) -> bool {
/// If the next token is the given keyword, returns `true` without eating it.
/// An expectation is also added for diagnostics purposes.
#[inline]
+ #[must_use]
fn check_keyword(&mut self, kw: Symbol) -> bool {
self.expected_tokens.push(TokenType::Keyword(kw));
self.token.is_keyword(kw)
}
#[inline]
+ #[must_use]
fn check_keyword_case(&mut self, kw: Symbol, case: Case) -> bool {
if self.check_keyword(kw) {
return true;
@@ -601,6 +638,7 @@ fn check_keyword_case(&mut self, kw: Symbol, case: Case) -> bool {
/// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
// Public for rustc_builtin_macros and rustfmt usage.
#[inline]
+ #[must_use]
pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
if self.check_keyword(kw) {
self.bump();
@@ -614,6 +652,7 @@ pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
/// If the case differs (and is ignored) an error is issued.
/// This is useful for recovery.
#[inline]
+ #[must_use]
fn eat_keyword_case(&mut self, kw: Symbol, case: Case) -> bool {
if self.eat_keyword(kw) {
return true;
@@ -635,6 +674,7 @@ fn eat_keyword_case(&mut self, kw: Symbol, case: Case) -> bool {
/// Otherwise, returns `false`. No expectation is added.
// Public for rustc_builtin_macros usage.
#[inline]
+ #[must_use]
pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
if self.token.is_keyword(kw) {
self.bump();
@@ -647,7 +687,7 @@ pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
/// If the given word is not a keyword, signals an error.
/// If the next token is not the given word, signals an error.
/// Otherwise, eats it.
- fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> {
+ pub fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> {
if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) }
}
@@ -1024,8 +1064,11 @@ fn parse_seq_to_end<T>(
f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
) -> PResult<'a, (ThinVec<T>, Trailing)> {
let (val, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?;
- if matches!(recovered, Recovered::No) {
- self.eat(ket);
+ if matches!(recovered, Recovered::No) && !self.eat(ket) {
+ self.dcx().span_delayed_bug(
+ self.token.span,
+ "recovered but `parse_seq_to_before_end` did not give us the ket token",
+ );
}
Ok((val, trailing))
}
@@ -1124,10 +1167,12 @@ pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R
match self.token_cursor.tree_cursor.look_ahead(0) {
Some(tree) => {
// Indexing stayed within the current token tree.
- return match tree {
- TokenTree::Token(token, _) => looker(token),
- TokenTree::Delimited(dspan, _, delim, _) => {
- looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+ match tree {
+ TokenTree::Token(token, _) => return looker(token),
+ &TokenTree::Delimited(dspan, _, delim, _) => {
+ if delim != Delimiter::Invisible {
+ return looker(&Token::new(token::OpenDelim(delim), dspan.open));
+ }
}
};
}
@@ -1208,9 +1253,6 @@ fn parse_safety(&mut self, case: Case) -> Safety {
if self.eat_keyword_case(kw::Unsafe, case) {
Safety::Unsafe(self.prev_token.uninterpolated_span())
} else if self.eat_keyword_case(kw::Safe, case) {
- self.psess
- .gated_spans
- .gate(sym::unsafe_extern_blocks, self.prev_token.uninterpolated_span());
Safety::Safe(self.prev_token.uninterpolated_span())
} else {
Safety::Default
@@ -1249,7 +1291,7 @@ fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
if pat {
self.psess.gated_spans.gate(sym::inline_const_pat, span);
}
- self.eat_keyword(kw::Const);
+ self.expect_keyword(kw::Const)?;
let (attrs, blk) = self.parse_inner_attrs_and_block()?;
let anon_const = AnonConst {
id: DUMMY_NODE_ID,
@@ -1346,7 +1388,7 @@ pub fn parse_token_tree(&mut self) -> TokenTree {
// can capture these tokens if necessary.
self.bump();
if self.token_cursor.stack.len() == target_depth {
- debug_assert!(matches!(self.token.kind, token::CloseDelim(_)));
+ debug_assert_matches!(self.token.kind, token::CloseDelim(_));
break;
}
}
diff --git a/compiler/rustc_parse/src/parser/mut_visit/tests.rs b/compiler/rustc_parse/src/parser/mut_visit/tests.rs
index 677bcdf..b82c295 100644
--- a/compiler/rustc_parse/src/parser/mut_visit/tests.rs
+++ b/compiler/rustc_parse/src/parser/mut_visit/tests.rs
@@ -1,10 +1,11 @@
-use crate::parser::tests::{matches_codepattern, string_to_crate};
use rustc_ast as ast;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast_pretty::pprust;
use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::Ident;
+use crate::parser::tests::{matches_codepattern, string_to_crate};
+
// This version doesn't care about getting comments or doc-strings in.
fn print_crate_items(krate: &ast::Crate) -> String {
krate.items.iter().map(|i| pprust::item_to_string(i)).collect::<Vec<_>>().join(" ")
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 886d6af..999f6f0 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,7 +1,8 @@
use rustc_ast::ptr::P;
-use rustc_ast::token::{
- self, Delimiter, Nonterminal::*, NonterminalKind, NtExprKind::*, NtPatKind::*, Token,
-};
+use rustc_ast::token::Nonterminal::*;
+use rustc_ast::token::NtExprKind::*;
+use rustc_ast::token::NtPatKind::*;
+use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
use rustc_ast::HasTokens;
use rustc_ast_pretty::pprust;
use rustc_data_structures::sync::Lrc;
@@ -38,6 +39,7 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
}
match kind {
+ // `expr_2021` and earlier
NonterminalKind::Expr(Expr2021 { .. }) => {
token.can_begin_expr()
// This exception is here for backwards compatibility.
@@ -45,8 +47,16 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool {
// This exception is here for backwards compatibility.
&& !token.is_keyword(kw::Const)
}
+ // Current edition expressions
NonterminalKind::Expr(Expr) => {
- token.can_begin_expr()
+ // In Edition 2024, `_` is considered an expression, so we
+ // need to allow it here because `token.can_begin_expr()` does
+ // not consider `_` to be an expression.
+ //
+ // Because `can_begin_expr` is used elsewhere, we need to reduce
+ // the scope of where the `_` is considered an expression to
+ // just macro parsing code.
+ (token.can_begin_expr() || token.is_keyword(kw::Underscore))
// This exception is here for backwards compatibility.
&& !token.is_keyword(kw::Let)
}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index aa81887..5bfb8bd 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,17 +1,3 @@
-use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing};
-use crate::errors::{
- self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
- DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
- ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
- InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
- ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern,
- SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
- TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern,
- UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
- UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
-};
-use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr};
-use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_ast::mut_visit::{walk_pat, MutVisitor};
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
@@ -27,6 +13,21 @@
use rustc_span::{BytePos, ErrorGuaranteed, Span};
use thin_vec::{thin_vec, ThinVec};
+use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing};
+use crate::errors::{
+ self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
+ DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
+ ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
+ InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
+ ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern,
+ SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
+ TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern,
+ UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
+ UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
+};
+use crate::parser::expr::could_be_unclosed_char_literal;
+use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
+
#[derive(PartialEq, Copy, Clone)]
pub enum Expected {
ParameterName,
@@ -402,8 +403,9 @@ fn maybe_recover_trailing_expr(
// Parse an associative expression such as `+ expr`, `% expr`, ...
// Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
- let lhs = LhsExpr::Parsed { expr, starts_statement: false };
- if let Ok(expr) = snapshot.parse_expr_assoc_with(0, lhs).map_err(|err| err.cancel()) {
+ if let Ok(expr) =
+ snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
+ {
// We got a valid expression.
self.restore_snapshot(snapshot);
self.restrictions.remove(Restrictions::IS_PAT);
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index b9014de..6f82d6b 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -1,8 +1,5 @@
-use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{Parser, Restrictions, TokenType};
-use crate::errors::PathSingleColon;
-use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::{errors, maybe_whole};
+use std::mem;
+
use ast::token::IdentIsRaw;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
@@ -14,10 +11,15 @@
use rustc_errors::{Applicability, Diag, PResult};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span};
-use std::mem;
use thin_vec::ThinVec;
use tracing::debug;
+use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
+use super::{Parser, Restrictions, TokenType};
+use crate::errors::PathSingleColon;
+use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
+use crate::{errors, maybe_whole};
+
/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
pub(super) enum PathStyle {
@@ -311,7 +313,8 @@ pub(super) fn parse_path_segment(
}
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
- self.eat(&token::PathSep);
+ // First, eat `::` if it exists.
+ let _ = self.eat(&token::PathSep);
let lo = self.token.span;
let args = if self.eat_lt() {
// `<'a, T, A = U>`
@@ -823,7 +826,8 @@ pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool
// We can only resolve single-segment paths at the moment, because multi-segment paths
// require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
ast::ExprKind::Path(None, path)
- if path.segments.len() == 1 && path.segments[0].args.is_none() =>
+ if let [segment] = path.segments.as_slice()
+ && segment.args.is_none() =>
{
true
}
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index d8de7c1..b206f13 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -1,31 +1,30 @@
-use super::attr::InnerAttrForbiddenReason;
-use super::diagnostics::AttemptLocalParseRecovery;
-use super::expr::LhsExpr;
-use super::pat::{PatternLocation, RecoverComma};
-use super::path::PathStyle;
-use super::{
- AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
-};
-use crate::errors;
-use crate::maybe_whole;
+use std::borrow::Cow;
+use std::mem;
-use crate::errors::MalformedLoopLabel;
use ast::Label;
use rustc_ast as ast;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, TokenKind};
use rustc_ast::util::classify::{self, TrailingBrace};
-use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle};
-use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Recovered, Stmt};
-use rustc_ast::{StmtKind, DUMMY_NODE_ID};
+use rustc_ast::{
+ AttrStyle, AttrVec, Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, LocalKind, MacCall,
+ MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind, DUMMY_NODE_ID,
+};
use rustc_errors::{Applicability, Diag, PResult};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, ErrorGuaranteed, Span};
-
-use std::borrow::Cow;
-use std::mem;
use thin_vec::{thin_vec, ThinVec};
+use super::attr::InnerAttrForbiddenReason;
+use super::diagnostics::AttemptLocalParseRecovery;
+use super::pat::{PatternLocation, RecoverComma};
+use super::path::PathStyle;
+use super::{
+ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
+};
+use crate::errors::MalformedLoopLabel;
+use crate::{errors, maybe_whole};
+
impl<'a> Parser<'a> {
/// Parses a statement. This stops just before trailing semicolons on everything but items.
/// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
@@ -66,7 +65,12 @@ pub fn parse_stmt_without_recovery(
}
Ok(Some(if self.token.is_keyword(kw::Let) {
- self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
+ self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
+ this.expect_keyword(kw::Let)?;
+ let local = this.parse_local(attrs)?;
+ let trailing = capture_semi && this.token.kind == token::Semi;
+ Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing))
+ })?
} else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() {
self.recover_stmt_local_after_let(
lo,
@@ -112,13 +116,12 @@ pub fn parse_stmt_without_recovery(
}
}
} else if let Some(item) = self.parse_item_common(
- attrs.clone(),
+ attrs.clone(), // FIXME: unwanted clone of attrs
false,
true,
FnParseMode { req_name: |_| true, req_body: true },
force_collect,
)? {
- // FIXME: Bad copy of attrs
self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
} else if self.eat(&token::Semi) {
// Do not attempt to parse an expression if we're done here.
@@ -173,7 +176,7 @@ fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a,
// Perform this outside of the `collect_tokens_trailing_token` closure,
// since our outer attributes do not apply to this part of the expression
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
- this.parse_expr_assoc_with(0, LhsExpr::Parsed { expr, starts_statement: true })
+ this.parse_expr_assoc_rest_with(0, true, expr)
})?;
Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr)))
} else {
@@ -206,8 +209,7 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
let e = self.maybe_recover_from_bad_qpath(e)?;
let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?;
- let e = self
- .parse_expr_assoc_with(0, LhsExpr::Parsed { expr: e, starts_statement: false })?;
+ let e = self.parse_expr_assoc_rest_with(0, false, e)?;
StmtKind::Expr(e)
};
Ok(self.mk_stmt(lo.to(hi), kind))
@@ -247,21 +249,6 @@ fn recover_stmt_local_after_let(
Ok(stmt)
}
- fn parse_local_mk(
- &mut self,
- lo: Span,
- attrs: AttrWrapper,
- capture_semi: bool,
- force_collect: ForceCollect,
- ) -> PResult<'a, Stmt> {
- self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
- this.expect_keyword(kw::Let)?;
- let local = this.parse_local(attrs)?;
- let trailing = capture_semi && this.token.kind == token::Semi;
- Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing))
- })
- }
-
/// Parses a local variable declaration.
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
let lo = self.prev_token.span;
@@ -421,10 +408,14 @@ fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> {
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
- // Recover `let x <op>= 1` as `let x = 1`
+ // Recover `let x <op>= 1` as `let x = 1` We must not use `+ BytePos(1)` here
+ // because `<op>` can be a multi-byte lookalike that was recovered, e.g. `➖=` (the
+ // `➖` is a U+2796 Heavy Minus Sign Unicode Character) that was recovered as a
+ // `-=`.
+ let extra_op_span = self.psess.source_map().start_point(self.token.span);
self.dcx().emit_err(errors::CompoundAssignmentExpressionInLet {
span: self.token.span,
- suggestion: self.token.span.with_hi(self.token.span.lo() + BytePos(1)),
+ suggestion: extra_op_span,
});
self.bump();
true
@@ -685,7 +676,7 @@ pub fn parse_full_stmt(
match &expr.kind {
ExprKind::Path(None, ast::Path { segments, .. })
- if segments.len() == 1 =>
+ if let [segment] = segments.as_slice() =>
{
if self.token == token::Colon
&& self.look_ahead(1, |token| {
@@ -702,8 +693,8 @@ pub fn parse_full_stmt(
let snapshot = self.create_snapshot_for_diagnostic();
let label = Label {
ident: Ident::from_str_and_span(
- &format!("'{}", segments[0].ident),
- segments[0].ident.span,
+ &format!("'{}", segment.ident),
+ segment.ident.span,
),
};
match self.parse_expr_labeled(label, false) {
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 491aa71..cb8e8d3 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -1,30 +1,28 @@
-use crate::parser::ForceCollect;
-use crate::{
- new_parser_from_source_str, parser::Parser, source_str_to_stream, unwrap_or_emit_fatal,
-};
+use std::assert_matches::assert_matches;
+use std::io::prelude::*;
+use std::iter::Peekable;
+use std::path::{Path, PathBuf};
+use std::sync::{Arc, Mutex};
+use std::{io, str};
+
use ast::token::IdentIsRaw;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
-use rustc_ast::visit;
-use rustc_ast::{self as ast, PatKind};
+use rustc_ast::{self as ast, visit, PatKind};
use rustc_ast_pretty::pprust::item_to_string;
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::HumanEmitter;
use rustc_errors::{DiagCtxt, MultiSpan, PResult};
use rustc_session::parse::ParseSess;
-use rustc_span::create_default_session_globals_then;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{BytePos, FileName, Pos, Span};
-use std::io;
-use std::io::prelude::*;
-use std::iter::Peekable;
-use std::path::{Path, PathBuf};
-use std::str;
-use std::sync::{Arc, Mutex};
+use rustc_span::{create_default_session_globals_then, BytePos, FileName, Pos, Span};
use termcolor::WriteColor;
+use crate::parser::{ForceCollect, Parser};
+use crate::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal};
+
fn psess() -> ParseSess {
ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE, crate::DEFAULT_LOCALE_RESOURCE])
}
@@ -1750,7 +1748,7 @@ fn out_of_line_mod() {
.unwrap();
let ast::ItemKind::Mod(_, mod_kind) = &item.kind else { panic!() };
- assert!(matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2));
+ assert_matches!(mod_kind, ast::ModKind::Loaded(items, ..) if items.len() == 2);
});
}
diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs
index 9be00a1..d518dfe 100644
--- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs
+++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs
@@ -1,8 +1,8 @@
-use crate::parser::tests::string_to_stream;
use rustc_ast::token::{self, IdentIsRaw};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
-use rustc_span::create_default_session_globals_then;
-use rustc_span::{BytePos, Span, Symbol};
+use rustc_span::{create_default_session_globals_then, BytePos, Span, Symbol};
+
+use crate::parser::tests::string_to_stream;
fn string_to_ts(string: &str) -> TokenStream {
string_to_stream(string.to_owned())
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index f95ecd2..352ddd9 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,13 +1,3 @@
-use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
-
-use crate::errors::{
- self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
- FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
- HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
- NestedCVariadicType, ReturnTypesUseThinArrow,
-};
-use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
-
use rustc_ast::ptr::P;
use rustc_ast::token::{self, BinOpToken, Delimiter, Token, TokenKind};
use rustc_ast::util::case::Case;
@@ -21,6 +11,15 @@
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use thin_vec::{thin_vec, ThinVec};
+use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
+use crate::errors::{
+ self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
+ FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
+ HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
+ NestedCVariadicType, ReturnTypesUseThinArrow,
+};
+use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
+
/// Signals whether parsing a type should allow `+`.
///
/// For example, let T be the type `impl Default + 'static`
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 3d5e637..a64c00f 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -1,7 +1,5 @@
//! Meta-syntax validation logic of attributes for post-expansion.
-use crate::{errors, parse_in};
-
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{
@@ -18,6 +16,8 @@
use rustc_session::parse::ParseSess;
use rustc_span::{sym, BytePos, Span, Symbol};
+use crate::{errors, parse_in};
+
pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
if attr.is_doc_comment() {
return;
@@ -26,76 +26,35 @@ pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
let attr_item = attr.get_normal_item();
- let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe);
-
- if features.unsafe_attributes {
- if is_unsafe_attr {
- if let ast::Safety::Default = attr_item.unsafety {
- let path_span = attr_item.path.span;
-
- // If the `attr_item`'s span is not from a macro, then just suggest
- // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
- // `unsafe(`, `)` right after and right before the opening and closing
- // square bracket respectively.
- let diag_span = if attr_item.span().can_be_used_for_suggestions() {
- attr_item.span()
- } else {
- attr.span
- .with_lo(attr.span.lo() + BytePos(2))
- .with_hi(attr.span.hi() - BytePos(1))
- };
-
- if attr.span.at_least_rust_2024() {
- psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
- span: path_span,
- suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
- left: diag_span.shrink_to_lo(),
- right: diag_span.shrink_to_hi(),
- },
- });
- } else {
- psess.buffer_lint(
- UNSAFE_ATTR_OUTSIDE_UNSAFE,
- path_span,
- ast::CRATE_NODE_ID,
- BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
- attribute_name_span: path_span,
- sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
- },
- );
- }
- }
- } else {
- if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
- psess.dcx().emit_err(errors::InvalidAttrUnsafe {
- span: unsafe_span,
- name: attr_item.path.clone(),
- });
- }
- }
- }
+ // All non-builtin attributes are considered safe
+ let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal);
+ check_attribute_safety(features, psess, safety, attr);
// Check input tokens for built-in and key-value attributes.
match attr_info {
// `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
match parse_meta(psess, attr) {
- Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, *name, *template),
+ // Don't check safety again, we just did that
+ Ok(meta) => check_builtin_meta_item(
+ features, psess, &meta, attr.style, *name, *template, false,
+ ),
Err(err) => {
err.emit();
}
}
}
- _ if let AttrArgs::Eq(..) = attr_item.args => {
- // All key-value attributes are restricted to meta-item syntax.
- match parse_meta(psess, attr) {
- Ok(_) => {}
- Err(err) => {
- err.emit();
+ _ => {
+ if let AttrArgs::Eq(..) = attr_item.args {
+ // All key-value attributes are restricted to meta-item syntax.
+ match parse_meta(psess, attr) {
+ Ok(_) => {}
+ Err(err) => {
+ err.emit();
+ }
}
}
}
- _ => {}
}
}
@@ -198,12 +157,85 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
}
}
+pub fn check_attribute_safety(
+ features: &Features,
+ psess: &ParseSess,
+ safety: AttributeSafety,
+ attr: &Attribute,
+) {
+ if !features.unsafe_attributes {
+ return;
+ }
+
+ let attr_item = attr.get_normal_item();
+
+ if safety == AttributeSafety::Unsafe {
+ if let ast::Safety::Default = attr_item.unsafety {
+ let path_span = attr_item.path.span;
+
+ // If the `attr_item`'s span is not from a macro, then just suggest
+ // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
+ // `unsafe(`, `)` right after and right before the opening and closing
+ // square bracket respectively.
+ let diag_span = if attr_item.span().can_be_used_for_suggestions() {
+ attr_item.span()
+ } else {
+ attr.span.with_lo(attr.span.lo() + BytePos(2)).with_hi(attr.span.hi() - BytePos(1))
+ };
+
+ if attr.span.at_least_rust_2024() {
+ psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
+ span: path_span,
+ suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
+ left: diag_span.shrink_to_lo(),
+ right: diag_span.shrink_to_hi(),
+ },
+ });
+ } else {
+ psess.buffer_lint(
+ UNSAFE_ATTR_OUTSIDE_UNSAFE,
+ path_span,
+ ast::CRATE_NODE_ID,
+ BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
+ attribute_name_span: path_span,
+ sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
+ },
+ );
+ }
+ }
+ } else {
+ if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
+ psess.dcx().emit_err(errors::InvalidAttrUnsafe {
+ span: unsafe_span,
+ name: attr_item.path.clone(),
+ });
+ }
+ }
+}
+
+// Called by `check_builtin_meta_item` and code that manually denies
+// `unsafe(...)` in `cfg`
+pub fn deny_builtin_meta_unsafety(features: &Features, psess: &ParseSess, meta: &MetaItem) {
+ // This only supports denying unsafety right now - making builtin attributes
+ // support unsafety will requite us to thread the actual `Attribute` through
+ // for the nice diagnostics.
+ if features.unsafe_attributes {
+ if let Safety::Unsafe(unsafe_span) = meta.unsafety {
+ psess
+ .dcx()
+ .emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() });
+ }
+ }
+}
+
pub fn check_builtin_meta_item(
+ features: &Features,
psess: &ParseSess,
meta: &MetaItem,
style: ast::AttrStyle,
name: Symbol,
template: AttributeTemplate,
+ deny_unsafety: bool,
) {
// Some special attributes like `cfg` must be checked
// before the generic check, so we skip them here.
@@ -212,6 +244,10 @@ pub fn check_builtin_meta_item(
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
emit_malformed_attribute(psess, style, meta.span, name, template);
}
+
+ if deny_unsafety {
+ deny_builtin_meta_unsafety(features, psess, meta);
+ }
}
fn emit_malformed_attribute(
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 7e22644..cb75815 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -15,16 +15,14 @@
)]
// tidy-alphabetical-end
+use std::{iter, str, string};
+
use rustc_lexer::unescape;
pub use Alignment::*;
pub use Count::*;
pub use Piece::*;
pub use Position::*;
-use std::iter;
-use std::str;
-use std::string;
-
// Note: copied from rustc_span
/// Range inside of a `Span` used for diagnostics when we only have access to relative positions.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index bfe0d54..0318d34 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -100,6 +100,10 @@
.label = labeled blocks cannot be `continue`'d
.block_label = labeled block the `continue` points to
+passes_coroutine_on_non_closure =
+ attribute should be applied to closures
+ .label = not a closure
+
passes_coverage_not_fn_or_closure =
attribute should be applied to a function definition or closure
.label = not a function or closure
@@ -219,6 +223,9 @@
.not_an_extern_crate_label = not an `extern crate` item
.note = read <https://doc.rust-lang.org/unstable-book/language-features/doc-masked.html> for more information
+passes_doc_rust_logo =
+ the `#[doc(rust_logo)]` attribute is used for Rust branding
+
passes_doc_test_literal = `#![doc(test(...)]` does not take a literal
passes_doc_test_takes_list =
@@ -542,6 +549,10 @@
*[unspecified] (unspecified--this is a compiler bug)
}
+passes_optimize_not_fn_or_closure =
+ attribute should be applied to function or closure
+ .label = not a function or closure
+
passes_outer_crate_level_attr =
crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
@@ -587,6 +598,9 @@
*[other] fields
}
+passes_repr_align_function =
+ `repr(align)` attributes on functions are unstable
+
passes_repr_conflicting =
conflicting representation hints
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e0cf65d..bd157d1 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -4,28 +4,29 @@
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::{errors, fluent_generated as fluent};
-use rustc_ast::{ast, AttrKind, AttrStyle, Attribute, LitKind};
-use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
+use std::cell::Cell;
+use std::collections::hash_map::Entry;
+
+use rustc_ast::{
+ ast, AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem,
+};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Applicability, IntoDiagArg, MultiSpan};
-use rustc_errors::{DiagCtxtHandle, StashKey};
+use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir::def_id::LocalModDefId;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{self as hir};
use rustc_hir::{
- self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
+ self as hir, self, FnSig, ForeignItem, HirId, Item, ItemKind, MethodKind, Safety, Target,
+ TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
};
-use rustc_hir::{MethodKind, Safety, Target};
use rustc_macros::LintDiagnostic;
-use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::query::Providers;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::{
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
@@ -37,10 +38,10 @@
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
use rustc_trait_selection::traits::ObligationCtxt;
-use std::cell::Cell;
-use std::collections::hash_map::Entry;
use tracing::debug;
+use crate::{errors, fluent_generated as fluent};
+
#[derive(LintDiagnostic)]
#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
struct DiagnosticOnUnimplementedOnlyForTraits;
@@ -115,132 +116,185 @@ fn check_attributes(
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs {
match attr.path().as_slice() {
- [sym::diagnostic, sym::do_not_recommend] => {
+ [sym::diagnostic, sym::do_not_recommend, ..] => {
self.check_do_not_recommend(attr.span, hir_id, target)
}
- [sym::diagnostic, sym::on_unimplemented] => {
+ [sym::diagnostic, sym::on_unimplemented, ..] => {
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
}
- [sym::inline] => self.check_inline(hir_id, attr, span, target),
- [sym::coverage] => self.check_coverage(attr, span, target),
- [sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target),
- [sym::marker] => self.check_marker(hir_id, attr, span, target),
- [sym::target_feature] => {
+ [sym::inline, ..] => self.check_inline(hir_id, attr, span, target),
+ [sym::coverage, ..] => self.check_coverage(attr, span, target),
+ [sym::optimize, ..] => self.check_optimize(hir_id, attr, target),
+ [sym::no_sanitize, ..] => self.check_no_sanitize(hir_id, attr, span, target),
+ [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
+ [sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
+ [sym::target_feature, ..] => {
self.check_target_feature(hir_id, attr, span, target, attrs)
}
- [sym::thread_local] => self.check_thread_local(attr, span, target),
- [sym::track_caller] => {
+ [sym::thread_local, ..] => self.check_thread_local(attr, span, target),
+ [sym::track_caller, ..] => {
self.check_track_caller(hir_id, attr.span, attrs, span, target)
}
- [sym::doc] => self.check_doc_attrs(
+ [sym::doc, ..] => self.check_doc_attrs(
attr,
hir_id,
target,
&mut specified_inline,
&mut doc_aliases,
),
- [sym::no_link] => self.check_no_link(hir_id, attr, span, target),
- [sym::export_name] => self.check_export_name(hir_id, attr, span, target),
- [sym::rustc_layout_scalar_valid_range_start]
- | [sym::rustc_layout_scalar_valid_range_end] => {
+ [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target),
+ [sym::export_name, ..] => self.check_export_name(hir_id, attr, span, target),
+ [sym::rustc_layout_scalar_valid_range_start, ..]
+ | [sym::rustc_layout_scalar_valid_range_end, ..] => {
self.check_rustc_layout_scalar_valid_range(attr, span, target)
}
- [sym::allow_internal_unstable] => {
+ [sym::allow_internal_unstable, ..] => {
self.check_allow_internal_unstable(hir_id, attr, span, target, attrs)
}
- [sym::debugger_visualizer] => self.check_debugger_visualizer(attr, target),
- [sym::rustc_allow_const_fn_unstable] => {
+ [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target),
+ [sym::rustc_allow_const_fn_unstable, ..] => {
self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target)
}
- [sym::rustc_std_internal_symbol] => {
+ [sym::rustc_std_internal_symbol, ..] => {
self.check_rustc_std_internal_symbol(attr, span, target)
}
- [sym::naked] => self.check_naked(hir_id, attr, span, target, attrs),
- [sym::rustc_never_returns_null_ptr] => {
+ [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs),
+ [sym::rustc_never_returns_null_ptr, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
- [sym::rustc_legacy_const_generics] => {
+ [sym::rustc_legacy_const_generics, ..] => {
self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item)
}
- [sym::rustc_lint_query_instability] => {
+ [sym::rustc_lint_query_instability, ..] => {
self.check_rustc_lint_query_instability(hir_id, attr, span, target)
}
- [sym::rustc_lint_diagnostics] => {
+ [sym::rustc_lint_diagnostics, ..] => {
self.check_rustc_lint_diagnostics(hir_id, attr, span, target)
}
- [sym::rustc_lint_opt_ty] => self.check_rustc_lint_opt_ty(attr, span, target),
- [sym::rustc_lint_opt_deny_field_access] => {
+ [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target),
+ [sym::rustc_lint_opt_deny_field_access, ..] => {
self.check_rustc_lint_opt_deny_field_access(attr, span, target)
}
- [sym::rustc_clean]
- | [sym::rustc_dirty]
- | [sym::rustc_if_this_changed]
- | [sym::rustc_then_this_would_need] => self.check_rustc_dirty_clean(attr),
- [sym::rustc_coinductive]
- | [sym::rustc_must_implement_one_of]
- | [sym::rustc_deny_explicit_impl]
- | [sym::const_trait] => self.check_must_be_applied_to_trait(attr, span, target),
- [sym::cmse_nonsecure_entry] => {
+ [sym::rustc_clean, ..]
+ | [sym::rustc_dirty, ..]
+ | [sym::rustc_if_this_changed, ..]
+ | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr),
+ [sym::rustc_coinductive, ..]
+ | [sym::rustc_must_implement_one_of, ..]
+ | [sym::rustc_deny_explicit_impl, ..]
+ | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
+ [sym::cmse_nonsecure_entry, ..] => {
self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
}
- [sym::collapse_debuginfo] => self.check_collapse_debuginfo(attr, span, target),
- [sym::must_not_suspend] => self.check_must_not_suspend(attr, span, target),
- [sym::must_use] => self.check_must_use(hir_id, attr, target),
- [sym::rustc_pass_by_value] => self.check_pass_by_value(attr, span, target),
- [sym::rustc_allow_incoherent_impl] => {
+ [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
+ [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
+ [sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
+ [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
+ [sym::rustc_allow_incoherent_impl, ..] => {
self.check_allow_incoherent_impl(attr, span, target)
}
- [sym::rustc_has_incoherent_inherent_impls] => {
+ [sym::rustc_has_incoherent_inherent_impls, ..] => {
self.check_has_incoherent_inherent_impls(attr, span, target)
}
- [sym::ffi_pure] => self.check_ffi_pure(attr.span, attrs, target),
- [sym::ffi_const] => self.check_ffi_const(attr.span, target),
- [sym::rustc_const_unstable]
- | [sym::rustc_const_stable]
- | [sym::unstable]
- | [sym::stable]
- | [sym::rustc_allowed_through_unstable_modules]
- | [sym::rustc_promotable] => self.check_stability_promotable(attr, target),
- [sym::link_ordinal] => self.check_link_ordinal(attr, span, target),
- [sym::rustc_confusables] => self.check_confusables(attr, target),
- [sym::rustc_safe_intrinsic] => {
+ [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span, attrs, target),
+ [sym::ffi_const, ..] => self.check_ffi_const(attr.span, target),
+ [sym::rustc_const_unstable, ..]
+ | [sym::rustc_const_stable, ..]
+ | [sym::unstable, ..]
+ | [sym::stable, ..]
+ | [sym::rustc_allowed_through_unstable_modules, ..]
+ | [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target),
+ [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
+ [sym::rustc_confusables, ..] => self.check_confusables(attr, target),
+ [sym::rustc_safe_intrinsic, ..] => {
self.check_rustc_safe_intrinsic(hir_id, attr, span, target)
}
- _ => true,
- };
-
- // lint-only checks
- match attr.name_or_empty() {
- sym::cold => self.check_cold(hir_id, attr, span, target),
- sym::link => self.check_link(hir_id, attr, span, target),
- sym::link_name => self.check_link_name(hir_id, attr, span, target),
- sym::link_section => self.check_link_section(hir_id, attr, span, target),
- sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
- sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
- sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
- sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod),
- sym::macro_export => self.check_macro_export(hir_id, attr, target),
- sym::ignore | sym::should_panic => {
+ [sym::cold, ..] => self.check_cold(hir_id, attr, span, target),
+ [sym::link, ..] => self.check_link(hir_id, attr, span, target),
+ [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target),
+ [sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target),
+ [sym::no_mangle, ..] => self.check_no_mangle(hir_id, attr, span, target),
+ [sym::deprecated, ..] => self.check_deprecated(hir_id, attr, span, target),
+ [sym::macro_use, ..] | [sym::macro_escape, ..] => {
+ self.check_macro_use(hir_id, attr, target)
+ }
+ [sym::path, ..] => self.check_generic_attr(hir_id, attr, target, Target::Mod),
+ [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
+ [sym::ignore, ..] | [sym::should_panic, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
}
- sym::automatically_derived => {
+ [sym::automatically_derived, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Impl)
}
- sym::no_implicit_prelude => {
+ [sym::no_implicit_prelude, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Mod)
}
- sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
- sym::proc_macro => {
+ [sym::rustc_object_lifetime_default, ..] => self.check_object_lifetime_default(hir_id),
+ [sym::proc_macro, ..] => {
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
}
- sym::proc_macro_attribute => {
+ [sym::proc_macro_attribute, ..] => {
self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
}
- sym::proc_macro_derive => {
+ [sym::proc_macro_derive, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Fn);
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
}
- _ => {}
+ [sym::coroutine, ..] => {
+ self.check_coroutine(attr, target);
+ }
+ [
+ // ok
+ sym::allow
+ | sym::expect
+ | sym::warn
+ | sym::deny
+ | sym::forbid
+ | sym::cfg
+ | sym::cfg_attr
+ // need to be fixed
+ | sym::cfi_encoding // FIXME(cfi_encoding)
+ | sym::may_dangle // FIXME(dropck_eyepatch)
+ | sym::pointee // FIXME(derive_smart_pointer)
+ | sym::linkage // FIXME(linkage)
+ | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
+ | sym::used // handled elsewhere to restrict to static items
+ | sym::repr // handled elsewhere to restrict to type decls items
+ | sym::instruction_set // broken on stable!!!
+ | sym::windows_subsystem // broken on stable!!!
+ | sym::patchable_function_entry // FIXME(patchable_function_entry)
+ | sym::deprecated_safe // FIXME(deprecated_safe)
+ // internal
+ | sym::prelude_import
+ | sym::panic_handler
+ | sym::allow_internal_unsafe
+ | sym::fundamental
+ | sym::lang
+ | sym::needs_allocator
+ | sym::default_lib_allocator
+ | sym::start
+ | sym::custom_mir,
+ ..
+ ] => {}
+ [name, ..] => {
+ match BUILTIN_ATTRIBUTE_MAP.get(name) {
+ // checked below
+ Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {}
+ Some(_) => {
+ // FIXME: differentiate between unstable and internal attributes just
+ // like we do with features instead of just accepting `rustc_`
+ // attributes by name. That should allow trimming the above list, too.
+ if !name.as_str().starts_with("rustc_") {
+ span_bug!(
+ attr.span,
+ "builtin attribute {name:?} not handled by `CheckAttrVisitor`"
+ )
+ }
+ }
+ None => (),
+ }
+ }
+ [] => unreachable!(),
}
let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
@@ -296,7 +350,7 @@ fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr: &Attribut
}
/// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
- fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) -> bool {
+ fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) {
if !matches!(target, Target::Impl) {
self.tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
@@ -305,16 +359,10 @@ fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target)
errors::IncorrectDoNotRecommendLocation,
);
}
- true
}
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
- fn check_diagnostic_on_unimplemented(
- &self,
- attr_span: Span,
- hir_id: HirId,
- target: Target,
- ) -> bool {
+ fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) {
if !matches!(target, Target::Trait) {
self.tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
@@ -323,72 +371,91 @@ fn check_diagnostic_on_unimplemented(
DiagnosticOnUnimplementedOnlyForTraits,
);
}
- true
}
- /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid.
- fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+ /// Checks if an `#[inline]` is applied to a function or a closure.
+ fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
Target::Fn
| Target::Closure
- | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+ | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredInlineAttrFnProto,
- );
- true
+ )
}
// FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with
// just a lint, because we previously erroneously allowed it and some crates used it
// accidentally, to be compatible with crates depending on them, we can't throw an
// error here.
- Target::AssocConst => {
- self.tcx.emit_node_span_lint(
- UNUSED_ATTRIBUTES,
- hir_id,
- attr.span,
- errors::IgnoredInlineAttrConstants,
- );
- true
- }
+ Target::AssocConst => self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::IgnoredInlineAttrConstants,
+ ),
// FIXME(#80564): Same for fields, arms, and macro defs
Target::Field | Target::Arm | Target::MacroDef => {
- self.inline_attr_str_error_with_macro_def(hir_id, attr, "inline");
- true
+ self.inline_attr_str_error_with_macro_def(hir_id, attr, "inline")
}
_ => {
self.dcx().emit_err(errors::InlineNotFnOrClosure {
attr_span: attr.span,
defn_span: span,
});
- false
}
}
}
/// Checks that `#[coverage(..)]` is applied to a function/closure/method,
/// or to an impl block or module.
- fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) {
match target {
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Impl
- | Target::Mod => true,
+ | Target::Mod => {}
_ => {
self.dcx().emit_err(errors::CoverageNotFnOrClosure {
attr_span: attr.span,
defn_span: span,
});
- false
}
}
}
+ /// Checks that `#[optimize(..)]` is applied to a function/closure/method,
+ /// or to an impl block or module.
+ // FIXME(#128488): this should probably be elevated to an error?
+ fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) {
+ match target {
+ Target::Fn
+ | Target::Closure
+ | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
+ | Target::Impl
+ | Target::Mod => {}
+
+ _ => {
+ self.tcx.emit_node_span_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::OptimizeNotFnOrClosure,
+ );
+ }
+ }
+ }
+
+ /// Checks that `#[no_sanitize(..)]` is applied to a function or method.
+ fn check_no_sanitize(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+ self.check_applied_to_fn_or_method(hir_id, attr, span, target)
+ }
+
fn check_generic_attr(
&self,
hir_id: HirId,
@@ -417,7 +484,7 @@ fn check_naked(
span: Span,
target: Target,
attrs: &[Attribute],
- ) -> bool {
+ ) {
// many attributes don't make sense in combination with #[naked].
// Notable attributes that are incompatible with `#[naked]` are:
//
@@ -460,6 +527,12 @@ fn check_naked(
Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
for other_attr in attrs {
+ // this covers "sugared doc comments" of the form `/// ...`
+ // it does not cover `#[doc = "..."]`, which is handled below
+ if other_attr.is_doc_comment() {
+ continue;
+ }
+
if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
span: other_attr.span,
@@ -467,19 +540,16 @@ fn check_naked(
attr: other_attr.name_or_empty(),
});
- return false;
+ return;
}
}
-
- true
}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[naked]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
- self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked");
- true
+ self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked")
}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
@@ -487,7 +557,6 @@ fn check_naked(
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
- false
}
}
}
@@ -499,17 +568,16 @@ fn check_cmse_nonsecure_entry(
attr: &Attribute,
span: Span,
target: Target,
- ) -> bool {
+ ) {
match target {
Target::Fn
- | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+ | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
attr_span: attr.span,
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
- false
}
}
}
@@ -535,19 +603,18 @@ fn check_object_lifetime_default(&self, hir_id: HirId) {
}
/// Checks if `#[collapse_debuginfo]` is applied to a macro.
- fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::MacroDef => true,
+ Target::MacroDef => {}
_ => {
self.tcx
.dcx()
.emit_err(errors::CollapseDebuginfo { attr_span: attr.span, defn_span: span });
- false
}
}
}
- /// Checks if a `#[track_caller]` is applied to a function. Returns `true` if valid.
+ /// Checks if a `#[track_caller]` is applied to a function.
fn check_track_caller(
&self,
hir_id: HirId,
@@ -555,7 +622,7 @@ fn check_track_caller(
attrs: &[Attribute],
span: Span,
target: Target,
- ) -> bool {
+ ) {
match target {
Target::Fn => {
// `#[track_caller]` is not valid on weak lang items because they are called via
@@ -571,12 +638,9 @@ fn check_track_caller(
name: lang_item,
sig_span: sig.span,
});
- false
- } else {
- true
}
}
- Target::Method(..) | Target::ForeignFn | Target::Closure => true,
+ Target::Method(..) | Target::ForeignFn | Target::Closure => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[track_caller]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
@@ -585,7 +649,6 @@ fn check_track_caller(
for attr in attrs {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "track_caller");
}
- true
}
_ => {
self.dcx().emit_err(errors::TrackedCallerWrongLocation {
@@ -593,62 +656,51 @@ fn check_track_caller(
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
- false
}
}
}
- /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid.
- fn check_non_exhaustive(
- &self,
- hir_id: HirId,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid.
+ fn check_non_exhaustive(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Struct | Target::Enum | Target::Variant => true,
+ Target::Struct | Target::Enum | Target::Variant => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[non_exhaustive]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "non_exhaustive");
- true
}
_ => {
self.dcx().emit_err(errors::NonExhaustiveWrongLocation {
attr_span: attr.span,
defn_span: span,
});
- false
}
}
}
- /// Checks if the `#[marker]` attribute on an `item` is valid. Returns `true` if valid.
- fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+ /// Checks if the `#[marker]` attribute on an `item` is valid.
+ fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Trait => true,
+ Target::Trait => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[marker]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "marker");
- true
}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait {
attr_span: attr.span,
defn_span: span,
});
- false
}
}
}
- /// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid.
+ /// Checks if the `#[target_feature]` attribute on `item` is valid.
fn check_target_feature(
&self,
hir_id: HirId,
@@ -656,7 +708,7 @@ fn check_target_feature(
span: Span,
target: Target,
attrs: &[Attribute],
- ) -> bool {
+ ) {
match target {
Target::Fn => {
// `#[target_feature]` is not allowed in lang items.
@@ -673,12 +725,9 @@ fn check_target_feature(
name: lang_item,
sig_span: sig.span,
});
- false
- } else {
- true
}
}
- Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+ Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
// FIXME: #[target_feature] was previously erroneously allowed on statements and some
// crates used this, so only emit a warning.
Target::Statement => {
@@ -688,7 +737,6 @@ fn check_target_feature(
attr.span,
errors::TargetFeatureOnStatement,
);
- true
}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[target_feature]` attribute with just a lint, because we previously
@@ -696,7 +744,6 @@ fn check_target_feature(
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
- true
}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
@@ -704,21 +751,19 @@ fn check_target_feature(
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
- false
}
}
}
- /// Checks if the `#[thread_local]` attribute on `item` is valid. Returns `true` if valid.
- fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ /// Checks if the `#[thread_local]` attribute on `item` is valid.
+ fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::ForeignStatic | Target::Static => true,
+ Target::ForeignStatic | Target::Static => {}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToStatic {
attr_span: attr.span,
defn_span: span,
});
- false
}
}
}
@@ -735,14 +780,14 @@ fn check_doc_alias_value(
target: Target,
is_list: bool,
aliases: &mut FxHashMap<String, Span>,
- ) -> bool {
+ ) {
let tcx = self.tcx;
let span = meta.name_value_literal_span().unwrap_or_else(|| meta.span());
let attr_str =
&format!("`#[doc(alias{})]`", if is_list { "(\"...\")" } else { " = \"...\"" });
if doc_alias == kw::Empty {
tcx.dcx().emit_err(errors::DocAliasEmpty { span, attr_str });
- return false;
+ return;
}
let doc_alias_str = doc_alias.as_str();
@@ -751,11 +796,11 @@ fn check_doc_alias_value(
.find(|&c| c == '"' || c == '\'' || (c.is_whitespace() && c != ' '))
{
tcx.dcx().emit_err(errors::DocAliasBadChar { span, attr_str, char_: c });
- return false;
+ return;
}
if doc_alias_str.starts_with(' ') || doc_alias_str.ends_with(' ') {
tcx.dcx().emit_err(errors::DocAliasStartEnd { span, attr_str });
- return false;
+ return;
}
let span = meta.span();
@@ -780,7 +825,7 @@ fn check_doc_alias_value(
}
}
// we check the validity of params elsewhere
- Target::Param => return false,
+ Target::Param => return,
Target::Expression
| Target::Statement
| Target::Arm
@@ -813,12 +858,12 @@ fn check_doc_alias_value(
| Target::ExprField => None,
} {
tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location });
- return false;
+ return;
}
let item_name = self.tcx.hir().name(hir_id);
if item_name == doc_alias {
tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str });
- return false;
+ return;
}
if let Err(entry) = aliases.try_insert(doc_alias_str.to_owned(), span) {
self.tcx.emit_node_span_lint(
@@ -828,7 +873,6 @@ fn check_doc_alias_value(
errors::DocAliasDuplicated { first_defn: *entry.entry.get() },
);
}
- true
}
fn check_doc_alias(
@@ -837,46 +881,39 @@ fn check_doc_alias(
hir_id: HirId,
target: Target,
aliases: &mut FxHashMap<String, Span>,
- ) -> bool {
+ ) {
if let Some(values) = meta.meta_item_list() {
- let mut errors = 0;
for v in values {
match v.lit() {
Some(l) => match l.kind {
LitKind::Str(s, _) => {
- if !self.check_doc_alias_value(v, s, hir_id, target, true, aliases) {
- errors += 1;
- }
+ self.check_doc_alias_value(v, s, hir_id, target, true, aliases);
}
_ => {
self.tcx
.dcx()
.emit_err(errors::DocAliasNotStringLiteral { span: v.span() });
- errors += 1;
}
},
None => {
self.tcx
.dcx()
.emit_err(errors::DocAliasNotStringLiteral { span: v.span() });
- errors += 1;
}
}
}
- errors == 0
} else if let Some(doc_alias) = meta.value_str() {
self.check_doc_alias_value(meta, doc_alias, hir_id, target, false, aliases)
} else {
self.dcx().emit_err(errors::DocAliasMalformed { span: meta.span() });
- false
}
}
- fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
+ fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) {
let doc_keyword = meta.value_str().unwrap_or(kw::Empty);
if doc_keyword == kw::Empty {
self.doc_attr_str_error(meta, "keyword");
- return false;
+ return;
}
let item_kind = match self.tcx.hir_node(hir_id) {
hir::Node::Item(item) => Some(&item.kind),
@@ -886,12 +923,12 @@ fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
Some(ItemKind::Mod(module)) => {
if !module.item_ids.is_empty() {
self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() });
- return false;
+ return;
}
}
_ => {
self.dcx().emit_err(errors::DocKeywordNotMod { span: meta.span() });
- return false;
+ return;
}
}
if !rustc_lexer::is_ident(doc_keyword.as_str()) {
@@ -899,12 +936,10 @@ fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
doc_keyword,
});
- return false;
}
- true
}
- fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
+ fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) {
let item_kind = match self.tcx.hir_node(hir_id) {
hir::Node::Item(item) => Some(&item.kind),
_ => None,
@@ -919,18 +954,15 @@ fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool
};
if !is_valid {
self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() });
- return false;
}
}
_ => {
self.dcx().emit_err(errors::DocKeywordOnlyImpl { span: meta.span() });
- return false;
}
}
- true
}
- /// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. Returns `true` if valid.
+ /// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes.
///
/// A doc inlining attribute is invalid if it is applied to a non-`use` item, or
/// if there are conflicting attributes for one item.
@@ -946,7 +978,7 @@ fn check_doc_inline(
hir_id: HirId,
target: Target,
specified_inline: &mut Option<(bool, Span)>,
- ) -> bool {
+ ) {
match target {
Target::Use | Target::ExternCrate => {
let do_inline = meta.name_or_empty() == sym::inline;
@@ -959,12 +991,9 @@ fn check_doc_inline(
fluent::passes_doc_inline_conflict_second,
);
self.dcx().emit_err(errors::DocKeywordConflict { spans });
- return false;
}
- true
} else {
*specified_inline = Some((do_inline, meta.span()));
- true
}
}
_ => {
@@ -978,7 +1007,6 @@ fn check_doc_inline(
.then(|| self.tcx.hir().span(hir_id)),
},
);
- false
}
}
}
@@ -989,7 +1017,7 @@ fn check_doc_masked(
meta: &NestedMetaItem,
hir_id: HirId,
target: Target,
- ) -> bool {
+ ) {
if target != Target::ExternCrate {
self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
@@ -1001,7 +1029,7 @@ fn check_doc_masked(
.then(|| self.tcx.hir().span(hir_id)),
},
);
- return false;
+ return;
}
if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() {
@@ -1015,10 +1043,7 @@ fn check_doc_masked(
.then(|| self.tcx.hir().span(hir_id)),
},
);
- return false;
}
-
- true
}
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
@@ -1063,8 +1088,7 @@ fn check_attr_crate_level(
/// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if
/// valid.
- fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
- let mut is_valid = true;
+ fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) {
if let Some(metas) = meta.meta_item_list() {
for i_meta in metas {
match (i_meta.name_or_empty(), i_meta.meta_item()) {
@@ -1078,7 +1102,6 @@ fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
path: rustc_ast_pretty::pprust::path_to_string(&m.path),
},
);
- is_valid = false;
}
(_, None) => {
self.tcx.emit_node_span_lint(
@@ -1087,7 +1110,6 @@ fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
i_meta.span(),
errors::DocTestLiteral,
);
- is_valid = false;
}
}
}
@@ -1098,34 +1120,28 @@ fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
meta.span(),
errors::DocTestTakesList,
);
- is_valid = false;
}
- is_valid
}
/// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes.
- /// Returns `true` if valid.
- fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
- if meta.meta_item_list().is_some() {
- true
- } else {
+ ///
+ fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) {
+ if meta.meta_item_list().is_none() {
self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
errors::DocCfgHideTakesList,
);
- false
}
}
- /// Runs various checks on `#[doc]` attributes. Returns `true` if valid.
+ /// Runs various checks on `#[doc]` attributes.
///
/// `specified_inline` should be initialized to `None` and kept for the scope
/// of one item. Read the documentation of [`check_doc_inline`] for more information.
///
/// [`check_doc_inline`]: Self::check_doc_inline
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn check_doc_attrs(
&self,
attr: &Attribute,
@@ -1133,34 +1149,35 @@ fn check_doc_attrs(
target: Target,
specified_inline: &mut Option<(bool, Span)>,
aliases: &mut FxHashMap<String, Span>,
- ) -> bool {
- let mut is_valid = true;
-
+ ) {
if let Some(mi) = attr.meta()
&& let Some(list) = mi.meta_item_list()
{
for meta in list {
if let Some(i_meta) = meta.meta_item() {
match i_meta.name_or_empty() {
- sym::alias
- if !self.check_attr_not_crate_level(meta, hir_id, "alias")
- || !self.check_doc_alias(meta, hir_id, target, aliases) =>
- {
- is_valid = false
+ sym::alias => {
+ if self.check_attr_not_crate_level(meta, hir_id, "alias") {
+ self.check_doc_alias(meta, hir_id, target, aliases);
+ }
}
- sym::keyword
- if !self.check_attr_not_crate_level(meta, hir_id, "keyword")
- || !self.check_doc_keyword(meta, hir_id) =>
- {
- is_valid = false
+ sym::keyword => {
+ if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
+ self.check_doc_keyword(meta, hir_id);
+ }
}
- sym::fake_variadic
- if !self.check_attr_not_crate_level(meta, hir_id, "fake_variadic")
- || !self.check_doc_fake_variadic(meta, hir_id) =>
- {
- is_valid = false
+ sym::fake_variadic => {
+ if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
+ self.check_doc_fake_variadic(meta, hir_id);
+ }
+ }
+
+ sym::test => {
+ if self.check_attr_crate_level(attr, meta, hir_id) {
+ self.check_test_attr(meta, hir_id);
+ }
}
sym::html_favicon_url
@@ -1168,78 +1185,46 @@ fn check_doc_attrs(
| sym::html_playground_url
| sym::issue_tracker_base_url
| sym::html_root_url
- | sym::html_no_source
- | sym::test
- | sym::rust_logo
- if !self.check_attr_crate_level(attr, meta, hir_id) =>
- {
- is_valid = false;
+ | sym::html_no_source => {
+ self.check_attr_crate_level(attr, meta, hir_id);
}
- sym::cfg_hide
- if !self.check_attr_crate_level(attr, meta, hir_id)
- || !self.check_doc_cfg_hide(meta, hir_id) =>
- {
- is_valid = false;
+ sym::cfg_hide => {
+ if self.check_attr_crate_level(attr, meta, hir_id) {
+ self.check_doc_cfg_hide(meta, hir_id);
+ }
}
- sym::inline | sym::no_inline
- if !self.check_doc_inline(
- attr,
- meta,
- hir_id,
- target,
- specified_inline,
- ) =>
- {
- is_valid = false;
+ sym::inline | sym::no_inline => {
+ self.check_doc_inline(attr, meta, hir_id, target, specified_inline)
}
- sym::masked if !self.check_doc_masked(attr, meta, hir_id, target) => {
- is_valid = false;
- }
+ sym::masked => self.check_doc_masked(attr, meta, hir_id, target),
// no_default_passes: deprecated
// passes: deprecated
// plugins: removed, but rustdoc warns about it itself
- sym::alias
- | sym::cfg
- | sym::cfg_hide
+ sym::cfg
| sym::hidden
- | sym::html_favicon_url
- | sym::html_logo_url
- | sym::html_no_source
- | sym::html_playground_url
- | sym::html_root_url
- | sym::inline
- | sym::issue_tracker_base_url
- | sym::keyword
- | sym::masked
| sym::no_default_passes
- | sym::no_inline
| sym::notable_trait
| sym::passes
- | sym::plugins
- | sym::fake_variadic => {}
+ | sym::plugins => {}
sym::rust_logo => {
- if !self.tcx.features().rustdoc_internals {
+ if self.check_attr_crate_level(attr, meta, hir_id)
+ && !self.tcx.features().rustdoc_internals
+ {
feature_err(
&self.tcx.sess,
sym::rustdoc_internals,
meta.span(),
- "the `#[doc(rust_logo)]` attribute is used for Rust branding",
+ fluent::passes_doc_rust_logo,
)
.emit();
}
}
- sym::test => {
- if !self.check_test_attr(meta, hir_id) {
- is_valid = false;
- }
- }
-
_ => {
let path = rustc_ast_pretty::pprust::path_to_string(&i_meta.path);
if i_meta.has_name(sym::spotlight) {
@@ -1281,7 +1266,6 @@ fn check_doc_attrs(
errors::DocTestUnknownAny { path },
);
}
- is_valid = false;
}
}
} else {
@@ -1291,79 +1275,60 @@ fn check_doc_attrs(
meta.span(),
errors::DocInvalid,
);
- is_valid = false;
}
}
}
-
- is_valid
}
/// Warns against some misuses of `#[pass_by_value]`
- fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Struct | Target::Enum | Target::TyAlias => true,
+ Target::Struct | Target::Enum | Target::TyAlias => {}
_ => {
self.dcx().emit_err(errors::PassByValue { attr_span: attr.span, span });
- false
}
}
}
- fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Method(MethodKind::Inherent) => true,
+ Target::Method(MethodKind::Inherent) => {}
_ => {
self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span: attr.span, span });
- false
}
}
}
- fn check_has_incoherent_inherent_impls(
- &self,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ fn check_has_incoherent_inherent_impls(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => {
- true
- }
+ Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => {}
_ => {
self.tcx
.dcx()
.emit_err(errors::HasIncoherentInherentImpl { attr_span: attr.span, span });
- false
}
}
}
- fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) -> bool {
+ fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) {
if target != Target::ForeignFn {
self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span });
- return false;
+ return;
}
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span });
- false
- } else {
- true
}
}
- fn check_ffi_const(&self, attr_span: Span, target: Target) -> bool {
- if target == Target::ForeignFn {
- true
- } else {
+ fn check_ffi_const(&self, attr_span: Span, target: Target) {
+ if target != Target::ForeignFn {
self.dcx().emit_err(errors::FfiConstInvalidTarget { attr_span });
- false
}
}
/// Warns against some misuses of `#[must_use]`
- fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
+ fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if !matches!(
target,
Target::Fn
@@ -1396,23 +1361,19 @@ fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> boo
errors::MustUseNoEffect { article, target },
);
}
-
- // For now, its always valid
- true
}
- /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid.
- fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ /// Checks if `#[must_not_suspend]` is applied to a function.
+ fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Struct | Target::Enum | Target::Union | Target::Trait => true,
+ Target::Struct | Target::Enum | Target::Union | Target::Trait => {}
_ => {
self.dcx().emit_err(errors::MustNotSuspend { attr_span: attr.span, span });
- false
}
}
}
- /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid.
+ /// Checks if `#[cold]` is applied to a non-function.
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {}
@@ -1488,21 +1449,19 @@ fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
}
}
- /// Checks if `#[no_link]` is applied to an `extern crate`. Returns `true` if valid.
- fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
+ /// Checks if `#[no_link]` is applied to an `extern crate`.
+ fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::ExternCrate => true,
+ Target::ExternCrate => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[no_link]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_link");
- true
}
_ => {
self.dcx().emit_err(errors::NoLink { attr_span: attr.span, span });
- false
}
}
}
@@ -1511,57 +1470,42 @@ fn is_impl_item(&self, hir_id: HirId) -> bool {
matches!(self.tcx.hir_node(hir_id), hir::Node::ImplItem(..))
}
- /// Checks if `#[export_name]` is applied to a function or static. Returns `true` if valid.
- fn check_export_name(
- &self,
- hir_id: HirId,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ /// Checks if `#[export_name]` is applied to a function or static.
+ fn check_export_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Static | Target::Fn => true,
- Target::Method(..) if self.is_impl_item(hir_id) => true,
+ Target::Static | Target::Fn => {}
+ Target::Method(..) if self.is_impl_item(hir_id) => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[export_name]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "export_name");
- true
}
_ => {
self.dcx().emit_err(errors::ExportName { attr_span: attr.span, span });
- false
}
}
}
- fn check_rustc_layout_scalar_valid_range(
- &self,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ fn check_rustc_layout_scalar_valid_range(&self, attr: &Attribute, span: Span, target: Target) {
if target != Target::Struct {
self.dcx().emit_err(errors::RustcLayoutScalarValidRangeNotStruct {
attr_span: attr.span,
span,
});
- return false;
+ return;
}
let Some(list) = attr.meta_item_list() else {
- return false;
+ return;
};
- if matches!(&list[..], &[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) {
- true
- } else {
+ if !matches!(&list[..], &[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Int(..), .. })])
+ {
self.tcx
.dcx()
.emit_err(errors::RustcLayoutScalarValidRangeArg { attr_span: attr.span });
- false
}
}
@@ -1573,7 +1517,7 @@ fn check_rustc_legacy_const_generics(
span: Span,
target: Target,
item: Option<ItemLike<'_>>,
- ) -> bool {
+ ) {
let is_function = matches!(target, Target::Fn);
if !is_function {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
@@ -1581,12 +1525,12 @@ fn check_rustc_legacy_const_generics(
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
- return false;
+ return;
}
let Some(list) = attr.meta_item_list() else {
// The attribute form is validated on AST.
- return false;
+ return;
};
let Some(ItemLike::Item(Item {
@@ -1604,7 +1548,7 @@ fn check_rustc_legacy_const_generics(
attr_span: attr.span,
param_span: param.span,
});
- return false;
+ return;
}
}
}
@@ -1614,7 +1558,7 @@ fn check_rustc_legacy_const_generics(
attr_span: attr.span,
generics_span: generics.span,
});
- return false;
+ return;
}
let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128;
@@ -1627,7 +1571,7 @@ fn check_rustc_legacy_const_generics(
span,
arg_count: arg_count as usize,
});
- return false;
+ return;
}
} else {
invalid_args.push(meta.span());
@@ -1636,9 +1580,6 @@ fn check_rustc_legacy_const_generics(
if !invalid_args.is_empty() {
self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexNegative { invalid_args });
- false
- } else {
- true
}
}
@@ -1650,7 +1591,7 @@ fn check_applied_to_fn_or_method(
attr: &Attribute,
span: Span,
target: Target,
- ) -> bool {
+ ) {
let is_function = matches!(target, Target::Fn | Target::Method(..));
if !is_function {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
@@ -1658,9 +1599,6 @@ fn check_applied_to_fn_or_method(
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
- false
- } else {
- true
}
}
@@ -1672,7 +1610,7 @@ fn check_rustc_lint_query_instability(
attr: &Attribute,
span: Span,
target: Target,
- ) -> bool {
+ ) {
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
@@ -1684,60 +1622,49 @@ fn check_rustc_lint_diagnostics(
attr: &Attribute,
span: Span,
target: Target,
- ) -> bool {
+ ) {
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
}
/// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
- fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Struct => true,
+ Target::Struct => {}
_ => {
self.dcx().emit_err(errors::RustcLintOptTy { attr_span: attr.span, span });
- false
}
}
}
/// Checks that the `#[rustc_lint_opt_deny_field_access]` attribute is only applied to a field.
- fn check_rustc_lint_opt_deny_field_access(
- &self,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ fn check_rustc_lint_opt_deny_field_access(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Field => true,
+ Target::Field => {}
_ => {
self.tcx
.dcx()
.emit_err(errors::RustcLintOptDenyFieldAccess { attr_span: attr.span, span });
- false
}
}
}
/// Checks that the dep-graph debugging attributes are only present when the query-dep-graph
/// option is passed to the compiler.
- fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool {
- if self.tcx.sess.opts.unstable_opts.query_dep_graph {
- true
- } else {
+ fn check_rustc_dirty_clean(&self, attr: &Attribute) {
+ if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
self.dcx().emit_err(errors::RustcDirtyClean { span: attr.span });
- false
}
}
/// Checks if the attribute is applied to a trait.
- fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+ fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Trait => true,
+ Target::Trait => {}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait {
attr_span: attr.span,
defn_span: span,
});
- false
}
}
}
@@ -1808,7 +1735,6 @@ fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
}
/// Checks if the `#[repr]` attributes on `item` are valid.
- #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn check_repr(
&self,
attrs: &[Attribute],
@@ -1865,7 +1791,7 @@ fn check_repr(
&self.tcx.sess,
sym::fn_align,
hint.span(),
- "`repr(align)` attributes on functions are unstable",
+ fluent::passes_repr_align_function,
)
.emit();
}
@@ -2035,43 +1961,38 @@ fn check_allow_internal_unstable(
span: Span,
target: Target,
attrs: &[Attribute],
- ) -> bool {
+ ) {
debug!("Checking target: {:?}", target);
match target {
Target::Fn => {
for attr in attrs {
if attr.is_proc_macro_attr() {
debug!("Is proc macro attr");
- return true;
+ return;
}
}
debug!("Is not proc macro attr");
- false
}
- Target::MacroDef => true,
+ Target::MacroDef => {}
// FIXME(#80564): We permit struct fields and match arms to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
- Target::Field | Target::Arm => {
- self.inline_attr_str_error_without_macro_def(
- hir_id,
- attr,
- "allow_internal_unstable",
- );
- true
- }
+ Target::Field | Target::Arm => self.inline_attr_str_error_without_macro_def(
+ hir_id,
+ attr,
+ "allow_internal_unstable",
+ ),
_ => {
self.tcx
.dcx()
.emit_err(errors::AllowInternalUnstable { attr_span: attr.span, span });
- false
}
}
}
/// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
- fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
+ fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) {
// Here we only check that the #[debugger_visualizer] attribute is attached
// to nothing other than a module. All other checks are done in the
// `debugger_visualizer` query where they need to be done for decoding
@@ -2080,11 +2001,8 @@ fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
Target::Mod => {}
_ => {
self.dcx().emit_err(errors::DebugVisualizerPlacement { span: attr.span });
- return false;
}
}
-
- true
}
/// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
@@ -2095,26 +2013,21 @@ fn check_rustc_allow_const_fn_unstable(
attr: &Attribute,
span: Span,
target: Target,
- ) -> bool {
+ ) {
match target {
Target::Fn | Target::Method(_)
- if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) =>
- {
- true
- }
+ if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) => {}
// FIXME(#80564): We permit struct fields and match arms to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
- self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable");
- true
+ self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable")
}
_ => {
self.tcx
.dcx()
.emit_err(errors::RustcAllowConstFnUnstable { attr_span: attr.span, span });
- false
}
}
}
@@ -2125,65 +2038,56 @@ fn check_rustc_safe_intrinsic(
attr: &Attribute,
span: Span,
target: Target,
- ) -> bool {
+ ) {
if let Target::ForeignFn = target
&& let hir::Node::Item(Item {
kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic, .. },
..
}) = self.tcx.parent_hir_node(hir_id)
{
- return true;
+ return;
}
self.dcx().emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span });
- false
}
- fn check_rustc_std_internal_symbol(
- &self,
- attr: &Attribute,
- span: Span,
- target: Target,
- ) -> bool {
+ fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
match target {
- Target::Fn | Target::Static => true,
+ Target::Fn | Target::Static => {}
_ => {
self.tcx
.dcx()
.emit_err(errors::RustcStdInternalSymbol { attr_span: attr.span, span });
- false
}
}
}
- fn check_stability_promotable(&self, attr: &Attribute, target: Target) -> bool {
+ fn check_stability_promotable(&self, attr: &Attribute, target: Target) {
match target {
Target::Expression => {
self.dcx().emit_err(errors::StabilityPromotable { attr_span: attr.span });
- false
}
- _ => true,
+ _ => {}
}
}
- fn check_link_ordinal(&self, attr: &Attribute, _span: Span, target: Target) -> bool {
+ fn check_link_ordinal(&self, attr: &Attribute, _span: Span, target: Target) {
match target {
- Target::ForeignFn | Target::ForeignStatic => true,
+ Target::ForeignFn | Target::ForeignStatic => {}
_ => {
self.dcx().emit_err(errors::LinkOrdinal { attr_span: attr.span });
- false
}
}
}
- fn check_confusables(&self, attr: &Attribute, target: Target) -> bool {
+ fn check_confusables(&self, attr: &Attribute, target: Target) {
match target {
Target::Method(MethodKind::Inherent) => {
let Some(meta) = attr.meta() else {
- return false;
+ return;
};
let ast::MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else {
- return false;
+ return;
};
let mut candidates = Vec::new();
@@ -2197,21 +2101,17 @@ fn check_confusables(&self, attr: &Attribute, target: Target) -> bool {
hi: meta.span().shrink_to_hi(),
},
});
- return false;
+ return;
};
candidates.push(meta_lit.symbol);
}
if candidates.is_empty() {
self.dcx().emit_err(errors::EmptyConfusables { span: attr.span });
- return false;
}
-
- true
}
_ => {
self.dcx().emit_err(errors::Confusables { attr_span: attr.span });
- false
}
}
}
@@ -2311,8 +2211,8 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
attr.name_or_empty(),
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
) && let Some(meta) = attr.meta_item_list()
- && meta.len() == 1
- && let Some(item) = meta[0].meta_item()
+ && let [meta] = meta.as_slice()
+ && let Some(item) = meta.meta_item()
&& let MetaItemKind::NameValue(_) = &item.kind
&& item.path == sym::reason
{
@@ -2438,6 +2338,15 @@ fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
self.abort.set(true);
}
}
+
+ fn check_coroutine(&self, attr: &Attribute, target: Target) {
+ match target {
+ Target::Closure => return,
+ _ => {
+ self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr.span });
+ }
+ }
+ }
}
impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 3f6eccb..be6449e 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -7,8 +7,6 @@
//! errors. We still look for those primitives in the MIR const-checker to ensure nothing slips
//! through, but errors for structured control flow in a `const` should be emitted here.
-use rustc_attr as attr;
-use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::hir::nested_filter;
@@ -17,6 +15,7 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
+use {rustc_attr as attr, rustc_hir as hir};
use crate::errors::SkippingConstChecks;
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 239bc8e..7ae5c90 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -3,6 +3,8 @@
// expectations such as `#[expect(unused)]` and `#[expect(dead_code)]` is live, and everything else
// is dead.
+use std::mem;
+
use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
use hir::ItemKind;
use rustc_data_structures::unord::UnordSet;
@@ -15,13 +17,12 @@
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::privacy::Level;
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, AssocItemContainer, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_session::lint::builtin::DEAD_CODE;
use rustc_span::symbol::{sym, Symbol};
use rustc_target::abi::FieldIdx;
-use std::mem;
use crate::errors::{
ChangeFields, IgnoredDerivedImpls, MultipleDeadCodes, ParentInfo, UselessAssignment,
@@ -43,79 +44,18 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
)
}
-struct Publicness {
- ty_is_public: bool,
- ty_and_all_fields_are_public: bool,
-}
-
-impl Publicness {
- fn new(ty_is_public: bool, ty_and_all_fields_are_public: bool) -> Self {
- Self { ty_is_public, ty_and_all_fields_are_public }
+fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool {
+ if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
+ && let Res::Def(def_kind, def_id) = path.res
+ && def_id.is_local()
+ && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
+ {
+ tcx.visibility(def_id).is_public()
+ } else {
+ true
}
}
-fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> {
- match ty.kind {
- TyKind::Path(hir::QPath::Resolved(_, path)) => {
- if let Res::Def(def_kind, def_id) = path.res
- && let Some(local_def_id) = def_id.as_local()
- {
- Some((local_def_id, def_kind))
- } else {
- None
- }
- }
- TyKind::Slice(ty) | TyKind::Array(ty, _) => adt_of(ty),
- TyKind::Ptr(ty) | TyKind::Ref(_, ty) => adt_of(ty.ty),
- _ => None,
- }
-}
-
-fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool {
- // treat PhantomData and positional ZST as public,
- // we don't want to lint types which only have them,
- // cause it's a common way to use such types to check things like well-formedness
- tcx.adt_def(id).all_fields().all(|field| {
- let field_type = tcx.type_of(field.did).instantiate_identity();
- if field_type.is_phantom_data() {
- return true;
- }
- let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
- if is_positional
- && tcx
- .layout_of(tcx.param_env(field.did).and(field_type))
- .map_or(true, |layout| layout.is_zst())
- {
- return true;
- }
- field.vis.is_public()
- })
-}
-
-/// check struct and its fields are public or not,
-/// for enum and union, just check they are public,
-/// and doesn't solve types like &T for now, just skip them
-fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness {
- if let Some((def_id, def_kind)) = adt_of(ty) {
- return match def_kind {
- DefKind::Enum | DefKind::Union => {
- let ty_is_public = tcx.visibility(def_id).is_public();
- Publicness::new(ty_is_public, ty_is_public)
- }
- DefKind::Struct => {
- let ty_is_public = tcx.visibility(def_id).is_public();
- Publicness::new(
- ty_is_public,
- ty_is_public && struct_all_fields_are_public(tcx, def_id),
- )
- }
- _ => Publicness::new(true, true),
- };
- }
-
- Publicness::new(true, true)
-}
-
/// Determine if a work from the worklist is coming from a `#[allow]`
/// or a `#[expect]` of `dead_code`
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -169,10 +109,7 @@ fn insert_def_id(&mut self, def_id: DefId) {
fn handle_res(&mut self, res: Res) {
match res {
- Res::Def(
- DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
- def_id,
- ) => {
+ Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
self.check_def_id(def_id);
}
_ if self.in_pat => {}
@@ -291,10 +228,7 @@ fn handle_field_pattern_match(
pats: &[hir::PatField<'_>],
) {
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
- ty::Adt(adt, _) => {
- self.check_def_id(adt.did());
- adt.variant_of_res(res)
- }
+ ty::Adt(adt, _) => adt.variant_of_res(res),
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
};
for pat in pats {
@@ -314,10 +248,7 @@ fn handle_tuple_field_pattern_match(
dotdot: hir::DotDotPos,
) {
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
- ty::Adt(adt, _) => {
- self.check_def_id(adt.did());
- adt.variant_of_res(res)
- }
+ ty::Adt(adt, _) => adt.variant_of_res(res),
_ => {
self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern");
return;
@@ -422,6 +353,31 @@ fn should_ignore_item(&mut self, def_id: DefId) -> bool {
return false;
}
+ // don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
+ // cause external crate may call such methods to construct values of these types
+ if let Some(local_impl_of) = impl_of.as_local()
+ && let Some(local_def_id) = def_id.as_local()
+ && let Some(fn_sig) =
+ self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
+ && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
+ && let TyKind::Path(hir::QPath::Resolved(_, path)) =
+ self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
+ && let Res::Def(def_kind, did) = path.res
+ {
+ match def_kind {
+ // for example, #[derive(Default)] pub struct T(i32);
+ // external crate can call T::default() to construct T,
+ // so that don't ignore impl Default for pub Enum and Structs
+ DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
+ return false;
+ }
+ // don't ignore impl Default for Enums,
+ // cause we don't know which variant is constructed
+ DefKind::Enum => return false,
+ _ => (),
+ };
+ }
+
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
{
@@ -464,7 +420,7 @@ fn visit_node(&mut self, node: Node<'tcx>) {
intravisit::walk_item(self, item)
}
hir::ItemKind::ForeignMod { .. } => {}
- hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => {
+ hir::ItemKind::Trait(..) => {
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
if let Some(local_def_id) = impl_def_id.as_local()
&& let ItemKind::Impl(impl_ref) =
@@ -477,12 +433,7 @@ fn visit_node(&mut self, node: Node<'tcx>) {
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
}
}
- // mark assoc ty live if the trait is live
- for trait_item in trait_item_refs {
- if let hir::AssocItemKind::Type = trait_item.kind {
- self.check_def_id(trait_item.id.owner_id.to_def_id());
- }
- }
+
intravisit::walk_item(self, item)
}
_ => intravisit::walk_item(self, item),
@@ -499,12 +450,11 @@ fn visit_node(&mut self, node: Node<'tcx>) {
&& let ItemKind::Impl(impl_ref) =
self.tcx.hir().expect_item(local_impl_id).kind
{
- if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
- .ty_and_all_fields_are_public
+ if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
+ && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
{
- // skip impl-items of non pure pub ty,
- // cause we don't know the ty is constructed or not,
- // check these later in `solve_rest_impl_items`
+ // skip methods of private ty,
+ // they would be solved in `solve_rest_impl_items`
continue;
}
@@ -579,25 +529,28 @@ fn solve_rest_impl_items(&mut self, mut unsolved_impl_items: Vec<(hir::ItemId, L
}
fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool {
- if let Some((local_def_id, def_kind)) =
- adt_of(self.tcx.hir().item(impl_id).expect_impl().self_ty)
+ if let TyKind::Path(hir::QPath::Resolved(_, path)) =
+ self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
+ && let Res::Def(def_kind, def_id) = path.res
+ && let Some(local_def_id) = def_id.as_local()
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
{
+ if self.tcx.visibility(impl_item_id).is_public() {
+ // for the public method, we don't know the trait item is used or not,
+ // so we mark the method live if the self is used
+ return self.live_symbols.contains(&local_def_id);
+ }
+
if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id
&& let Some(local_id) = trait_item_id.as_local()
{
- // for the local impl item, we can know the trait item is used or not,
+ // for the private method, we can know the trait item is used or not,
// so we mark the method live if the self is used and the trait item is used
- self.live_symbols.contains(&local_id) && self.live_symbols.contains(&local_def_id)
- } else {
- // for the foreign method and inherent pub method,
- // we don't know the trait item or the method is used or not,
- // so we mark the method live if the self is used
- self.live_symbols.contains(&local_def_id)
+ return self.live_symbols.contains(&local_id)
+ && self.live_symbols.contains(&local_def_id);
}
- } else {
- false
}
+ false
}
}
@@ -683,9 +636,6 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
self.handle_field_pattern_match(pat, res, fields);
}
PatKind::Path(ref qpath) => {
- if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() {
- self.check_def_id(adt.did());
- }
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
self.handle_res(res);
}
@@ -822,9 +772,7 @@ fn check_item<'tcx>(
.iter()
.filter_map(|def_id| def_id.as_local());
- let self_ty = tcx.hir().item(id).expect_impl().self_ty;
- let Publicness { ty_is_public, ty_and_all_fields_are_public } =
- ty_ref_to_pub_struct(tcx, self_ty);
+ let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
// And we access the Map here to get HirId from LocalDefId
for local_def_id in local_def_ids {
@@ -840,19 +788,18 @@ fn check_item<'tcx>(
// for trait impl blocks,
// mark the method live if the self_ty is public,
// or the method is public and may construct self
- if tcx.visibility(local_def_id).is_public()
- && (ty_and_all_fields_are_public || (ty_is_public && may_construct_self))
+ if of_trait
+ && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn)
+ || tcx.visibility(local_def_id).is_public()
+ && (ty_is_pub || may_construct_self))
{
- // if the impl item is public,
- // and the ty may be constructed or can be constructed in foreign crates,
- // mark the impl item live
worklist.push((local_def_id, ComesFromAllowExpect::No));
} else if let Some(comes_from_allow) =
has_allow_dead_code_or_lang_attr(tcx, local_def_id)
{
worklist.push((local_def_id, comes_from_allow));
- } else if of_trait || tcx.visibility(local_def_id).is_public() && ty_is_public {
- // private impl items of traits || public impl items not constructs self
+ } else if of_trait {
+ // private method || public method not constructs self
unsolved_impl_items.push((id, local_def_id));
}
}
@@ -878,13 +825,10 @@ fn check_trait_item(
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
id: hir::TraitItemId,
) {
- use hir::TraitItemKind::{Const, Fn, Type};
- if matches!(
- tcx.def_kind(id.owner_id),
- DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn
- ) {
+ use hir::TraitItemKind::{Const, Fn};
+ if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
let trait_item = tcx.hir().trait_item(id);
- if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..))
+ if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
&& let Some(comes_from_allow) =
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
{
@@ -922,14 +866,6 @@ fn create_and_seed_worklist(
effective_vis
.is_public_at_level(Level::Reachable)
.then_some(id)
- .filter(|&id|
- // checks impls, impl-items and pub structs with all public fields later
- match tcx.def_kind(id) {
- DefKind::Impl { .. } => false,
- DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
- DefKind::Struct => struct_all_fields_are_public(tcx, id) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
- _ => true
- })
.map(|id| (id, ComesFromAllowExpect::No))
})
// Seed entry point
@@ -1213,7 +1149,6 @@ fn check_definition(&mut self, def_id: LocalDefId) {
}
match self.tcx.def_kind(def_id) {
DefKind::AssocConst
- | DefKind::AssocTy
| DefKind::AssocFn
| DefKind::Fn
| DefKind::Static { .. }
@@ -1255,14 +1190,10 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
{
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
- // We have diagnosed unused assocs in traits
+ // We have diagnosed unused methods in traits
if matches!(def_kind, DefKind::Impl { of_trait: true })
- && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn)
- // skip unused public inherent methods,
- // cause we have diagnosed unconstructed struct
- || matches!(def_kind, DefKind::Impl { of_trait: false })
- && tcx.visibility(def_id).is_public()
- && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
+ && tcx.def_kind(def_id) == DefKind::AssocFn
+ || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn
{
continue;
}
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 96893e5..5d871ba 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -3,11 +3,9 @@
use rustc_ast::Attribute;
use rustc_data_structures::sync::Lrc;
use rustc_expand::base::resolve_path;
-use rustc_middle::{
- middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType},
- query::{LocalCrate, Providers},
- ty::TyCtxt,
-};
+use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
+use rustc_middle::query::{LocalCrate, Providers};
+use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::sym;
@@ -21,9 +19,7 @@ fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
return;
};
- let hint = if hints.len() == 1 {
- &hints[0]
- } else {
+ let [hint] = hints.as_slice() else {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
return;
};
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 906ecdf..659281c 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -12,8 +12,7 @@
use rustc_ast as ast;
use rustc_hir::diagnostic_items::DiagnosticItems;
use rustc_hir::OwnerId;
-use rustc_middle::query::LocalCrate;
-use rustc_middle::query::Providers;
+use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::{sym, Symbol};
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index b43c828..ecb345b 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -6,8 +6,8 @@
use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{sigpipe, CrateType, EntryFnType};
-use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
+use rustc_session::config::{sigpipe, CrateType, EntryFnType, RemapPathScopeComponents};
+use rustc_session::RemapFileNameExt;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
@@ -106,7 +106,6 @@ fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
}
}
-#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> {
if let Some((def_id, _)) = visitor.start_fn {
Some((def_id.to_def_id(), EntryFnType::Start))
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index b195ba9..36dfc40 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1,13 +1,11 @@
-use std::{
- io::Error,
- path::{Path, PathBuf},
-};
+use std::io::Error;
+use std::path::{Path, PathBuf};
-use crate::fluent_generated as fluent;
use rustc_ast::Label;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee,
- Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
+ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
+ MultiSpan, SubdiagMessageOp, Subdiagnostic,
};
use rustc_hir::{self as hir, ExprKind, Target};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -15,6 +13,7 @@
use rustc_span::{Span, Symbol, DUMMY_SP};
use crate::check_attr::ProcMacroKind;
+use crate::fluent_generated as fluent;
use crate::lang_items::Duplicate;
#[derive(LintDiagnostic)]
@@ -69,6 +68,10 @@ pub struct CoverageNotFnOrClosure {
pub defn_span: Span,
}
+#[derive(LintDiagnostic)]
+#[diag(passes_optimize_not_fn_or_closure)]
+pub struct OptimizeNotFnOrClosure;
+
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_fn)]
pub struct AttrShouldBeAppliedToFn {
@@ -634,6 +637,13 @@ pub struct Confusables {
}
#[derive(Diagnostic)]
+#[diag(passes_coroutine_on_non_closure)]
+pub struct CoroutineOnNonClosure {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
#[diag(passes_empty_confusables)]
pub(crate) struct EmptyConfusables {
#[primary_span]
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index fb7529d..38e8c3c 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -2,13 +2,11 @@
// pieces of AST and HIR. The resulting numbers are good approximations but not
// completely accurate (some things might be counted twice, others missed).
-use rustc_ast::visit as ast_visit;
use rustc_ast::visit::BoundKind;
-use rustc_ast::{self as ast, AttrId, NodeId};
+use rustc_ast::{self as ast, visit as ast_visit, AttrId, NodeId};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
-use rustc_hir::intravisit as hir_visit;
-use rustc_hir::HirId;
+use rustc_hir::{intravisit as hir_visit, HirId};
use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt;
use rustc_middle::util::common::to_readable_str;
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index b3722e9..3f1be87 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -7,23 +7,22 @@
//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
//! * Functions called by the compiler itself.
-use crate::errors::{
- DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem,
-};
-use crate::weak_lang_items;
-
use rustc_ast as ast;
use rustc_ast::visit;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::{extract, GenericRequirement};
use rustc_hir::{LangItem, LanguageItems, MethodKind, Target};
+use rustc_middle::query::Providers;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_session::cstore::ExternCrate;
use rustc_span::symbol::kw::Empty;
use rustc_span::Span;
-use rustc_middle::query::Providers;
+use crate::errors::{
+ DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem,
+};
+use crate::weak_lang_items;
pub(crate) enum Duplicate {
Plain,
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 6f59c78..e1bc770 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -9,7 +9,8 @@
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
-use rustc_trait_selection::{infer::TyCtxtInferExt, traits};
+use rustc_trait_selection::infer::TyCtxtInferExt;
+use rustc_trait_selection::traits;
use crate::errors::{
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index dfa7dfa..d3b85da 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -81,10 +81,9 @@
//! We generate various special nodes for various, well, special purposes.
//! These are described in the `Liveness` struct.
-use crate::errors;
-
-use self::LiveNodeKind::*;
-use self::VarKind::*;
+use std::io;
+use std::io::prelude::*;
+use std::rc::Rc;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
@@ -99,11 +98,12 @@
use rustc_session::lint;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{BytePos, Span};
-use std::io;
-use std::io::prelude::*;
-use std::rc::Rc;
use tracing::{debug, instrument};
+use self::LiveNodeKind::*;
+use self::VarKind::*;
+use crate::errors;
+
mod rwu_table;
rustc_index::newtype_index! {
diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs
index 053bf5c..6e2f976 100644
--- a/compiler/rustc_passes/src/liveness/rwu_table.rs
+++ b/compiler/rustc_passes/src/liveness/rwu_table.rs
@@ -1,6 +1,7 @@
-use crate::liveness::{LiveNode, Variable};
use std::iter;
+use crate::liveness::{LiveNode, Variable};
+
#[derive(Clone, Copy)]
pub(super) struct RWU {
pub(super) reader: bool,
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 2587a18..25115c5 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -1,6 +1,5 @@
use std::collections::BTreeMap;
use std::fmt;
-use Context::*;
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
@@ -13,6 +12,7 @@
use rustc_session::Session;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::{BytePos, Span};
+use Context::*;
use crate::errors::{
BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 2c34f47..4d58590 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1,7 +1,9 @@
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-use crate::errors;
+use std::mem::replace;
+use std::num::NonZero;
+
use rustc_attr::{
self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
Unstable, UnstableReason, VERSION_PLACEHOLDER,
@@ -25,10 +27,10 @@
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
-use std::mem::replace;
-use std::num::NonZero;
use tracing::{debug, info};
+use crate::errors;
+
#[derive(PartialEq)]
enum AnnotationKind {
/// Annotation is required if not inherited from unstable parents.
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index f3e8e54..3a2a75a 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -180,16 +180,14 @@
use std::fmt;
use std::iter::once;
-use smallvec::SmallVec;
-
use rustc_apfloat::ieee::{DoubleS, HalfS, IeeeFloat, QuadS, SingleS};
use rustc_index::bit_set::{BitSet, GrowableBitSet};
use rustc_index::IndexVec;
+use smallvec::SmallVec;
use self::Constructor::*;
use self::MaybeInfiniteInt::*;
use self::SliceKind::*;
-
use crate::PatCx;
/// Whether we have seen a constructor in the column or not.
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index 27f227e..1f7852e 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -1,6 +1,5 @@
use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::thir::Pat;
use rustc_middle::ty::Ty;
use rustc_span::Span;
@@ -8,18 +7,18 @@
#[derive(Subdiagnostic)]
#[label(pattern_analysis_uncovered)]
-pub struct Uncovered<'tcx> {
+pub struct Uncovered {
#[primary_span]
span: Span,
count: usize,
- witness_1: Pat<'tcx>,
- witness_2: Pat<'tcx>,
- witness_3: Pat<'tcx>,
+ witness_1: String, // a printed pattern
+ witness_2: String, // a printed pattern
+ witness_3: String, // a printed pattern
remainder: usize,
}
-impl<'tcx> Uncovered<'tcx> {
- pub fn new<'p>(
+impl Uncovered {
+ pub fn new<'p, 'tcx>(
span: Span,
cx: &RustcPatCtxt<'p, 'tcx>,
witnesses: Vec<WitnessPat<'p, 'tcx>>,
@@ -27,19 +26,13 @@ pub fn new<'p>(
where
'tcx: 'p,
{
- let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap());
+ let witness_1 = cx.print_witness_pat(witnesses.get(0).unwrap());
Self {
span,
count: witnesses.len(),
// Substitute dummy values if witnesses is smaller than 3. These will never be read.
- witness_2: witnesses
- .get(1)
- .map(|w| cx.hoist_witness_pat(w))
- .unwrap_or_else(|| witness_1.clone()),
- witness_3: witnesses
- .get(2)
- .map(|w| cx.hoist_witness_pat(w))
- .unwrap_or_else(|| witness_1.clone()),
+ witness_2: witnesses.get(1).map(|w| cx.print_witness_pat(w)).unwrap_or_default(),
+ witness_3: witnesses.get(2).map(|w| cx.print_witness_pat(w)).unwrap_or_default(),
witness_1,
remainder: witnesses.len().saturating_sub(3),
}
@@ -49,19 +42,19 @@ pub fn new<'p>(
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_overlapping_range_endpoints)]
#[note]
-pub struct OverlappingRangeEndpoints<'tcx> {
+pub struct OverlappingRangeEndpoints {
#[label]
pub range: Span,
#[subdiagnostic]
- pub overlap: Vec<Overlap<'tcx>>,
+ pub overlap: Vec<Overlap>,
}
-pub struct Overlap<'tcx> {
+pub struct Overlap {
pub span: Span,
- pub range: Pat<'tcx>,
+ pub range: String, // a printed pattern
}
-impl<'tcx> Subdiagnostic for Overlap<'tcx> {
+impl Subdiagnostic for Overlap {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
@@ -78,38 +71,38 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_excluside_range_missing_max)]
-pub struct ExclusiveRangeMissingMax<'tcx> {
+pub struct ExclusiveRangeMissingMax {
#[label]
#[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
/// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`).
pub first_range: Span,
/// Suggest `lo..=max` instead.
pub suggestion: String,
- pub max: Pat<'tcx>,
+ pub max: String, // a printed pattern
}
#[derive(LintDiagnostic)]
#[diag(pattern_analysis_excluside_range_missing_gap)]
-pub struct ExclusiveRangeMissingGap<'tcx> {
+pub struct ExclusiveRangeMissingGap {
#[label]
#[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
/// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`).
pub first_range: Span,
- pub gap: Pat<'tcx>,
+ pub gap: String, // a printed pattern
/// Suggest `lo..=gap` instead.
pub suggestion: String,
#[subdiagnostic]
/// All these ranges skipped over `gap` which we think is probably a mistake.
- pub gap_with: Vec<GappedRange<'tcx>>,
+ pub gap_with: Vec<GappedRange>,
}
-pub struct GappedRange<'tcx> {
+pub struct GappedRange {
pub span: Span,
- pub gap: Pat<'tcx>,
- pub first_range: Pat<'tcx>,
+ pub gap: String, // a printed pattern
+ pub first_range: String, // a printed pattern
}
-impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
+impl Subdiagnostic for GappedRange {
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
self,
diag: &mut Diag<'_, G>,
@@ -134,7 +127,7 @@ fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
pub scrut_ty: Ty<'tcx>,
#[subdiagnostic]
- pub uncovered: Uncovered<'tcx>,
+ pub uncovered: Uncovered,
}
#[derive(LintDiagnostic)]
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index a5c0b13..6c9c848 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -5,6 +5,7 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(feature = "rustc", feature(let_chains))]
// tidy-alphabetical-end
pub mod constructor;
@@ -54,7 +55,6 @@ pub trait PatCx: Sized + fmt::Debug {
type PatData: Clone;
fn is_exhaustive_patterns_feature_on(&self) -> bool;
- fn is_min_exhaustive_patterns_feature_on(&self) -> bool;
/// The number of fields for this constructor.
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index 892aacd..6bcef0e 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -1,11 +1,12 @@
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
+use rustc_span::ErrorGuaranteed;
+use tracing::instrument;
+
use crate::constructor::Constructor;
use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered};
use crate::pat_column::PatternColumn;
use crate::rustc::{RevealedTy, RustcPatCtxt, WitnessPat};
use crate::MatchArm;
-use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
-use rustc_span::ErrorGuaranteed;
-use tracing::instrument;
/// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned
/// in a given column.
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index a591c3c..d91deab 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -5,11 +5,10 @@
use smallvec::{smallvec, SmallVec};
+use self::Constructor::*;
use crate::constructor::{Constructor, Slice, SliceKind};
use crate::{PatCx, PrivateUninhabitedField};
-use self::Constructor::*;
-
/// A globally unique id to distinguish patterns.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct PatId(u32);
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 910dd4c..10b7968 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -7,7 +7,7 @@
use rustc_index::{Idx, IndexVec};
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::mir::{self, Const};
-use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary};
+use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{
self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
@@ -17,15 +17,17 @@
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT};
+use crate::constructor::Constructor::*;
use crate::constructor::{
IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility,
};
use crate::lints::lint_nonexhaustive_missing_variants;
use crate::pat_column::PatternColumn;
+use crate::rustc::print::EnumInfo;
use crate::usefulness::{compute_match_usefulness, PlaceValidity};
use crate::{errors, Captures, PatCx, PrivateUninhabitedField};
-use crate::constructor::Constructor::*;
+mod print;
// Re-export rustc-specific versions of all these types.
pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcPatCtxt<'p, 'tcx>>;
@@ -236,9 +238,7 @@ fn reveal_and_alloc<'a, 'tcx>(
let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
let is_visible =
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
- let is_uninhabited = (cx.tcx.features().exhaustive_patterns
- || cx.tcx.features().min_exhaustive_patterns)
- && cx.is_uninhabited(*ty);
+ let is_uninhabited = cx.is_uninhabited(*ty);
let skip = is_uninhabited && (!is_visible || is_non_exhaustive);
(ty, PrivateUninhabitedField(skip))
});
@@ -744,7 +744,7 @@ pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> {
/// Note: it is possible to get `isize/usize::MAX+1` here, as explained in the doc for
/// [`IntRange::split`]. This cannot be represented as a `Const`, so we represent it with
/// `PosInfinity`.
- pub(crate) fn hoist_pat_range_bdy(
+ fn hoist_pat_range_bdy(
&self,
miint: MaybeInfiniteInt,
ty: RevealedTy<'tcx>,
@@ -774,8 +774,9 @@ pub(crate) fn hoist_pat_range_bdy(
}
}
- /// Convert back to a `thir::Pat` for diagnostic purposes.
- pub(crate) fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> Pat<'tcx> {
+ /// Convert to a [`print::Pat`] for diagnostic purposes.
+ fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> {
+ use print::{Pat, PatKind};
use MaybeInfiniteInt::*;
let cx = self;
let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
@@ -809,83 +810,79 @@ pub(crate) fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) ->
PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() }))
};
- Pat { ty: ty.inner(), span: DUMMY_SP, kind }
+ Pat { ty: ty.inner(), kind }
}
- /// Convert back to a `thir::Pat` for diagnostic purposes. This panics for patterns that don't
+
+ /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes.
+ pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String {
+ // This works by converting the witness pattern to a `print::Pat`
+ // and then printing that, but callers don't need to know that.
+ self.hoist_witness_pat(pat).to_string()
+ }
+
+ /// Convert to a [`print::Pat`] for diagnostic purposes. This panics for patterns that don't
/// appear in diagnostics, like float ranges.
- pub fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> {
+ fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> print::Pat<'tcx> {
+ use print::{FieldPat, Pat, PatKind};
let cx = self;
- let is_wildcard = |pat: &Pat<'_>| matches!(pat.kind, PatKind::Wild);
- let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p)));
+ let hoist = |p| Box::new(cx.hoist_witness_pat(p));
let kind = match pat.ctor() {
Bool(b) => PatKind::Constant { value: mir::Const::from_bool(cx.tcx, *b) },
IntRange(range) => return self.hoist_pat_range(range, *pat.ty()),
- Struct | Variant(_) | UnionField => match pat.ty().kind() {
- ty::Tuple(..) => PatKind::Leaf {
- subpatterns: subpatterns
- .enumerate()
- .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
- .collect(),
- },
- ty::Adt(adt_def, _) if adt_def.is_box() => {
- // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
- // of `std`). So this branch is only reachable when the feature is enabled and
- // the pattern is a box pattern.
- PatKind::Deref { subpattern: subpatterns.next().unwrap() }
- }
- ty::Adt(adt_def, args) => {
- let variant_index = RustcPatCtxt::variant_index_for_adt(&pat.ctor(), *adt_def);
- let subpatterns = subpatterns
- .enumerate()
- .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern })
- .collect();
-
- if adt_def.is_enum() {
- PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns }
- } else {
- PatKind::Leaf { subpatterns }
- }
- }
- _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()),
- },
- // Note: given the expansion of `&str` patterns done in `expand_pattern`, we should
- // be careful to reconstruct the correct constant pattern here. However a string
- // literal pattern will never be reported as a non-exhaustiveness witness, so we
- // ignore this issue.
- Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
- Slice(slice) => {
- match slice.kind {
- SliceKind::FixedLen(_) => PatKind::Slice {
- prefix: subpatterns.collect(),
- slice: None,
- suffix: Box::new([]),
+ Struct if pat.ty().is_box() => {
+ // Outside of the `alloc` crate, the only way to create a struct pattern
+ // of type `Box` is to use a `box` pattern via #[feature(box_patterns)].
+ PatKind::Box { subpattern: hoist(&pat.fields[0]) }
+ }
+ Struct | Variant(_) | UnionField => {
+ let enum_info = match *pat.ty().kind() {
+ ty::Adt(adt_def, _) if adt_def.is_enum() => EnumInfo::Enum {
+ adt_def,
+ variant_index: RustcPatCtxt::variant_index_for_adt(pat.ctor(), adt_def),
},
- SliceKind::VarLen(prefix, _) => {
- let mut subpatterns = subpatterns.peekable();
- let mut prefix: Vec<_> = subpatterns.by_ref().take(prefix).collect();
- if slice.array_len.is_some() {
- // Improves diagnostics a bit: if the type is a known-size array, instead
- // of reporting `[x, _, .., _, y]`, we prefer to report `[x, .., y]`.
- // This is incorrect if the size is not known, since `[_, ..]` captures
- // arrays of lengths `>= 1` whereas `[..]` captures any length.
- while !prefix.is_empty() && is_wildcard(prefix.last().unwrap()) {
- prefix.pop();
- }
- while subpatterns.peek().is_some()
- && is_wildcard(subpatterns.peek().unwrap())
- {
- subpatterns.next();
- }
- }
- let suffix: Box<[_]> = subpatterns.collect();
- let wild = Pat::wildcard_from_ty(pat.ty().inner());
- PatKind::Slice {
- prefix: prefix.into_boxed_slice(),
- slice: Some(Box::new(wild)),
- suffix,
- }
+ ty::Adt(..) | ty::Tuple(..) => EnumInfo::NotEnum,
+ _ => bug!("unexpected ctor for type {:?} {:?}", pat.ctor(), *pat.ty()),
+ };
+
+ let subpatterns = pat
+ .iter_fields()
+ .enumerate()
+ .map(|(i, pat)| FieldPat { field: FieldIdx::new(i), pattern: hoist(pat) })
+ .collect::<Vec<_>>();
+
+ PatKind::StructLike { enum_info, subpatterns }
+ }
+ Ref => PatKind::Deref { subpattern: hoist(&pat.fields[0]) },
+ Slice(slice) => {
+ let (prefix_len, has_dot_dot) = match slice.kind {
+ SliceKind::FixedLen(len) => (len, false),
+ SliceKind::VarLen(prefix_len, _) => (prefix_len, true),
+ };
+
+ let (mut prefix, mut suffix) = pat.fields.split_at(prefix_len);
+
+ // If the pattern contains a `..`, but is applied to values of statically-known
+ // length (arrays), then we can slightly simplify diagnostics by merging any
+ // adjacent wildcard patterns into the `..`: `[x, _, .., _, y]` => `[x, .., y]`.
+ // (This simplification isn't allowed for slice values, because in that case
+ // `[x, .., y]` would match some slices that `[x, _, .., _, y]` would not.)
+ if has_dot_dot && slice.array_len.is_some() {
+ while let [rest @ .., last] = prefix
+ && would_print_as_wildcard(cx.tcx, last)
+ {
+ prefix = rest;
+ }
+ while let [first, rest @ ..] = suffix
+ && would_print_as_wildcard(cx.tcx, first)
+ {
+ suffix = rest;
}
}
+
+ let prefix = prefix.iter().map(hoist).collect();
+ let suffix = suffix.iter().map(hoist).collect();
+
+ PatKind::Slice { prefix, has_dot_dot, suffix }
}
&Str(value) => PatKind::Constant { value },
Never if self.tcx.features().never_patterns => PatKind::Never,
@@ -899,7 +896,23 @@ pub fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> {
}
};
- Pat { ty: pat.ty().inner(), span: DUMMY_SP, kind }
+ Pat { ty: pat.ty().inner(), kind }
+ }
+}
+
+/// Returns `true` if the given pattern would be printed as a wildcard (`_`).
+fn would_print_as_wildcard(tcx: TyCtxt<'_>, p: &WitnessPat<'_, '_>) -> bool {
+ match p.ctor() {
+ Constructor::IntRange(IntRange {
+ lo: MaybeInfiniteInt::NegInfinity,
+ hi: MaybeInfiniteInt::PosInfinity,
+ })
+ | Constructor::Wildcard
+ | Constructor::NonExhaustive
+ | Constructor::Hidden
+ | Constructor::PrivateUninhabited => true,
+ Constructor::Never if !tcx.features().never_patterns => true,
+ _ => false,
}
}
@@ -914,9 +927,6 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
fn is_exhaustive_patterns_feature_on(&self) -> bool {
self.tcx.features().exhaustive_patterns
}
- fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
- self.tcx.features().min_exhaustive_patterns
- }
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
self.ctor_arity(ctor, *ty)
@@ -966,7 +976,7 @@ fn lint_overlapping_range_endpoints(
let overlaps: Vec<_> = overlaps_with
.iter()
.map(|pat| pat.data().span)
- .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
+ .map(|span| errors::Overlap { range: overlap_as_pat.to_string(), span })
.collect();
let pat_span = pat.data().span;
self.tcx.emit_node_span_lint(
@@ -996,12 +1006,11 @@ fn lint_non_contiguous_range_endpoints(
}
// `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with
// `gap+1`.
- let suggested_range: thir::Pat<'_> = {
+ let suggested_range: String = {
// Suggest `lo..=gap` instead.
- let mut suggested_range = thir_pat.clone();
- let thir::PatKind::Range(range) = &mut suggested_range.kind else { unreachable!() };
- range.end = rustc_hir::RangeEnd::Included;
- suggested_range
+ let mut suggested_range = PatRange::clone(range);
+ suggested_range.end = rustc_hir::RangeEnd::Included;
+ suggested_range.to_string()
};
let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty());
if gapped_with.is_empty() {
@@ -1014,9 +1023,9 @@ fn lint_non_contiguous_range_endpoints(
// Point at this range.
first_range: thir_pat.span,
// That's the gap that isn't covered.
- max: gap_as_pat.clone(),
+ max: gap_as_pat.to_string(),
// Suggest `lo..=max` instead.
- suggestion: suggested_range.to_string(),
+ suggestion: suggested_range,
},
);
} else {
@@ -1028,17 +1037,17 @@ fn lint_non_contiguous_range_endpoints(
// Point at this range.
first_range: thir_pat.span,
// That's the gap that isn't covered.
- gap: gap_as_pat.clone(),
+ gap: gap_as_pat.to_string(),
// Suggest `lo..=gap` instead.
- suggestion: suggested_range.to_string(),
+ suggestion: suggested_range,
// All these ranges skipped over `gap` which we think is probably a
// mistake.
gap_with: gapped_with
.iter()
.map(|pat| errors::GappedRange {
span: pat.data().span,
- gap: gap_as_pat.clone(),
- first_range: thir_pat.clone(),
+ gap: gap_as_pat.to_string(),
+ first_range: range.to_string(),
})
.collect(),
},
diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs
new file mode 100644
index 0000000..7d63871
--- /dev/null
+++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs
@@ -0,0 +1,219 @@
+//! Pattern analysis sometimes wants to print patterns as part of a user-visible
+//! diagnostic.
+//!
+//! Historically it did so by creating a synthetic [`thir::Pat`](rustc_middle::thir::Pat)
+//! and printing that, but doing so was making it hard to modify the THIR pattern
+//! representation for other purposes.
+//!
+//! So this module contains a forked copy of `thir::Pat` that is used _only_
+//! for diagnostics, and has been partly simplified to remove things that aren't
+//! needed for printing.
+
+use std::fmt;
+
+use rustc_middle::thir::PatRange;
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_middle::{bug, mir};
+use rustc_span::sym;
+use rustc_target::abi::{FieldIdx, VariantIdx};
+
+#[derive(Clone, Debug)]
+pub(crate) struct FieldPat<'tcx> {
+ pub(crate) field: FieldIdx,
+ pub(crate) pattern: Box<Pat<'tcx>>,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) struct Pat<'tcx> {
+ pub(crate) ty: Ty<'tcx>,
+ pub(crate) kind: PatKind<'tcx>,
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum PatKind<'tcx> {
+ Wild,
+
+ StructLike {
+ enum_info: EnumInfo<'tcx>,
+ subpatterns: Vec<FieldPat<'tcx>>,
+ },
+
+ Box {
+ subpattern: Box<Pat<'tcx>>,
+ },
+
+ Deref {
+ subpattern: Box<Pat<'tcx>>,
+ },
+
+ Constant {
+ value: mir::Const<'tcx>,
+ },
+
+ Range(Box<PatRange<'tcx>>),
+
+ Slice {
+ prefix: Box<[Box<Pat<'tcx>>]>,
+ /// True if this slice-like pattern should include a `..` between the
+ /// prefix and suffix.
+ has_dot_dot: bool,
+ suffix: Box<[Box<Pat<'tcx>>]>,
+ },
+
+ Never,
+}
+
+impl<'tcx> fmt::Display for Pat<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.kind {
+ PatKind::Wild => write!(f, "_"),
+ PatKind::Never => write!(f, "!"),
+ PatKind::Box { ref subpattern } => write!(f, "box {subpattern}"),
+ PatKind::StructLike { ref enum_info, ref subpatterns } => {
+ ty::tls::with(|tcx| write_struct_like(f, tcx, self.ty, enum_info, subpatterns))
+ }
+ PatKind::Deref { ref subpattern } => write_ref_like(f, self.ty, subpattern),
+ PatKind::Constant { value } => write!(f, "{value}"),
+ PatKind::Range(ref range) => write!(f, "{range}"),
+ PatKind::Slice { ref prefix, has_dot_dot, ref suffix } => {
+ write_slice_like(f, prefix, has_dot_dot, suffix)
+ }
+ }
+ }
+}
+
+/// Returns a closure that will return `""` when called the first time,
+/// and then return `", "` when called any subsequent times.
+/// Useful for printing comma-separated lists.
+fn start_or_comma() -> impl FnMut() -> &'static str {
+ let mut first = true;
+ move || {
+ if first {
+ first = false;
+ ""
+ } else {
+ ", "
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+pub(crate) enum EnumInfo<'tcx> {
+ Enum { adt_def: AdtDef<'tcx>, variant_index: VariantIdx },
+ NotEnum,
+}
+
+fn write_struct_like<'tcx>(
+ f: &mut impl fmt::Write,
+ tcx: TyCtxt<'_>,
+ ty: Ty<'tcx>,
+ enum_info: &EnumInfo<'tcx>,
+ subpatterns: &[FieldPat<'tcx>],
+) -> fmt::Result {
+ let variant_and_name = match *enum_info {
+ EnumInfo::Enum { adt_def, variant_index } => {
+ let variant = adt_def.variant(variant_index);
+ let adt_did = adt_def.did();
+ let name = if tcx.is_diagnostic_item(sym::Option, adt_did)
+ || tcx.is_diagnostic_item(sym::Result, adt_did)
+ {
+ variant.name.to_string()
+ } else {
+ format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
+ };
+ Some((variant, name))
+ }
+ EnumInfo::NotEnum => ty.ty_adt_def().and_then(|adt_def| {
+ Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
+ }),
+ };
+
+ let mut start_or_comma = start_or_comma();
+
+ if let Some((variant, name)) = &variant_and_name {
+ write!(f, "{name}")?;
+
+ // Only for Adt we can have `S {...}`,
+ // which we handle separately here.
+ if variant.ctor.is_none() {
+ write!(f, " {{ ")?;
+
+ let mut printed = 0;
+ for p in subpatterns {
+ if let PatKind::Wild = p.pattern.kind {
+ continue;
+ }
+ let name = variant.fields[p.field].name;
+ write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
+ printed += 1;
+ }
+
+ let is_union = ty.ty_adt_def().is_some_and(|adt| adt.is_union());
+ if printed < variant.fields.len() && (!is_union || printed == 0) {
+ write!(f, "{}..", start_or_comma())?;
+ }
+
+ return write!(f, " }}");
+ }
+ }
+
+ let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
+ if num_fields != 0 || variant_and_name.is_none() {
+ write!(f, "(")?;
+ for i in 0..num_fields {
+ write!(f, "{}", start_or_comma())?;
+
+ // Common case: the field is where we expect it.
+ if let Some(p) = subpatterns.get(i) {
+ if p.field.index() == i {
+ write!(f, "{}", p.pattern)?;
+ continue;
+ }
+ }
+
+ // Otherwise, we have to go looking for it.
+ if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
+ write!(f, "{}", p.pattern)?;
+ } else {
+ write!(f, "_")?;
+ }
+ }
+ write!(f, ")")?;
+ }
+
+ Ok(())
+}
+
+fn write_ref_like<'tcx>(
+ f: &mut impl fmt::Write,
+ ty: Ty<'tcx>,
+ subpattern: &Pat<'tcx>,
+) -> fmt::Result {
+ match ty.kind() {
+ ty::Ref(_, _, mutbl) => {
+ write!(f, "&{}", mutbl.prefix_str())?;
+ }
+ _ => bug!("{ty} is a bad ref pattern type"),
+ }
+ write!(f, "{subpattern}")
+}
+
+fn write_slice_like<'tcx>(
+ f: &mut impl fmt::Write,
+ prefix: &[Box<Pat<'tcx>>],
+ has_dot_dot: bool,
+ suffix: &[Box<Pat<'tcx>>],
+) -> fmt::Result {
+ let mut start_or_comma = start_or_comma();
+ write!(f, "[")?;
+ for p in prefix.iter() {
+ write!(f, "{}{}", start_or_comma(), p)?;
+ }
+ if has_dot_dot {
+ write!(f, "{}..", start_or_comma())?;
+ }
+ for p in suffix.iter() {
+ write!(f, "{}{}", start_or_comma(), p)?;
+ }
+ write!(f, "]")
+}
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 76dc338..6535afc 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -543,13 +543,11 @@
//! recurse into subpatterns. That second part is done through [`PlaceValidity`], most notably
//! [`PlaceValidity::specialize`].
//!
-//! Having said all that, in practice we don't fully follow what's been presented in this section.
-//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or
-//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart
-//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow
-//! omitting patterns in the cases described above. There's a final detail: in the toplevel
-//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking
-//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior.
+//! Having said all that, we don't fully follow what's been presented in this section. For
+//! backwards-compatibility, we ignore place validity when checking whether a pattern is required
+//! for exhaustiveness in two cases: when the `exhaustive_patterns` feature gate is on, or when the
+//! match scrutinee itself has type `!` or `EmptyEnum`. I (Nadrieril) hope to deprecate this
+//! exception.
//!
//!
//!
@@ -709,18 +707,19 @@
//! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific
//! reason not to, for example if they crucially depend on a particular feature like `or_patterns`.
+use std::fmt;
+
+#[cfg(feature = "rustc")]
+use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_index::bit_set::BitSet;
+use smallvec::{smallvec, SmallVec};
+use tracing::{debug, instrument};
+
use self::PlaceValidity::*;
use crate::constructor::{Constructor, ConstructorSet, IntRange};
use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat};
use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField};
-use rustc_hash::{FxHashMap, FxHashSet};
-use rustc_index::bit_set::BitSet;
-use smallvec::{smallvec, SmallVec};
-use std::fmt;
-use tracing::{debug, instrument};
-
-#[cfg(feature = "rustc")]
-use rustc_data_structures::stack::ensure_sufficient_stack;
#[cfg(not(feature = "rustc"))]
pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
f()
@@ -952,13 +951,10 @@ fn split_column_ctors<'a>(
self.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
// Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
// it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
- let empty_arms_are_unreachable = self.validity.is_known_valid()
- && (is_toplevel_exception
- || cx.is_exhaustive_patterns_feature_on()
- || cx.is_min_exhaustive_patterns_feature_on());
+ let empty_arms_are_unreachable = self.validity.is_known_valid();
// Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
// toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
- let can_omit_empty_arms = empty_arms_are_unreachable
+ let can_omit_empty_arms = self.validity.is_known_valid()
|| is_toplevel_exception
|| cx.is_exhaustive_patterns_feature_on();
diff --git a/compiler/rustc_pattern_analysis/tests/common/mod.rs b/compiler/rustc_pattern_analysis/tests/common/mod.rs
index 68ec75b..ec0bcd4 100644
--- a/compiler/rustc_pattern_analysis/tests/common/mod.rs
+++ b/compiler/rustc_pattern_analysis/tests/common/mod.rs
@@ -1,10 +1,8 @@
-use rustc_pattern_analysis::{
- constructor::{
- Constructor, ConstructorSet, IntRange, MaybeInfiniteInt, RangeEnd, VariantVisibility,
- },
- usefulness::{PlaceValidity, UsefulnessReport},
- Captures, MatchArm, PatCx, PrivateUninhabitedField,
+use rustc_pattern_analysis::constructor::{
+ Constructor, ConstructorSet, IntRange, MaybeInfiniteInt, RangeEnd, VariantVisibility,
};
+use rustc_pattern_analysis::usefulness::{PlaceValidity, UsefulnessReport};
+use rustc_pattern_analysis::{Captures, MatchArm, PatCx, PrivateUninhabitedField};
/// Sets up `tracing` for easier debugging. Tries to look like the `rustc` setup.
pub fn init_tracing() {
@@ -154,10 +152,6 @@ fn is_exhaustive_patterns_feature_on(&self) -> bool {
false
}
- fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
- true
- }
-
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize {
ty.sub_tys(ctor).len()
}
diff --git a/compiler/rustc_pattern_analysis/tests/complexity.rs b/compiler/rustc_pattern_analysis/tests/complexity.rs
index 19242d4..3a9b9e9 100644
--- a/compiler/rustc_pattern_analysis/tests/complexity.rs
+++ b/compiler/rustc_pattern_analysis/tests/complexity.rs
@@ -1,7 +1,9 @@
//! Test the pattern complexity limit.
use common::*;
-use rustc_pattern_analysis::{pat::DeconstructedPat, usefulness::PlaceValidity, MatchArm};
+use rustc_pattern_analysis::pat::DeconstructedPat;
+use rustc_pattern_analysis::usefulness::PlaceValidity;
+use rustc_pattern_analysis::MatchArm;
#[macro_use]
mod common;
diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
index 205d430..2192940 100644
--- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
+++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
@@ -1,11 +1,9 @@
//! Test exhaustiveness checking.
use common::*;
-use rustc_pattern_analysis::{
- pat::{DeconstructedPat, WitnessPat},
- usefulness::PlaceValidity,
- MatchArm,
-};
+use rustc_pattern_analysis::pat::{DeconstructedPat, WitnessPat};
+use rustc_pattern_analysis::usefulness::PlaceValidity;
+use rustc_pattern_analysis::MatchArm;
#[macro_use]
mod common;
diff --git a/compiler/rustc_pattern_analysis/tests/intersection.rs b/compiler/rustc_pattern_analysis/tests/intersection.rs
index 8c8cb3c..1c26e17 100644
--- a/compiler/rustc_pattern_analysis/tests/intersection.rs
+++ b/compiler/rustc_pattern_analysis/tests/intersection.rs
@@ -1,7 +1,9 @@
//! Test the computation of arm intersections.
use common::*;
-use rustc_pattern_analysis::{pat::DeconstructedPat, usefulness::PlaceValidity, MatchArm};
+use rustc_pattern_analysis::pat::DeconstructedPat;
+use rustc_pattern_analysis::usefulness::PlaceValidity;
+use rustc_pattern_analysis::MatchArm;
#[macro_use]
mod common;
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index ee04c33..89face10 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -1,4 +1,5 @@
-use rustc_errors::{codes::*, DiagArgFromDisplay};
+use rustc_errors::codes::*;
+use rustc_errors::DiagArgFromDisplay;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index d370562..d1d1e5e 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -10,29 +10,6 @@
mod errors;
-use rustc_ast::visit::{try_visit, VisitorResult};
-use rustc_ast::MacroDef;
-use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::intern::Interned;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
-use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
-use rustc_middle::query::Providers;
-use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::{self, Const, GenericParamDefKind};
-use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_middle::{bug, span_bug};
-use rustc_session::lint;
-use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
-use tracing::debug;
-
use std::fmt;
use std::marker::PhantomData;
use std::ops::ControlFlow;
@@ -42,6 +19,28 @@
ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
UnnamedItemIsPrivate,
};
+use rustc_ast::visit::{try_visit, VisitorResult};
+use rustc_ast::MacroDef;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::intern::Interned;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
+use rustc_middle::query::Providers;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
+use rustc_middle::ty::{
+ self, Const, GenericArgs, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
+ TypeVisitable, TypeVisitor,
+};
+use rustc_middle::{bug, span_bug};
+use rustc_session::lint;
+use rustc_span::hygiene::Transparency;
+use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::Span;
+use tracing::debug;
+use {rustc_attr as attr, rustc_hir as hir};
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 825c1e2..18f97d6 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -10,20 +10,17 @@
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
-use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
-use crate::profiling_support::QueryKeyStringCache;
use field_offset::offset_of;
use rustc_data_structures::stable_hasher::HashStable;
use rustc_data_structures::sync::AtomicU64;
use rustc_middle::arena::Arena;
-use rustc_middle::dep_graph::DepNodeIndex;
-use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
+use rustc_middle::dep_graph::{self, DepKind, DepKindStruct, DepNodeIndex};
use rustc_middle::query::erase::{erase, restore, Erase};
use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
use rustc_middle::query::plumbing::{DynamicQuery, QuerySystem, QuerySystemFns};
-use rustc_middle::query::AsLocalKey;
use rustc_middle::query::{
- queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
+ queries, AsLocalKey, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine,
+ QueryStates,
};
use rustc_middle::ty::TyCtxt;
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
@@ -32,10 +29,12 @@
get_query_incr, get_query_non_incr, CycleError, HashResult, QueryCache, QueryConfig, QueryMap,
QueryMode, QueryState,
};
-use rustc_query_system::HandleCycleError;
-use rustc_query_system::Value;
+use rustc_query_system::{HandleCycleError, Value};
use rustc_span::{ErrorGuaranteed, Span};
+use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
+use crate::profiling_support::QueryKeyStringCache;
+
#[macro_use]
mod plumbing;
pub use crate::plumbing::{query_key_hash_verify_all, QueryCtxt};
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 62e3937..b9e700c1 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -2,19 +2,21 @@
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.
-use crate::QueryConfigRestored;
+use std::num::NonZero;
+
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_data_structures::sync::Lock;
use rustc_data_structures::unord::UnordMap;
use rustc_errors::DiagInner;
use rustc_index::Idx;
use rustc_middle::bug;
-use rustc_middle::dep_graph::dep_kinds;
use rustc_middle::dep_graph::{
- self, DepContext, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
+ self, dep_kinds, DepContext, DepKind, DepKindStruct, DepNode, DepNodeIndex,
+ SerializedDepNodeIndex,
};
-use rustc_middle::query::on_disk_cache::AbsoluteBytePos;
-use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
+use rustc_middle::query::on_disk_cache::{
+ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex,
+};
use rustc_middle::query::Key;
use rustc_middle::ty::print::with_reduced_queries;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
@@ -26,13 +28,13 @@
QueryStackFrame,
};
use rustc_query_system::{LayoutOfDepth, QueryOverflow};
-use rustc_serialize::Decodable;
-use rustc_serialize::Encodable;
+use rustc_serialize::{Decodable, Encodable};
use rustc_session::Limit;
use rustc_span::def_id::LOCAL_CRATE;
-use std::num::NonZero;
use thin_vec::ThinVec;
+use crate::QueryConfigRestored;
+
#[derive(Copy, Clone)]
pub struct QueryCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index e0d7a4f..599316d 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -1,3 +1,6 @@
+use std::fmt::Debug;
+use std::io::Write;
+
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
@@ -5,8 +8,6 @@
use rustc_hir::definitions::DefPathData;
use rustc_middle::ty::TyCtxt;
use rustc_query_system::query::QueryCache;
-use std::fmt::Debug;
-use std::io::Write;
pub(crate) struct QueryKeyStringCache {
def_id_cache: FxHashMap<DefId, StringId>,
diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs
index d8a5bdb..1b8332a 100644
--- a/compiler/rustc_query_system/src/cache.rs
+++ b/compiler/rustc_query_system/src/cache.rs
@@ -1,11 +1,11 @@
//! Cache for candidate selection.
-use crate::dep_graph::{DepContext, DepNodeIndex};
+use std::hash::Hash;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
-use std::hash::Hash;
+use crate::dep_graph::{DepContext, DepNodeIndex};
pub struct Cache<Key, Value> {
hashmap: Lock<FxHashMap<Key, WithDepNode<Value>>>,
diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_query_system/src/dep_graph/debug.rs
index 103a6c0..12ed574 100644
--- a/compiler/rustc_query_system/src/dep_graph/debug.rs
+++ b/compiler/rustc_query_system/src/dep_graph/debug.rs
@@ -1,9 +1,11 @@
//! Code for debugging the dep-graph.
-use super::{DepNode, DepNodeIndex};
+use std::error::Error;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lock;
-use std::error::Error;
+
+use super::{DepNode, DepNodeIndex};
/// A dep-node filter goes from a user-defined string to a query over
/// nodes. Right now the format is like this:
@@ -44,15 +46,14 @@ pub struct EdgeFilter {
impl EdgeFilter {
pub fn new(test: &str) -> Result<EdgeFilter, Box<dyn Error>> {
- let parts: Vec<_> = test.split("->").collect();
- if parts.len() != 2 {
- Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into())
- } else {
+ if let [source, target] = *test.split("->").collect::<Vec<_>>() {
Ok(EdgeFilter {
- source: DepNodeFilter::new(parts[0]),
- target: DepNodeFilter::new(parts[1]),
+ source: DepNodeFilter::new(source),
+ target: DepNodeFilter::new(target),
index_to_node: Lock::new(FxHashMap::default()),
})
+ } else {
+ Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into())
}
}
diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
index f2a68e3..dfd0527 100644
--- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
@@ -42,16 +42,17 @@
//! `DefId` it was computed from. In other cases, too much information gets
//! lost during fingerprint computation.
-use super::{DepContext, FingerprintStyle};
-use crate::ich::StableHashingContext;
+use std::fmt;
+use std::hash::Hash;
use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey};
use rustc_data_structures::AtomicRef;
use rustc_hir::definitions::DefPathHash;
use rustc_macros::{Decodable, Encodable};
-use std::fmt;
-use std::hash::Hash;
+
+use super::{DepContext, FingerprintStyle};
+use crate::ich::StableHashingContext;
/// This serves as an index into arrays built by `make_dep_kind_array`.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
@@ -312,8 +313,9 @@ impl StableOrd for WorkProductId {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(DepKind, 2);
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
diff --git a/compiler/rustc_query_system/src/dep_graph/edges.rs b/compiler/rustc_query_system/src/dep_graph/edges.rs
index 63d46f4..9a3763b 100644
--- a/compiler/rustc_query_system/src/dep_graph/edges.rs
+++ b/compiler/rustc_query_system/src/dep_graph/edges.rs
@@ -1,8 +1,10 @@
-use crate::dep_graph::DepNodeIndex;
-use smallvec::SmallVec;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
+use smallvec::SmallVec;
+
+use crate::dep_graph::DepNodeIndex;
+
#[derive(Default, Debug)]
pub(crate) struct EdgesVec {
max: u32,
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 66fb313..b6aa1d5 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -1,3 +1,11 @@
+use std::assert_matches::assert_matches;
+use std::collections::hash_map::Entry;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::marker::PhantomData;
+use std::sync::atomic::Ordering;
+use std::sync::Arc;
+
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
@@ -8,14 +16,9 @@
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
-use std::assert_matches::assert_matches;
-use std::collections::hash_map::Entry;
-use std::fmt::Debug;
-use std::hash::Hash;
-use std::marker::PhantomData;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
use tracing::{debug, instrument};
+#[cfg(debug_assertions)]
+use {super::debug::EdgeFilter, std::env};
use super::query::DepGraphQuery;
use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex};
@@ -24,9 +27,6 @@
use crate::ich::StableHashingContext;
use crate::query::{QueryContext, QuerySideEffects};
-#[cfg(debug_assertions)]
-use {super::debug::EdgeFilter, std::env};
-
#[derive(Clone)]
pub struct DepGraph<D: Deps> {
data: Option<Lrc<DepGraphData<D>>>,
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index cfb25ec..291f275 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -5,18 +5,19 @@
mod query;
mod serialized;
+use std::panic;
+
pub use dep_node::{DepKind, DepKindStruct, DepNode, DepNodeParams, WorkProductId};
pub(crate) use graph::DepGraphData;
pub use graph::{hash_result, DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap};
pub use query::DepGraphQuery;
+use rustc_data_structures::profiling::SelfProfilerRef;
+use rustc_session::Session;
pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};
+use tracing::instrument;
use self::graph::{print_markframe_trace, MarkFrame};
use crate::ich::StableHashingContext;
-use rustc_data_structures::profiling::SelfProfilerRef;
-use rustc_session::Session;
-use std::panic;
-use tracing::instrument;
pub trait DepContext: Copy {
type Deps: Deps;
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 8e91d9d..ff1c343 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -35,11 +35,11 @@
//! If the number of edges in this node does not fit in the bits available in the header, we
//! store it directly after the header with leb128.
-use super::query::DepGraphQuery;
-use super::{DepKind, DepNode, DepNodeIndex, Deps};
-use crate::dep_graph::edges::EdgesVec;
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fingerprint::PackedFingerprint;
+use std::iter;
+use std::marker::PhantomData;
+use std::sync::Arc;
+
+use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::outline;
use rustc_data_structures::profiling::SelfProfilerRef;
@@ -48,11 +48,12 @@
use rustc_index::{Idx, IndexVec};
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::iter;
-use std::marker::PhantomData;
-use std::sync::Arc;
use tracing::{debug, instrument};
+use super::query::DepGraphQuery;
+use super::{DepKind, DepNode, DepNodeIndex, Deps};
+use crate::dep_graph::edges::EdgesVec;
+
// The maximum value of `SerializedDepNodeIndex` leaves the upper two bits
// unused so that we can store multiple index types in `CompressedHybridIndex`,
// and use those bits to encode which index type it contains.
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index e7eb969..756ad3b 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -1,5 +1,3 @@
-use crate::ich;
-
use rustc_ast as ast;
use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
use rustc_data_structures::sync::Lrc;
@@ -11,6 +9,8 @@
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData, DUMMY_SP};
+use crate::ich;
+
/// This is the context state available during incr. comp. hashing. It contains
/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
/// a reference to the `TyCtxt`) and it holds a few caches for speeding up various
diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs
index 39da5e3..8d7a6e4 100644
--- a/compiler/rustc_query_system/src/ich/impls_syntax.rs
+++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs
@@ -1,15 +1,15 @@
//! This module contains `HashStable` implementations for various data types
//! from `rustc_ast` in no particular order.
-use crate::ich::StableHashingContext;
+use std::assert_matches::assert_matches;
use rustc_ast as ast;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_span::SourceFile;
-use std::assert_matches::assert_matches;
-
use smallvec::SmallVec;
+use crate::ich::StableHashingContext;
+
impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {}
impl<'a> HashStable<StableHashingContext<'a>> for [ast::Attribute] {
diff --git a/compiler/rustc_query_system/src/ich/mod.rs b/compiler/rustc_query_system/src/ich/mod.rs
index 86e3ecb..bae7688 100644
--- a/compiler/rustc_query_system/src/ich/mod.rs
+++ b/compiler/rustc_query_system/src/ich/mod.rs
@@ -1,8 +1,9 @@
//! ICH - Incremental Compilation Hash
-pub use self::hcx::StableHashingContext;
use rustc_span::symbol::{sym, Symbol};
+pub use self::hcx::StableHashingContext;
+
mod hcx;
mod impls_syntax;
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index 41222e8..7a50a95 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -14,9 +14,7 @@
pub mod query;
mod values;
-pub use error::HandleCycleError;
-pub use error::LayoutOfDepth;
-pub use error::QueryOverflow;
+pub use error::{HandleCycleError, LayoutOfDepth, QueryOverflow};
pub use values::Value;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index acc29b6..a4ced3d 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -1,14 +1,14 @@
-use crate::dep_graph::DepNodeIndex;
+use std::fmt::Debug;
+use std::hash::Hash;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded::{self, Sharded};
use rustc_data_structures::sync::{Lock, OnceLock};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_index::{Idx, IndexVec};
-use rustc_span::def_id::DefId;
-use rustc_span::def_id::DefIndex;
-use std::fmt::Debug;
-use std::hash::Hash;
+use rustc_span::def_id::{DefId, DefIndex};
+
+use crate::dep_graph::DepNodeIndex;
pub trait QueryCache: Sized {
type Key: Hash + Eq + Copy + Debug;
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index 958d9fd..371b896 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -1,16 +1,16 @@
//! Query configuration and description traits.
+use std::fmt::Debug;
+use std::hash::Hash;
+
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_span::ErrorGuaranteed;
+
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
use crate::error::HandleCycleError;
use crate::ich::StableHashingContext;
use crate::query::caches::QueryCache;
-use crate::query::DepNodeIndex;
-use crate::query::{CycleError, QueryContext, QueryState};
-
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_span::ErrorGuaranteed;
-use std::fmt::Debug;
-use std::hash::Hash;
+use crate::query::{CycleError, DepNodeIndex, QueryContext, QueryState};
pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 3f44b11..ca3efc1 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -1,18 +1,12 @@
-use crate::dep_graph::DepContext;
-use crate::error::CycleStack;
-use crate::query::plumbing::CycleError;
-use crate::query::DepKind;
-use crate::query::{QueryContext, QueryStackFrame};
+use std::hash::Hash;
+use std::io::Write;
+use std::num::NonZero;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{Diag, DiagCtxtHandle};
use rustc_hir::def::DefKind;
use rustc_session::Session;
use rustc_span::Span;
-
-use std::hash::Hash;
-use std::io::Write;
-use std::num::NonZero;
-
#[cfg(parallel_compiler)]
use {
parking_lot::{Condvar, Mutex},
@@ -23,6 +17,11 @@
std::sync::Arc,
};
+use crate::dep_graph::DepContext;
+use crate::error::CycleStack;
+use crate::query::plumbing::CycleError;
+use crate::query::{DepKind, QueryContext, QueryStackFrame};
+
/// Represents a span and a query key.
#[derive(Clone, Debug)]
pub struct QueryInfo {
@@ -589,7 +588,7 @@ pub fn report_cycle<'a>(
cycle_stack,
stack_bottom: stack[0].query.description.to_owned(),
alias,
- cycle_usage: cycle_usage,
+ cycle_usage,
stack_count,
note_span: (),
};
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index ab4f48f..db00c26 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -12,10 +12,6 @@
pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache};
mod config;
-pub use self::config::{HashResult, QueryConfig};
-
-use crate::dep_graph::DepKind;
-use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
use rustc_data_structures::stable_hasher::Hash64;
use rustc_data_structures::sync::Lock;
use rustc_errors::DiagInner;
@@ -25,6 +21,9 @@
use rustc_span::Span;
use thin_vec::ThinVec;
+pub use self::config::{HashResult, QueryConfig};
+use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
+
/// Description of a frame in the query stack.
///
/// This is mostly used in case of cycles for error reporting.
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index d37d5bc..8ef680c 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -2,16 +2,12 @@
//! generate the actual methods on tcx which find and execute the provider,
//! manage the caches, and so forth.
-use crate::dep_graph::DepGraphData;
-use crate::dep_graph::{DepContext, DepNode, DepNodeIndex, DepNodeParams};
-use crate::ich::StableHashingContext;
-use crate::query::caches::QueryCache;
-#[cfg(parallel_compiler)]
-use crate::query::job::QueryLatch;
-use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
-use crate::query::SerializedDepNodeIndex;
-use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame};
-use crate::HandleCycleError;
+use std::cell::Cell;
+use std::collections::hash_map::Entry;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::mem;
+
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sharded::Sharded;
@@ -21,15 +17,20 @@
use rustc_data_structures::{outline, sync};
use rustc_errors::{Diag, FatalError, StashKey};
use rustc_span::{Span, DUMMY_SP};
-use std::cell::Cell;
-use std::collections::hash_map::Entry;
-use std::fmt::Debug;
-use std::hash::Hash;
-use std::mem;
use thin_vec::ThinVec;
use tracing::instrument;
use super::QueryConfig;
+use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
+use crate::ich::StableHashingContext;
+use crate::query::caches::QueryCache;
+#[cfg(parallel_compiler)]
+use crate::query::job::QueryLatch;
+use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
+use crate::query::{
+ QueryContext, QueryMap, QuerySideEffects, QueryStackFrame, SerializedDepNodeIndex,
+};
+use crate::HandleCycleError;
pub struct QueryState<K> {
active: Sharded<FxHashMap<K, QueryResult>>,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index ced5ac1..d57dabd 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -5,18 +5,13 @@
//! unexpanded macros in the fragment are visited and registered.
//! Imports are also considered items and placed into modules here, but not resolved yet.
-use crate::def_collector::collect_definitions;
-use crate::imports::{ImportData, ImportKind};
-use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
-use crate::Namespace::{MacroNS, TypeNS, ValueNS};
-use crate::{errors, BindingKey, MacroData, NameBindingData};
-use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
-use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError};
-use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError};
+use std::cell::Cell;
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
-use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
-use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
+use rustc_ast::{
+ self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item,
+ ItemKind, MetaItemKind, NodeId, StmtKind,
+};
use rustc_attr as attr;
use rustc_data_structures::sync::Lrc;
use rustc_expand::base::ResolverExpand;
@@ -30,11 +25,18 @@
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-
-use std::cell::Cell;
-
use tracing::debug;
+use crate::def_collector::collect_definitions;
+use crate::imports::{ImportData, ImportKind};
+use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
+use crate::Namespace::{MacroNS, TypeNS, ValueNS};
+use crate::{
+ errors, BindingKey, Determinacy, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind,
+ ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
+ ResolutionError, Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError,
+};
+
type Res = def::Res<NodeId>;
impl<'a, Id: Into<DefId>> ToNameBinding<'a>
@@ -281,6 +283,7 @@ fn try_resolve_visibility<'ast>(
parent_scope,
finalize.then(|| Finalize::new(id, path.span)),
None,
+ None,
) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
let res = module.res().expect("visibility resolved to unnamed block");
@@ -370,8 +373,7 @@ fn add_import(
has_attributes: !item.attrs.is_empty(),
root_span,
root_id,
- vis: Cell::new(Some(vis)),
- used: Default::default(),
+ vis,
});
self.r.indeterminate_imports.push(import);
@@ -886,9 +888,11 @@ fn build_reduced_graph_for_extern_crate(
root_span: item.span,
span: item.span,
module_path: Vec::new(),
- vis: Cell::new(Some(vis)),
- used: Cell::new(used.then_some(Used::Other)),
+ vis,
});
+ if used {
+ self.r.import_use_map.insert(import, Used::Other);
+ }
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
if parent == self.r.graph_root {
@@ -1087,8 +1091,7 @@ fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool
root_span: span,
span,
module_path: Vec::new(),
- vis: Cell::new(Some(ty::Visibility::Restricted(CRATE_DEF_ID))),
- used: Default::default(),
+ vis: ty::Visibility::Restricted(CRATE_DEF_ID),
})
};
@@ -1123,6 +1126,7 @@ fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool
ident,
MacroNS,
&self.parent_scope,
+ None,
);
if let Ok(binding) = result {
let import = macro_use_import(self, ident.span, false);
@@ -1251,9 +1255,9 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> {
root_span: span,
span,
module_path: Vec::new(),
- vis: Cell::new(Some(vis)),
- used: Cell::new(Some(Used::Other)),
+ vis,
});
+ self.r.import_use_map.insert(import, Used::Other);
let import_binding = self.r.import(binding, import);
self.r.define(self.r.graph_root, ident, MacroNS, import_binding);
} else {
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index fc3669f..1cee876 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -23,23 +23,22 @@
// - `check_unused` finally emits the diagnostics based on the data generated
// in the last step
-use crate::imports::{Import, ImportKind};
-use crate::module_to_string;
-use crate::Resolver;
-
-use crate::{LexicalScopeBinding, NameBindingKind};
use rustc_ast as ast;
use rustc_ast::visit::{self, Visitor};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::unord::UnordSet;
use rustc_errors::MultiSpan;
use rustc_hir::def::{DefKind, Res};
-use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES};
-use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS};
+use rustc_session::lint::builtin::{
+ MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS, UNUSED_QUALIFICATIONS,
+};
use rustc_session::lint::BuiltinLintDiag;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, DUMMY_SP};
+use crate::imports::{Import, ImportKind};
+use crate::{module_to_string, LexicalScopeBinding, NameBindingKind, Resolver};
+
struct UnusedImport {
use_tree: ast::UseTree,
use_tree_id: ast::NodeId,
@@ -382,9 +381,9 @@ pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
for import in self.potentially_unused_imports.iter() {
match import.kind {
- _ if import.used.get().is_some()
- || import.expect_vis().is_public()
- || import.span.is_dummy() =>
+ _ if import.vis.is_public()
+ || import.span.is_dummy()
+ || self.import_use_map.contains_key(import) =>
{
if let ImportKind::MacroUse { .. } = import.kind {
if !import.span.is_dummy() {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 1fb942d..ed23870 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -1,4 +1,5 @@
-use crate::{ImplTraitContext, Resolver};
+use std::mem;
+
use rustc_ast::visit::FnKind;
use rustc_ast::*;
use rustc_expand::expand::AstFragment;
@@ -8,9 +9,10 @@
use rustc_span::hygiene::LocalExpnId;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use std::mem;
use tracing::debug;
+use crate::{ImplTraitContext, Resolver};
+
pub(crate) fn collect_definitions(
resolver: &mut Resolver<'_, '_>,
fragment: &AstFragment,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index df80f4d..942026e 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1,12 +1,15 @@
use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::ptr::P;
use rustc_ast::visit::{self, Visitor};
-use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ID};
-use rustc_ast::{MetaItemKind, NestedMetaItem};
+use rustc_ast::{
+ self as ast, Crate, ItemKind, MetaItemKind, ModKind, NestedMetaItem, NodeId, Path,
+ CRATE_NODE_ID,
+};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, report_ambiguity_error, struct_span_code_err, Applicability, Diag, DiagCtxtHandle,
+ report_ambiguity_error, struct_span_code_err, Applicability, Diag, DiagCtxtHandle,
ErrorGuaranteed, MultiSpan, SuggestionStyle,
};
use rustc_feature::BUILTIN_ATTRIBUTES;
@@ -16,9 +19,10 @@
use rustc_hir::PrimTy;
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
-use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
-use rustc_session::lint::builtin::AMBIGUOUS_GLOB_IMPORTS;
-use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
+use rustc_session::lint::builtin::{
+ ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS,
+ MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+};
use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag};
use rustc_session::Session;
use rustc_span::edit_distance::find_best_match_for_name;
@@ -36,13 +40,13 @@
};
use crate::imports::{Import, ImportKind};
use crate::late::{PatternSource, Rib};
-use crate::{errors as errs, BindingKey};
-use crate::{path_names_to_string, Used};
-use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
-use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot};
-use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
-use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet};
-use crate::{Segment, UseError};
+use crate::{
+ errors as errs, path_names_to_string, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind,
+ BindingError, BindingKey, Finalize, HasGenericParams, LexicalScopeBinding, MacroRulesScope,
+ Module, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
+ PrivacyError, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
+ VisResolutionError,
+};
type Res = def::Res<ast::NodeId>;
@@ -1048,6 +1052,7 @@ fn early_lookup_typo_candidate(
parent_scope,
false,
false,
+ None,
) {
suggestions.extend(
ext.helper_attrs
@@ -1502,6 +1507,7 @@ pub(crate) fn unresolved_macro_suggestions(
None,
false,
None,
+ None,
) {
let desc = match binding.res() {
Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
@@ -1979,6 +1985,7 @@ pub(crate) fn report_path_resolution_error(
parent_scope: &ParentScope<'a>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
module: Option<ModuleOrUniformRoot<'a>>,
failed_segment_idx: usize,
ident: Ident,
@@ -2022,14 +2029,17 @@ pub(crate) fn report_path_resolution_error(
Applicability::MaybeIncorrect,
)),
)
+ } else if ident.name == kw::Underscore {
+ (format!("`_` is not a valid crate or module name"), None)
} else if self.tcx.sess.is_rust_2015() {
(
format!("you might be missing crate `{ident}`"),
Some((
- vec![],
- format!(
- "consider adding `extern crate {ident}` to use the `{ident}` crate"
- ),
+ vec![(
+ self.current_crate_outer_attr_insert_span,
+ format!("extern crate {ident};\n"),
+ )],
+ format!("consider importing the `{ident}` crate"),
Applicability::MaybeIncorrect,
)),
)
@@ -2059,11 +2069,13 @@ pub(crate) fn report_path_resolution_error(
parent_scope,
None,
ignore_binding,
+ ignore_import,
)
.ok()
} else if let Some(ribs) = ribs
&& let Some(TypeNS | ValueNS) = opt_ns
{
+ assert!(ignore_import.is_none());
match self.resolve_ident_in_lexical_scope(
ident,
ns_to_try,
@@ -2084,6 +2096,7 @@ pub(crate) fn report_path_resolution_error(
None,
false,
ignore_binding,
+ ignore_import,
)
.ok()
};
@@ -2125,6 +2138,7 @@ pub(crate) fn report_path_resolution_error(
} else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
// Check whether the name refers to an item in the value namespace.
let binding = if let Some(ribs) = ribs {
+ assert!(ignore_import.is_none());
self.resolve_ident_in_lexical_scope(
ident,
ValueNS,
@@ -2199,6 +2213,7 @@ pub(crate) fn report_path_resolution_error(
None,
false,
ignore_binding,
+ ignore_import,
) {
let descr = binding.res().descr();
(format!("{descr} `{ident}` is not a crate or module"), suggestion)
@@ -2252,7 +2267,7 @@ fn make_missing_self_suggestion(
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `self` and check if that is valid.
path[0].ident.name = kw::SelfLower;
- let result = self.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
}
@@ -2271,7 +2286,7 @@ fn make_missing_crate_suggestion(
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = kw::Crate;
- let result = self.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some((
@@ -2302,7 +2317,7 @@ fn make_missing_super_suggestion(
) -> Option<(Vec<Segment>, Option<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = kw::Super;
- let result = self.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
}
@@ -2336,7 +2351,7 @@ fn make_external_crate_suggestion(
for name in extern_crate_names.into_iter() {
// Replace first ident with a crate name and check if that is valid.
path[0].ident.name = name;
- let result = self.maybe_resolve_path(&path, None, parent_scope);
+ let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!(
"make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result
@@ -2502,12 +2517,7 @@ pub(crate) fn check_for_module_export_macro(
}
/// Finds a cfg-ed out item inside `module` with the matching name.
- pub(crate) fn find_cfg_stripped(
- &mut self,
- err: &mut Diag<'_>,
- segment: &Symbol,
- module: DefId,
- ) {
+ pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
let local_items;
let symbols = if module.is_local() {
local_items = self
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index dabed23..5ee495d 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -1,18 +1,15 @@
-use crate::{NameBinding, NameBindingKind, Resolver};
-use rustc_ast::ast;
-use rustc_ast::visit;
-use rustc_ast::visit::Visitor;
-use rustc_ast::Crate;
-use rustc_ast::EnumDef;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_middle::middle::privacy::Level;
-use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
-use rustc_middle::ty::Visibility;
use std::mem;
+
+use rustc_ast::visit::Visitor;
+use rustc_ast::{ast, visit, Crate, EnumDef};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
+use rustc_middle::ty::Visibility;
use tracing::info;
+use crate::{NameBinding, NameBindingKind, Resolver};
+
#[derive(Clone, Copy)]
enum ParentId<'a> {
Def(LocalDefId),
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 6981477..ad1841e 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1,11 +1,11 @@
-use rustc_errors::{codes::*, Applicability, ElidedLifetimeInPathSubdiag, MultiSpan};
+use rustc_errors::codes::*;
+use rustc_errors::{Applicability, ElidedLifetimeInPathSubdiag, MultiSpan};
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_span::{
- symbol::{Ident, Symbol},
- Span,
-};
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::Span;
-use crate::{late::PatternSource, Res};
+use crate::late::PatternSource;
+use crate::Res;
#[derive(Diagnostic)]
#[diag(resolve_generic_params_from_outer_item, code = E0401)]
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index f1934ff..149c639 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1,30 +1,29 @@
use rustc_ast::{self as ast, NodeId};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
-use rustc_middle::bug;
-use rustc_middle::ty;
+use rustc_middle::{bug, ty};
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::feature_err;
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
-use rustc_span::sym;
use rustc_span::symbol::{kw, Ident};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
use tracing::{debug, instrument};
-
-use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
-use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
-use crate::macros::{sub_namespace_match, MacroRulesScope};
-use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
-use crate::{BindingKey, Used};
-use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
-use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
-use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak};
-
use Determinacy::*;
use Namespace::*;
+use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
+use crate::imports::Import;
+use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
+use crate::macros::{sub_namespace_match, MacroRulesScope};
+use crate::{
+ errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, Determinacy, Finalize,
+ ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding,
+ NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope,
+ ScopeSet, Segment, ToNameBinding, Used, Weak,
+};
+
type Visibility = ty::Visibility<LocalDefId>;
#[derive(Copy, Clone)]
@@ -353,6 +352,7 @@ pub(crate) fn resolve_ident_in_lexical_scope(
parent_scope,
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
ignore_binding,
+ None,
);
if let Ok(binding) = item {
// The ident resolves to an item.
@@ -366,6 +366,7 @@ pub(crate) fn resolve_ident_in_lexical_scope(
finalize,
finalize.is_some(),
ignore_binding,
+ None,
)
.ok()
.map(LexicalScopeBinding::Item)
@@ -385,6 +386,7 @@ pub(crate) fn early_resolve_ident_in_lexical_scope(
finalize: Option<Finalize>,
force: bool,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> {
bitflags::bitflags! {
#[derive(Clone, Copy)]
@@ -457,6 +459,7 @@ struct Flags: u8 {
parent_scope,
true,
force,
+ ignore_import,
) {
Ok((Some(ext), _)) => {
if ext.helper_attrs.contains(&ident.name) {
@@ -498,6 +501,7 @@ struct Flags: u8 {
parent_scope,
finalize,
ignore_binding,
+ ignore_import,
);
match binding {
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
@@ -520,6 +524,7 @@ struct Flags: u8 {
!matches!(scope_set, ScopeSet::Late(..)),
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
ignore_binding,
+ ignore_import,
);
match binding {
Ok(binding) => {
@@ -587,6 +592,7 @@ struct Flags: u8 {
parent_scope,
None,
ignore_binding,
+ ignore_import,
) {
if matches!(use_prelude, UsePrelude::Yes)
|| this.is_builtin_macro(binding.res())
@@ -740,8 +746,9 @@ pub(crate) fn maybe_resolve_ident_in_module(
ident: Ident,
ns: Namespace,
parent_scope: &ParentScope<'a>,
+ ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> {
- self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None)
+ self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import)
.map_err(|(determinacy, _)| determinacy)
}
@@ -754,9 +761,18 @@ pub(crate) fn resolve_ident_in_module(
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> {
- self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding)
- .map_err(|(determinacy, _)| determinacy)
+ self.resolve_ident_in_module_ext(
+ module,
+ ident,
+ ns,
+ parent_scope,
+ finalize,
+ ignore_binding,
+ ignore_import,
+ )
+ .map_err(|(determinacy, _)| determinacy)
}
#[instrument(level = "debug", skip(self))]
@@ -768,6 +784,7 @@ fn resolve_ident_in_module_ext(
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let tmp_parent_scope;
let mut adjusted_parent_scope = parent_scope;
@@ -794,6 +811,7 @@ fn resolve_ident_in_module_ext(
false,
finalize,
ignore_binding,
+ ignore_import,
)
}
@@ -806,6 +824,7 @@ fn resolve_ident_in_module_unadjusted(
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_unadjusted_ext(
module,
@@ -815,6 +834,7 @@ fn resolve_ident_in_module_unadjusted(
false,
finalize,
ignore_binding,
+ ignore_import,
)
.map_err(|(determinacy, _)| determinacy)
}
@@ -833,6 +853,7 @@ fn resolve_ident_in_module_unadjusted_ext(
// This binding should be ignored during in-module resolution, so that we don't get
// "self-confirming" import resolutions during import validation and checking.
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
@@ -845,6 +866,7 @@ fn resolve_ident_in_module_unadjusted_ext(
finalize,
finalize.is_some(),
ignore_binding,
+ ignore_import,
);
return binding.map_err(|determinacy| (determinacy, Weak::No));
}
@@ -881,6 +903,7 @@ fn resolve_ident_in_module_unadjusted_ext(
finalize,
finalize.is_some(),
ignore_binding,
+ ignore_import,
);
return binding.map_err(|determinacy| (determinacy, Weak::No));
}
@@ -964,25 +987,23 @@ fn resolve_ident_in_module_unadjusted_ext(
// Check if one of single imports can still define the name,
// if it can then our result is not determined and can be invalidated.
for single_import in &resolution.single_imports {
- let Some(import_vis) = single_import.vis.get() else {
- // This branch handles a cycle in single imports, which occurs
- // when we've previously **steal** the `vis` value during an import
- // process.
+ if ignore_import == Some(*single_import) {
+ // This branch handles a cycle in single imports.
//
// For example:
// ```
// use a::b;
// use b as a;
// ```
- // 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the
+ // 1. Record `use a::b` as the `ignore_import` and attempt to locate `a` in the
// current module.
// 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
// and try to find `b` in the current module.
// 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
// This leads to entering this branch.
continue;
- };
- if !self.is_accessible_from(import_vis, parent_scope.module) {
+ }
+ if !self.is_accessible_from(single_import.vis, parent_scope.module) {
continue;
}
if let Some(ignored) = ignore_binding
@@ -1024,6 +1045,7 @@ fn resolve_ident_in_module_unadjusted_ext(
&single_import.parent_scope,
None,
ignore_binding,
+ ignore_import,
) {
Err(Determined) => continue,
Ok(binding)
@@ -1072,10 +1094,10 @@ fn resolve_ident_in_module_unadjusted_ext(
// Check if one of glob imports can still define the name,
// if it can then our "no resolution" result is not determined and can be invalidated.
for glob_import in module.globs.borrow().iter() {
- let Some(import_vis) = glob_import.vis.get() else {
+ if ignore_import == Some(*glob_import) {
continue;
- };
- if !self.is_accessible_from(import_vis, parent_scope.module) {
+ }
+ if !self.is_accessible_from(glob_import.vis, parent_scope.module) {
continue;
}
let module = match glob_import.imported_module.get() {
@@ -1102,6 +1124,7 @@ fn resolve_ident_in_module_unadjusted_ext(
adjusted_parent_scope,
None,
ignore_binding,
+ ignore_import,
);
match result {
@@ -1414,8 +1437,9 @@ pub(crate) fn maybe_resolve_path(
path: &[Segment],
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
+ ignore_import: Option<Import<'a>>,
) -> PathResult<'a> {
- self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None)
+ self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import)
}
#[instrument(level = "debug", skip(self))]
@@ -1426,8 +1450,17 @@ pub(crate) fn resolve_path(
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> PathResult<'a> {
- self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding)
+ self.resolve_path_with_ribs(
+ path,
+ opt_ns,
+ parent_scope,
+ finalize,
+ None,
+ ignore_binding,
+ ignore_import,
+ )
}
pub(crate) fn resolve_path_with_ribs(
@@ -1438,6 +1471,7 @@ pub(crate) fn resolve_path_with_ribs(
finalize: Option<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
ignore_binding: Option<NameBinding<'a>>,
+ ignore_import: Option<Import<'a>>,
) -> PathResult<'a> {
let mut module = None;
let mut allow_super = true;
@@ -1540,10 +1574,12 @@ pub(crate) fn resolve_path_with_ribs(
parent_scope,
finalize,
ignore_binding,
+ ignore_import,
)
} else if let Some(ribs) = ribs
&& let Some(TypeNS | ValueNS) = opt_ns
{
+ assert!(ignore_import.is_none());
match self.resolve_ident_in_lexical_scope(
ident,
ns,
@@ -1572,6 +1608,7 @@ pub(crate) fn resolve_path_with_ribs(
finalize,
finalize.is_some(),
ignore_binding,
+ ignore_import,
)
};
@@ -1646,6 +1683,7 @@ pub(crate) fn resolve_path_with_ribs(
parent_scope,
ribs,
ignore_binding,
+ ignore_import,
module,
segment_idx,
ident,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index d05326e..42171ed 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1,32 +1,20 @@
//! A bunch of methods and structures more or less related to resolving imports.
-use crate::diagnostics::{import_candidates, DiagMode, Suggestion};
-use crate::errors::{
- CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
- CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
- ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
- ItemsInTraitsAreNotImportable,
-};
-use crate::Determinacy::{self, *};
-use crate::{module_to_string, names_to_string, ImportSuggestion};
-use crate::{AmbiguityError, Namespace::*};
-use crate::{AmbiguityKind, BindingKey, ResolutionError, Resolver, Segment};
-use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
-use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult, Used};
+use std::cell::Cell;
+use std::mem;
use rustc_ast::NodeId;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
-use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
+use rustc_errors::codes::*;
+use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan};
use rustc_hir::def::{self, DefKind, PartialRes};
use rustc_hir::def_id::DefId;
-use rustc_middle::metadata::ModChild;
-use rustc_middle::metadata::Reexport;
-use rustc_middle::span_bug;
-use rustc_middle::ty;
+use rustc_middle::metadata::{ModChild, Reexport};
+use rustc_middle::{span_bug, ty};
use rustc_session::lint::builtin::{
AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
- UNUSED_IMPORTS,
+ REDUNDANT_IMPORTS, UNUSED_IMPORTS,
};
use rustc_session::lint::BuiltinLintDiag;
use rustc_span::edit_distance::find_best_match_for_name;
@@ -36,8 +24,20 @@
use smallvec::SmallVec;
use tracing::debug;
-use std::cell::Cell;
-use std::mem;
+use crate::diagnostics::{import_candidates, DiagMode, Suggestion};
+use crate::errors::{
+ CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
+ CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
+ ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
+ ItemsInTraitsAreNotImportable,
+};
+use crate::Determinacy::{self, *};
+use crate::Namespace::*;
+use crate::{
+ module_to_string, names_to_string, AmbiguityError, AmbiguityKind, BindingKey, Finalize,
+ ImportSuggestion, Module, ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind,
+ ParentScope, PathResult, PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used,
+};
type Res = def::Res<NodeId>;
@@ -48,6 +48,7 @@ pub(crate) enum ImportKind<'a> {
/// `source` in `use prefix::source as target`.
source: Ident,
/// `target` in `use prefix::source as target`.
+ /// It will directly use `source` when the format is `use prefix::source`.
target: Ident,
/// Bindings to which `source` refers to.
source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
@@ -174,8 +175,7 @@ pub(crate) struct ImportData<'a> {
pub module_path: Vec<Segment>,
/// The resolution of `module_path`.
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
- pub vis: Cell<Option<ty::Visibility>>,
- pub used: Cell<Option<Used>>,
+ pub vis: ty::Visibility,
}
/// All imports are unique and allocated on a same arena,
@@ -194,10 +194,6 @@ pub(crate) fn is_nested(&self) -> bool {
}
}
- pub(crate) fn expect_vis(&self) -> ty::Visibility {
- self.vis.get().expect("encountered cleared import visibility")
- }
-
pub(crate) fn id(&self) -> Option<NodeId> {
match self.kind {
ImportKind::Single { id, .. }
@@ -266,7 +262,7 @@ fn pub_use_of_private_extern_crate_hack(
match (&import.kind, &binding.kind) {
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
if let ImportKind::ExternCrate { id, .. } = binding_import.kind
- && import.expect_vis().is_public() =>
+ && import.vis.is_public() =>
{
Some(id)
}
@@ -278,7 +274,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Given a binding and an import that resolves to it,
/// return the corresponding binding defined by the import.
pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
- let import_vis = import.expect_vis().to_def_id();
+ let import_vis = import.vis.to_def_id();
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|| pub_use_of_private_extern_crate_hack(import, binding).is_some()
{
@@ -487,7 +483,7 @@ fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) {
});
self.record_use(target, dummy_binding, Used::Other);
} else if import.imported_module.get().is_none() {
- import.used.set(Some(Used::Other));
+ self.import_use_map.insert(import, Used::Other);
if let Some(id) = import.id() {
self.used_imports.insert(id);
}
@@ -772,11 +768,12 @@ fn resolve_import(&mut self, import: Import<'a>) -> usize {
let module = if let Some(module) = import.imported_module.get() {
module
} else {
- // For better failure detection, pretend that the import will
- // not define any names while resolving its module path.
- let orig_vis = import.vis.take();
- let path_res = self.maybe_resolve_path(&import.module_path, None, &import.parent_scope);
- import.vis.set(orig_vis);
+ let path_res = self.maybe_resolve_path(
+ &import.module_path,
+ None,
+ &import.parent_scope,
+ Some(import),
+ );
match path_res {
PathResult::Module(module) => module,
@@ -806,16 +803,13 @@ fn resolve_import(&mut self, import: Import<'a>) -> usize {
self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
if let Err(Undetermined) = source_bindings[ns].get() {
- // For better failure detection, pretend that the import will
- // not define any names while resolving its module path.
- let orig_vis = import.vis.take();
let binding = this.maybe_resolve_ident_in_module(
module,
source,
ns,
&import.parent_scope,
+ Some(import),
);
- import.vis.set(orig_vis);
source_bindings[ns].set(binding);
} else {
return;
@@ -854,7 +848,6 @@ fn resolve_import(&mut self, import: Import<'a>) -> usize {
/// Optionally returns an unresolved import error. This error is buffered and used to
/// consolidate multiple unresolved import errors into a single diagnostic.
fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
- let orig_vis = import.vis.take();
let ignore_binding = match &import.kind {
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
_ => None,
@@ -873,11 +866,12 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
&import.parent_scope,
Some(finalize),
ignore_binding,
+ Some(import),
);
let no_ambiguity =
ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
- import.vis.set(orig_vis);
+
let module = match path_res {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
@@ -1012,8 +1006,7 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
}
if !is_prelude
&& let Some(max_vis) = max_vis.get()
- && let import_vis = import.expect_vis()
- && !max_vis.is_at_least(import_vis, self.tcx)
+ && !max_vis.is_at_least(import.vis, self.tcx)
{
let def_id = self.local_def_id(id);
self.lint_buffer.buffer_lint(
@@ -1022,7 +1015,7 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
import.span,
BuiltinLintDiag::RedundantImportVisibility {
max_vis: max_vis.to_string(def_id, self.tcx),
- import_vis: import_vis.to_string(def_id, self.tcx),
+ import_vis: import.vis.to_string(def_id, self.tcx),
span: import.span,
},
);
@@ -1037,9 +1030,14 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
// importing it if available.
let mut path = import.module_path.clone();
path.push(Segment::from_ident(ident));
- if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
- self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding)
- {
+ if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(
+ &path,
+ None,
+ &import.parent_scope,
+ Some(finalize),
+ ignore_binding,
+ None,
+ ) {
let res = module.res().map(|r| (r, ident));
for error in &mut self.privacy_errors[privacy_errors_len..] {
error.outermost_res = res;
@@ -1050,7 +1048,6 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
let mut all_ns_err = true;
self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
- let orig_vis = import.vis.take();
let binding = this.resolve_ident_in_module(
module,
ident,
@@ -1058,8 +1055,8 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
&import.parent_scope,
Some(Finalize { report_private: false, ..finalize }),
target_bindings[ns].get(),
+ Some(import),
);
- import.vis.set(orig_vis);
match binding {
Ok(binding) => {
@@ -1122,6 +1119,7 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
&import.parent_scope,
Some(finalize),
None,
+ None,
);
if binding.is_ok() {
all_ns_failed = false;
@@ -1232,7 +1230,7 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportErro
let mut crate_private_reexport = false;
self.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
- if !binding.vis.is_at_least(import.expect_vis(), this.tcx) {
+ if !binding.vis.is_at_least(import.vis, this.tcx) {
reexport_error = Some((ns, binding));
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
if binding_def_id.is_top_level_module() {
@@ -1348,7 +1346,7 @@ pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool
// module defined by a block).
// Skip if the import is public or was used through non scope-based resolution,
// e.g. through a module-relative path.
- if import.used.get() == Some(Used::Other)
+ if self.import_use_map.get(&import) == Some(&Used::Other)
|| self.effective_visibilities.is_exported(self.local_def_id(id))
{
return false;
@@ -1369,6 +1367,7 @@ pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool
None,
false,
target_bindings[ns].get(),
+ None,
) {
Ok(other_binding) => {
is_redundant = binding.res() == other_binding.res()
@@ -1387,14 +1386,12 @@ pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
redundant_spans.sort();
redundant_spans.dedup();
- /* FIXME(unused_imports): Add this back as a new lint
- self.lint_buffer.buffer_lint_with_diagnostic(
- UNUSED_IMPORTS,
+ self.lint_buffer.buffer_lint(
+ REDUNDANT_IMPORTS,
id,
import.span,
BuiltinLintDiag::RedundantImport(redundant_spans, source),
);
- */
return true;
}
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 51414d7..4a70fc0 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -6,16 +6,18 @@
//! If you wonder why there's no `early.rs`, that's because it's split into three files -
//! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.
-use crate::{errors, path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
-use crate::{BindingKey, Used};
-use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
-use crate::{ResolutionError, Resolver, Segment, TyCtxt, UseError};
+use std::assert_matches::debug_assert_matches;
+use std::borrow::Cow;
+use std::collections::hash_map::Entry;
+use std::collections::BTreeSet;
+use std::mem::{replace, swap, take};
use rustc_ast::ptr::P;
use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{codes::*, Applicability, DiagArgValue, IntoDiagArg, StashKey};
+use rustc_errors::codes::*;
+use rustc_errors::{Applicability, DiagArgValue, IntoDiagArg, StashKey};
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -32,10 +34,11 @@
use smallvec::{smallvec, SmallVec};
use tracing::{debug, instrument, trace};
-use std::assert_matches::debug_assert_matches;
-use std::borrow::Cow;
-use std::collections::{hash_map::Entry, BTreeSet};
-use std::mem::{replace, swap, take};
+use crate::{
+ errors, path_names_to_string, rustdoc, BindingError, BindingKey, Finalize, LexicalScopeBinding,
+ Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult, ResolutionError, Resolver,
+ Segment, TyCtxt, UseError, Used,
+};
mod diagnostics;
@@ -442,8 +445,8 @@ fn descr_expected(self) -> &'static str {
Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind {
// the case of `::some_crate()`
ExprKind::Path(_, path)
- if path.segments.len() == 2
- && path.segments[0].ident.name == kw::PathRoot =>
+ if let [segment, _] = path.segments.as_slice()
+ && segment.ident.name == kw::PathRoot =>
{
"external crate"
}
@@ -1385,6 +1388,7 @@ fn resolve_path(
finalize,
Some(&self.ribs),
None,
+ None,
)
}
@@ -2392,15 +2396,14 @@ fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
}
fn future_proof_import(&mut self, use_tree: &UseTree) {
- let segments = &use_tree.prefix.segments;
- if !segments.is_empty() {
- let ident = segments[0].ident;
+ if let [segment, rest @ ..] = use_tree.prefix.segments.as_slice() {
+ let ident = segment.ident;
if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
return;
}
let nss = match use_tree.kind {
- UseTreeKind::Simple(..) if segments.len() == 1 => &[TypeNS, ValueNS][..],
+ UseTreeKind::Simple(..) if rest.is_empty() => &[TypeNS, ValueNS][..],
_ => &[TypeNS],
};
let report_error = |this: &Self, ns| {
@@ -2664,119 +2667,128 @@ fn with_generic_param_rib<'c, F>(
let mut function_type_rib = Rib::new(kind);
let mut function_value_rib = Rib::new(kind);
let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
- let mut seen_bindings = FxHashMap::default();
- // Store all seen lifetimes names from outer scopes.
- let mut seen_lifetimes = FxHashSet::default();
- // We also can't shadow bindings from the parent item
- if let RibKind::AssocItem = kind {
- let mut add_bindings_for_ns = |ns| {
- let parent_rib = self.ribs[ns]
- .iter()
- .rfind(|r| matches!(r.kind, RibKind::Item(..)))
- .expect("associated item outside of an item");
- seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
- };
- add_bindings_for_ns(ValueNS);
- add_bindings_for_ns(TypeNS);
- }
+ // Only check for shadowed bindings if we're declaring new params.
+ if !params.is_empty() {
+ let mut seen_bindings = FxHashMap::default();
+ // Store all seen lifetimes names from outer scopes.
+ let mut seen_lifetimes = FxHashSet::default();
- // Forbid shadowing lifetime bindings
- for rib in self.lifetime_ribs.iter().rev() {
- seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
- if let LifetimeRibKind::Item = rib.kind {
- break;
- }
- }
+ // We also can't shadow bindings from associated parent items.
+ for ns in [ValueNS, TypeNS] {
+ for parent_rib in self.ribs[ns].iter().rev() {
+ seen_bindings
+ .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
- for param in params {
- let ident = param.ident.normalize_to_macros_2_0();
- debug!("with_generic_param_rib: {}", param.id);
-
- if let GenericParamKind::Lifetime = param.kind
- && let Some(&original) = seen_lifetimes.get(&ident)
- {
- diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
- // Record lifetime res, so lowering knows there is something fishy.
- self.record_lifetime_param(param.id, LifetimeRes::Error);
- continue;
- }
-
- match seen_bindings.entry(ident) {
- Entry::Occupied(entry) => {
- let span = *entry.get();
- let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
- self.report_error(param.ident.span, err);
- let rib = match param.kind {
- GenericParamKind::Lifetime => {
- // Record lifetime res, so lowering knows there is something fishy.
- self.record_lifetime_param(param.id, LifetimeRes::Error);
- continue;
- }
- GenericParamKind::Type { .. } => &mut function_type_rib,
- GenericParamKind::Const { .. } => &mut function_value_rib,
- };
-
- // Taint the resolution in case of errors to prevent follow up errors in typeck
- self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
- rib.bindings.insert(ident, Res::Err);
- continue;
- }
- Entry::Vacant(entry) => {
- entry.insert(param.ident.span);
- }
- }
-
- if param.ident.name == kw::UnderscoreLifetime {
- self.r
- .dcx()
- .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
- // Record lifetime res, so lowering knows there is something fishy.
- self.record_lifetime_param(param.id, LifetimeRes::Error);
- continue;
- }
-
- if param.ident.name == kw::StaticLifetime {
- self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
- span: param.ident.span,
- lifetime: param.ident,
- });
- // Record lifetime res, so lowering knows there is something fishy.
- self.record_lifetime_param(param.id, LifetimeRes::Error);
- continue;
- }
-
- let def_id = self.r.local_def_id(param.id);
-
- // Plain insert (no renaming).
- let (rib, def_kind) = match param.kind {
- GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
- GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam),
- GenericParamKind::Lifetime => {
- let res = LifetimeRes::Param { param: def_id, binder };
- self.record_lifetime_param(param.id, res);
- function_lifetime_rib.bindings.insert(ident, (param.id, res));
- continue;
- }
- };
-
- let res = match kind {
- RibKind::Item(..) | RibKind::AssocItem => Res::Def(def_kind, def_id.to_def_id()),
- RibKind::Normal => {
- // FIXME(non_lifetime_binders): Stop special-casing
- // const params to error out here.
- if self.r.tcx.features().non_lifetime_binders
- && matches!(param.kind, GenericParamKind::Type { .. })
- {
- Res::Def(def_kind, def_id.to_def_id())
- } else {
- Res::Err
+ // Break at mod level, to account for nested items which are
+ // allowed to shadow generic param names.
+ if matches!(parent_rib.kind, RibKind::Module(..)) {
+ break;
}
}
- _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
- };
- self.r.record_partial_res(param.id, PartialRes::new(res));
- rib.bindings.insert(ident, res);
+ }
+
+ // Forbid shadowing lifetime bindings
+ for rib in self.lifetime_ribs.iter().rev() {
+ seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
+ if let LifetimeRibKind::Item = rib.kind {
+ break;
+ }
+ }
+
+ for param in params {
+ let ident = param.ident.normalize_to_macros_2_0();
+ debug!("with_generic_param_rib: {}", param.id);
+
+ if let GenericParamKind::Lifetime = param.kind
+ && let Some(&original) = seen_lifetimes.get(&ident)
+ {
+ diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
+ // Record lifetime res, so lowering knows there is something fishy.
+ self.record_lifetime_param(param.id, LifetimeRes::Error);
+ continue;
+ }
+
+ match seen_bindings.entry(ident) {
+ Entry::Occupied(entry) => {
+ let span = *entry.get();
+ let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
+ self.report_error(param.ident.span, err);
+ let rib = match param.kind {
+ GenericParamKind::Lifetime => {
+ // Record lifetime res, so lowering knows there is something fishy.
+ self.record_lifetime_param(param.id, LifetimeRes::Error);
+ continue;
+ }
+ GenericParamKind::Type { .. } => &mut function_type_rib,
+ GenericParamKind::Const { .. } => &mut function_value_rib,
+ };
+
+ // Taint the resolution in case of errors to prevent follow up errors in typeck
+ self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
+ rib.bindings.insert(ident, Res::Err);
+ continue;
+ }
+ Entry::Vacant(entry) => {
+ entry.insert(param.ident.span);
+ }
+ }
+
+ if param.ident.name == kw::UnderscoreLifetime {
+ self.r
+ .dcx()
+ .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
+ // Record lifetime res, so lowering knows there is something fishy.
+ self.record_lifetime_param(param.id, LifetimeRes::Error);
+ continue;
+ }
+
+ if param.ident.name == kw::StaticLifetime {
+ self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
+ span: param.ident.span,
+ lifetime: param.ident,
+ });
+ // Record lifetime res, so lowering knows there is something fishy.
+ self.record_lifetime_param(param.id, LifetimeRes::Error);
+ continue;
+ }
+
+ let def_id = self.r.local_def_id(param.id);
+
+ // Plain insert (no renaming).
+ let (rib, def_kind) = match param.kind {
+ GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
+ GenericParamKind::Const { .. } => {
+ (&mut function_value_rib, DefKind::ConstParam)
+ }
+ GenericParamKind::Lifetime => {
+ let res = LifetimeRes::Param { param: def_id, binder };
+ self.record_lifetime_param(param.id, res);
+ function_lifetime_rib.bindings.insert(ident, (param.id, res));
+ continue;
+ }
+ };
+
+ let res = match kind {
+ RibKind::Item(..) | RibKind::AssocItem => {
+ Res::Def(def_kind, def_id.to_def_id())
+ }
+ RibKind::Normal => {
+ // FIXME(non_lifetime_binders): Stop special-casing
+ // const params to error out here.
+ if self.r.tcx.features().non_lifetime_binders
+ && matches!(param.kind, GenericParamKind::Type { .. })
+ {
+ Res::Def(def_kind, def_id.to_def_id())
+ } else {
+ Res::Err
+ }
+ }
+ _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
+ };
+ self.r.record_partial_res(param.id, PartialRes::new(res));
+ rib.bindings.insert(ident, res);
+ }
}
self.lifetime_ribs.push(function_lifetime_rib);
@@ -3996,16 +4008,15 @@ fn append_result<T, E>(res1: &mut Result<Vec<T>, E>, res2: Result<Vec<T>, E>) {
if this.should_report_errs() {
if candidates.is_empty() {
- if path.len() == 2 && prefix_path.len() == 1 {
+ if path.len() == 2
+ && let [segment] = prefix_path
+ {
// Delay to check whether methond name is an associated function or not
// ```
// let foo = Foo {};
// foo::bar(); // possibly suggest to foo.bar();
//```
- err.stash(
- prefix_path[0].ident.span,
- rustc_errors::StashKey::CallAssocMethod,
- );
+ err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod);
} else {
// When there is no suggested imports, we can just emit the error
// and suggestions immediately. Note that we bypass the usually error
@@ -4183,7 +4194,7 @@ fn resolve_qpath_anywhere(
let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
if let Ok((_, res)) =
- self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false)
+ self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None)
{
return Ok(Some(PartialRes::new(res)));
}
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 941fb64..f778b0e 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1,13 +1,8 @@
// ignore-tidy-filelength
-use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
-use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind};
-use crate::late::{LifetimeBinderKind, LifetimeRes, LifetimeRibKind, LifetimeUseSet};
-use crate::ty::fast_reject::SimplifiedType;
-use crate::{errors, path_names_to_string};
-use crate::{Module, ModuleKind, ModuleOrUniformRoot};
-use crate::{PathResult, PathSource, Segment};
-use rustc_hir::def::Namespace::{self, *};
+use std::borrow::Cow;
+use std::iter;
+use std::ops::Deref;
use rustc_ast::ptr::P;
use rustc_ast::visit::{walk_ty, FnCtxt, FnKind, LifetimeCtxt, Visitor};
@@ -16,34 +11,38 @@
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
+ pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan,
SuggestionStyle,
};
use rustc_hir as hir;
+use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::{MissingLifetimeKind, PrimTy};
-use rustc_session::lint;
-use rustc_session::Session;
+use rustc_middle::ty;
+use rustc_session::{lint, Session};
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-
-use rustc_middle::ty;
-
-use std::borrow::Cow;
-use std::iter;
-use std::ops::Deref;
-
use thin_vec::ThinVec;
use tracing::debug;
use super::NoConstantGenericsReason;
+use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
+use crate::late::{
+ AliasPossibility, LateResolutionVisitor, LifetimeBinderKind, LifetimeRes, LifetimeRibKind,
+ LifetimeUseSet, RibKind,
+};
+use crate::ty::fast_reject::SimplifiedType;
+use crate::{
+ errors, path_names_to_string, Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource,
+ Segment,
+};
type Res = def::Res<ast::NodeId>;
@@ -651,14 +650,14 @@ fn try_lookup_name_relaxed(
let typo_sugg = self
.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
.to_opt_suggestion();
- if path.len() == 1
+ if let [segment] = path
&& !matches!(source, PathSource::Delegation)
&& self.self_type_is_available()
{
if let Some(candidate) =
self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
{
- let self_is_available = self.self_value_is_available(path[0].ident.span);
+ let self_is_available = self.self_value_is_available(segment.ident.span);
// Account for `Foo { field }` when suggesting `self.field` so we result on
// `Foo { field: self.field }`.
let pre = match source {
@@ -666,7 +665,7 @@ fn try_lookup_name_relaxed(
if expr
.fields
.iter()
- .any(|f| f.ident == path[0].ident && f.is_shorthand) =>
+ .any(|f| f.ident == segment.ident && f.is_shorthand) =>
{
format!("{path_str}: ")
}
@@ -1259,8 +1258,7 @@ fn get_single_associated_item(
)
})
.collect();
- if targets.len() == 1 {
- let target = targets[0];
+ if let [target] = targets.as_slice() {
return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1));
}
}
@@ -2059,6 +2057,7 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
ident,
ns,
&self.parent_scope,
+ None,
) {
let res = binding.res();
if filter_fn(res) {
@@ -2105,8 +2104,8 @@ fn lookup_typo_candidate(
filter_fn: &impl Fn(Res) -> bool,
) -> TypoCandidate {
let mut names = Vec::new();
- if path.len() == 1 {
- let mut ctxt = path.last().unwrap().ident.span.ctxt();
+ if let [segment] = path {
+ let mut ctxt = segment.ident.span.ctxt();
// Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates.
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 3dcb83d..02fdc1a 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -23,43 +23,9 @@
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
-use rustc_arena::{DroplessArena, TypedArena};
-use rustc_ast::expand::StrippedCfgItem;
-use rustc_ast::node_id::NodeMap;
-use rustc_ast::{self as ast, attr, NodeId, CRATE_NODE_ID};
-use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_data_structures::intern::Interned;
-use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{FreezeReadGuard, Lrc};
-use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed};
-use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind};
-use rustc_feature::BUILTIN_ATTRIBUTES;
-use rustc_hir::def::Namespace::{self, *};
-use rustc_hir::def::NonMacroAttrKind;
-use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
-use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::{PrimTy, TraitCandidate};
-use rustc_index::IndexVec;
-use rustc_metadata::creader::{CStore, CrateLoader};
-use rustc_middle::metadata::ModChild;
-use rustc_middle::middle::privacy::EffectiveVisibilities;
-use rustc_middle::query::Providers;
-use rustc_middle::span_bug;
-use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools};
-use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed};
-use rustc_query_system::ich::StableHashingContext;
-use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
-use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
-use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
-use smallvec::{smallvec, SmallVec};
use std::cell::{Cell, RefCell};
use std::collections::BTreeSet;
use std::fmt;
-use tracing::debug;
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use effective_visibilities::EffectiveVisibilitiesVisitor;
@@ -69,6 +35,44 @@
use imports::{Import, ImportData, ImportKind, NameResolution};
use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
+use rustc_arena::{DroplessArena, TypedArena};
+use rustc_ast::expand::StrippedCfgItem;
+use rustc_ast::node_id::NodeMap;
+use rustc_ast::{
+ self as ast, attr, AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind,
+ NodeId, Path, CRATE_NODE_ID,
+};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::intern::Interned;
+use rustc_data_structures::steal::Steal;
+use rustc_data_structures::sync::{FreezeReadGuard, Lrc};
+use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed};
+use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind};
+use rustc_feature::BUILTIN_ATTRIBUTES;
+use rustc_hir::def::Namespace::{self, *};
+use rustc_hir::def::{
+ self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS,
+};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::{PrimTy, TraitCandidate};
+use rustc_index::IndexVec;
+use rustc_metadata::creader::{CStore, CrateLoader};
+use rustc_middle::metadata::ModChild;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
+use rustc_middle::query::Providers;
+use rustc_middle::span_bug;
+use rustc_middle::ty::{
+ self, DelegationFnSig, Feed, MainDefinition, RegisteredTools, ResolverGlobalCtxt,
+ ResolverOutputs, TyCtxt, TyCtxtFeed,
+};
+use rustc_query_system::ich::StableHashingContext;
+use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
+use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
+use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{Span, DUMMY_SP};
+use smallvec::{smallvec, SmallVec};
+use tracing::debug;
type Res = def::Res<NodeId>;
@@ -174,8 +178,8 @@ enum ImplTraitContext {
/// Used for tracking import use types which will be used for redundant import checking.
/// ### Used::Scope Example
-/// ```rust,ignore (redundant_imports)
-/// #![deny(unused_imports)]
+/// ```rust,compile_fail
+/// #![deny(redundant_imports)]
/// use std::mem::drop;
/// fn main() {
/// let s = Box::new(32);
@@ -1012,6 +1016,8 @@ pub struct Resolver<'a, 'tcx> {
partial_res_map: NodeMap<PartialRes>,
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
import_res_map: NodeMap<PerNS<Option<Res>>>,
+ /// An import will be inserted into this map if it has been used.
+ import_use_map: FxHashMap<Import<'a>, Used>,
/// Resolutions for labels (node IDs of their corresponding blocks or loops).
label_res_map: NodeMap<NodeId>,
/// Resolutions for lifetimes.
@@ -1125,9 +1131,6 @@ pub struct Resolver<'a, 'tcx> {
/// Also includes of list of each fields visibility
struct_constructors: LocalDefIdMap<(Res, ty::Visibility<DefId>, Vec<ty::Visibility<DefId>>)>,
- /// Features declared for this crate.
- declared_features: FxHashSet<Symbol>,
-
lint_buffer: LintBuffer,
next_node_id: NodeId,
@@ -1176,6 +1179,10 @@ pub struct Resolver<'a, 'tcx> {
/// Simplified analogue of module `resolutions` but in trait impls, excluding glob delegations.
/// Needed because glob delegations exclude explicitly defined names.
impl_binding_keys: FxHashMap<LocalDefId, FxHashSet<BindingKey>>,
+
+ /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo`
+ /// could be a crate that wasn't imported. For diagnostics use only.
+ current_crate_outer_attr_insert_span: Span,
}
/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1338,6 +1345,7 @@ pub fn new(
tcx: TyCtxt<'tcx>,
attrs: &[ast::Attribute],
crate_span: Span,
+ current_crate_outer_attr_insert_span: Span,
arenas: &'a ResolverArenas<'a>,
) -> Resolver<'a, 'tcx> {
let root_def_id = CRATE_DEF_ID.to_def_id();
@@ -1393,7 +1401,6 @@ pub fn new(
let registered_tools = tcx.registered_tools(());
- let features = tcx.features();
let pub_vis = ty::Visibility::<DefId>::Public;
let edition = tcx.sess.edition();
@@ -1417,6 +1424,7 @@ pub fn new(
pat_span_map: Default::default(),
partial_res_map: Default::default(),
import_res_map: Default::default(),
+ import_use_map: Default::default(),
label_res_map: Default::default(),
lifetimes_res_map: Default::default(),
extra_lifetime_params_map: Default::default(),
@@ -1497,7 +1505,6 @@ pub fn new(
multi_segment_macro_resolutions: Default::default(),
builtin_attrs: Default::default(),
containers_deriving_copy: Default::default(),
- declared_features: features.declared_features.clone(),
lint_buffer: LintBuffer::default(),
next_node_id: CRATE_NODE_ID,
node_id_to_def_id,
@@ -1521,6 +1528,7 @@ pub fn new(
glob_delegation_invoc_ids: Default::default(),
impl_unexpanded_invocations: Default::default(),
impl_binding_keys: Default::default(),
+ current_crate_outer_attr_insert_span,
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1834,7 +1842,7 @@ fn resolution(
}
/// Test if AmbiguityError ambi is any identical to any one inside ambiguity_errors
- fn matches_previous_ambiguity_error(&mut self, ambi: &AmbiguityError<'_>) -> bool {
+ fn matches_previous_ambiguity_error(&self, ambi: &AmbiguityError<'_>) -> bool {
for ambiguity_error in &self.ambiguity_errors {
// if the span location and ident as well as its span are the same
if ambiguity_error.kind == ambi.kind
@@ -1895,10 +1903,9 @@ fn record_use_inner(
}
}
}
- let old_used = import.used.get();
- let new_used = Some(used);
- if new_used > old_used {
- import.used.set(new_used);
+ let old_used = self.import_use_map.entry(import).or_insert(used);
+ if *old_used < used {
+ *old_used = used;
}
if let Some(id) = import.id() {
self.used_imports.insert(id);
@@ -2110,7 +2117,7 @@ fn resolve_rustdoc_path(
}
}
- match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) {
+ match self.maybe_resolve_path(&segments, Some(ns), &parent_scope, None) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
PathResult::NonModule(path_res) => path_res.full_res(),
PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
@@ -2194,6 +2201,7 @@ fn resolve_main(&mut self) {
ident,
ValueNS,
parent_scope,
+ None,
) else {
return;
};
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index cb9bebd..7203fbe 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,13 +1,9 @@
//! A bunch of methods and structures more or less related to resolving macros and
//! interface provided by `Resolver` to macro expander.
-use crate::errors::CannotDetermineMacroResolution;
-use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope};
-use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive};
-use crate::Namespace::*;
-use crate::{BindingKey, BuiltinMacroState, Determinacy, MacroData, NameBindingKind, Used};
-use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
-use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
+use std::cell::Cell;
+use std::mem;
+
use rustc_ast::expand::StrippedCfgItem;
use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId};
use rustc_ast_pretty::pprust;
@@ -15,8 +11,10 @@
use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, StashKey};
-use rustc_expand::base::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand};
-use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::base::{
+ Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension,
+ SyntaxExtensionKind,
+};
use rustc_expand::compile_declarative_macro;
use rustc_expand::expand::{
AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
@@ -24,8 +22,7 @@
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_middle::middle::stability;
-use rustc_middle::ty::RegisteredTools;
-use rustc_middle::ty::{TyCtxt, Visibility};
+use rustc_middle::ty::{RegisteredTools, TyCtxt, Visibility};
use rustc_session::lint::builtin::{
LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, SOFT_UNSTABLE,
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_MACROS, UNUSED_MACRO_RULES,
@@ -34,12 +31,21 @@
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::edit_distance;
use rustc_span::edition::Edition;
-use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId};
-use rustc_span::hygiene::{AstPass, MacroKind};
+use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use std::cell::Cell;
-use std::mem;
+
+use crate::errors::{
+ self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
+ MacroExpectedFound, RemoveSurroundingDerive,
+};
+use crate::imports::Import;
+use crate::Namespace::*;
+use crate::{
+ BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, MacroData, ModuleKind,
+ ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError,
+ Resolver, ScopeSet, Segment, ToNameBinding, Used,
+};
type Res = def::Res<NodeId>;
@@ -103,8 +109,8 @@ enum SubNS {
// `format!("{}", path)`, because that tries to insert
// line-breaks and is slow.
fn fast_print_path(path: &ast::Path) -> Symbol {
- if path.segments.len() == 1 {
- path.segments[0].ident.name
+ if let [segment] = path.segments.as_slice() {
+ segment.ident.name
} else {
let mut path_str = String::with_capacity(64);
for (i, segment) in path.segments.iter().enumerate() {
@@ -394,6 +400,7 @@ fn resolve_derives(
&parent_scope,
true,
force,
+ None,
) {
Ok((Some(ext), _)) => {
if !ext.helper_attrs.is_empty() {
@@ -546,6 +553,7 @@ fn smart_resolve_macro_path(
force,
deleg_impl,
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
+ None,
) {
Ok((Some(ext), res)) => (ext, res),
Ok((None, res)) => (self.dummy_ext(kind), res),
@@ -699,8 +707,18 @@ pub(crate) fn resolve_macro_path(
parent_scope: &ParentScope<'a>,
trace: bool,
force: bool,
+ ignore_import: Option<Import<'a>>,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
- self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None, None)
+ self.resolve_macro_or_delegation_path(
+ path,
+ kind,
+ parent_scope,
+ trace,
+ force,
+ None,
+ None,
+ ignore_import,
+ )
}
fn resolve_macro_or_delegation_path(
@@ -712,6 +730,7 @@ fn resolve_macro_or_delegation_path(
force: bool,
deleg_impl: Option<LocalDefId>,
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
+ ignore_import: Option<Import<'a>>,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
let path_span = ast_path.span;
let mut path = Segment::from_path(ast_path);
@@ -719,16 +738,16 @@ fn resolve_macro_or_delegation_path(
// Possibly apply the macro helper hack
if deleg_impl.is_none()
&& kind == Some(MacroKind::Bang)
- && path.len() == 1
- && path[0].ident.span.ctxt().outer_expn_data().local_inner_macros
+ && let [segment] = path.as_slice()
+ && segment.ident.span.ctxt().outer_expn_data().local_inner_macros
{
- let root = Ident::new(kw::DollarCrate, path[0].ident.span);
+ let root = Ident::new(kw::DollarCrate, segment.ident.span);
path.insert(0, Segment::from_ident(root));
}
let res = if deleg_impl.is_some() || path.len() > 1 {
let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
- let res = match self.maybe_resolve_path(&path, Some(ns), parent_scope) {
+ let res = match self.maybe_resolve_path(&path, Some(ns), parent_scope, ignore_import) {
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
PathResult::NonModule(..)
@@ -763,6 +782,7 @@ fn resolve_macro_or_delegation_path(
None,
force,
None,
+ None,
);
if let Err(Determinacy::Undetermined) = binding {
return Err(Determinacy::Undetermined);
@@ -847,6 +867,7 @@ pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
&parent_scope,
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
None,
+ None,
) {
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
check_consistency(self, &path, path_span, kind, initial_res, res)
@@ -866,7 +887,7 @@ pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
if let PathResult::Failed { span, label, module, .. } = path_res {
// try to suggest if it's not a macro, maybe a function
if let PathResult::NonModule(partial_res) =
- self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope)
+ self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
&& partial_res.unresolved_segments() == 0
{
let sm = self.tcx.sess.source_map();
@@ -916,6 +937,7 @@ pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
true,
None,
+ None,
) {
Ok(binding) => {
let initial_res = initial_binding.map(|initial_binding| {
@@ -961,6 +983,7 @@ pub(crate) fn finalize_macro_resolutions(&mut self, krate: &Crate) {
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
true,
None,
+ None,
);
}
}
@@ -978,7 +1001,8 @@ fn check_stability_and_deprecation(
let feature = stability.feature;
let is_allowed = |feature| {
- self.declared_features.contains(&feature) || span.allows_unstable(feature)
+ self.tcx.features().declared_features.contains(&feature)
+ || span.allows_unstable(feature)
};
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
if !is_allowed(feature) && !allowed_by_implication {
@@ -1065,6 +1089,7 @@ fn report_out_of_scope_macro_calls(
None,
false,
None,
+ None,
);
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
self.tcx.sess.psess.buffer_lint(
@@ -1138,7 +1163,7 @@ fn path_accessible(
let mut indeterminate = false;
for ns in namespaces {
- match self.maybe_resolve_path(path, Some(*ns), &parent_scope) {
+ match self.maybe_resolve_path(path, Some(*ns), &parent_scope, None) {
PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
return Ok(true);
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 4c49c15..de4fc5c 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -1,3 +1,6 @@
+use std::mem;
+use std::ops::Range;
+
use pulldown_cmark::{
BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, Options, Parser, Tag,
};
@@ -8,8 +11,6 @@
use rustc_span::def_id::DefId;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{InnerSpan, Span, DUMMY_SP};
-use std::mem;
-use std::ops::Range;
use tracing::{debug, trace};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 190ea44..61de338 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -5,9 +5,9 @@
//! For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
//! see design document in the tracking issue #89653.
-use rustc_data_structures::base_n::ToBaseN;
-use rustc_data_structures::base_n::ALPHANUMERIC_ONLY;
-use rustc_data_structures::base_n::CASE_INSENSITIVE;
+use std::fmt::Write as _;
+
+use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY, CASE_INSENSITIVE};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_middle::bug;
@@ -20,7 +20,6 @@
use rustc_span::sym;
use rustc_target::abi::Integer;
use rustc_target::spec::abi::Abi;
-use std::fmt::Write as _;
use tracing::instrument;
use crate::cfi::typeid::itanium_cxx_abi::transform::{TransformTy, TransformTyOptions};
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
index ac664c5..cb15c67 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs
@@ -6,7 +6,7 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::bug;
-use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
use tracing::instrument;
@@ -112,11 +112,12 @@ pub fn typeid_for_instance<'tcx>(
instance: Instance<'tcx>,
options: TypeIdOptions,
) -> String {
+ assert!(!instance.has_non_region_param(), "{instance:#?} must be fully monomorphic");
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
.unwrap_or_else(|| bug!("typeid_for_instance: invalid option(s) `{:?}`", options.bits()));
let instance = transform_instance(tcx, instance, transform_ty_options);
let fn_abi = tcx
- .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty())))
+ .fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty())))
.unwrap_or_else(|error| {
bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}")
});
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 9b05576..e628c17 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -4,6 +4,8 @@
//! For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
//! see design document in the tracking issue #89653.
+use std::iter;
+
use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_middle::bug;
@@ -12,9 +14,9 @@
self, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy, List, TraitRef, Ty,
TyCtxt, TypeFoldable, TypeVisitableExt, UintTy,
};
-use rustc_span::{def_id::DefId, sym};
+use rustc_span::def_id::DefId;
+use rustc_span::sym;
use rustc_trait_selection::traits;
-use std::iter;
use tracing::{debug, instrument};
use crate::cfi::typeid::itanium_cxx_abi::encode::EncodeTyOptions;
@@ -230,6 +232,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
tcx.associated_items(super_poly_trait_ref.def_id())
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Type)
+ .filter(|item| !tcx.generics_require_sized_self(item.def_id))
.map(move |assoc_ty| {
super_poly_trait_ref.map_bound(|super_trait_ref| {
let alias_ty =
diff --git a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs
index bfe907e..b47a091 100644
--- a/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs
+++ b/compiler/rustc_sanitizers/src/kcfi/typeid/mod.rs
@@ -4,9 +4,10 @@
//! For more information about LLVM KCFI and cross-language LLVM KCFI support for the Rust compiler,
//! see the tracking issue #123479.
+use std::hash::Hasher;
+
use rustc_middle::ty::{Instance, InstanceKind, ReifyReason, Ty, TyCtxt};
use rustc_target::abi::call::FnAbi;
-use std::hash::Hasher;
use twox_hash::XxHash64;
pub use crate::cfi::typeid::{itanium_cxx_abi, TypeIdOptions};
diff --git a/compiler/rustc_serialize/src/leb128.rs b/compiler/rustc_serialize/src/leb128.rs
index 4432480..aa7c285 100644
--- a/compiler/rustc_serialize/src/leb128.rs
+++ b/compiler/rustc_serialize/src/leb128.rs
@@ -1,9 +1,8 @@
-use crate::opaque::MemDecoder;
-use crate::serialize::Decoder;
-
// This code is very hot and uses lots of arithmetic, avoid overflow checks for performance.
// See https://github.com/rust-lang/rust/pull/119440#issuecomment-1874255727
use crate::int_overflow::DebugStrictAdd;
+use crate::opaque::MemDecoder;
+use crate::serialize::Decoder;
/// Returns the length of the longest LEB128 encoding for `T`, assuming `T` is an integer type
pub const fn max_leb128_len<T>() -> usize {
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index d27dfd8..d8609cc 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,15 +1,14 @@
-use crate::leb128;
-use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fs::File;
use std::io::{self, Write};
use std::marker::PhantomData;
use std::ops::Range;
-use std::path::Path;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
// This code is very hot and uses lots of arithmetic, avoid overflow checks for performance.
// See https://github.com/rust-lang/rust/pull/119440#issuecomment-1874255727
use crate::int_overflow::DebugStrictAdd;
+use crate::leb128;
+use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
// -----------------------------------------------------------------------------
// Encoder
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index c84bb26..2d37f5b 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -1,6 +1,5 @@
//! Support code for encoding and decoding types.
-use smallvec::{Array, SmallVec};
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque};
@@ -10,6 +9,8 @@
use std::path;
use std::rc::Rc;
use std::sync::Arc;
+
+use smallvec::{Array, SmallVec};
use thin_vec::ThinVec;
/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string.
diff --git a/compiler/rustc_serialize/tests/leb128.rs b/compiler/rustc_serialize/tests/leb128.rs
index fafe4b9..b06a28d 100644
--- a/compiler/rustc_serialize/tests/leb128.rs
+++ b/compiler/rustc_serialize/tests/leb128.rs
@@ -1,6 +1,5 @@
use rustc_serialize::leb128::*;
-use rustc_serialize::opaque::MemDecoder;
-use rustc_serialize::opaque::MAGIC_END_BYTES;
+use rustc_serialize::opaque::{MemDecoder, MAGIC_END_BYTES};
use rustc_serialize::Decoder;
macro_rules! impl_test_unsigned_leb128 {
diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs
index 833151d..0543e17 100644
--- a/compiler/rustc_serialize/tests/opaque.rs
+++ b/compiler/rustc_serialize/tests/opaque.rs
@@ -1,10 +1,11 @@
#![allow(rustc::internal)]
+use std::fmt::Debug;
+use std::fs;
+
use rustc_macros::{Decodable_Generic, Encodable_Generic};
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
use rustc_serialize::{Decodable, Encodable};
-use std::fmt::Debug;
-use std::fs;
#[derive(PartialEq, Clone, Debug, Encodable_Generic, Decodable_Generic)]
struct Struct {
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index 93839fa..3668fe4 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -1,9 +1,10 @@
+use std::cmp;
+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lock;
use rustc_span::def_id::DefId;
use rustc_span::Symbol;
use rustc_target::abi::{Align, Size};
-use std::cmp;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct VariantInfo {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e748d1f..95d1714 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -3,13 +3,17 @@
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
-pub use crate::options::*;
+use std::collections::btree_map::{
+ Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
+};
+use std::collections::{BTreeMap, BTreeSet};
+use std::ffi::OsStr;
+use std::hash::Hash;
+use std::path::{Path, PathBuf};
+use std::str::{self, FromStr};
+use std::sync::LazyLock;
+use std::{fmt, fs, iter};
-use crate::errors::FileWriteFail;
-use crate::search_paths::SearchPath;
-use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use crate::{filesearch, lint, HashStableContext};
-use crate::{EarlyDiagCtxt, Session};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
use rustc_errors::emitter::HumanReadableErrorType;
@@ -19,22 +23,17 @@
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
-use rustc_target::spec::{FramePointer, LinkSelfContainedComponents, LinkerFeatures};
-use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
-use std::collections::btree_map::{
- Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
+use rustc_target::spec::{
+ FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTriple,
};
-use std::collections::{BTreeMap, BTreeSet};
-use std::ffi::OsStr;
-use std::fmt;
-use std::fs;
-use std::hash::Hash;
-use std::iter;
-use std::path::{Path, PathBuf};
-use std::str::{self, FromStr};
-use std::sync::LazyLock;
use tracing::debug;
+use crate::errors::FileWriteFail;
+pub use crate::options::*;
+use crate::search_paths::SearchPath;
+use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
+use crate::{filesearch, lint, EarlyDiagCtxt, HashStableContext, Session};
+
mod cfg;
pub mod sigpipe;
@@ -603,7 +602,7 @@ pub fn is_text_output(&self) -> bool {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
/// Output meant for the consumption of humans.
- HumanReadable(HumanReadableErrorType),
+ HumanReadable(HumanReadableErrorType, ColorConfig),
/// Output that's consumed by other tools such as `rustfix` or the `RLS`.
Json {
/// Render the JSON in a human readable way (with indents and newlines).
@@ -611,12 +610,13 @@ pub enum ErrorOutputType {
/// The JSON output includes a `rendered` field that includes the rendered
/// human output.
json_rendered: HumanReadableErrorType,
+ color_config: ColorConfig,
},
}
impl Default for ErrorOutputType {
fn default() -> Self {
- Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
+ Self::HumanReadable(HumanReadableErrorType::Default, ColorConfig::Auto)
}
}
@@ -839,10 +839,14 @@ pub enum Input {
impl Input {
pub fn filestem(&self) -> &str {
- match *self {
- Input::File(ref ifile) => ifile.file_stem().unwrap().to_str().unwrap(),
- Input::Str { .. } => "rust_out",
+ if let Input::File(ifile) = self {
+ // If for some reason getting the file stem as a UTF-8 string fails,
+ // then fallback to a fixed name.
+ if let Some(name) = ifile.file_stem().and_then(OsStr::to_str) {
+ return name;
+ }
}
+ "rust_out"
}
pub fn source_name(&self) -> FileName {
@@ -1301,7 +1305,10 @@ pub(crate) const fn default_lib_output() -> CrateType {
}
pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
- // Combine the configuration requested by the session (command line) with
+ // First disallow some configuration given on the command line
+ cfg::disallow_cfgs(sess, &user_cfg);
+
+ // Then combine the configuration requested by the session (command line) with
// some default and generated configuration items.
user_cfg.extend(cfg::default_configuration(sess));
user_cfg
@@ -1625,6 +1632,7 @@ pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Col
/// Possible json config files
pub struct JsonConfig {
pub json_rendered: HumanReadableErrorType,
+ pub json_color: ColorConfig,
json_artifact_notifications: bool,
pub json_unused_externs: JsonUnusedExterns,
json_future_incompat: bool,
@@ -1662,8 +1670,7 @@ pub fn is_loud(&self) -> bool {
/// The first value returned is how to render JSON diagnostics, and the second
/// is whether or not artifact notifications are enabled.
pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig {
- let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
- HumanReadableErrorType::Default;
+ let mut json_rendered = HumanReadableErrorType::Default;
let mut json_color = ColorConfig::Never;
let mut json_artifact_notifications = false;
let mut json_unused_externs = JsonUnusedExterns::No;
@@ -1690,7 +1697,8 @@ pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Json
}
JsonConfig {
- json_rendered: json_rendered(json_color),
+ json_rendered,
+ json_color,
json_artifact_notifications,
json_unused_externs,
json_future_incompat,
@@ -1702,6 +1710,7 @@ pub fn parse_error_format(
early_dcx: &mut EarlyDiagCtxt,
matches: &getopts::Matches,
color: ColorConfig,
+ json_color: ColorConfig,
json_rendered: HumanReadableErrorType,
) -> ErrorOutputType {
// We need the `opts_present` check because the driver will send us Matches
@@ -1711,18 +1720,22 @@ pub fn parse_error_format(
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
match matches.opt_str("error-format").as_deref() {
None | Some("human") => {
- ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
+ ErrorOutputType::HumanReadable(HumanReadableErrorType::Default, color)
}
Some("human-annotate-rs") => {
- ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color))
+ ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet, color)
}
- Some("json") => ErrorOutputType::Json { pretty: false, json_rendered },
- Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered },
- Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
-
+ Some("json") => {
+ ErrorOutputType::Json { pretty: false, json_rendered, color_config: json_color }
+ }
+ Some("pretty-json") => {
+ ErrorOutputType::Json { pretty: true, json_rendered, color_config: json_color }
+ }
+ Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short, color),
Some(arg) => {
early_dcx.abort_if_error_and_set_error_format(ErrorOutputType::HumanReadable(
- HumanReadableErrorType::Default(color),
+ HumanReadableErrorType::Default,
+ color,
));
early_dcx.early_fatal(format!(
"argument for `--error-format` must be `human`, `json` or \
@@ -1731,7 +1744,7 @@ pub fn parse_error_format(
}
}
} else {
- ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
+ ErrorOutputType::HumanReadable(HumanReadableErrorType::Default, color)
};
match error_format {
@@ -1785,7 +1798,7 @@ fn check_error_format_stability(
if let ErrorOutputType::Json { pretty: true, .. } = error_format {
early_dcx.early_fatal("`--error-format=pretty-json` is unstable");
}
- if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
+ if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet, _) =
error_format
{
early_dcx.early_fatal("`--error-format=human-annotate-rs` is unstable");
@@ -2386,12 +2399,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
let JsonConfig {
json_rendered,
+ json_color,
json_artifact_notifications,
json_unused_externs,
json_future_incompat,
} = parse_json(early_dcx, matches);
- let error_format = parse_error_format(early_dcx, matches, color, json_rendered);
+ let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered);
early_dcx.abort_if_error_and_set_error_format(error_format);
@@ -2765,9 +2779,10 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
}
pub mod nightly_options {
+ use rustc_feature::UnstableFeatures;
+
use super::{OptionStability, RustcOptGroup};
use crate::EarlyDiagCtxt;
- use rustc_feature::UnstableFeatures;
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
match_is_nightly_build(matches)
@@ -2960,6 +2975,22 @@ pub enum WasiExecModel {
/// we have an opt-in scheme here, so one is hopefully forced to think about
/// how the hash should be calculated when adding a new command-line argument.
pub(crate) mod dep_tracking {
+ use std::collections::BTreeMap;
+ use std::hash::{DefaultHasher, Hash};
+ use std::num::NonZero;
+ use std::path::PathBuf;
+
+ use rustc_data_structures::fx::FxIndexMap;
+ use rustc_data_structures::stable_hasher::Hash64;
+ use rustc_errors::LanguageIdentifier;
+ use rustc_feature::UnstableFeatures;
+ use rustc_span::edition::Edition;
+ use rustc_span::RealFileName;
+ use rustc_target::spec::{
+ CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
+ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, WasmCAbi,
+ };
+
use super::{
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
@@ -2971,20 +3002,6 @@ pub(crate) mod dep_tracking {
};
use crate::lint;
use crate::utils::NativeLib;
- use rustc_data_structures::fx::FxIndexMap;
- use rustc_data_structures::stable_hasher::Hash64;
- use rustc_errors::LanguageIdentifier;
- use rustc_feature::UnstableFeatures;
- use rustc_span::edition::Edition;
- use rustc_span::RealFileName;
- use rustc_target::spec::{
- CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
- RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, WasmCAbi,
- };
- use std::collections::BTreeMap;
- use std::hash::{DefaultHasher, Hash};
- use std::num::NonZero;
- use std::path::PathBuf;
pub(crate) trait DepTrackingHash {
fn hash(
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 2fa04bb..a64b1e2 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -17,20 +17,23 @@
//! - Add the activation logic in [`default_configuration`]
//! - Add the cfg to [`CheckCfg::fill_well_known`] (and related files),
//! so that the compiler can know the cfg is expected
+//! - Add the cfg in [`disallow_cfgs`] to disallow users from setting it via `--cfg`
//! - Add the feature gating in `compiler/rustc_feature/src/builtin_attrs.rs`
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::Align;
-use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet};
-use rustc_target::spec::{Target, TargetTriple, TARGETS};
-
-use crate::config::CrateType;
-use crate::Session;
-
use std::hash::Hash;
use std::iter;
+use rustc_ast::ast;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use rustc_lint_defs::builtin::EXPLICIT_BUILTIN_CFGS_IN_FLAGS;
+use rustc_lint_defs::BuiltinLintDiag;
+use rustc_span::symbol::{sym, Symbol};
+use rustc_target::abi::Align;
+use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, Target, TargetTriple, TARGETS};
+
+use crate::config::CrateType;
+use crate::Session;
+
/// The parsed `--cfg` options that define the compilation environment of the
/// crate, used to drive conditional compilation.
///
@@ -83,6 +86,67 @@ fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
}
}
+/// Disallow builtin cfgs from the CLI.
+pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
+ let disallow = |cfg: &(Symbol, Option<Symbol>), controlled_by| {
+ let cfg_name = cfg.0;
+ let cfg = if let Some(value) = cfg.1 {
+ format!(r#"{}="{}""#, cfg_name, value)
+ } else {
+ format!("{}", cfg_name)
+ };
+ sess.psess.opt_span_buffer_lint(
+ EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
+ None,
+ ast::CRATE_NODE_ID,
+ BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by },
+ )
+ };
+
+ // We want to restrict setting builtin cfgs that will produce incoherent behavior
+ // between the cfg and the rustc cli flag that sets it.
+ //
+ // The tests are in tests/ui/cfg/disallowed-cli-cfgs.rs.
+
+ // By-default all builtin cfgs are disallowed, only those are allowed:
+ // - test: as it makes sense to the have the `test` cfg active without the builtin
+ // test harness. See Cargo `harness = false` config.
+ //
+ // Cargo `--cfg test`: https://github.com/rust-lang/cargo/blob/bc89bffa5987d4af8f71011c7557119b39e44a65/src/cargo/core/compiler/mod.rs#L1124
+
+ for cfg in user_cfgs {
+ match cfg {
+ (sym::overflow_checks, None) => disallow(cfg, "-C overflow-checks"),
+ (sym::debug_assertions, None) => disallow(cfg, "-C debug-assertions"),
+ (sym::ub_checks, None) => disallow(cfg, "-Z ub-checks"),
+ (sym::sanitize, None | Some(_)) => disallow(cfg, "-Z sanitizer"),
+ (
+ sym::sanitizer_cfi_generalize_pointers | sym::sanitizer_cfi_normalize_integers,
+ None | Some(_),
+ ) => disallow(cfg, "-Z sanitizer=cfi"),
+ (sym::proc_macro, None) => disallow(cfg, "--crate-type proc-macro"),
+ (sym::panic, Some(sym::abort | sym::unwind)) => disallow(cfg, "-C panic"),
+ (sym::target_feature, Some(_)) => disallow(cfg, "-C target-feature"),
+ (sym::unix, None)
+ | (sym::windows, None)
+ | (sym::relocation_model, Some(_))
+ | (sym::target_abi, None | Some(_))
+ | (sym::target_arch, Some(_))
+ | (sym::target_endian, Some(_))
+ | (sym::target_env, None | Some(_))
+ | (sym::target_family, Some(_))
+ | (sym::target_os, Some(_))
+ | (sym::target_pointer_width, Some(_))
+ | (sym::target_vendor, None | Some(_))
+ | (sym::target_has_atomic, Some(_))
+ | (sym::target_has_atomic_equal_alignment, Some(_))
+ | (sym::target_has_atomic_load_store, Some(_))
+ | (sym::target_thread_local, None) => disallow(cfg, "--target"),
+ _ => {}
+ }
+ }
+}
+
/// Generate the default configs for a given session
pub(crate) fn default_configuration(sess: &Session) -> Cfg {
let mut ret = Cfg::default();
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 2c20c3f..da7a82f 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -2,8 +2,9 @@
//! are *mostly* used as a part of that interface, but these should
//! probably get a better home if someone can find one.
-use crate::search_paths::PathKind;
-use crate::utils::NativeLibKind;
+use std::any::Any;
+use std::path::PathBuf;
+
use rustc_ast as ast;
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
use rustc_hir::def_id::{
@@ -15,8 +16,8 @@
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
-use std::any::Any;
-use std::path::PathBuf;
+use crate::search_paths::PathKind;
+use crate::utils::NativeLibKind;
// lonely orphan structs and enums looking for a better home
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 4cbc1b5..5cc54a5 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -2,15 +2,17 @@
use rustc_ast::token;
use rustc_ast::util::literal::LitError;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed,
- Level, MultiSpan,
+ Diag, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level,
+ MultiSpan,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
-use crate::{config::CrateType, parse::ParseSess};
+use crate::config::CrateType;
+use crate::parse::ParseSess;
pub(crate) struct FeatureGateError {
pub(crate) span: MultiSpan,
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 6f63776..63ca5fe 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -1,13 +1,14 @@
//! A module for searching for libraries
-use crate::search_paths::{PathKind, SearchPath};
+use std::path::{Path, PathBuf};
+use std::{env, fs};
+
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
use smallvec::{smallvec, SmallVec};
-use std::env;
-use std::fs;
-use std::path::{Path, PathBuf};
use tracing::debug;
+use crate::search_paths::{PathKind, SearchPath};
+
#[derive(Clone)]
pub struct FileSearch<'a> {
sysroot: &'a Path,
@@ -18,6 +19,11 @@ pub struct FileSearch<'a> {
}
impl<'a> FileSearch<'a> {
+ pub fn cli_search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
+ let kind = self.kind;
+ self.cli_search_paths.iter().filter(move |sp| sp.kind.matches(kind))
+ }
+
pub fn search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
let kind = self.kind;
self.cli_search_paths
@@ -129,12 +135,10 @@ fn current_dll_path() -> Result<PathBuf, String> {
use std::io;
use std::os::windows::prelude::*;
- use windows::{
- core::PCWSTR,
- Win32::Foundation::HMODULE,
- Win32::System::LibraryLoader::{
- GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- },
+ use windows::core::PCWSTR;
+ use windows::Win32::Foundation::HMODULE;
+ use windows::Win32::System::LibraryLoader::{
+ GetModuleFileNameW, GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
};
let mut module = HMODULE::default();
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 8fd1876..df72e24 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1,27 +1,27 @@
-use crate::config::*;
-use crate::search_paths::SearchPath;
-use crate::utils::NativeLib;
-use crate::{lint, EarlyDiagCtxt};
-use rustc_data_structures::fx::FxIndexMap;
-use rustc_data_structures::profiling::TimePassesFormat;
-use rustc_data_structures::stable_hasher::Hash64;
-use rustc_errors::ColorConfig;
-use rustc_errors::{LanguageIdentifier, TerminalUrl};
-use rustc_feature::UnstableFeatures;
-use rustc_span::edition::Edition;
-use rustc_span::RealFileName;
-use rustc_span::SourceFileHashAlgorithm;
-use rustc_target::spec::{
- CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
- RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
- WasmCAbi,
-};
use std::collections::BTreeMap;
use std::hash::{DefaultHasher, Hasher};
use std::num::{IntErrorKind, NonZero};
use std::path::PathBuf;
use std::str;
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::profiling::TimePassesFormat;
+use rustc_data_structures::stable_hasher::Hash64;
+use rustc_errors::{ColorConfig, LanguageIdentifier, TerminalUrl};
+use rustc_feature::UnstableFeatures;
+use rustc_span::edition::Edition;
+use rustc_span::{RealFileName, SourceFileHashAlgorithm};
+use rustc_target::spec::{
+ CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
+ RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
+ WasmCAbi,
+};
+
+use crate::config::*;
+use crate::search_paths::SearchPath;
+use crate::utils::NativeLib;
+use crate::{lint, EarlyDiagCtxt};
+
macro_rules! insert {
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => {
if $sub_hashes
@@ -447,9 +447,10 @@ mod desc {
}
mod parse {
- pub(crate) use super::*;
use std::str::FromStr;
+ pub(crate) use super::*;
+
/// This is for boolean options that don't take a value and start with
/// `no-`. This style of option is deprecated.
pub(crate) fn parse_no_flag(slot: &mut bool, v: Option<&str>) -> bool {
@@ -911,16 +912,9 @@ pub(crate) fn parse_optimization_fuel(
match v {
None => false,
Some(s) => {
- let parts = s.split('=').collect::<Vec<_>>();
- if parts.len() != 2 {
- return false;
- }
- let crate_name = parts[0].to_string();
- let fuel = parts[1].parse::<u64>();
- if fuel.is_err() {
- return false;
- }
- *slot = Some((crate_name, fuel.unwrap()));
+ let [crate_name, fuel] = *s.split('=').collect::<Vec<_>>() else { return false };
+ let Ok(fuel) = fuel.parse::<u64>() else { return false };
+ *slot = Some((crate_name.to_string(), fuel));
true
}
}
@@ -1826,6 +1820,8 @@ pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
the same values as the target option of the same name"),
meta_stats: bool = (false, parse_bool, [UNTRACKED],
"gather metadata statistics (default: no)"),
+ metrics_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
+ "stores metrics about the errors being emitted by rustc to disk"),
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
(default: no)"),
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 9a53143..c2ca19e 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -1,16 +1,18 @@
//! Related to out filenames of compilation (e.g. binaries).
+use std::path::Path;
+
+use rustc_ast::{self as ast, attr};
+use rustc_errors::FatalError;
+use rustc_span::symbol::sym;
+use rustc_span::{Span, Symbol};
+
use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType};
use crate::errors::{
self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
InvalidCharacterInCrateName, InvalidCrateNameHelp,
};
use crate::Session;
-use rustc_ast::{self as ast, attr};
-use rustc_errors::FatalError;
-use rustc_span::symbol::sym;
-use rustc_span::{Span, Symbol};
-use std::path::Path;
pub fn out_filename(
sess: &Session,
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 200505a..d6c58e9 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -1,15 +1,9 @@
//! Contains `ParseSess` which holds state living beyond what one `Parser` might.
//! It also serves as an input to the parser itself.
-use crate::config::{Cfg, CheckCfg};
-use crate::errors::{
- CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp,
- FeatureDiagnosticSuggestion, FeatureGateError, SuggestUpgradeCompiler,
-};
-use crate::lint::{
- builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiag, Lint, LintId,
-};
-use crate::Session;
+use std::str;
+
+use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
@@ -24,8 +18,14 @@
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{Span, Symbol};
-use rustc_ast::attr::AttrIdGenerator;
-use std::str;
+use crate::config::{Cfg, CheckCfg};
+use crate::errors::{
+ CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp,
+ FeatureDiagnosticSuggestion, FeatureGateError, SuggestUpgradeCompiler,
+};
+use crate::lint::builtin::UNSTABLE_SYNTAX_PRE_EXPANSION;
+use crate::lint::{BufferedEarlyLint, BuiltinLintDiag, Lint, LintId};
+use crate::Session;
/// Collected spans during parsing for places where a certain feature was
/// used and should be feature gated accordingly in `check_crate`.
@@ -307,9 +307,19 @@ pub fn buffer_lint(
node_id: NodeId,
diagnostic: BuiltinLintDiag,
) {
+ self.opt_span_buffer_lint(lint, Some(span.into()), node_id, diagnostic)
+ }
+
+ pub fn opt_span_buffer_lint(
+ &self,
+ lint: &'static Lint,
+ span: Option<MultiSpan>,
+ node_id: NodeId,
+ diagnostic: BuiltinLintDiag,
+ ) {
self.buffered_lints.with_lock(|buffered_lints| {
buffered_lints.push(BufferedEarlyLint {
- span: span.into(),
+ span,
node_id,
lint_id: LintId::of(lint),
diagnostic,
diff --git a/compiler/rustc_session/src/search_paths.rs b/compiler/rustc_session/src/search_paths.rs
index 5e8adff..d65b1b8 100644
--- a/compiler/rustc_session/src/search_paths.rs
+++ b/compiler/rustc_session/src/search_paths.rs
@@ -1,8 +1,10 @@
-use crate::filesearch::make_target_lib_path;
-use crate::EarlyDiagCtxt;
+use std::path::{Path, PathBuf};
+
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_target::spec::TargetTriple;
-use std::path::{Path, PathBuf};
+
+use crate::filesearch::make_target_lib_path;
+use crate::EarlyDiagCtxt;
#[derive(Clone, Debug)]
pub struct SearchPath {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 89d029f..672dddf 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1,14 +1,11 @@
-use crate::code_stats::CodeStats;
-pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
-use crate::config::{
- self, CoverageLevel, CrateType, FunctionReturn, InstrumentCoverage, OptLevel, OutFileName,
- OutputType, RemapPathScopeComponents, SwitchWithOptPath,
-};
-use crate::config::{ErrorOutputType, Input};
-use crate::errors;
-use crate::parse::{add_feature_diagnostics, ParseSess};
-use crate::search_paths::{PathKind, SearchPath};
-use crate::{filesearch, lint};
+use std::any::Any;
+use std::ops::{Div, Mul};
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+use std::sync::atomic::AtomicBool;
+use std::sync::atomic::Ordering::SeqCst;
+use std::sync::Arc;
+use std::{env, fmt, io};
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
@@ -18,33 +15,34 @@
AtomicU64, DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock,
};
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
+use rustc_errors::codes::*;
use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter, HumanReadableErrorType};
use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{
- codes::*, fallback_fluent_bundle, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic,
+ fallback_fluent_bundle, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic,
ErrorGuaranteed, FatalAbort, FluentBundle, LazyFallbackBundle, TerminalUrl,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
use rustc_span::edition::Edition;
use rustc_span::source_map::{FilePathMapping, SourceMap};
-use rustc_span::{FileNameDisplayPreference, RealFileName};
-use rustc_span::{Span, Symbol};
+use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol};
use rustc_target::asm::InlineAsmArch;
-use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
use rustc_target::spec::{
- DebuginfoKind, SanitizerSet, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
+ CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo,
+ StackProtector, Target, TargetTriple, TlsModel,
};
-use std::any::Any;
-use std::env;
-use std::fmt;
-use std::io;
-use std::ops::{Div, Mul};
-use std::path::{Path, PathBuf};
-use std::str::FromStr;
-use std::sync::{atomic::AtomicBool, atomic::Ordering::SeqCst, Arc};
+use crate::code_stats::CodeStats;
+pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
+use crate::config::{
+ self, CoverageLevel, CrateType, ErrorOutputType, FunctionReturn, Input, InstrumentCoverage,
+ OptLevel, OutFileName, OutputType, RemapPathScopeComponents, SwitchWithOptPath,
+};
+use crate::parse::{add_feature_diagnostics, ParseSess};
+use crate::search_paths::{PathKind, SearchPath};
+use crate::{errors, filesearch, lint};
struct OptimizationFuel {
/// If `-zfuel=crate=n` is specified, initially set to `n`, otherwise `0`.
@@ -952,10 +950,10 @@ fn default_emitter(
t => t,
};
match sopts.error_format {
- config::ErrorOutputType::HumanReadable(kind) => {
- let (short, color_config) = kind.unzip();
+ config::ErrorOutputType::HumanReadable(kind, color_config) => {
+ let short = kind.short();
- if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
+ if let HumanReadableErrorType::AnnotateSnippet = kind {
let emitter = AnnotateSnippetEmitter::new(
Some(source_map),
bundle,
@@ -980,13 +978,14 @@ fn default_emitter(
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
}
}
- config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(
+ config::ErrorOutputType::Json { pretty, json_rendered, color_config } => Box::new(
JsonEmitter::new(
Box::new(io::BufWriter::new(io::stderr())),
source_map,
fallback_bundle,
pretty,
json_rendered,
+ color_config,
)
.registry(Some(registry))
.fluent_bundle(bundle)
@@ -1427,20 +1426,23 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
let fallback_bundle =
fallback_fluent_bundle(vec![rustc_errors::DEFAULT_LOCALE_RESOURCE], false);
let emitter: Box<DynEmitter> = match output {
- config::ErrorOutputType::HumanReadable(kind) => {
- let (short, color_config) = kind.unzip();
+ config::ErrorOutputType::HumanReadable(kind, color_config) => {
+ let short = kind.short();
Box::new(
HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.short_message(short),
)
}
- config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(JsonEmitter::new(
- Box::new(io::BufWriter::new(io::stderr())),
- Lrc::new(SourceMap::new(FilePathMapping::empty())),
- fallback_bundle,
- pretty,
- json_rendered,
- )),
+ config::ErrorOutputType::Json { pretty, json_rendered, color_config } => {
+ Box::new(JsonEmitter::new(
+ Box::new(io::BufWriter::new(io::stderr())),
+ Lrc::new(SourceMap::new(FilePathMapping::empty())),
+ fallback_bundle,
+ pretty,
+ json_rendered,
+ color_config,
+ ))
+ }
};
emitter
}
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index f70a53e..37528a4 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -1,11 +1,11 @@
-use crate::session::Session;
+use std::path::{Path, PathBuf};
+use std::sync::OnceLock;
+
use rustc_data_structures::profiling::VerboseTimingGuard;
use rustc_fs_util::try_canonicalize;
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use std::{
- path::{Path, PathBuf},
- sync::OnceLock,
-};
+
+use crate::session::Session;
impl Session {
pub fn timer(&self, what: &'static str) -> VerboseTimingGuard<'_> {
diff --git a/compiler/rustc_session/src/version.rs b/compiler/rustc_session/src/version.rs
index e244c77..79f97fd 100644
--- a/compiler/rustc_session/src/version.rs
+++ b/compiler/rustc_session/src/version.rs
@@ -1,10 +1,8 @@
-use rustc_macros::{current_rustc_version, Decodable, Encodable, HashStable_Generic};
-use std::{
- borrow::Cow,
- fmt::{self, Display},
-};
+use std::borrow::Cow;
+use std::fmt::{self, Display};
use rustc_errors::IntoDiagArg;
+use rustc_macros::{current_rustc_version, Decodable, Encodable, HashStable_Generic};
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(HashStable_Generic)]
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 854295d..a457746 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -5,7 +5,6 @@
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
-use crate::rustc_smir::Tables;
use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt};
use rustc_span::Symbol;
use stable_mir::abi::Layout;
@@ -21,6 +20,7 @@
use stable_mir::{CrateItem, CrateNum, DefId};
use super::RustcInternal;
+use crate::rustc_smir::Tables;
impl RustcInternal for CrateItem {
type T<'tcx> = rustc_span::def_id::DefId;
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 810ffc1..e997ea2 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -3,7 +3,11 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete.
-use crate::rustc_smir::{context::TablesWrapper, Stable, Tables};
+use std::cell::{Cell, RefCell};
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::ops::Index;
+
use rustc_data_structures::fx;
use rustc_data_structures::fx::FxIndexMap;
use rustc_middle::mir::interpret::AllocId;
@@ -15,11 +19,9 @@
use stable_mir::abi::Layout;
use stable_mir::ty::IndexedVal;
use stable_mir::Error;
-use std::cell::Cell;
-use std::cell::RefCell;
-use std::fmt::Debug;
-use std::hash::Hash;
-use std::ops::Index;
+
+use crate::rustc_smir::context::TablesWrapper;
+use crate::rustc_smir::{Stable, Tables};
mod internal;
pub mod pretty;
diff --git a/compiler/rustc_smir/src/rustc_internal/pretty.rs b/compiler/rustc_smir/src/rustc_internal/pretty.rs
index c0dce08..b752ad7 100644
--- a/compiler/rustc_smir/src/rustc_internal/pretty.rs
+++ b/compiler/rustc_smir/src/rustc_internal/pretty.rs
@@ -1,8 +1,9 @@
use std::io;
-use super::run;
use rustc_middle::ty::TyCtxt;
+use super::run;
+
pub fn write_smir_pretty<'tcx, W: io::Write>(tcx: TyCtxt<'tcx>, w: &mut W) -> io::Result<()> {
writeln!(
w,
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 5d02e3d..0519722 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -1,12 +1,10 @@
-use rustc_middle::mir::{
- interpret::{alloc_range, AllocRange, Pointer},
- ConstValue,
-};
+use rustc_middle::mir::interpret::{alloc_range, AllocRange, Pointer};
+use rustc_middle::mir::ConstValue;
+use stable_mir::mir::Mutability;
+use stable_mir::ty::{Allocation, ProvenanceMap};
use stable_mir::Error;
use crate::rustc_smir::{Stable, Tables};
-use stable_mir::mir::Mutability;
-use stable_mir::ty::{Allocation, ProvenanceMap};
/// Creates new empty `Allocation` from given `Align`.
fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs
index 0986651..883ab7c 100644
--- a/compiler/rustc_smir/src/rustc_smir/builder.rs
+++ b/compiler/rustc_smir/src/rustc_smir/builder.rs
@@ -4,12 +4,13 @@
//! monomorphic body using internal representation.
//! After that, we convert the internal representation into a stable one.
-use crate::rustc_smir::{Stable, Tables};
use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::ty::{self, TyCtxt};
+use crate::rustc_smir::{Stable, Tables};
+
/// Builds a monomorphic body for a given instance.
pub struct BodyBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index b0ced8e..f9663f2 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -5,6 +5,9 @@
#![allow(rustc::usage_of_qualified_ty)]
+use std::cell::RefCell;
+use std::iter;
+
use rustc_abi::HasDataLayout;
use rustc_hir::LangItem;
use rustc_middle::ty::layout::{
@@ -28,8 +31,6 @@
TyConst, TyKind, UintTy, VariantDef,
};
use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol};
-use std::cell::RefCell;
-use std::iter;
use crate::rustc_internal::RustcInternal;
use crate::rustc_smir::builder::BodyBuilder;
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index cbc3aae..9f554ec 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -2,7 +2,6 @@
#![allow(rustc::usage_of_qualified_ty)]
-use crate::rustc_smir::{Stable, Tables};
use rustc_middle::ty;
use rustc_target::abi::call::Conv;
use stable_mir::abi::{
@@ -14,6 +13,8 @@
use stable_mir::target::MachineSize as Size;
use stable_mir::ty::{Align, IndexedVal, VariantIdx};
+use crate::rustc_smir::{Stable, Tables};
+
impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
type T = VariantIdx;
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/error.rs b/compiler/rustc_smir/src/rustc_smir/convert/error.rs
index 3d68970..82ecfa6 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/error.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/error.rs
@@ -2,10 +2,11 @@
//!
//! Currently we encode everything as [stable_mir::Error], which is represented as a string.
-use crate::rustc_smir::{Stable, Tables};
use rustc_middle::mir::interpret::AllocError;
use rustc_middle::ty::layout::LayoutError;
+use crate::rustc_smir::{Stable, Tables};
+
impl<'tcx> Stable<'tcx> for LayoutError<'tcx> {
type T = stable_mir::Error;
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 8bfaa11..da705e6 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -1,9 +1,8 @@
//! Conversion of internal Rust compiler `mir` items to stable ones.
-use rustc_middle::bug;
-use rustc_middle::mir;
use rustc_middle::mir::interpret::alloc_range;
use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::{bug, mir};
use stable_mir::mir::alloc::GlobalAlloc;
use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
use stable_mir::ty::{Allocation, ConstantKind, MirConst};
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 82522e9..41e9698 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,6 +7,8 @@
//!
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
+use std::ops::RangeInclusive;
+
use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::mir::interpret::AllocId;
@@ -16,7 +18,6 @@
use stable_mir::mir::mono::InstanceDef;
use stable_mir::ty::{MirConstId, Span, TyConstId};
use stable_mir::{CtorKind, ItemKind};
-use std::ops::RangeInclusive;
use tracing::debug;
use crate::rustc_internal::IndexMap;
diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs
index 4c7029c..26aa782 100644
--- a/compiler/rustc_span/src/caching_source_map_view.rs
+++ b/compiler/rustc_span/src/caching_source_map_view.rs
@@ -1,7 +1,9 @@
+use std::ops::Range;
+
+use rustc_data_structures::sync::Lrc;
+
use crate::source_map::SourceMap;
use crate::{BytePos, Pos, RelativeBytePos, SourceFile, SpanData};
-use rustc_data_structures::sync::Lrc;
-use std::ops::Range;
#[derive(Clone)]
struct CacheEntry {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 5456303..a45b676 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,4 +1,6 @@
-use crate::{HashStableContext, SpanDecoder, SpanEncoder, Symbol};
+use std::fmt;
+use std::hash::{BuildHasherDefault, Hash, Hasher};
+
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{
Hash64, HashStable, StableHasher, StableOrd, ToStableHashKey,
@@ -8,8 +10,8 @@
use rustc_index::Idx;
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_serialize::{Decodable, Encodable};
-use std::fmt;
-use std::hash::{BuildHasherDefault, Hash, Hasher};
+
+use crate::{HashStableContext, SpanDecoder, SpanEncoder, Symbol};
pub type StableCrateIdMap =
indexmap::IndexMap<StableCrateId, CrateNum, BuildHasherDefault<Unhasher>>;
diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
index 87a0ccb..4f120db 100644
--- a/compiler/rustc_span/src/edit_distance.rs
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -9,9 +9,10 @@
// algorithm should not matter to the caller of the methods, which is why it is not noted in the
// documentation.
-use crate::symbol::Symbol;
use std::{cmp, mem};
+use crate::symbol::Symbol;
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 483e32c..434df35 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -24,10 +24,11 @@
// because getting it wrong can lead to nested `HygieneData::with` calls that
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
-use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
-use crate::edition::Edition;
-use crate::symbol::{kw, sym, Symbol};
-use crate::{with_session_globals, HashStableContext, Span, SpanDecoder, SpanEncoder, DUMMY_SP};
+use std::cell::RefCell;
+use std::collections::hash_map::Entry;
+use std::fmt;
+use std::hash::Hash;
+
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::{Hash64, HashStable, HashingControls, StableHasher};
@@ -36,12 +37,13 @@
use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::cell::RefCell;
-use std::collections::hash_map::Entry;
-use std::fmt;
-use std::hash::Hash;
use tracing::{debug, trace};
+use crate::def_id::{CrateNum, DefId, StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
+use crate::edition::Edition;
+use crate::symbol::{kw, sym, Symbol};
+use crate::{with_session_globals, HashStableContext, Span, SpanDecoder, SpanEncoder, DUMMY_SP};
+
/// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct SyntaxContext(u32);
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index b94f910..35fe28c 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -47,15 +47,17 @@
mod caching_source_map_view;
pub mod source_map;
-pub use self::caching_source_map_view::CachingSourceMapView;
use source_map::{SourceMap, SourceMapInputs};
+pub use self::caching_source_map_view::CachingSourceMapView;
+
pub mod edition;
use edition::Edition;
pub mod hygiene;
use hygiene::Transparency;
-pub use hygiene::{DesugaringKind, ExpnKind, MacroKind};
-pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
+pub use hygiene::{
+ DesugaringKind, ExpnData, ExpnHash, ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext,
+};
use rustc_data_structures::stable_hasher::HashingControls;
pub mod def_id;
use def_id::{CrateNum, DefId, DefIndex, DefPathHash, LocalDefId, StableCrateId, LOCAL_CRATE};
@@ -71,10 +73,6 @@
pub mod profiling;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{Hash128, Hash64, HashStable, StableHasher};
-use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock, Lrc};
-
use std::borrow::Cow;
use std::cmp::{self, Ordering};
use std::hash::Hash;
@@ -83,8 +81,10 @@
use std::str::FromStr;
use std::{fmt, iter};
-use md5::Digest;
-use md5::Md5;
+use md5::{Digest, Md5};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{Hash128, Hash64, HashStable, StableHasher};
+use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock, Lrc};
use sha1::Sha1;
use sha2::Sha256;
diff --git a/compiler/rustc_span/src/profiling.rs b/compiler/rustc_span/src/profiling.rs
index 66e5369..c5a8bd3 100644
--- a/compiler/rustc_span/src/profiling.rs
+++ b/compiler/rustc_span/src/profiling.rs
@@ -1,9 +1,9 @@
-use crate::source_map::SourceMap;
-
use std::borrow::Borrow;
use rustc_data_structures::profiling::EventArgRecorder;
+use crate::source_map::SourceMap;
+
/// Extension trait for self-profiling purposes: allows to record spans within a generic activity's
/// event arguments.
pub trait SpannedEventArgRecorder {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 14c157a..f914e8d 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -9,15 +9,16 @@
//! within the `SourceMap`, which upon request can be converted to line and column
//! information, source code snippets, etc.
-use crate::*;
+use std::io::{self, BorrowedBuf, Read};
+use std::{fs, path};
+
use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock};
use rustc_data_structures::unhash::UnhashMap;
use rustc_macros::{Decodable, Encodable};
-use std::fs;
-use std::io::{self, BorrowedBuf, Read};
-use std::path;
use tracing::{debug, instrument, trace};
+use crate::*;
+
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index 53d7b75..8988bec 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -1,14 +1,12 @@
-use crate::def_id::{DefIndex, LocalDefId};
-use crate::hygiene::SyntaxContext;
-use crate::SPAN_TRACK;
-use crate::{BytePos, SpanData};
-
use rustc_data_structures::fx::FxIndexSet;
-
// This code is very hot and uses lots of arithmetic, avoid overflow checks for performance.
// See https://github.com/rust-lang/rust/pull/119440#issuecomment-1874255727
use rustc_serialize::int_overflow::DebugStrictAdd;
+use crate::def_id::{DefIndex, LocalDefId};
+use crate::hygiene::SyntaxContext;
+use crate::{BytePos, SpanData, SPAN_TRACK};
+
/// A compressed span.
///
/// [`SpanData`] is 16 bytes, which is too big to stick everywhere. `Span` only
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index cfd263d..9cb729e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2,6 +2,9 @@
//! allows bidirectional lookup; i.e., given a value, one can easily find the
//! type, and vice versa.
+use std::hash::{Hash, Hasher};
+use std::{fmt, str};
+
use rustc_arena::DroplessArena;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::stable_hasher::{
@@ -10,10 +13,6 @@
use rustc_data_structures::sync::Lock;
use rustc_macros::{symbols, Decodable, Encodable, HashStable_Generic};
-use std::fmt;
-use std::hash::{Hash, Hasher};
-use std::str;
-
use crate::{with_session_globals, Edition, Span, DUMMY_SP};
#[cfg(test)]
@@ -277,6 +276,7 @@
Path,
PathBuf,
Pending,
+ PinCoerceUnsized,
Pointer,
Poll,
ProcMacro,
@@ -1217,6 +1217,7 @@
mir_static_mut,
mir_storage_dead,
mir_storage_live,
+ mir_tail_call,
mir_unreachable,
mir_unwind_cleanup,
mir_unwind_continue,
@@ -1618,6 +1619,7 @@
rustc_dirty,
rustc_do_not_const_check,
rustc_doc_primitive,
+ rustc_driver,
rustc_dummy,
rustc_dump_def_parents,
rustc_dump_item_bounds,
@@ -1702,9 +1704,11 @@
saturating_add,
saturating_div,
saturating_sub,
+ select_unpredictable,
self_in_typedefs,
self_struct_ctor,
semitransparent,
+ sha512_sm_x86,
shadow_call_stack,
shl,
shl_assign,
@@ -2446,13 +2450,11 @@ pub mod kw {
/// Given that `sym` is imported, use them like `sym::symbol_name`.
/// For example `sym::rustfmt` or `sym::u8`.
pub mod sym {
- use super::Symbol;
-
- #[doc(inline)]
- pub use super::sym_generated::*;
-
// Used from a macro in `librustc_feature/accepted.rs`
pub use super::kw::MacroRules as macro_rules;
+ #[doc(inline)]
+ pub use super::sym_generated::*;
+ use super::Symbol;
/// Get the symbol for an integer.
///
diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs
index 4366c5a..c6aa762 100644
--- a/compiler/rustc_span/src/symbol/tests.rs
+++ b/compiler/rustc_span/src/symbol/tests.rs
@@ -1,5 +1,4 @@
use super::*;
-
use crate::create_default_session_globals_then;
#[test]
diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs
index 9b87a14..775f311 100644
--- a/compiler/rustc_symbol_mangling/src/errors.rs
+++ b/compiler/rustc_symbol_mangling/src/errors.rs
@@ -1,8 +1,9 @@
//! Errors emitted by symbol_mangling.
+use std::fmt;
+
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
use rustc_span::Span;
-use std::fmt;
pub struct TestOutput {
pub span: Span,
diff --git a/compiler/rustc_symbol_mangling/src/hashed.rs b/compiler/rustc_symbol_mangling/src/hashed.rs
index d4cd616..8e2f949 100644
--- a/compiler/rustc_symbol_mangling/src/hashed.rs
+++ b/compiler/rustc_symbol_mangling/src/hashed.rs
@@ -1,9 +1,10 @@
-use crate::v0;
+use std::fmt::Write;
+
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::CrateNum;
use rustc_middle::ty::{Instance, TyCtxt};
-use std::fmt::Write;
+use crate::v0;
pub(super) fn mangle<'tcx>(
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 5aa46cc..0f91684 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -1,12 +1,14 @@
+use std::fmt::{self, Write};
+use std::mem::{self, discriminant};
+
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_hir::def_id::CrateNum;
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::bug;
use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer};
-use rustc_middle::ty::{self, Instance, ReifyReason, Ty, TyCtxt, TypeVisitableExt};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
-use std::fmt::{self, Write};
-use std::mem::{self, discriminant};
+use rustc_middle::ty::{
+ self, GenericArg, GenericArgKind, Instance, ReifyReason, Ty, TyCtxt, TypeVisitableExt,
+};
use tracing::debug;
pub(super) fn mangle<'tcx>(
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index e65d308..dea4eb0 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -97,8 +97,7 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
+use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Instance, TyCtxt};
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index f0fb87f..774d0b5 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -4,12 +4,13 @@
//! def-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
-use crate::errors::{Kind, TestOutput};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{GenericArgs, Instance, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
+use crate::errors::{Kind, TestOutput};
+
const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
const DEF_PATH: Symbol = sym::rustc_def_path;
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 5f8029a..c2451c0 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -1,3 +1,7 @@
+use std::fmt::Write;
+use std::iter;
+use std::ops::Range;
+
use rustc_data_structures::base_n::ToBaseN;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
@@ -9,18 +13,13 @@
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::print::{Print, PrintError, Printer};
use rustc_middle::ty::{
- self, EarlyBinder, FloatTy, Instance, IntTy, ReifyReason, Ty, TyCtxt, TypeVisitable,
- TypeVisitableExt, UintTy,
+ self, EarlyBinder, FloatTy, GenericArg, GenericArgKind, Instance, IntTy, ReifyReason, Ty,
+ TyCtxt, TypeVisitable, TypeVisitableExt, UintTy,
};
-use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::kw;
use rustc_target::abi::Integer;
use rustc_target::spec::abi::Abi;
-use std::fmt::Write;
-use std::iter;
-use std::ops::Range;
-
pub(super) fn mangle<'tcx>(
tcx: TyCtxt<'tcx>,
instance: Instance<'tcx>,
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 2cb8ac7..c7d2415 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -22,5 +22,5 @@
# tidy-alphabetical-start
default-features = false
features = ["elf", "macho"]
-version = "0.32.0"
+version = "0.36.2"
# tidy-alphabetical-end
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 9f13c19..5bfc528 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -1,11 +1,12 @@
-use crate::abi::{self, Abi, Align, FieldsShape, Size};
-use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
-use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
-use rustc_macros::HashStable_Generic;
-use rustc_span::Symbol;
use std::fmt;
use std::str::FromStr;
+use rustc_macros::HashStable_Generic;
+use rustc_span::Symbol;
+
+use crate::abi::{self, Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
+
mod aarch64;
mod amdgpu;
mod arm;
@@ -237,8 +238,10 @@ pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
_ => panic!("unsupported integer: {self:?}"),
},
RegKind::Float => match self.size.bits() {
+ 16 => dl.f16_align.abi,
32 => dl.f32_align.abi,
64 => dl.f64_align.abi,
+ 128 => dl.f128_align.abi,
_ => panic!("unsupported float: {self:?}"),
},
RegKind::Vector => dl.vector_align(self.size).abi,
@@ -967,8 +970,9 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(ArgAbi<'_, usize>, 56);
static_assert_size!(FnAbi<'_, usize>, 80);
diff --git a/compiler/rustc_target/src/abi/call/nvptx64.rs b/compiler/rustc_target/src/abi/call/nvptx64.rs
index ac68e88..27d197a 100644
--- a/compiler/rustc_target/src/abi/call/nvptx64.rs
+++ b/compiler/rustc_target/src/abi/call/nvptx64.rs
@@ -1,8 +1,7 @@
+use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget};
use crate::abi::call::{ArgAbi, FnAbi, PassMode, Reg, Size, Uniform};
use crate::abi::{HasDataLayout, TyAbiInterface};
-use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget};
-
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if ret.layout.is_aggregate() && ret.layout.is_sized() {
classify_aggregate(ret)
diff --git a/compiler/rustc_target/src/abi/call/powerpc64.rs b/compiler/rustc_target/src/abi/call/powerpc64.rs
index 11a6cb5..749eea0 100644
--- a/compiler/rustc_target/src/abi/call/powerpc64.rs
+++ b/compiler/rustc_target/src/abi/call/powerpc64.rs
@@ -41,59 +41,12 @@ fn is_homogeneous_aggregate<'a, Ty, C>(
})
}
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
+fn classify<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI, is_ret: bool)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
- if !ret.layout.is_sized() {
- // Not touching this...
- return;
- }
- if !ret.layout.is_aggregate() {
- ret.extend_integer_width_to(64);
- return;
- }
-
- // The ELFv1 ABI doesn't return aggregates in registers
- if abi == ELFv1 {
- ret.make_indirect();
- return;
- }
-
- if let Some(uniform) = is_homogeneous_aggregate(cx, ret, abi) {
- ret.cast_to(uniform);
- return;
- }
-
- let size = ret.layout.size;
- let bits = size.bits();
- if bits <= 128 {
- let unit = if cx.data_layout().endian == Endian::Big {
- Reg { kind: RegKind::Integer, size }
- } else if bits <= 8 {
- Reg::i8()
- } else if bits <= 16 {
- Reg::i16()
- } else if bits <= 32 {
- Reg::i32()
- } else {
- Reg::i64()
- };
-
- ret.cast_to(Uniform::new(unit, size));
- return;
- }
-
- ret.make_indirect();
-}
-
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
-where
- Ty: TyAbiInterface<'a, C> + Copy,
- C: HasDataLayout,
-{
- if !arg.layout.is_sized() {
+ if arg.is_ignore() || !arg.layout.is_sized() {
// Not touching this...
return;
}
@@ -102,13 +55,22 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
return;
}
+ // The ELFv1 ABI doesn't return aggregates in registers
+ if is_ret && abi == ELFv1 {
+ arg.make_indirect();
+ return;
+ }
+
if let Some(uniform) = is_homogeneous_aggregate(cx, arg, abi) {
arg.cast_to(uniform);
return;
}
let size = arg.layout.size;
- if size.bits() <= 64 {
+ if is_ret && size.bits() > 128 {
+ // Non-homogeneous aggregates larger than two doublewords are returned indirectly.
+ arg.make_indirect();
+ } else if size.bits() <= 64 {
// Aggregates smaller than a doubleword should appear in
// the least-significant bits of the parameter doubleword.
arg.cast_to(Reg { kind: RegKind::Integer, size })
@@ -138,14 +100,9 @@ pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
}
};
- if !fn_abi.ret.is_ignore() {
- classify_ret(cx, &mut fn_abi.ret, abi);
- }
+ classify(cx, &mut fn_abi.ret, abi, true);
for arg in fn_abi.args.iter_mut() {
- if arg.is_ignore() {
- continue;
- }
- classify_arg(cx, arg, abi);
+ classify(cx, arg, abi, false);
}
}
diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/abi/call/x86_win64.rs
index 90de1a4..4e19460 100644
--- a/compiler/rustc_target/src/abi/call/x86_win64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_win64.rs
@@ -1,5 +1,5 @@
use crate::abi::call::{ArgAbi, FnAbi, Reg};
-use crate::abi::Abi;
+use crate::abi::{Abi, Float, Primitive};
// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
@@ -18,8 +18,12 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
// FIXME(eddyb) there should be a size cap here
// (probably what clang calls "illegal vectors").
}
- Abi::Scalar(_) => {
- if a.layout.size.bytes() > 8 {
+ Abi::Scalar(scalar) => {
+ // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up
+ // with what LLVM expects.
+ if a.layout.size.bytes() > 8
+ && !matches!(scalar.primitive(), Primitive::Float(Float::F128))
+ {
a.make_indirect();
} else {
a.extend_integer_width_to(32);
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 737e9a8..9bd0aff 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1,15 +1,14 @@
+use std::fmt;
+use std::ops::Deref;
+
use rustc_data_structures::intern::Interned;
+use rustc_macros::HashStable_Generic;
pub use Float::*;
pub use Integer::*;
pub use Primitive::*;
use crate::json::{Json, ToJson};
-use std::fmt;
-use std::ops::Deref;
-
-use rustc_macros::HashStable_Generic;
-
pub mod call;
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index 1a3218d..358efb4 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -1,8 +1,10 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use crate::spec::{RelocModel, Target};
+use std::fmt;
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::Symbol;
-use std::fmt;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{RelocModel, Target};
def_reg_class! {
AArch64 AArch64InlineAsmRegClass {
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index 70fcaab..f8d0d40 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -1,8 +1,10 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use crate::spec::{RelocModel, Target};
+use std::fmt;
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::{sym, Symbol};
-use std::fmt;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{RelocModel, Target};
def_reg_class! {
Arm ArmInlineAsmRegClass {
diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs
index 6943fd9..276f376 100644
--- a/compiler/rustc_target/src/asm/avr.rs
+++ b/compiler/rustc_target/src/asm/avr.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Avr AvrInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/bpf.rs b/compiler/rustc_target/src/asm/bpf.rs
index faaeabb..500fb41 100644
--- a/compiler/rustc_target/src/asm/bpf.rs
+++ b/compiler/rustc_target/src/asm/bpf.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Bpf BpfInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/csky.rs b/compiler/rustc_target/src/asm/csky.rs
index db6cdec..a4913ed 100644
--- a/compiler/rustc_target/src/asm/csky.rs
+++ b/compiler/rustc_target/src/asm/csky.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
CSKY CSKYInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/hexagon.rs b/compiler/rustc_target/src/asm/hexagon.rs
index 7a809ef..f7e726c 100644
--- a/compiler/rustc_target/src/asm/hexagon.rs
+++ b/compiler/rustc_target/src/asm/hexagon.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Hexagon HexagonInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs
index 534b696..b1c01d2 100644
--- a/compiler/rustc_target/src/asm/loongarch.rs
+++ b/compiler/rustc_target/src/asm/loongarch.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
LoongArch LoongArchInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/m68k.rs b/compiler/rustc_target/src/asm/m68k.rs
index ea367e3..680404b 100644
--- a/compiler/rustc_target/src/asm/m68k.rs
+++ b/compiler/rustc_target/src/asm/m68k.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
M68k M68kInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/mips.rs b/compiler/rustc_target/src/asm/mips.rs
index f0d659c..e28b845 100644
--- a/compiler/rustc_target/src/asm/mips.rs
+++ b/compiler/rustc_target/src/asm/mips.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Mips MipsInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index b057bf9..4d8c5ce 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -1,10 +1,12 @@
-use crate::spec::Target;
-use crate::{abi::Size, spec::RelocModel};
+use std::fmt;
+use std::str::FromStr;
+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::Symbol;
-use std::fmt;
-use std::str::FromStr;
+
+use crate::abi::Size;
+use crate::spec::{RelocModel, Target};
pub struct ModifierInfo {
pub modifier: char,
diff --git a/compiler/rustc_target/src/asm/msp430.rs b/compiler/rustc_target/src/asm/msp430.rs
index 14013cd..5ed2023 100644
--- a/compiler/rustc_target/src/asm/msp430.rs
+++ b/compiler/rustc_target/src/asm/msp430.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Msp430 Msp430InlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/nvptx.rs b/compiler/rustc_target/src/asm/nvptx.rs
index 6c066ad..da8b79d 100644
--- a/compiler/rustc_target/src/asm/nvptx.rs
+++ b/compiler/rustc_target/src/asm/nvptx.rs
@@ -1,6 +1,7 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_span::Symbol;
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Nvptx NvptxInlineAsmRegClass {
reg16,
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index 45e9ace..b241646 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
PowerPC PowerPCInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/riscv.rs b/compiler/rustc_target/src/asm/riscv.rs
index 02a4a5e..2b9d611 100644
--- a/compiler/rustc_target/src/asm/riscv.rs
+++ b/compiler/rustc_target/src/asm/riscv.rs
@@ -1,8 +1,10 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use crate::spec::{RelocModel, Target};
+use std::fmt;
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::{sym, Symbol};
-use std::fmt;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{RelocModel, Target};
def_reg_class! {
RiscV RiscVInlineAsmRegClass {
diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs
index 2bab41c..4258b23 100644
--- a/compiler/rustc_target/src/asm/s390x.rs
+++ b/compiler/rustc_target/src/asm/s390x.rs
@@ -1,7 +1,9 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use rustc_span::Symbol;
use std::fmt;
+use rustc_span::Symbol;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
S390x S390xInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/spirv.rs b/compiler/rustc_target/src/asm/spirv.rs
index f242fae..c050c4e 100644
--- a/compiler/rustc_target/src/asm/spirv.rs
+++ b/compiler/rustc_target/src/asm/spirv.rs
@@ -1,6 +1,7 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_span::Symbol;
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
SpirV SpirVInlineAsmRegClass {
reg,
diff --git a/compiler/rustc_target/src/asm/wasm.rs b/compiler/rustc_target/src/asm/wasm.rs
index b5f4d10..0fbfa52 100644
--- a/compiler/rustc_target/src/asm/wasm.rs
+++ b/compiler/rustc_target/src/asm/wasm.rs
@@ -1,6 +1,7 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_span::Symbol;
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+
def_reg_class! {
Wasm WasmInlineAsmRegClass {
local,
diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs
index 8452961..15c1925 100644
--- a/compiler/rustc_target/src/asm/x86.rs
+++ b/compiler/rustc_target/src/asm/x86.rs
@@ -1,8 +1,10 @@
-use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
-use crate::spec::{RelocModel, Target};
+use std::fmt;
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::Symbol;
-use std::fmt;
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{RelocModel, Target};
def_reg_class! {
X86 X86InlineAsmRegClass {
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index ecc91ab..b2116c5 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -9,12 +9,12 @@
// tidy-alphabetical-start
#![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)]
#![feature(assert_matches)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![feature(min_exhaustive_patterns)]
#![feature(rustc_attrs)]
#![feature(rustdoc_internals)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_target/src/spec/abi/tests.rs b/compiler/rustc_target/src/spec/abi/tests.rs
index 251a12f..4823058 100644
--- a/compiler/rustc_target/src/spec/abi/tests.rs
+++ b/compiler/rustc_target/src/spec/abi/tests.rs
@@ -1,3 +1,5 @@
+use std::assert_matches::assert_matches;
+
use super::*;
#[allow(non_snake_case)]
@@ -16,7 +18,7 @@ fn lookup_cdecl() {
#[test]
fn lookup_baz() {
let abi = lookup("baz");
- assert!(matches!(abi, Err(AbiUnsupported::Unrecognized)))
+ assert_matches!(abi, Err(AbiUnsupported::Unrecognized));
}
#[test]
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index 0554200..39d7cf7 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -1,8 +1,10 @@
-use std::{borrow::Cow, env};
+use std::borrow::Cow;
+use std::env;
-use crate::spec::{add_link_args, add_link_args_iter};
-use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs, LinkerFlavor, Lld};
-use crate::spec::{SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions};
+use crate::spec::{
+ add_link_args, add_link_args_iter, cvs, Cc, DebuginfoKind, FramePointer, LinkArgs,
+ LinkerFlavor, Lld, SplitDebuginfo, StackProbeType, StaticCow, Target, TargetOptions,
+};
#[cfg(test)]
mod tests;
diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs
index 211d52f..c3d0344 100644
--- a/compiler/rustc_target/src/spec/base/avr_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/avr_gnu.rs
@@ -1,6 +1,7 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
use object::elf;
+use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
+
/// A base target for AVR devices using the GNU toolchain.
///
/// Requires GNU avr-gcc and avr-binutils on the host system.
diff --git a/compiler/rustc_target/src/spec/base/linux.rs b/compiler/rustc_target/src/spec/base/linux.rs
index df8e848..34b2eb0 100644
--- a/compiler/rustc_target/src/spec/base/linux.rs
+++ b/compiler/rustc_target/src/spec/base/linux.rs
@@ -1,6 +1,7 @@
-use crate::spec::{cvs, RelroLevel, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;
+use crate::spec::{cvs, RelroLevel, SplitDebuginfo, TargetOptions};
+
pub fn opts() -> TargetOptions {
TargetOptions {
os: "linux".into(),
diff --git a/compiler/rustc_target/src/spec/base/linux_musl.rs b/compiler/rustc_target/src/spec/base/linux_musl.rs
index 5117cad..42aa1e1 100644
--- a/compiler/rustc_target/src/spec/base/linux_musl.rs
+++ b/compiler/rustc_target/src/spec/base/linux_musl.rs
@@ -1,5 +1,4 @@
-use crate::spec::crt_objects;
-use crate::spec::{base, LinkSelfContainedDefault, TargetOptions};
+use crate::spec::{base, crt_objects, LinkSelfContainedDefault, TargetOptions};
pub fn opts() -> TargetOptions {
let mut base = base::linux::opts();
diff --git a/compiler/rustc_target/src/spec/base/msvc.rs b/compiler/rustc_target/src/spec/base/msvc.rs
index 44fc376..720cf03 100644
--- a/compiler/rustc_target/src/spec/base/msvc.rs
+++ b/compiler/rustc_target/src/spec/base/msvc.rs
@@ -1,6 +1,7 @@
-use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;
+use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
+
pub fn opts() -> TargetOptions {
// Suppress the verbose logo and authorship debugging output, which would needlessly
// clog any log files.
diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs
index 1357de2..7346e42 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs
@@ -1,8 +1,10 @@
-use crate::spec::LinkSelfContainedDefault;
-use crate::spec::{add_link_args, crt_objects};
-use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;
+use crate::spec::{
+ add_link_args, crt_objects, cvs, Cc, DebuginfoKind, LinkSelfContainedDefault, LinkerFlavor,
+ Lld, SplitDebuginfo, TargetOptions,
+};
+
pub fn opts() -> TargetOptions {
let mut pre_link_args = TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::No, Lld::No),
diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
index b1d8e2b..88c3b8a 100644
--- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs
@@ -1,6 +1,7 @@
-use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;
+use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
+
pub fn opts() -> TargetOptions {
// We cannot use `-nodefaultlibs` because compiler-rt has to be passed
// as a path since it's not added to linker search path by the default.
diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs
index 53f710b..e3b6430 100644
--- a/compiler/rustc_target/src/spec/crt_objects.rs
+++ b/compiler/rustc_target/src/spec/crt_objects.rs
@@ -40,10 +40,11 @@
//! but not gcc's. As a result rustc cannot link with C++ static libraries (#36710)
//! when linking in self-contained mode.
-use crate::spec::LinkOutputKind;
use std::borrow::Cow;
use std::collections::BTreeMap;
+use crate::spec::LinkOutputKind;
+
pub type CrtObjects = BTreeMap<LinkOutputKind, Vec<Cow<'static, str>>>;
pub(super) fn new(obj_table: &[(LinkOutputKind, &[&'static str])]) -> CrtObjects {
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 0efe682..8ce51ba 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -34,16 +34,6 @@
//! the target's settings, though `target-feature` and `link-args` will *add*
//! to the list specified by the target, rather than replace.
-use crate::abi::call::Conv;
-use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors};
-use crate::json::{Json, ToJson};
-use crate::spec::abi::Abi;
-use crate::spec::crt_objects::CrtObjects;
-use rustc_fs_util::try_canonicalize;
-use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_span::symbol::{kw, sym, Symbol};
-use serde_json::Value;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};
@@ -51,15 +41,28 @@
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{fmt, io};
+
+use rustc_fs_util::try_canonicalize;
+use rustc_macros::{Decodable, Encodable, HashStable_Generic};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use rustc_span::symbol::{kw, sym, Symbol};
+use serde_json::Value;
use tracing::debug;
+use crate::abi::call::Conv;
+use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors};
+use crate::json::{Json, ToJson};
+use crate::spec::abi::Abi;
+use crate::spec::crt_objects::CrtObjects;
+
pub mod abi;
pub mod crt_objects;
mod base;
-pub use base::apple::deployment_target as current_apple_deployment_target;
-pub use base::apple::platform as current_apple_platform;
-pub use base::apple::sdk_version as current_apple_sdk_version;
+pub use base::apple::{
+ deployment_target as current_apple_deployment_target, platform as current_apple_platform,
+ sdk_version as current_apple_sdk_version,
+};
pub use base::avr_gnu::ef_avr_arch;
/// Linker is called through a C/C++ compiler.
@@ -3146,11 +3149,10 @@ macro_rules! key {
if let Some(a) = o.as_array() {
for o in a {
if let Some(s) = o.as_str() {
- let p = s.split('=').collect::<Vec<_>>();
- if p.len() == 2 {
- let k = p[0].to_string();
- let v = p[1].to_string();
- base.$key_name.to_mut().push((k.into(), v.into()));
+ if let [k, v] = *s.split('=').collect::<Vec<_>>() {
+ base.$key_name
+ .to_mut()
+ .push((k.to_string().into(), v.to_string().into()))
}
}
}
@@ -3353,8 +3355,7 @@ pub fn search(
target_triple: &TargetTriple,
sysroot: &Path,
) -> Result<(Target, TargetWarnings), String> {
- use std::env;
- use std::fs;
+ use std::{env, fs};
fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
let contents = fs::read_to_string(path).map_err(|e| e.to_string())?;
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index f37781c..65f2a1e 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -17,7 +17,7 @@ pub fn target() -> Target {
llvm_target: macos_llvm_target(arch).into(),
metadata: crate::spec::TargetMetadata {
description: Some("ARM64 macOS (11.0+, Big Sur+)".into()),
- tier: Some(2),
+ tier: Some(1),
host_tools: Some(true),
std: Some(true),
},
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index 5924e4f..726a85c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -1,5 +1,4 @@
-use crate::spec::SanitizerSet;
-use crate::spec::{base, StackProbeType, Target, TargetOptions};
+use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = base::linux_ohos::opts();
diff --git a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
index 8cddb6f..eb223af 100644
--- a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
@@ -1,5 +1,5 @@
-use crate::spec::Target;
-use crate::{abi::Endian, spec::base};
+use crate::abi::Endian;
+use crate::spec::{base, Target};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
index d070aa0..12164ad 100644
--- a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
@@ -1,5 +1,5 @@
-use crate::spec::Target;
-use crate::{abi::Endian, spec::base};
+use crate::abi::Endian;
+use crate::spec::{base, Target};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
index 19b0460..f7a6e0b 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -4,10 +4,10 @@ pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-linux-musl".into(),
metadata: crate::spec::TargetMetadata {
- description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.3".into()),
- tier: Some(3),
- host_tools: Some(false),
- std: None, // ?
+ description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.5".into()),
+ tier: Some(2),
+ host_tools: Some(true),
+ std: Some(true),
},
pointer_width: 64,
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
index 744ffff..c7f47da 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -1,11 +1,12 @@
-use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{
+ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+};
pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-none".into(),
metadata: crate::spec::TargetMetadata {
- description: None,
+ description: Some("Freestanding/bare-metal LoongArch64".into()),
tier: Some(2),
host_tools: Some(false),
std: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
index a382e7a..21e4f4a 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
@@ -1,11 +1,12 @@
-use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{
+ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions,
+};
pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-none".into(),
metadata: crate::spec::TargetMetadata {
- description: None,
+ description: Some("Freestanding/bare-metal LoongArch64 softfloat".into()),
tier: Some(2),
host_tools: Some(false),
std: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
index 15156fb..ec5edfb 100644
--- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
@@ -1,5 +1,6 @@
-use crate::spec::LinkSelfContainedDefault;
-use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions};
+use crate::spec::{
+ LinkSelfContainedDefault, LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions,
+};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
index 726778a..8aa5e09 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index 3e575fd..8b40132 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -21,6 +21,7 @@ pub fn target() -> Target {
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
+ crt_static_default: false,
..base::linux_musl::opts()
},
}
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index a75f896..bfd88bd 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -1,6 +1,7 @@
-use crate::spec::SanitizerSet;
-use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelocModel, Target, TargetOptions};
+use crate::spec::{
+ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
+ TargetOptions,
+};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
index 6a46822..5bea708 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs
@@ -1,6 +1,7 @@
-use crate::spec::SanitizerSet;
-use crate::spec::{cvs, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelocModel, Target, TargetOptions};
+use crate::spec::{
+ cvs, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
+ TargetOptions,
+};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
index ba9a10e..fa3f1ef 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
@@ -1,5 +1,7 @@
-use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelocModel, SanitizerSet, Target, TargetOptions};
+use crate::spec::{
+ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
+ TargetOptions,
+};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
index 1e18466..215c072 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs
@@ -1,6 +1,7 @@
-use crate::spec::SanitizerSet;
-use crate::spec::{cvs, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelocModel, Target, TargetOptions};
+use crate::spec::{
+ cvs, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target,
+ TargetOptions,
+};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
index 96dd858..8806f3e 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
@@ -9,8 +9,7 @@
//! The default link script is very likely wrong, so you should use
//! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
-use crate::spec::{base, PanicStrategy, RelocModel, Target, TargetOptions};
-use crate::spec::{cvs, FramePointer};
+use crate::spec::{base, cvs, FramePointer, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
index a8e7f22..29e6dff 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -10,9 +10,7 @@
//! was since renamed to `wasm32-wasip1` after the preview2 target was
//! introduced.
-use crate::spec::crt_objects;
-use crate::spec::LinkSelfContainedDefault;
-use crate::spec::{base, Cc, LinkerFlavor, Target};
+use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target};
pub fn target() -> Target {
let mut options = base::wasm::options();
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index 63d1f48..489bae4 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -16,9 +16,7 @@
//! You can see more about wasi at <https://wasi.dev> and the component model at
//! <https://github.com/WebAssembly/component-model>.
-use crate::spec::crt_objects;
-use crate::spec::LinkSelfContainedDefault;
-use crate::spec::{base, RelocModel, Target};
+use crate::spec::{base, crt_objects, LinkSelfContainedDefault, RelocModel, Target};
pub fn target() -> Target {
let mut options = base::wasm::options();
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 94638ae..c3a52a5 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,6 +1,5 @@
use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::X86_64;
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index 5497069..175a53f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -4,8 +4,10 @@
// `target-cpu` compiler flags to opt-in more hardware-specific
// features.
-use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use crate::spec::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions};
+use crate::spec::{
+ Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelroLevel, SanitizerSet, StackProbeType,
+ Target, TargetOptions,
+};
pub fn target() -> Target {
let opts = TargetOptions {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
index 6da1fcc..2933da9 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
@@ -5,10 +5,8 @@
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
-use crate::{
- abi::call::Conv,
- spec::{base, Target},
-};
+use crate::abi::call::Conv;
+use crate::spec::{base, Target};
pub fn target() -> Target {
let mut base = base::uefi_msvc::opts();
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index 72cbc1b..a932d4a 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,6 +1,5 @@
use crate::spec::base::apple::{macos_llvm_target, opts, Arch, TargetAbi};
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::X86_64h;
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs
index 1b66fdb..f041e79 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_espidf.rs
@@ -1,5 +1,6 @@
use crate::abi::Endian;
-use crate::spec::{base::xtensa, cvs, Target, TargetOptions};
+use crate::spec::base::xtensa;
+use crate::spec::{cvs, Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs
index bf52371..05666bd 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{base::xtensa, Target, TargetOptions};
+use crate::spec::base::xtensa;
+use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs
index ad5fda8..83ef520 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_espidf.rs
@@ -1,5 +1,6 @@
use crate::abi::Endian;
-use crate::spec::{base::xtensa, cvs, Target, TargetOptions};
+use crate::spec::base::xtensa;
+use crate::spec::{cvs, Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs
index 219b2aa..aa125eb 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s2_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{base::xtensa, Target, TargetOptions};
+use crate::spec::base::xtensa;
+use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs
index ab1d1df..e18acfc 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_espidf.rs
@@ -1,5 +1,6 @@
use crate::abi::Endian;
-use crate::spec::{base::xtensa, cvs, Target, TargetOptions};
+use crate::spec::base::xtensa;
+use crate::spec::{cvs, Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs
index 632eef3..ecbb51d 100644
--- a/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp32s3_none_elf.rs
@@ -1,4 +1,5 @@
-use crate::spec::{base::xtensa, Target, TargetOptions};
+use crate::spec::base::xtensa;
+use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
Target {
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index 3be18ef..fc5bd84 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -1,6 +1,7 @@
-use super::super::*;
use std::assert_matches::assert_matches;
+use super::super::*;
+
// Test target self-consistency and JSON encoding/decoding roundtrip.
pub(super) fn test_target(mut target: Target) {
let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 4fb0323..da66ba2 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -1,5 +1,5 @@
-use rustc_span::symbol::sym;
-use rustc_span::symbol::Symbol;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_span::symbol::{sym, Symbol};
/// Features that control behaviour of rustc, rather than the codegen.
pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
@@ -54,136 +54,154 @@ pub fn is_stable(self) -> bool {
//
// Stabilizing a target feature requires t-lang approval.
-const ARM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+type ImpliedFeatures = &'static [&'static str];
+
+const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("aclass", Unstable(sym::arm_target_feature)),
- ("aes", Unstable(sym::arm_target_feature)),
- ("crc", Unstable(sym::arm_target_feature)),
- ("d32", Unstable(sym::arm_target_feature)),
- ("dotprod", Unstable(sym::arm_target_feature)),
- ("dsp", Unstable(sym::arm_target_feature)),
- ("fp-armv8", Unstable(sym::arm_target_feature)),
- ("i8mm", Unstable(sym::arm_target_feature)),
- ("mclass", Unstable(sym::arm_target_feature)),
- ("neon", Unstable(sym::arm_target_feature)),
- ("rclass", Unstable(sym::arm_target_feature)),
- ("sha2", Unstable(sym::arm_target_feature)),
+ ("aclass", Unstable(sym::arm_target_feature), &[]),
+ ("aes", Unstable(sym::arm_target_feature), &["neon"]),
+ ("crc", Unstable(sym::arm_target_feature), &[]),
+ ("d32", Unstable(sym::arm_target_feature), &[]),
+ ("dotprod", Unstable(sym::arm_target_feature), &["neon"]),
+ ("dsp", Unstable(sym::arm_target_feature), &[]),
+ ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]),
+ ("i8mm", Unstable(sym::arm_target_feature), &["neon"]),
+ ("mclass", Unstable(sym::arm_target_feature), &[]),
+ ("neon", Unstable(sym::arm_target_feature), &["vfp3"]),
+ ("rclass", Unstable(sym::arm_target_feature), &[]),
+ ("sha2", Unstable(sym::arm_target_feature), &["neon"]),
// This is needed for inline assembly, but shouldn't be stabilized as-is
// since it should be enabled per-function using #[instruction_set], not
// #[target_feature].
- ("thumb-mode", Unstable(sym::arm_target_feature)),
- ("thumb2", Unstable(sym::arm_target_feature)),
- ("trustzone", Unstable(sym::arm_target_feature)),
- ("v5te", Unstable(sym::arm_target_feature)),
- ("v6", Unstable(sym::arm_target_feature)),
- ("v6k", Unstable(sym::arm_target_feature)),
- ("v6t2", Unstable(sym::arm_target_feature)),
- ("v7", Unstable(sym::arm_target_feature)),
- ("v8", Unstable(sym::arm_target_feature)),
- ("vfp2", Unstable(sym::arm_target_feature)),
- ("vfp3", Unstable(sym::arm_target_feature)),
- ("vfp4", Unstable(sym::arm_target_feature)),
- ("virtualization", Unstable(sym::arm_target_feature)),
+ ("thumb-mode", Unstable(sym::arm_target_feature), &[]),
+ ("thumb2", Unstable(sym::arm_target_feature), &[]),
+ ("trustzone", Unstable(sym::arm_target_feature), &[]),
+ ("v5te", Unstable(sym::arm_target_feature), &[]),
+ ("v6", Unstable(sym::arm_target_feature), &["v5te"]),
+ ("v6k", Unstable(sym::arm_target_feature), &["v6"]),
+ ("v6t2", Unstable(sym::arm_target_feature), &["v6k", "thumb2"]),
+ ("v7", Unstable(sym::arm_target_feature), &["v6t2"]),
+ ("v8", Unstable(sym::arm_target_feature), &["v7"]),
+ ("vfp2", Unstable(sym::arm_target_feature), &[]),
+ ("vfp3", Unstable(sym::arm_target_feature), &["vfp2", "d32"]),
+ ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
+ ("virtualization", Unstable(sym::arm_target_feature), &[]),
// tidy-alphabetical-end
];
-const AARCH64_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
// FEAT_AES & FEAT_PMULL
- ("aes", Stable),
+ ("aes", Stable, &["neon"]),
// FEAT_BF16
- ("bf16", Stable),
+ ("bf16", Stable, &[]),
// FEAT_BTI
- ("bti", Stable),
+ ("bti", Stable, &[]),
// FEAT_CRC
- ("crc", Stable),
+ ("crc", Stable, &[]),
// FEAT_DIT
- ("dit", Stable),
+ ("dit", Stable, &[]),
// FEAT_DotProd
- ("dotprod", Stable),
+ ("dotprod", Stable, &["neon"]),
// FEAT_DPB
- ("dpb", Stable),
+ ("dpb", Stable, &[]),
// FEAT_DPB2
- ("dpb2", Stable),
+ ("dpb2", Stable, &["dpb"]),
// FEAT_F32MM
- ("f32mm", Stable),
+ ("f32mm", Stable, &["sve"]),
// FEAT_F64MM
- ("f64mm", Stable),
+ ("f64mm", Stable, &["sve"]),
// FEAT_FCMA
- ("fcma", Stable),
+ ("fcma", Stable, &["neon"]),
// FEAT_FHM
- ("fhm", Stable),
+ ("fhm", Stable, &["fp16"]),
// FEAT_FLAGM
- ("flagm", Stable),
+ ("flagm", Stable, &[]),
// FEAT_FP16
- ("fp16", Stable),
+ // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
+ ("fp16", Stable, &["neon"]),
// FEAT_FRINTTS
- ("frintts", Stable),
+ ("frintts", Stable, &[]),
// FEAT_I8MM
- ("i8mm", Stable),
+ ("i8mm", Stable, &[]),
// FEAT_JSCVT
- ("jsconv", Stable),
+ // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608
+ ("jsconv", Stable, &["neon"]),
// FEAT_LOR
- ("lor", Stable),
+ ("lor", Stable, &[]),
// FEAT_LSE
- ("lse", Stable),
+ ("lse", Stable, &[]),
// FEAT_MTE & FEAT_MTE2
- ("mte", Stable),
+ ("mte", Stable, &[]),
// FEAT_AdvSimd & FEAT_FP
- ("neon", Stable),
+ ("neon", Stable, &[]),
// FEAT_PAUTH (address authentication)
- ("paca", Stable),
+ ("paca", Stable, &[]),
// FEAT_PAUTH (generic authentication)
- ("pacg", Stable),
+ ("pacg", Stable, &[]),
// FEAT_PAN
- ("pan", Stable),
+ ("pan", Stable, &[]),
// FEAT_PMUv3
- ("pmuv3", Stable),
+ ("pmuv3", Stable, &[]),
// FEAT_RAND
- ("rand", Stable),
+ ("rand", Stable, &[]),
// FEAT_RAS & FEAT_RASv1p1
- ("ras", Stable),
+ ("ras", Stable, &[]),
// FEAT_RCPC
- ("rcpc", Stable),
+ ("rcpc", Stable, &[]),
// FEAT_RCPC2
- ("rcpc2", Stable),
+ ("rcpc2", Stable, &["rcpc"]),
// FEAT_RDM
- ("rdm", Stable),
+ ("rdm", Stable, &["neon"]),
// FEAT_SB
- ("sb", Stable),
+ ("sb", Stable, &[]),
// FEAT_SHA1 & FEAT_SHA256
- ("sha2", Stable),
+ ("sha2", Stable, &["neon"]),
// FEAT_SHA512 & FEAT_SHA3
- ("sha3", Stable),
+ ("sha3", Stable, &["sha2"]),
// FEAT_SM3 & FEAT_SM4
- ("sm4", Stable),
+ ("sm4", Stable, &["neon"]),
// FEAT_SPE
- ("spe", Stable),
+ ("spe", Stable, &[]),
// FEAT_SSBS & FEAT_SSBS2
- ("ssbs", Stable),
+ ("ssbs", Stable, &[]),
// FEAT_SVE
- ("sve", Stable),
+ // It was decided that SVE requires Neon: https://github.com/rust-lang/rust/pull/91608
+ //
+ // LLVM doesn't enable Neon for SVE. ARM indicates that they're separate, but probably always
+ // exist together: https://developer.arm.com/documentation/102340/0100/New-features-in-SVE2
+ //
+ // "For backwards compatibility, Neon and VFP are required in the latest architectures."
+ ("sve", Stable, &["neon"]),
// FEAT_SVE2
- ("sve2", Stable),
+ ("sve2", Stable, &["sve"]),
// FEAT_SVE2_AES
- ("sve2-aes", Stable),
+ ("sve2-aes", Stable, &["sve2", "aes"]),
// FEAT_SVE2_BitPerm
- ("sve2-bitperm", Stable),
+ ("sve2-bitperm", Stable, &["sve2"]),
// FEAT_SVE2_SHA3
- ("sve2-sha3", Stable),
+ ("sve2-sha3", Stable, &["sve2", "sha3"]),
// FEAT_SVE2_SM4
- ("sve2-sm4", Stable),
+ ("sve2-sm4", Stable, &["sve2", "sm4"]),
// FEAT_TME
- ("tme", Stable),
- ("v8.1a", Unstable(sym::aarch64_ver_target_feature)),
- ("v8.2a", Unstable(sym::aarch64_ver_target_feature)),
- ("v8.3a", Unstable(sym::aarch64_ver_target_feature)),
- ("v8.4a", Unstable(sym::aarch64_ver_target_feature)),
- ("v8.5a", Unstable(sym::aarch64_ver_target_feature)),
- ("v8.6a", Unstable(sym::aarch64_ver_target_feature)),
- ("v8.7a", Unstable(sym::aarch64_ver_target_feature)),
+ ("tme", Stable, &[]),
+ (
+ "v8.1a",
+ Unstable(sym::aarch64_ver_target_feature),
+ &["crc", "lse", "rdm", "pan", "lor", "vh"],
+ ),
+ ("v8.2a", Unstable(sym::aarch64_ver_target_feature), &["v8.1a", "ras", "dpb"]),
+ (
+ "v8.3a",
+ Unstable(sym::aarch64_ver_target_feature),
+ &["v8.2a", "rcpc", "paca", "pacg", "jsconv"],
+ ),
+ ("v8.4a", Unstable(sym::aarch64_ver_target_feature), &["v8.3a", "dotprod", "dit", "flagm"]),
+ ("v8.5a", Unstable(sym::aarch64_ver_target_feature), &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
+ ("v8.6a", Unstable(sym::aarch64_ver_target_feature), &["v8.5a", "bf16", "i8mm"]),
+ ("v8.7a", Unstable(sym::aarch64_ver_target_feature), &[]),
// FEAT_VHE
- ("vh", Stable),
+ ("vh", Stable, &[]),
// tidy-alphabetical-end
];
@@ -191,219 +209,223 @@ pub fn is_stable(self) -> bool {
&["paca", "pacg"], // Together these represent `pauth` in LLVM
];
-const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("adx", Stable),
- ("aes", Stable),
- ("amx-bf16", Unstable(sym::x86_amx_intrinsics)),
- ("amx-complex", Unstable(sym::x86_amx_intrinsics)),
- ("amx-fp16", Unstable(sym::x86_amx_intrinsics)),
- ("amx-int8", Unstable(sym::x86_amx_intrinsics)),
- ("amx-tile", Unstable(sym::x86_amx_intrinsics)),
- ("avx", Stable),
- ("avx2", Stable),
- ("avx512bf16", Unstable(sym::avx512_target_feature)),
- ("avx512bitalg", Unstable(sym::avx512_target_feature)),
- ("avx512bw", Unstable(sym::avx512_target_feature)),
- ("avx512cd", Unstable(sym::avx512_target_feature)),
- ("avx512dq", Unstable(sym::avx512_target_feature)),
- ("avx512f", Unstable(sym::avx512_target_feature)),
- ("avx512fp16", Unstable(sym::avx512_target_feature)),
- ("avx512ifma", Unstable(sym::avx512_target_feature)),
- ("avx512vbmi", Unstable(sym::avx512_target_feature)),
- ("avx512vbmi2", Unstable(sym::avx512_target_feature)),
- ("avx512vl", Unstable(sym::avx512_target_feature)),
- ("avx512vnni", Unstable(sym::avx512_target_feature)),
- ("avx512vp2intersect", Unstable(sym::avx512_target_feature)),
- ("avx512vpopcntdq", Unstable(sym::avx512_target_feature)),
- ("avxifma", Unstable(sym::avx512_target_feature)),
- ("avxneconvert", Unstable(sym::avx512_target_feature)),
- ("avxvnni", Unstable(sym::avx512_target_feature)),
- ("avxvnniint16", Unstable(sym::avx512_target_feature)),
- ("avxvnniint8", Unstable(sym::avx512_target_feature)),
- ("bmi1", Stable),
- ("bmi2", Stable),
- ("cmpxchg16b", Stable),
- ("ermsb", Unstable(sym::ermsb_target_feature)),
- ("f16c", Stable),
- ("fma", Stable),
- ("fxsr", Stable),
- ("gfni", Unstable(sym::avx512_target_feature)),
- ("lahfsahf", Unstable(sym::lahfsahf_target_feature)),
- ("lzcnt", Stable),
- ("movbe", Stable),
- ("pclmulqdq", Stable),
- ("popcnt", Stable),
- ("prfchw", Unstable(sym::prfchw_target_feature)),
- ("rdrand", Stable),
- ("rdseed", Stable),
- ("rtm", Unstable(sym::rtm_target_feature)),
- ("sha", Stable),
- ("sse", Stable),
- ("sse2", Stable),
- ("sse3", Stable),
- ("sse4.1", Stable),
- ("sse4.2", Stable),
- ("sse4a", Unstable(sym::sse4a_target_feature)),
- ("ssse3", Stable),
- ("tbm", Unstable(sym::tbm_target_feature)),
- ("vaes", Unstable(sym::avx512_target_feature)),
- ("vpclmulqdq", Unstable(sym::avx512_target_feature)),
- ("xop", Unstable(sym::xop_target_feature)),
- ("xsave", Stable),
- ("xsavec", Stable),
- ("xsaveopt", Stable),
- ("xsaves", Stable),
+ ("adx", Stable, &[]),
+ ("aes", Stable, &["sse2"]),
+ ("amx-bf16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-complex", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-fp16", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-int8", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+ ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
+ ("avx", Stable, &["sse4.2"]),
+ ("avx2", Stable, &["avx"]),
+ ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
+ ("avx512bitalg", Unstable(sym::avx512_target_feature), &["avx512bw"]),
+ ("avx512bw", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512cd", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512dq", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512f", Unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]),
+ ("avx512fp16", Unstable(sym::avx512_target_feature), &["avx512bw", "avx512vl", "avx512dq"]),
+ ("avx512ifma", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512vbmi", Unstable(sym::avx512_target_feature), &["avx512bw"]),
+ ("avx512vbmi2", Unstable(sym::avx512_target_feature), &["avx512bw"]),
+ ("avx512vl", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512vnni", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512vp2intersect", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avx512vpopcntdq", Unstable(sym::avx512_target_feature), &["avx512f"]),
+ ("avxifma", Unstable(sym::avx512_target_feature), &["avx2"]),
+ ("avxneconvert", Unstable(sym::avx512_target_feature), &["avx2"]),
+ ("avxvnni", Unstable(sym::avx512_target_feature), &["avx2"]),
+ ("avxvnniint16", Unstable(sym::avx512_target_feature), &["avx2"]),
+ ("avxvnniint8", Unstable(sym::avx512_target_feature), &["avx2"]),
+ ("bmi1", Stable, &[]),
+ ("bmi2", Stable, &[]),
+ ("cmpxchg16b", Stable, &[]),
+ ("ermsb", Unstable(sym::ermsb_target_feature), &[]),
+ ("f16c", Stable, &["avx"]),
+ ("fma", Stable, &["avx"]),
+ ("fxsr", Stable, &[]),
+ ("gfni", Unstable(sym::avx512_target_feature), &["sse2"]),
+ ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
+ ("lzcnt", Stable, &[]),
+ ("movbe", Stable, &[]),
+ ("pclmulqdq", Stable, &[]),
+ ("popcnt", Stable, &[]),
+ ("prfchw", Unstable(sym::prfchw_target_feature), &[]),
+ ("rdrand", Stable, &[]),
+ ("rdseed", Stable, &[]),
+ ("rtm", Unstable(sym::rtm_target_feature), &[]),
+ ("sha", Stable, &["sse2"]),
+ ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
+ ("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
+ ("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
+ ("sse", Stable, &[]),
+ ("sse2", Stable, &["sse"]),
+ ("sse3", Stable, &["sse2"]),
+ ("sse4.1", Stable, &["ssse3"]),
+ ("sse4.2", Stable, &["sse4.1"]),
+ ("sse4a", Unstable(sym::sse4a_target_feature), &["sse3"]),
+ ("ssse3", Stable, &["sse3"]),
+ ("tbm", Unstable(sym::tbm_target_feature), &[]),
+ ("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]),
+ ("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
+ ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
+ ("xsave", Stable, &[]),
+ ("xsavec", Stable, &["xsave"]),
+ ("xsaveopt", Stable, &["xsave"]),
+ ("xsaves", Stable, &["xsave"]),
// tidy-alphabetical-end
];
-const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("hvx", Unstable(sym::hexagon_target_feature)),
- ("hvx-length128b", Unstable(sym::hexagon_target_feature)),
+ ("hvx", Unstable(sym::hexagon_target_feature), &[]),
+ ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
// tidy-alphabetical-end
];
-const POWERPC_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("altivec", Unstable(sym::powerpc_target_feature)),
- ("power10-vector", Unstable(sym::powerpc_target_feature)),
- ("power8-altivec", Unstable(sym::powerpc_target_feature)),
- ("power8-vector", Unstable(sym::powerpc_target_feature)),
- ("power9-altivec", Unstable(sym::powerpc_target_feature)),
- ("power9-vector", Unstable(sym::powerpc_target_feature)),
- ("vsx", Unstable(sym::powerpc_target_feature)),
+ ("altivec", Unstable(sym::powerpc_target_feature), &[]),
+ ("power10-vector", Unstable(sym::powerpc_target_feature), &["power9-vector"]),
+ ("power8-altivec", Unstable(sym::powerpc_target_feature), &["altivec"]),
+ ("power8-vector", Unstable(sym::powerpc_target_feature), &["vsx", "power8-altivec"]),
+ ("power9-altivec", Unstable(sym::powerpc_target_feature), &["power8-altivec"]),
+ ("power9-vector", Unstable(sym::powerpc_target_feature), &["power8-vector", "power9-altivec"]),
+ ("vsx", Unstable(sym::powerpc_target_feature), &["altivec"]),
// tidy-alphabetical-end
];
-const MIPS_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("fp64", Unstable(sym::mips_target_feature)),
- ("msa", Unstable(sym::mips_target_feature)),
- ("virt", Unstable(sym::mips_target_feature)),
+ ("fp64", Unstable(sym::mips_target_feature), &[]),
+ ("msa", Unstable(sym::mips_target_feature), &[]),
+ ("virt", Unstable(sym::mips_target_feature), &[]),
// tidy-alphabetical-end
];
-const RISCV_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("a", Stable),
- ("c", Stable),
- ("d", Unstable(sym::riscv_target_feature)),
- ("e", Unstable(sym::riscv_target_feature)),
- ("f", Unstable(sym::riscv_target_feature)),
- ("m", Stable),
- ("relax", Unstable(sym::riscv_target_feature)),
- ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature)),
- ("v", Unstable(sym::riscv_target_feature)),
- ("zba", Stable),
- ("zbb", Stable),
- ("zbc", Stable),
- ("zbkb", Stable),
- ("zbkc", Stable),
- ("zbkx", Stable),
- ("zbs", Stable),
- ("zdinx", Unstable(sym::riscv_target_feature)),
- ("zfh", Unstable(sym::riscv_target_feature)),
- ("zfhmin", Unstable(sym::riscv_target_feature)),
- ("zfinx", Unstable(sym::riscv_target_feature)),
- ("zhinx", Unstable(sym::riscv_target_feature)),
- ("zhinxmin", Unstable(sym::riscv_target_feature)),
- ("zk", Stable),
- ("zkn", Stable),
- ("zknd", Stable),
- ("zkne", Stable),
- ("zknh", Stable),
- ("zkr", Stable),
- ("zks", Stable),
- ("zksed", Stable),
- ("zksh", Stable),
- ("zkt", Stable),
+ ("a", Stable, &[]),
+ ("c", Stable, &[]),
+ ("d", Unstable(sym::riscv_target_feature), &["f"]),
+ ("e", Unstable(sym::riscv_target_feature), &[]),
+ ("f", Unstable(sym::riscv_target_feature), &[]),
+ ("m", Stable, &[]),
+ ("relax", Unstable(sym::riscv_target_feature), &[]),
+ ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
+ ("v", Unstable(sym::riscv_target_feature), &[]),
+ ("zba", Stable, &[]),
+ ("zbb", Stable, &[]),
+ ("zbc", Stable, &[]),
+ ("zbkb", Stable, &[]),
+ ("zbkc", Stable, &[]),
+ ("zbkx", Stable, &[]),
+ ("zbs", Stable, &[]),
+ ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]),
+ ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]),
+ ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]),
+ ("zfinx", Unstable(sym::riscv_target_feature), &[]),
+ ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]),
+ ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]),
+ ("zk", Stable, &["zkn", "zkr", "zkt"]),
+ ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
+ ("zknd", Stable, &[]),
+ ("zkne", Stable, &[]),
+ ("zknh", Stable, &[]),
+ ("zkr", Stable, &[]),
+ ("zks", Stable, &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
+ ("zksed", Stable, &[]),
+ ("zksh", Stable, &[]),
+ ("zkt", Stable, &[]),
// tidy-alphabetical-end
];
-const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("atomics", Unstable(sym::wasm_target_feature)),
- ("bulk-memory", Stable),
- ("exception-handling", Unstable(sym::wasm_target_feature)),
- ("extended-const", Stable),
- ("multivalue", Unstable(sym::wasm_target_feature)),
- ("mutable-globals", Stable),
- ("nontrapping-fptoint", Stable),
- ("reference-types", Unstable(sym::wasm_target_feature)),
- ("relaxed-simd", Unstable(sym::wasm_target_feature)),
- ("sign-ext", Stable),
- ("simd128", Stable),
+ ("atomics", Unstable(sym::wasm_target_feature), &[]),
+ ("bulk-memory", Stable, &[]),
+ ("exception-handling", Unstable(sym::wasm_target_feature), &[]),
+ ("extended-const", Stable, &[]),
+ ("multivalue", Unstable(sym::wasm_target_feature), &[]),
+ ("mutable-globals", Stable, &[]),
+ ("nontrapping-fptoint", Stable, &[]),
+ ("reference-types", Unstable(sym::wasm_target_feature), &[]),
+ ("relaxed-simd", Stable, &["simd128"]),
+ ("sign-ext", Stable, &[]),
+ ("simd128", Stable, &[]),
// tidy-alphabetical-end
];
-const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))];
+const BPF_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
+ &[("alu32", Unstable(sym::bpf_target_feature), &[])];
-const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("10e60", Unstable(sym::csky_target_feature)),
- ("2e3", Unstable(sym::csky_target_feature)),
- ("3e3r1", Unstable(sym::csky_target_feature)),
- ("3e3r2", Unstable(sym::csky_target_feature)),
- ("3e3r3", Unstable(sym::csky_target_feature)),
- ("3e7", Unstable(sym::csky_target_feature)),
- ("7e10", Unstable(sym::csky_target_feature)),
- ("cache", Unstable(sym::csky_target_feature)),
- ("doloop", Unstable(sym::csky_target_feature)),
- ("dsp1e2", Unstable(sym::csky_target_feature)),
- ("dspe60", Unstable(sym::csky_target_feature)),
- ("e1", Unstable(sym::csky_target_feature)),
- ("e2", Unstable(sym::csky_target_feature)),
- ("edsp", Unstable(sym::csky_target_feature)),
- ("elrw", Unstable(sym::csky_target_feature)),
- ("float1e2", Unstable(sym::csky_target_feature)),
- ("float1e3", Unstable(sym::csky_target_feature)),
- ("float3e4", Unstable(sym::csky_target_feature)),
- ("float7e60", Unstable(sym::csky_target_feature)),
- ("floate1", Unstable(sym::csky_target_feature)),
- ("hard-tp", Unstable(sym::csky_target_feature)),
- ("high-registers", Unstable(sym::csky_target_feature)),
- ("hwdiv", Unstable(sym::csky_target_feature)),
- ("mp", Unstable(sym::csky_target_feature)),
- ("mp1e2", Unstable(sym::csky_target_feature)),
- ("nvic", Unstable(sym::csky_target_feature)),
- ("trust", Unstable(sym::csky_target_feature)),
- ("vdsp2e60f", Unstable(sym::csky_target_feature)),
- ("vdspv1", Unstable(sym::csky_target_feature)),
- ("vdspv2", Unstable(sym::csky_target_feature)),
+ ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
+ ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
+ ("3e3r1", Unstable(sym::csky_target_feature), &[]),
+ ("3e3r2", Unstable(sym::csky_target_feature), &["3e3r1", "doloop"]),
+ ("3e3r3", Unstable(sym::csky_target_feature), &["doloop"]),
+ ("3e7", Unstable(sym::csky_target_feature), &["2e3"]),
+ ("7e10", Unstable(sym::csky_target_feature), &["3e7"]),
+ ("cache", Unstable(sym::csky_target_feature), &[]),
+ ("doloop", Unstable(sym::csky_target_feature), &[]),
+ ("dsp1e2", Unstable(sym::csky_target_feature), &[]),
+ ("dspe60", Unstable(sym::csky_target_feature), &[]),
+ ("e1", Unstable(sym::csky_target_feature), &["elrw"]),
+ ("e2", Unstable(sym::csky_target_feature), &["e2"]),
+ ("edsp", Unstable(sym::csky_target_feature), &[]),
+ ("elrw", Unstable(sym::csky_target_feature), &[]),
+ ("float1e2", Unstable(sym::csky_target_feature), &[]),
+ ("float1e3", Unstable(sym::csky_target_feature), &[]),
+ ("float3e4", Unstable(sym::csky_target_feature), &[]),
+ ("float7e60", Unstable(sym::csky_target_feature), &[]),
+ ("floate1", Unstable(sym::csky_target_feature), &[]),
+ ("hard-tp", Unstable(sym::csky_target_feature), &[]),
+ ("high-registers", Unstable(sym::csky_target_feature), &[]),
+ ("hwdiv", Unstable(sym::csky_target_feature), &[]),
+ ("mp", Unstable(sym::csky_target_feature), &["2e3"]),
+ ("mp1e2", Unstable(sym::csky_target_feature), &["3e7"]),
+ ("nvic", Unstable(sym::csky_target_feature), &[]),
+ ("trust", Unstable(sym::csky_target_feature), &[]),
+ ("vdsp2e60f", Unstable(sym::csky_target_feature), &[]),
+ ("vdspv1", Unstable(sym::csky_target_feature), &[]),
+ ("vdspv2", Unstable(sym::csky_target_feature), &[]),
// tidy-alphabetical-end
//fpu
// tidy-alphabetical-start
- ("fdivdu", Unstable(sym::csky_target_feature)),
- ("fpuv2_df", Unstable(sym::csky_target_feature)),
- ("fpuv2_sf", Unstable(sym::csky_target_feature)),
- ("fpuv3_df", Unstable(sym::csky_target_feature)),
- ("fpuv3_hf", Unstable(sym::csky_target_feature)),
- ("fpuv3_hi", Unstable(sym::csky_target_feature)),
- ("fpuv3_sf", Unstable(sym::csky_target_feature)),
- ("hard-float", Unstable(sym::csky_target_feature)),
- ("hard-float-abi", Unstable(sym::csky_target_feature)),
+ ("fdivdu", Unstable(sym::csky_target_feature), &[]),
+ ("fpuv2_df", Unstable(sym::csky_target_feature), &[]),
+ ("fpuv2_sf", Unstable(sym::csky_target_feature), &[]),
+ ("fpuv3_df", Unstable(sym::csky_target_feature), &[]),
+ ("fpuv3_hf", Unstable(sym::csky_target_feature), &[]),
+ ("fpuv3_hi", Unstable(sym::csky_target_feature), &[]),
+ ("fpuv3_sf", Unstable(sym::csky_target_feature), &[]),
+ ("hard-float", Unstable(sym::csky_target_feature), &[]),
+ ("hard-float-abi", Unstable(sym::csky_target_feature), &[]),
// tidy-alphabetical-end
];
-const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("d", Unstable(sym::loongarch_target_feature)),
- ("f", Unstable(sym::loongarch_target_feature)),
- ("frecipe", Unstable(sym::loongarch_target_feature)),
- ("lasx", Unstable(sym::loongarch_target_feature)),
- ("lbt", Unstable(sym::loongarch_target_feature)),
- ("lsx", Unstable(sym::loongarch_target_feature)),
- ("lvz", Unstable(sym::loongarch_target_feature)),
- ("relax", Unstable(sym::loongarch_target_feature)),
- ("ual", Unstable(sym::loongarch_target_feature)),
+ ("d", Unstable(sym::loongarch_target_feature), &["f"]),
+ ("f", Unstable(sym::loongarch_target_feature), &[]),
+ ("frecipe", Unstable(sym::loongarch_target_feature), &[]),
+ ("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]),
+ ("lbt", Unstable(sym::loongarch_target_feature), &[]),
+ ("lsx", Unstable(sym::loongarch_target_feature), &["d"]),
+ ("lvz", Unstable(sym::loongarch_target_feature), &[]),
+ ("relax", Unstable(sym::loongarch_target_feature), &[]),
+ ("ual", Unstable(sym::loongarch_target_feature), &[]),
// tidy-alphabetical-end
];
-const IBMZ_ALLOWED_FEATURES: &[(&str, Stability)] = &[
+const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-start
- ("backchain", Unstable(sym::s390x_target_feature)),
- ("vector", Unstable(sym::s390x_target_feature)),
+ ("backchain", Unstable(sym::s390x_target_feature), &[]),
+ ("vector", Unstable(sym::s390x_target_feature), &[]),
// tidy-alphabetical-end
];
@@ -426,10 +448,13 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
.chain(LOONGARCH_ALLOWED_FEATURES)
.chain(IBMZ_ALLOWED_FEATURES)
.cloned()
+ .map(|(f, s, _)| (f, s))
}
impl super::spec::Target {
- pub fn supported_target_features(&self) -> &'static [(&'static str, Stability)] {
+ pub fn supported_target_features(
+ &self,
+ ) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
match &*self.arch {
"arm" => ARM_ALLOWED_FEATURES,
"aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES,
@@ -453,4 +478,28 @@ pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] {
_ => &[],
}
}
+
+ pub fn implied_target_features(
+ &self,
+ base_features: impl Iterator<Item = Symbol>,
+ ) -> FxHashSet<Symbol> {
+ let implied_features = self
+ .supported_target_features()
+ .iter()
+ .map(|(f, _, i)| (Symbol::intern(f), i))
+ .collect::<FxHashMap<_, _>>();
+
+ // implied target features have their own implied target features, so we traverse the
+ // map until there are no more features to add
+ let mut features = FxHashSet::default();
+ let mut new_features = base_features.collect::<Vec<Symbol>>();
+ while let Some(new_feature) = new_features.pop() {
+ if features.insert(new_feature) {
+ if let Some(implied_features) = implied_features.get(&new_feature) {
+ new_features.extend(implied_features.iter().copied().map(Symbol::intern))
+ }
+ }
+ }
+ features
+ }
}
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index daabdec..8ccb2a8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -60,12 +60,11 @@
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::error::TypeErrorToStringExt;
+use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt};
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
use rustc_middle::ty::{
- self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
- TypeVisitable, TypeVisitableExt,
+ self, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
+ TypeVisitableExt,
};
use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 56ea70b..f6dd789 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -1,13 +1,11 @@
-use crate::error_reporting::TypeErrCtxt;
-use crate::errors::{
- AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
- SourceKindMultiSuggestion, SourceKindSubdiag,
-};
-use crate::infer::InferCtxt;
-use rustc_errors::{codes::*, Diag, IntoDiagArg};
+use std::borrow::Cow;
+use std::iter;
+use std::path::PathBuf;
+
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, IntoDiagArg};
use rustc_hir as hir;
-use rustc_hir::def::Res;
-use rustc_hir::def::{CtorOf, DefKind, Namespace};
+use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource};
@@ -21,9 +19,13 @@
};
use rustc_span::symbol::{sym, Ident};
use rustc_span::{BytePos, Span, DUMMY_SP};
-use std::borrow::Cow;
-use std::iter;
-use std::path::PathBuf;
+
+use crate::error_reporting::TypeErrCtxt;
+use crate::errors::{
+ AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
+ SourceKindMultiSuggestion, SourceKindSubdiag,
+};
+use crate::infer::InferCtxt;
pub enum TypeAnnotationNeeded {
/// ```compile_fail,E0282
@@ -932,13 +934,13 @@ fn expr_inferred_arg_iter(
// which makes this somewhat difficult and prevents us from just
// using `self.path_inferred_arg_iter` here.
hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
- // FIXME(TaKO8Ki): Ideally we should support this. For that
- // we have to map back from the self type to the
- // type alias though. That's difficult.
+ // FIXME(TaKO8Ki): Ideally we should support other kinds,
+ // such as `TyAlias` or `AssocTy`. For that we have to map
+ // back from the self type to the type alias though. That's difficult.
//
// See the `need_type_info/issue-103053.rs` test for
// a example.
- if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => {
+ if matches!(path.res, Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) => {
if let Some(ty) = self.opt_node_type(expr.hir_id)
&& let ty::Adt(_, args) = ty.kind()
{
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
index 74dcde0..8f84d77 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/different_lifetimes.rs
@@ -1,21 +1,17 @@
//! Error Reporting for Anonymous Region Lifetime Errors
//! where both the regions are anonymous.
-use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
-use crate::error_reporting::infer::nice_region_error::util::AnonymousParamInfo;
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::AddLifetimeParamsSuggestion;
-use crate::errors::LifetimeMismatch;
-use crate::errors::LifetimeMismatchLabels;
-use crate::infer::RegionResolutionError;
-use crate::infer::SubregionOrigin;
-
-use rustc_errors::Subdiagnostic;
-use rustc_errors::{Diag, ErrorGuaranteed};
+use rustc_errors::{Diag, ErrorGuaranteed, Subdiagnostic};
use rustc_hir::def_id::LocalDefId;
use rustc_hir::Ty;
use rustc_middle::ty::{Region, TyCtxt};
+use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
+use crate::error_reporting::infer::nice_region_error::util::AnonymousParamInfo;
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::{AddLifetimeParamsSuggestion, LifetimeMismatch, LifetimeMismatchLabels};
+use crate::infer::{RegionResolutionError, SubregionOrigin};
+
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when both the concerned regions are anonymous.
///
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
index a892ce5..3f35391 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
@@ -1,4 +1,5 @@
use core::ops::ControlFlow;
+
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
index 550cc45..221f667 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs
@@ -1,14 +1,6 @@
//! Error Reporting for when the lifetime for a type doesn't match the `impl` selected for a predicate
//! to hold.
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
-use crate::errors::{
- DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime,
-};
-use crate::infer::RegionResolutionError;
-use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::ObligationCauseCode;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
@@ -16,6 +8,14 @@
use rustc_middle::bug;
use rustc_middle::ty::TypeVisitor;
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::{
+ note_and_explain, DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag,
+ IntroducesStaticBecauseUnmetLifetimeReq, MismatchedStaticLifetime,
+};
+use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace};
+use crate::traits::ObligationCauseCode;
+
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaranteed> {
let error = self.error.as_ref()?;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs
index b83ecd8..79a770a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs
@@ -1,11 +1,12 @@
-use crate::error_reporting::TypeErrCtxt;
-use crate::infer::RegionResolutionError;
-use crate::infer::RegionResolutionError::*;
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
+use crate::error_reporting::TypeErrCtxt;
+use crate::infer::RegionResolutionError;
+use crate::infer::RegionResolutionError::*;
+
mod different_lifetimes;
pub mod find_anon_type;
mod mismatched_static_lifetime;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
index d1802d2..f91a81f 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
@@ -1,13 +1,14 @@
//! Error Reporting for Anonymous Region Lifetime Errors
//! where one region is named and the other is anonymous.
-use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::ExplicitLifetimeRequired;
use rustc_errors::Diag;
use rustc_middle::ty;
use rustc_span::symbol::kw;
+use crate::error_reporting::infer::nice_region_error::find_anon_type::find_anon_type;
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::ExplicitLifetimeRequired;
+
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// When given a `ConcreteFailure` for a function with parameters containing a named region and
/// an anonymous region, emit an descriptive diagnostic error.
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs
index 476ac3f..8da0edb 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs
@@ -1,12 +1,5 @@
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{
- ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
- TraitPlaceholderMismatch, TyOrSig,
-};
-use crate::infer::RegionResolutionError;
-use crate::infer::ValuePairs;
-use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::{ObligationCause, ObligationCauseCode};
+use std::fmt;
+
use rustc_data_structures::intern::Interned;
use rustc_errors::{Diag, IntoDiagArg};
use rustc_hir::def::Namespace;
@@ -14,10 +7,15 @@
use rustc_middle::bug;
use rustc_middle::ty::error::ExpectedFound;
use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
+use rustc_middle::ty::{self, GenericArgsRef, RePlaceholder, Region, TyCtxt};
-use std::fmt;
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::{
+ ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
+ TraitPlaceholderMismatch, TyOrSig,
+};
+use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace, ValuePairs};
+use crate::traits::{ObligationCause, ObligationCauseCode};
// HACK(eddyb) maybe move this in a more central location.
#[derive(Copy, Clone)]
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
index e9f17a3..9c772f4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
@@ -1,10 +1,11 @@
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::PlaceholderRelationLfNotSatisfied;
-use crate::infer::{RegionResolutionError, SubregionOrigin};
use rustc_data_structures::intern::Interned;
use rustc_errors::Diag;
use rustc_middle::ty::{self, RePlaceholder, Region};
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::PlaceholderRelationLfNotSatisfied;
+use crate::infer::{RegionResolutionError, SubregionOrigin};
+
impl<'tcx> NiceRegionError<'_, 'tcx> {
/// Emitted wwhen given a `ConcreteFailure` when relating two placeholders.
pub(super) fn try_report_placeholder_relation(&self) -> Option<Diag<'tcx>> {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index e5d9797..dc775b8 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -1,13 +1,5 @@
//! Error Reporting for static impl Traits.
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{
- ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted,
- ReqIntroducedLocations,
-};
-use crate::infer::RegionResolutionError;
-use crate::infer::{SubregionOrigin, TypeTrace};
-use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, Subdiagnostic};
use rustc_hir::def_id::DefId;
@@ -19,10 +11,17 @@
use rustc_middle::ty::{
self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
+use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::Ident;
use rustc_span::Span;
-use rustc_span::def_id::LocalDefId;
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::{
+ ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted,
+ ReqIntroducedLocations,
+};
+use crate::infer::{RegionResolutionError, SubregionOrigin, TypeTrace};
+use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static `impl Trait`,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
index c58c7e1..09af00b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs
@@ -1,9 +1,5 @@
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
-use crate::error_reporting::infer::nice_region_error::NiceRegionError;
-use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
-use crate::infer::RegionResolutionError;
-use crate::infer::{Subtype, ValuePairs};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::Res;
@@ -16,6 +12,10 @@
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::Span;
+use crate::error_reporting::infer::nice_region_error::NiceRegionError;
+use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
+use crate::infer::{RegionResolutionError, Subtype, ValuePairs};
+
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorGuaranteed> {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
index aeb3049..04e1be2 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note.rs
@@ -1,10 +1,3 @@
-use crate::error_reporting::infer::{note_and_explain_region, TypeErrCtxt};
-use crate::errors::{
- note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
- RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
-};
-use crate::fluent_generated as fluent;
-use crate::infer::{self, SubregionOrigin};
use rustc_errors::{Diag, Subdiagnostic};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::traits::ObligationCauseCode;
@@ -13,6 +6,13 @@
use rustc_span::symbol::kw;
use super::ObligationCauseAsDiagArg;
+use crate::error_reporting::infer::{note_and_explain_region, TypeErrCtxt};
+use crate::errors::{
+ note_and_explain, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
+ RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
+};
+use crate::fluent_generated as fluent;
+use crate::infer::{self, SubregionOrigin};
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
pub(super) fn note_region_origin(&self, err: &mut Diag<'_>, origin: &SubregionOrigin<'tcx>) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index f9110cf..864510b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -2,14 +2,12 @@
use rustc_errors::{pluralize, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::print::Printer;
-use rustc_middle::{
- traits::ObligationCause,
- ty::{self, error::TypeError, print::FmtPrinter, suggest_constraining_type_param, Ty},
-};
-use rustc_span::{def_id::DefId, sym, BytePos, Span, Symbol};
+use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::print::{FmtPrinter, Printer};
+use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
+use rustc_span::def_id::DefId;
+use rustc_span::{sym, BytePos, Span, Symbol};
use crate::error_reporting::TypeErrCtxt;
use crate::infer::InferCtxtExt;
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
index 1ef32d1..ee159aa 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs
@@ -1,5 +1,5 @@
-use crate::error_reporting::infer::hir::Path;
use core::ops::ControlFlow;
+
use hir::def::CtorKind;
use hir::intravisit::{walk_expr, walk_stmt, Visitor};
use hir::{LetStmt, QPath};
@@ -7,8 +7,7 @@
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::def::Res;
-use rustc_hir::MatchSource;
-use rustc_hir::Node;
+use rustc_hir::{MatchSource, Node};
use rustc_middle::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
StatementAsExpression,
@@ -17,6 +16,7 @@
use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt};
use rustc_span::{sym, Span};
+use crate::error_reporting::infer::hir::Path;
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index 72a4d4c..9ab4705 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -388,39 +388,67 @@ pub(super) fn maybe_report_ambiguity(
trait_impls.non_blanket_impls().values().flatten().count();
// If there is only one implementation of the trait, suggest using it.
// Otherwise, use a placeholder comment for the implementation.
- let (message, self_type) = if non_blanket_impl_count == 1 {
+ let (message, self_types) = if non_blanket_impl_count == 1 {
(
"use the fully-qualified path to the only available \
implementation",
- format!(
+ vec![format!(
"{}",
self.tcx.type_of(impl_def_id).instantiate_identity()
- ),
+ )],
+ )
+ } else if non_blanket_impl_count < 20 {
+ (
+ "use a fully-qualified path to one of the available \
+ implementations",
+ trait_impls
+ .non_blanket_impls()
+ .values()
+ .flatten()
+ .map(|id| {
+ format!(
+ "{}",
+ self.tcx.type_of(id).instantiate_identity()
+ )
+ })
+ .collect::<Vec<String>>(),
)
} else {
(
"use a fully-qualified path to a specific available \
implementation",
- "/* self type */".to_string(),
+ vec!["/* self type */".to_string()],
)
};
- let mut suggestions =
- vec![(path.span.shrink_to_lo(), format!("<{self_type} as "))];
- if let Some(generic_arg) = trait_path_segment.args {
- let between_span =
- trait_path_segment.ident.span.between(generic_arg.span_ext);
- // get rid of :: between Trait and <type>
- // must be '::' between them, otherwise the parser won't accept the code
- suggestions.push((between_span, "".to_string()));
- suggestions
- .push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
- } else {
- suggestions.push((
- trait_path_segment.ident.span.shrink_to_hi(),
- ">".to_string(),
- ));
- }
- err.multipart_suggestion(
+ let suggestions: Vec<_> = self_types
+ .into_iter()
+ .map(|self_type| {
+ let mut suggestions = vec![(
+ path.span.shrink_to_lo(),
+ format!("<{self_type} as "),
+ )];
+ if let Some(generic_arg) = trait_path_segment.args {
+ let between_span = trait_path_segment
+ .ident
+ .span
+ .between(generic_arg.span_ext);
+ // get rid of :: between Trait and <type>
+ // must be '::' between them, otherwise the parser won't accept the code
+ suggestions.push((between_span, "".to_string()));
+ suggestions.push((
+ generic_arg.span_ext.shrink_to_hi(),
+ ">".to_string(),
+ ));
+ } else {
+ suggestions.push((
+ trait_path_segment.ident.span.shrink_to_hi(),
+ ">".to_string(),
+ ));
+ }
+ suggestions
+ })
+ .collect();
+ err.multipart_suggestions(
message,
suggestions,
Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index a7ea308..f908d8a 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1,31 +1,17 @@
-use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
-use super::suggestions::get_explanation_based_on_obligation;
-use crate::error_reporting::infer::TyCategory;
-use crate::error_reporting::traits::report_object_safety_error;
-use crate::error_reporting::TypeErrCtxt;
-use crate::errors::{
- AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
-};
-use crate::infer::InferCtxtExt as _;
-use crate::infer::{self, InferCtxt};
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::NormalizeExt;
-use crate::traits::{
- elaborate, MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
- ObligationCtxt, Overflow, PredicateObligation, SelectionError, SignatureMismatch,
- TraitNotObjectSafe,
-};
use core::ops::ControlFlow;
+use std::borrow::Cow;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, StringPart};
-use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
+use rustc_errors::{
+ pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey,
+ StringPart,
+};
use rustc_hir::def::Namespace;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::intravisit::Visitor;
-use rustc_hir::Node;
-use rustc_hir::{self as hir, LangItem};
+use rustc_hir::{self as hir, LangItem, Node};
use rustc_infer::infer::{InferOk, TypeTrace};
use rustc_middle::traits::select::OverflowError;
use rustc_middle::traits::SignatureMismatchData;
@@ -42,11 +28,25 @@
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::sym;
use rustc_span::{BytePos, Span, Symbol, DUMMY_SP};
-use std::borrow::Cow;
+use super::on_unimplemented::{AppendConstMessage, OnUnimplementedNote};
+use super::suggestions::get_explanation_based_on_obligation;
use super::{
ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate, UnsatisfiedConst,
};
+use crate::error_reporting::infer::TyCategory;
+use crate::error_reporting::traits::report_object_safety_error;
+use crate::error_reporting::TypeErrCtxt;
+use crate::errors::{
+ AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
+};
+use crate::infer::{self, InferCtxt, InferCtxtExt as _};
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::{
+ elaborate, MismatchedProjectionTypes, NormalizeExt, Obligation, ObligationCause,
+ ObligationCauseCode, ObligationCtxt, Overflow, PredicateObligation, SelectionError,
+ SignatureMismatch, TraitNotObjectSafe,
+};
impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
/// The `root_obligation` parameter should be the `root_obligation` field
@@ -687,10 +687,7 @@ pub(super) fn apply_do_not_recommend(
let mut applied_do_not_recommend = false;
loop {
if let ObligationCauseCode::ImplDerived(ref c) = base_cause {
- if self.tcx.has_attrs_with_path(
- c.impl_or_alias_def_id,
- &[sym::diagnostic, sym::do_not_recommend],
- ) {
+ if self.tcx.do_not_recommend_impl(c.impl_or_alias_def_id) {
let code = (*c.derived.parent_code).clone();
obligation.cause.map_code(|_| code);
obligation.predicate = c.derived.parent_trait_pred.upcast(self.tcx);
@@ -944,8 +941,7 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
// The current method call returns `Result<_, ()>`
&& self.can_eq(obligation.param_env, ty, found_ty)
// There's a single argument in the method call and it is a closure
- && args.len() == 1
- && let Some(arg) = args.get(0)
+ && let [arg] = args
&& let hir::ExprKind::Closure(closure) = arg.kind
// The closure has a block for its body with no tail expression
&& let body = self.tcx.hir().body(closure.body)
@@ -1625,9 +1621,127 @@ pub(super) fn report_similar_impl_candidates(
other: bool,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
- // If we have a single implementation, try to unify it with the trait ref
- // that failed. This should uncover a better hint for what *is* implemented.
+ let alternative_candidates = |def_id: DefId| {
+ let mut impl_candidates: Vec<_> = self
+ .tcx
+ .all_impls(def_id)
+ // ignore `do_not_recommend` items
+ .filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id))
+ // Ignore automatically derived impls and `!Trait` impls.
+ .filter_map(|def_id| self.tcx.impl_trait_header(def_id))
+ .filter_map(|header| {
+ (header.polarity != ty::ImplPolarity::Negative
+ || self.tcx.is_automatically_derived(def_id))
+ .then(|| header.trait_ref.instantiate_identity())
+ })
+ .filter(|trait_ref| {
+ let self_ty = trait_ref.self_ty();
+ // Avoid mentioning type parameters.
+ if let ty::Param(_) = self_ty.kind() {
+ false
+ }
+ // Avoid mentioning types that are private to another crate
+ else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
+ // FIXME(compiler-errors): This could be generalized, both to
+ // be more granular, and probably look past other `#[fundamental]`
+ // types, too.
+ self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
+ } else {
+ true
+ }
+ })
+ .collect();
+
+ impl_candidates.sort_by_key(|tr| tr.to_string());
+ impl_candidates.dedup();
+ impl_candidates
+ };
+
+ // We'll check for the case where the reason for the mismatch is that the trait comes from
+ // one crate version and the type comes from another crate version, even though they both
+ // are from the same crate.
+ let trait_def_id = trait_ref.def_id();
+ if let ty::Adt(def, _) = trait_ref.self_ty().skip_binder().peel_refs().kind()
+ && let found_type = def.did()
+ && trait_def_id.krate != found_type.krate
+ && self.tcx.crate_name(trait_def_id.krate) == self.tcx.crate_name(found_type.krate)
+ {
+ let name = self.tcx.crate_name(trait_def_id.krate);
+ let spans: Vec<_> = [trait_def_id, found_type]
+ .into_iter()
+ .filter_map(|def_id| self.tcx.extern_crate(def_id))
+ .map(|data| {
+ let dependency = if data.dependency_of == LOCAL_CRATE {
+ "direct dependency of the current crate".to_string()
+ } else {
+ let dep = self.tcx.crate_name(data.dependency_of);
+ format!("dependency of crate `{dep}`")
+ };
+ (
+ data.span,
+ format!("one version of crate `{name}` is used here, as a {dependency}"),
+ )
+ })
+ .collect();
+ let mut span: MultiSpan = spans.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
+ for (sp, label) in spans.into_iter() {
+ span.push_span_label(sp, label);
+ }
+ err.highlighted_span_help(
+ span,
+ vec![
+ StringPart::normal("you have ".to_string()),
+ StringPart::highlighted("multiple different versions".to_string()),
+ StringPart::normal(" of crate `".to_string()),
+ StringPart::highlighted(format!("{name}")),
+ StringPart::normal("` in your dependency graph".to_string()),
+ ],
+ );
+ let candidates = if impl_candidates.is_empty() {
+ alternative_candidates(trait_def_id)
+ } else {
+ impl_candidates.into_iter().map(|cand| cand.trait_ref).collect()
+ };
+ if let Some((sp_candidate, sp_found)) = candidates.iter().find_map(|trait_ref| {
+ if let ty::Adt(def, _) = trait_ref.self_ty().peel_refs().kind()
+ && let candidate_def_id = def.did()
+ && let Some(name) = self.tcx.opt_item_name(candidate_def_id)
+ && let Some(found) = self.tcx.opt_item_name(found_type)
+ && name == found
+ && candidate_def_id.krate != found_type.krate
+ && self.tcx.crate_name(candidate_def_id.krate)
+ == self.tcx.crate_name(found_type.krate)
+ {
+ // A candidate was found of an item with the same name, from two separate
+ // versions of the same crate, let's clarify.
+ Some((self.tcx.def_span(candidate_def_id), self.tcx.def_span(found_type)))
+ } else {
+ None
+ }
+ }) {
+ let mut span: MultiSpan = vec![sp_candidate, sp_found].into();
+ span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait");
+ span.push_span_label(sp_candidate, "this type implements the required trait");
+ span.push_span_label(sp_found, "this type doesn't implement the required trait");
+ err.highlighted_span_note(
+ span,
+ vec![
+ StringPart::normal(
+ "two types coming from two different versions of the same crate are \
+ different types "
+ .to_string(),
+ ),
+ StringPart::highlighted("even if they look the same".to_string()),
+ ],
+ );
+ }
+ err.help("you can use `cargo tree` to explore your dependency tree");
+ return true;
+ }
+
if let [single] = &impl_candidates {
+ // If we have a single implementation, try to unify it with the trait ref
+ // that failed. This should uncover a better hint for what *is* implemented.
if self.probe(|_| {
let ocx = ObligationCtxt::new(self);
@@ -1782,12 +1896,7 @@ pub(super) fn report_similar_impl_candidates(
let impl_candidates = impl_candidates
.into_iter()
.cloned()
- .filter(|cand| {
- !self.tcx.has_attrs_with_path(
- cand.impl_def_id,
- &[sym::diagnostic, sym::do_not_recommend],
- )
- })
+ .filter(|cand| !self.tcx.do_not_recommend_impl(cand.impl_def_id))
.collect::<Vec<_>>();
let def_id = trait_ref.def_id();
@@ -1799,43 +1908,7 @@ pub(super) fn report_similar_impl_candidates(
// Mentioning implementers of `Copy`, `Debug` and friends is not useful.
return false;
}
- let mut impl_candidates: Vec<_> = self
- .tcx
- .all_impls(def_id)
- // ignore `do_not_recommend` items
- .filter(|def_id| {
- !self
- .tcx
- .has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend])
- })
- // Ignore automatically derived impls and `!Trait` impls.
- .filter_map(|def_id| self.tcx.impl_trait_header(def_id))
- .filter_map(|header| {
- (header.polarity != ty::ImplPolarity::Negative
- || self.tcx.is_automatically_derived(def_id))
- .then(|| header.trait_ref.instantiate_identity())
- })
- .filter(|trait_ref| {
- let self_ty = trait_ref.self_ty();
- // Avoid mentioning type parameters.
- if let ty::Param(_) = self_ty.kind() {
- false
- }
- // Avoid mentioning types that are private to another crate
- else if let ty::Adt(def, _) = self_ty.peel_refs().kind() {
- // FIXME(compiler-errors): This could be generalized, both to
- // be more granular, and probably look past other `#[fundamental]`
- // types, too.
- self.tcx.visibility(def.did()).is_accessible_from(body_def_id, self.tcx)
- } else {
- true
- }
- })
- .collect();
-
- impl_candidates.sort_by_key(|tr| tr.to_string());
- impl_candidates.dedup();
- return report(impl_candidates, err);
+ return report(alternative_candidates(def_id), err);
}
// Sort impl candidates so that ordering is consistent for UI tests.
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
index 89ae6f4..40a1c18 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -19,11 +19,10 @@
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{ErrorGuaranteed, ExpnKind, Span};
+pub use self::overflow::*;
use crate::error_reporting::TypeErrCtxt;
use crate::traits::{FulfillmentError, FulfillmentErrorCode};
-pub use self::overflow::*;
-
// When outputting impl candidates, prefer showing those that are more similar.
//
// We also compare candidates after skipping lifetimes, which has a lower
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index f65de59..f656f9b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -1,29 +1,27 @@
+use std::iter;
+use std::path::PathBuf;
+
+use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItem, NestedMetaItem};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_macros::LintDiagnostic;
+use rustc_middle::bug;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
+use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt};
+use rustc_parse_format::{ParseMode, Parser, Piece, Position};
+use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
+use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
+use {rustc_attr as attr, rustc_hir as hir};
+
use super::{ObligationCauseCode, PredicateObligation};
use crate::error_reporting::TypeErrCtxt;
use crate::errors::{
EmptyOnClauseInOnUnimplemented, InvalidOnClauseInOnUnimplemented, NoValueInOnUnimplemented,
};
use crate::infer::InferCtxtExt;
-use rustc_ast::AttrArgs;
-use rustc_ast::AttrArgsEq;
-use rustc_ast::AttrKind;
-use rustc_ast::{Attribute, MetaItem, NestedMetaItem};
-use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_macros::LintDiagnostic;
-use rustc_middle::bug;
-use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
-use rustc_parse_format::{ParseMode, Parser, Piece, Position};
-use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
-use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
-use std::iter;
-use std::path::PathBuf;
/// The symbols which are always allowed in a format string
static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
@@ -75,10 +73,10 @@ fn impl_similar_to(
}
});
- let impl_def_id_and_args = if self_match_impls.len() == 1 {
- self_match_impls[0]
- } else if fuzzy_match_impls.len() == 1 {
- fuzzy_match_impls[0]
+ let impl_def_id_and_args = if let [impl_] = self_match_impls[..] {
+ impl_
+ } else if let [impl_] = fuzzy_match_impls[..] {
+ impl_
} else {
return None;
};
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index d1381d2..9269177 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -1,34 +1,33 @@
// ignore-tidy-filelength
-use super::{
- DefIdOrName, FindExprBySpan, ImplCandidate, Obligation, ObligationCause, ObligationCauseCode,
- PredicateObligation,
-};
+use std::assert_matches::debug_assert_matches;
+use std::borrow::Cow;
+use std::iter;
-use crate::error_reporting::TypeErrCtxt;
-use crate::errors;
-use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};
-
+use itertools::{EitherOrBoth, Itertools};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, pluralize, struct_span_code_err, Applicability, Diag, EmissionGuarantee, MultiSpan,
- Style, SuggestionStyle,
+ pluralize, struct_span_code_err, Applicability, Diag, EmissionGuarantee, MultiSpan, Style,
+ SuggestionStyle,
};
use rustc_hir as hir;
-use rustc_hir::def::CtorOf;
-use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
-use rustc_hir::is_range_literal;
use rustc_hir::lang_items::LangItem;
-use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node};
-use rustc_infer::infer::InferCtxt;
-use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
+use rustc_hir::{
+ is_range_literal, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
+};
+use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_middle::hir::map;
use rustc_middle::traits::IsConstable;
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::print::PrintPolyTraitRefExt;
+use rustc_middle::ty::print::{
+ with_forced_trimmed_paths, with_no_trimmed_paths, PrintPolyTraitPredicateExt as _,
+ PrintPolyTraitRefExt, PrintTraitPredicateExt as _,
+};
use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, GenericArgs,
InferTy, IsSuggestable, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder,
@@ -39,19 +38,16 @@
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
-use std::assert_matches::debug_assert_matches;
-use std::borrow::Cow;
-use std::iter;
+use super::{
+ DefIdOrName, FindExprBySpan, ImplCandidate, Obligation, ObligationCause, ObligationCauseCode,
+ PredicateObligation,
+};
+use crate::error_reporting::TypeErrCtxt;
+use crate::errors;
use crate::infer::InferCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_middle::ty::print::{
- with_forced_trimmed_paths, with_no_trimmed_paths, PrintPolyTraitPredicateExt as _,
- PrintTraitPredicateExt as _,
-};
-
-use itertools::EitherOrBoth;
-use itertools::Itertools;
+use crate::traits::{ImplDerivedCause, NormalizeExt, ObligationCtxt};
#[derive(Debug)]
pub enum CoroutineInteriorOrUpvar {
@@ -5304,7 +5300,8 @@ fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
match ty.kind {
hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {}
hir::TyKind::Path(hir::QPath::Resolved(None, path))
- if path.segments.len() == 1 && path.segments[0].ident.name == self.param =>
+ if let [segment] = path.segments
+ && segment.ident.name == self.param =>
{
if !self.nested {
debug!(?ty, "FindTypeParam::visit_ty");
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 0ee4485..78f1f7d 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,19 +1,18 @@
+use std::path::PathBuf;
+
use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::codes::*;
use rustc_errors::{
- codes::*, Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
+ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{walk_ty, Visitor};
-use rustc_hir::FnRetTy;
-use rustc_hir::GenericParamKind;
+use rustc_hir::{FnRetTy, GenericParamKind};
use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
-use rustc_middle::ty::{
- self, print::PrintTraitRefExt as _, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty,
- TyCtxt,
-};
+use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
+use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{BytePos, Span};
@@ -22,8 +21,6 @@
use crate::error_reporting::infer::ObligationCauseAsDiagArg;
use crate::fluent_generated as fluent;
-use std::path::PathBuf;
-
pub mod note_and_explain;
#[derive(Diagnostic)]
@@ -1585,10 +1582,7 @@ pub enum TypeErrorAdditionalDiags {
span: Span,
code: String,
},
- #[multipart_suggestion(
- trait_selection_meant_str_literal,
- applicability = "machine-applicable"
- )]
+ #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")]
MeantStrLiteral {
#[suggestion_part(code = "\"")]
start: Span,
diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
index 1f18cd8..b147776 100644
--- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
@@ -1,10 +1,12 @@
-use crate::error_reporting::infer::nice_region_error::find_anon_type;
-use crate::fluent_generated as fluent;
use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::bug;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::{symbol::kw, Span};
+use rustc_span::symbol::kw;
+use rustc_span::Span;
+
+use crate::error_reporting::infer::nice_region_error::find_anon_type;
+use crate::fluent_generated as fluent;
struct DescriptionCtx<'a> {
span: Option<Span>,
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index ad08762..c22925b 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -1,20 +1,18 @@
-use crate::infer::at::ToTrace;
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext};
+use std::fmt::Debug;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
+pub use rustc_infer::infer::*;
use rustc_macros::extension;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
-use rustc_middle::ty::{GenericArg, Upcast};
+use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast};
use rustc_span::DUMMY_SP;
-use std::fmt::Debug;
-
-pub use rustc_infer::infer::*;
+use crate::infer::at::ToTrace;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext};
#[extension(pub trait InferCtxtExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs
index 5f986e2..65762cf 100644
--- a/compiler/rustc_trait_selection/src/regions.rs
+++ b/compiler/rustc_trait_selection/src/regions.rs
@@ -1,10 +1,11 @@
-use crate::traits::ScrubbedTraitError;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
use rustc_macros::extension;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
+use crate::traits::ScrubbedTraitError;
+
#[extension(pub trait InferCtxtRegionExt<'tcx>)]
impl<'tcx> InferCtxt<'tcx> {
/// Resolve regions, using the deep normalizer to normalize any type-outlives
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 76b88ae..de8951e 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -13,13 +13,11 @@
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, TyCtxt};
use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as _};
-use rustc_span::symbol::sym;
-
-use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError};
use super::delegate::SolverDelegate;
use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
use super::Certainty;
+use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError};
/// A trait engine using the new trait solver.
///
@@ -441,10 +439,7 @@ fn visit_goal(&mut self, goal: &inspect::InspectGoal<'_, 'tcx>) -> Self::Result
source: CandidateSource::Impl(impl_def_id),
result: _,
} = candidate.kind()
- && goal
- .infcx()
- .tcx
- .has_attrs_with_path(impl_def_id, &[sym::diagnostic, sym::do_not_recommend])
+ && goal.infcx().tcx.do_not_recommend_impl(impl_def_id)
{
return ControlFlow::Break(self.obligation.clone());
}
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index e8de845..1a459aa4 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -9,6 +9,8 @@
//! coherence right now and was annoying to implement, so I am leaving it
//! as is until we start using it for something else.
+use std::assert_matches::assert_matches;
+
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
@@ -273,10 +275,10 @@ fn candidates_recur(
steps.push(step)
}
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
- assert!(matches!(
+ assert_matches!(
shallow_certainty.replace(c),
None | Some(Certainty::Maybe(MaybeCause::Ambiguity))
- ));
+ );
}
inspect::ProbeStep::NestedProbe(ref probe) => {
match probe.kind {
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index ddaef7c..c93c40b 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -1,20 +1,22 @@
+use std::assert_matches::assert_matches;
use std::fmt::Debug;
use std::marker::PhantomData;
-use crate::error_reporting::traits::OverflowCause;
-use crate::error_reporting::InferCtxtErrorExt;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::infer::at::At;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine};
use rustc_middle::traits::ObligationCause;
-use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
-use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
+use rustc_middle::ty::{
+ self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt, UniverseIndex,
+};
use super::{FulfillmentCtxt, NextSolverError};
+use crate::error_reporting::traits::OverflowCause;
+use crate::error_reporting::InferCtxtErrorExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
/// its input to be already fully resolved.
@@ -62,7 +64,7 @@ impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
- assert!(matches!(alias_ty.kind(), ty::Alias(..)));
+ assert_matches!(alias_ty.kind(), ty::Alias(..));
let infcx = self.at.infcx;
let tcx = infcx.tcx;
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 796f7fd..29f78f9 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -1,11 +1,8 @@
//! Support code for rustdoc and external tools.
//! You really don't want to be using this unless you need to.
-use super::*;
-
-use crate::errors::UnableToConstructConstantValue;
-use crate::infer::region_constraints::{Constraint, RegionConstraintData};
-use crate::traits::project::ProjectAndUnifyResult;
+use std::collections::VecDeque;
+use std::iter;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
use rustc_data_structures::unord::UnordSet;
@@ -13,8 +10,10 @@
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::{Region, RegionVid};
-use std::collections::VecDeque;
-use std::iter;
+use super::*;
+use crate::errors::UnableToConstructConstantValue;
+use crate::infer::region_constraints::{Constraint, RegionConstraintData};
+use crate::traits::project::ProjectAndUnifyResult;
// FIXME(twk): this is obviously not nice to duplicate like that
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 7e996c5..2d843d8 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -4,15 +4,8 @@
//! [trait-resolution]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
//! [trait-specialization]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
-use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::InferOk;
-use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
-use crate::solve::{deeply_normalize_for_diagnostics, inspect};
-use crate::traits::select::IntercrateAmbiguityCause;
-use crate::traits::NormalizeExt;
-use crate::traits::SkipLeakCheck;
-use crate::traits::{util, FulfillmentErrorCode};
-use crate::traits::{Obligation, ObligationCause, PredicateObligation, SelectionContext};
+use std::fmt::Debug;
+
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Diag, EmissionGuarantee};
use rustc_hir::def::DefKind;
@@ -28,10 +21,18 @@
pub use rustc_next_trait_solver::coherence::*;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
-use std::fmt::Debug;
use super::ObligationCtxt;
use crate::error_reporting::traits::suggest_new_overflow_limit;
+use crate::infer::outlives::env::OutlivesEnvironment;
+use crate::infer::InferOk;
+use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
+use crate::solve::{deeply_normalize_for_diagnostics, inspect};
+use crate::traits::select::IntercrateAmbiguityCause;
+use crate::traits::{
+ util, FulfillmentErrorCode, NormalizeExt, Obligation, ObligationCause, PredicateObligation,
+ SelectionContext, SkipLeakCheck,
+};
pub struct OverlapResult<'tcx> {
pub impl_header: ty::ImplHeader<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 49730b5..de1d4ef 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -1,16 +1,6 @@
use std::cell::RefCell;
use std::fmt::Debug;
-use super::{FromSolverError, TraitEngine};
-use super::{FulfillmentContext, ScrubbedTraitError};
-use crate::error_reporting::InferCtxtErrorExt;
-use crate::regions::InferCtxtRegionExt;
-use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
-use crate::solve::NextSolverError;
-use crate::traits::fulfill::OldSolverError;
-use crate::traits::NormalizeExt;
-use crate::traits::StructurallyNormalizeExt;
-use crate::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -19,16 +9,22 @@
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::RegionResolutionError;
-use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
+use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk, RegionResolutionError};
use rustc_macros::extension;
use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::error::TypeError;
-use rustc_middle::ty::TypeFoldable;
-use rustc_middle::ty::Upcast;
-use rustc_middle::ty::Variance;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast, Variance};
+
+use super::{FromSolverError, FulfillmentContext, ScrubbedTraitError, TraitEngine};
+use crate::error_reporting::InferCtxtErrorExt;
+use crate::regions::InferCtxtRegionExt;
+use crate::solve::{FulfillmentCtxt as NextFulfillmentCtxt, NextSolverError};
+use crate::traits::fulfill::OldSolverError;
+use crate::traits::{
+ FulfillmentError, NormalizeExt, Obligation, ObligationCause, PredicateObligation,
+ StructurallyNormalizeExt,
+};
#[extension(pub trait TraitEngineExt<'tcx, E>)]
impl<'tcx, E> dyn TraitEngine<'tcx, E>
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index cc0bb7a..a6db22e 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -1,32 +1,29 @@
-use crate::infer::{InferCtxt, TyOrConstInferVar};
-use crate::traits::normalize::normalize_with_depth_to;
+use std::marker::PhantomData;
+
use rustc_data_structures::captures::Captures;
-use rustc_data_structures::obligation_forest::ProcessResult;
-use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
-use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
+use rustc_data_structures::obligation_forest::{
+ Error, ForestObligation, ObligationForest, ObligationProcessor, Outcome, ProcessResult,
+};
use rustc_infer::infer::DefineOpaqueTypes;
-use rustc_infer::traits::{FromSolverError, ProjectionCacheKey};
-use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
+use rustc_infer::traits::{
+ FromSolverError, PolyTraitObligation, ProjectionCacheKey, SelectionError, TraitEngine,
+};
use rustc_middle::bug;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Binder, Const, TypeVisitableExt};
-use std::marker::PhantomData;
+use rustc_middle::ty::{self, Binder, Const, GenericArgsRef, TypeVisitableExt};
use super::project::{self, ProjectAndUnifyResult};
use super::select::SelectionContext;
-use super::wf;
-use super::EvaluationResult;
-use super::PredicateObligation;
-use super::Unimplemented;
-use super::{const_evaluatable, ScrubbedTraitError};
-use super::{FulfillmentError, FulfillmentErrorCode};
-
+use super::{
+ const_evaluatable, wf, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
+ PredicateObligation, ScrubbedTraitError, Unimplemented,
+};
use crate::error_reporting::InferCtxtErrorExt;
-use crate::traits::project::PolyProjectionObligation;
-use crate::traits::project::ProjectionCacheKeyExt as _;
+use crate::infer::{InferCtxt, TyOrConstInferVar};
+use crate::traits::normalize::normalize_with_depth_to;
+use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
use crate::traits::query::evaluate_obligation::InferCtxtExt;
impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index d749b68..3e65194 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,7 +1,6 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
-use crate::regions::InferCtxtRegionExt;
-use crate::traits::{self, FulfillmentError, ObligationCause};
+use std::assert_matches::assert_matches;
use hir::LangItem;
use rustc_ast::Mutability;
@@ -12,6 +11,8 @@
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
use super::outlives_bounds::InferCtxtExt;
+use crate::regions::InferCtxtRegionExt;
+use crate::traits::{self, FulfillmentError, ObligationCause};
pub enum CopyImplementationError<'tcx> {
InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
@@ -93,7 +94,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
lang_item: LangItem,
parent_cause: ObligationCause<'tcx>,
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
- assert!(matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy));
+ assert_matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy);
let inner_tys: Vec<_> = match *self_type.kind() {
// Trivially okay as these types are all:
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index c57ca01..a350b76 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -22,51 +22,55 @@
pub mod vtable;
pub mod wf;
-use crate::error_reporting::InferCtxtErrorExt;
-use crate::infer::outlives::env::OutlivesEnvironment;
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::regions::InferCtxtRegionExt;
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use std::fmt::Debug;
+use std::ops::ControlFlow;
+
use rustc_errors::ErrorGuaranteed;
+pub use rustc_infer::traits::*;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast};
-use rustc_middle::ty::{GenericArgs, GenericArgsRef};
+use rustc_middle::ty::{
+ self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperVisitable, Upcast,
+};
use rustc_span::def_id::DefId;
use rustc_span::Span;
-use std::fmt::Debug;
-use std::ops::ControlFlow;
-
-pub use self::coherence::{add_placeholder_note, orphan_check_trait_ref, overlapping_impls};
-pub use self::coherence::{InCrate, IsFirstInputType, UncoveredTyParams};
-pub use self::coherence::{OrphanCheckErr, OrphanCheckMode, OverlapResult};
+pub use self::coherence::{
+ add_placeholder_note, orphan_check_trait_ref, overlapping_impls, InCrate, IsFirstInputType,
+ OrphanCheckErr, OrphanCheckMode, OverlapResult, UncoveredTyParams,
+};
pub use self::engine::{ObligationCtxt, TraitEngineExt};
pub use self::fulfill::{FulfillmentContext, OldSolverError, PendingPredicateObligation};
pub use self::normalize::NormalizeExt;
-pub use self::object_safety::hir_ty_lowering_object_safety_violations;
-pub use self::object_safety::is_vtable_safe_method;
-pub use self::object_safety::object_safety_violations_for_assoc_item;
-pub use self::object_safety::ObjectSafetyViolation;
+pub use self::object_safety::{
+ hir_ty_lowering_object_safety_violations, is_vtable_safe_method,
+ object_safety_violations_for_assoc_item, ObjectSafetyViolation,
+};
pub use self::project::{normalize_inherent_projection, normalize_projection_ty};
-pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
-pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
-pub use self::specialize::specialization_graph::FutureCompatOverlapError;
-pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
+pub use self::select::{
+ EvaluationCache, EvaluationResult, IntercrateAmbiguityCause, OverflowError, SelectionCache,
+ SelectionContext,
+};
+pub use self::specialize::specialization_graph::{
+ FutureCompatOverlapError, FutureCompatOverlapErrorKind,
+};
pub use self::specialize::{
specialization_graph, translate_args, translate_args_with_cause, OverlapError,
};
pub use self::structural_normalize::StructurallyNormalizeExt;
-pub use self::util::elaborate;
-pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
-pub use self::util::{impl_item_is_final, upcast_choices};
-pub use self::util::{supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item};
-pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
-
-pub use rustc_infer::traits::*;
+pub use self::util::{
+ elaborate, expand_trait_aliases, impl_item_is_final, supertraits,
+ transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars,
+ BoundVarReplacer, PlaceholderReplacer, TraitAliasExpander, TraitAliasExpansionInfo,
+};
+use crate::error_reporting::InferCtxtErrorExt;
+use crate::infer::outlives::env::OutlivesEnvironment;
+use crate::infer::{InferCtxt, TyCtxtInferExt};
+use crate::regions::InferCtxtRegionExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
pub struct FulfillmentError<'tcx> {
pub obligation: PredicateObligation<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs
index 26cb9bb..81f8633 100644
--- a/compiler/rustc_trait_selection/src/traits/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/normalize.rs
@@ -1,20 +1,24 @@
//! Deeply normalize types using the old trait solver.
-use super::SelectionContext;
-use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
-use crate::error_reporting::traits::OverflowCause;
-use crate::error_reporting::InferCtxtErrorExt;
-use crate::solve::NextSolverError;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::infer::at::At;
use rustc_infer::infer::InferOk;
-use rustc_infer::traits::FromSolverError;
-use rustc_infer::traits::PredicateObligation;
-use rustc_infer::traits::{Normalized, Obligation, TraitEngine};
+use rustc_infer::traits::{
+ FromSolverError, Normalized, Obligation, PredicateObligation, TraitEngine,
+};
use rustc_macros::extension;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder};
-use rustc_middle::ty::{TypeFoldable, TypeSuperFoldable, TypeVisitable, TypeVisitableExt};
+use rustc_middle::ty::{
+ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt,
+};
+
+use super::{
+ project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer,
+ SelectionContext,
+};
+use crate::error_reporting::traits::OverflowCause;
+use crate::error_reporting::InferCtxtErrorExt;
+use crate::solve::NextSolverError;
#[extension(pub trait NormalizeExt<'tcx>)]
impl<'tcx> At<'_, 'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index ec19cf2..8e1fc0d 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -8,11 +8,9 @@
//! - not reference the erased type `Self` except for in this receiver;
//! - not have generic type parameters.
-use super::elaborate;
+use std::iter;
+use std::ops::ControlFlow;
-use crate::infer::TyCtxtInferExt;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{util, Obligation, ObligationCause};
use rustc_errors::FatalError;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@@ -27,9 +25,10 @@
use rustc_target::abi::Abi;
use smallvec::SmallVec;
-use std::iter;
-use std::ops::ControlFlow;
-
+use super::elaborate;
+use crate::infer::TyCtxtInferExt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{util, Obligation, ObligationCause};
pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation};
/// Returns the object safety violations that affect HIR ty lowering.
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 1dc2ebf..0fe7505 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -1,15 +1,15 @@
-use crate::infer::InferCtxt;
-use crate::traits::{ObligationCause, ObligationCtxt};
use rustc_data_structures::fx::FxIndexSet;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::infer::InferOk;
use rustc_macros::extension;
use rustc_middle::infer::canonical::{OriginalQueryValues, QueryRegionConstraints};
use rustc_middle::span_bug;
+pub use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
use rustc_span::def_id::LocalDefId;
-pub use rustc_middle::traits::query::OutlivesBound;
+use crate::infer::InferCtxt;
+use crate::traits::{ObligationCause, ObligationCtxt};
pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index b96e0c8..8a17d7e 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2,29 +2,6 @@
use std::ops::ControlFlow;
-use super::specialization_graph;
-use super::translate_args;
-use super::util;
-use super::MismatchedProjectionTypes;
-use super::Obligation;
-use super::ObligationCause;
-use super::PredicateObligation;
-use super::Selection;
-use super::SelectionContext;
-use super::SelectionError;
-use super::{Normalized, NormalizedTerm, ProjectionCacheEntry, ProjectionCacheKey};
-use rustc_infer::traits::ObligationCauseCode;
-use rustc_middle::traits::BuiltinImplSource;
-use rustc_middle::traits::ImplSource;
-use rustc_middle::traits::ImplSourceUserDefinedData;
-use rustc_middle::{bug, span_bug};
-
-use crate::errors::InherentProjectionNormalizationOverflow;
-use crate::infer::{BoundRegionConversionTime, InferOk};
-use crate::traits::normalize::normalize_with_depth;
-use crate::traits::normalize::normalize_with_depth_to;
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
-use crate::traits::select::ProjectionMatchesProjection;
use rustc_data_structures::sso::SsoHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::ErrorGuaranteed;
@@ -32,13 +9,26 @@
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::infer::DefineOpaqueTypes;
+use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::select::OverflowError;
+pub use rustc_middle::traits::Reveal;
+use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Term, Ty, TyCtxt, Upcast};
+use rustc_middle::{bug, span_bug};
use rustc_span::symbol::sym;
-pub use rustc_middle::traits::Reveal;
+use super::{
+ specialization_graph, translate_args, util, MismatchedProjectionTypes, Normalized,
+ NormalizedTerm, Obligation, ObligationCause, PredicateObligation, ProjectionCacheEntry,
+ ProjectionCacheKey, Selection, SelectionContext, SelectionError,
+};
+use crate::errors::InherentProjectionNormalizationOverflow;
+use crate::infer::{BoundRegionConversionTime, InferOk};
+use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
+use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::select::ProjectionMatchesProjection;
pub type PolyProjectionObligation<'tcx> = Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
@@ -1120,7 +1110,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Error(_) => false,
}
} else if tcx.is_lang_item(trait_ref.def_id, LangItem::PointeeTrait) {
- let tail = selcx.tcx().struct_tail_with_normalize(
+ let tail = selcx.tcx().struct_tail_raw(
self_ty,
|ty| {
// We throw away any obligations we get from this, since we normalize
@@ -1159,10 +1149,10 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
| ty::Never
// Extern types have unit metadata, according to RFC 2850
| ty::Foreign(_)
- // If returned by `struct_tail_without_normalization` this is a unit struct
+ // If returned by `struct_tail` this is a unit struct
// without any fields, or not a struct, and therefore is Sized.
| ty::Adt(..)
- // If returned by `struct_tail_without_normalization` this is the empty tuple.
+ // If returned by `struct_tail` this is the empty tuple.
| ty::Tuple(..)
// Integers and floats are always Sized, and so have unit type metadata.
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 7dc051e..d3a1ed5 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -1,12 +1,12 @@
-use crate::traits::query::normalize::QueryNormalizeExt;
-use crate::traits::query::NoSolution;
-use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
-
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
use rustc_span::{Span, DUMMY_SP};
+use crate::traits::query::normalize::QueryNormalizeExt;
+use crate::traits::query::NoSolution;
+use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
+
/// This returns true if the type `ty` is "trivial" for
/// dropck-outlives -- that is, if it doesn't require any types to
/// outlive. This is similar but not *quite* the same as the
@@ -42,8 +42,15 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
| ty::Foreign(..)
| ty::Error(_) => true,
- // `T is PAT`, `[T; N]`, and `[T]` have same properties as T.
- ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty),
+ // `T is PAT` and `[T]` have same properties as T.
+ ty::Pat(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty),
+ ty::Array(ty, size) => {
+ // Empty array never has a dtor. See issue #110288.
+ match size.try_to_target_usize(tcx) {
+ Some(0) => true,
+ _ => trivial_dropck_outlives(tcx, *ty),
+ }
+ }
// (T1..Tn) and closures have same properties as T1..Tn --
// check if *all* of them are trivial.
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 75f1af7..247b6e4 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -2,26 +2,26 @@
//! which folds deeply, invoking the underlying
//! `normalize_canonicalized_projection_ty` query when it encounters projections.
-use crate::error_reporting::traits::OverflowCause;
-use crate::error_reporting::InferCtxtErrorExt;
-use crate::infer::at::At;
-use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::normalize::needs_normalization;
-use crate::traits::Normalized;
-use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
-use crate::traits::{ObligationCause, PredicateObligation, Reveal};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_macros::extension;
+pub use rustc_middle::traits::query::NormalizationResult;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;
use super::NoSolution;
-
-pub use rustc_middle::traits::query::NormalizationResult;
+use crate::error_reporting::traits::OverflowCause;
+use crate::error_reporting::InferCtxtErrorExt;
+use crate::infer::at::At;
+use crate::infer::canonical::OriginalQueryValues;
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::normalize::needs_normalization;
+use crate::traits::{
+ BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, PredicateObligation,
+ Reveal, ScrubbedTraitError,
+};
#[extension(pub trait QueryNormalizeExt<'tcx>)]
impl<'cx, 'tcx> At<'cx, 'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
index aca1695..5e4de43 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
@@ -1,14 +1,14 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_infer::traits::Obligation;
+pub use rustc_middle::traits::query::type_op::AscribeUserType;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserArgs, UserSelfTy, UserType};
-
-pub use rustc_middle::traits::query::type_op::AscribeUserType;
use rustc_span::{Span, DUMMY_SP};
+use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::traits::ObligationCtxt;
+
impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
type QueryResponse = ();
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index d533e69..34e678e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,14 +1,15 @@
-use crate::infer::canonical::query_response;
-use crate::infer::InferCtxt;
-use crate::traits::query::type_op::TypeOpOutput;
-use crate::traits::ObligationCtxt;
+use std::fmt;
+
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{TyCtxt, TypeFoldable};
use rustc_span::Span;
-use std::fmt;
+use crate::infer::canonical::query_response;
+use crate::infer::InferCtxt;
+use crate::traits::query::type_op::TypeOpOutput;
+use crate::traits::ObligationCtxt;
pub struct CustomTypeOp<F> {
closure: F,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
index 57e649f..656130c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/eq.rs
@@ -1,10 +1,10 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
+pub use rustc_middle::traits::query::type_op::Eq;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
-pub use rustc_middle::traits::query::type_op::Eq;
+use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::traits::ObligationCtxt;
impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
type QueryResponse = ();
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
index 8525215..b5b209c 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs
@@ -1,7 +1,3 @@
-use crate::traits::query::NoSolution;
-use crate::traits::wf;
-use crate::traits::ObligationCtxt;
-
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_infer::traits::query::OutlivesBound;
@@ -14,6 +10,9 @@
use rustc_type_ir::outlives::{push_outlives_components, Component};
use smallvec::{smallvec, SmallVec};
+use crate::traits::query::NoSolution;
+use crate::traits::{wf, ObligationCtxt};
+
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct ImpliedOutlivesBounds<'tcx> {
pub ty: Ty<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index c1b1bfd..2f64ed9 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -1,8 +1,5 @@
-use crate::infer::canonical::{
- Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
-};
-use crate::infer::{InferCtxt, InferOk};
-use crate::traits::{ObligationCause, ObligationCtxt};
+use std::fmt;
+
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::canonical::Certainty;
use rustc_infer::traits::PredicateObligation;
@@ -10,7 +7,12 @@
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use rustc_span::Span;
-use std::fmt;
+
+use crate::infer::canonical::{
+ Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
+};
+use crate::infer::{InferCtxt, InferOk};
+use crate::traits::{ObligationCause, ObligationCtxt};
pub mod ascribe_user_type;
pub mod custom;
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index e9948bf..41c34f6 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,12 +1,13 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
+use std::fmt;
+
+pub use rustc_middle::traits::query::type_op::Normalize;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
-use std::fmt;
-pub use rustc_middle::traits::query::type_op::Normalize;
+use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::traits::ObligationCtxt;
impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
where
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 3e7aa52..49d324f 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -1,11 +1,12 @@
+use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
+use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution};
+use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
+
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::dropck_outlives::{
compute_dropck_outlives_inner, trivial_dropck_outlives,
};
use crate::traits::ObligationCtxt;
-use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
-use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution};
-use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct DropckOutlives<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 6328974..294c6bf 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -1,11 +1,11 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
use rustc_infer::traits::Obligation;
+pub use rustc_middle::traits::query::type_op::ProvePredicate;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
-pub use rustc_middle::traits::query::type_op::ProvePredicate;
+use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::traits::ObligationCtxt;
impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
type QueryResponse = ();
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
index ae11b08..892c2a1 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/subtype.rs
@@ -1,10 +1,10 @@
-use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
+pub use rustc_middle::traits::query::type_op::Subtype;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
-pub use rustc_middle::traits::query::type_op::Subtype;
+use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
+use crate::traits::ObligationCtxt;
impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
type QueryResponse = ();
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 06b79ea..9de6203 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -12,20 +12,17 @@
use hir::LangItem;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir as hir;
-use rustc_infer::traits::ObligationCause;
-use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
+use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
+use super::SelectionCandidate::*;
+use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
use crate::traits;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::util;
-use super::BuiltinImplConditions;
-use super::SelectionCandidate::*;
-use super::{SelectionCandidateSet, SelectionContext, TraitObligationStack};
-
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self, stack), level = "debug")]
pub(super) fn assemble_candidates<'o>(
@@ -470,8 +467,20 @@ fn assemble_async_closure_candidates(
}
candidates.vec.push(AsyncClosureCandidate);
}
- ty::FnDef(..) | ty::FnPtr(..) => {
- candidates.vec.push(AsyncClosureCandidate);
+ // Provide an impl, but only for suitable `fn` pointers.
+ ty::FnPtr(sig) => {
+ if sig.is_fn_trait_compatible() {
+ candidates.vec.push(AsyncClosureCandidate);
+ }
+ }
+ // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
+ ty::FnDef(def_id, _) => {
+ let tcx = self.tcx();
+ if tcx.fn_sig(def_id).skip_binder().is_fn_trait_compatible()
+ && tcx.codegen_fn_attrs(def_id).target_features.is_empty()
+ {
+ candidates.vec.push(AsyncClosureCandidate);
+ }
}
_ => {}
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 9508a3e..ddd8b97 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -7,11 +7,13 @@
//! [rustc dev guide]:
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
+use std::iter;
+use std::ops::ControlFlow;
+
use rustc_ast::Mutability;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
-use rustc_infer::infer::HigherRankedType;
-use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
+use rustc_infer::infer::{DefineOpaqueTypes, HigherRankedType, InferOk};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
use rustc_middle::ty::{
@@ -21,6 +23,8 @@
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
+use super::SelectionCandidate::{self, *};
+use super::{BuiltinImplConditions, SelectionContext};
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
use crate::traits::util::{self, closure_trait_ref_and_return_type};
use crate::traits::{
@@ -29,13 +33,6 @@
SignatureMismatch, TraitNotObjectSafe, TraitObligation, Unimplemented,
};
-use super::BuiltinImplConditions;
-use super::SelectionCandidate::{self, *};
-use super::SelectionContext;
-
-use std::iter;
-use std::ops::ControlFlow;
-
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self))]
pub(super) fn confirm_candidate(
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 699c054..1b2767a 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2,31 +2,12 @@
//!
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
-use self::EvaluationResult::*;
-use self::SelectionCandidate::*;
+use std::cell::{Cell, RefCell};
+use std::fmt::{self, Display};
+use std::ops::ControlFlow;
+use std::{cmp, iter};
-use super::coherence::{self, Conflict};
-use super::const_evaluatable;
-use super::project;
-use super::project::ProjectionTermObligation;
-use super::util;
-use super::util::closure_trait_ref_and_return_type;
-use super::wf;
-use super::{
- ImplDerivedCause, Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow,
- PolyTraitObligation, PredicateObligation, Selection, SelectionError, SelectionResult,
- TraitQueryMode,
-};
-
-use crate::error_reporting::InferCtxtErrorExt;
-use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener};
-use crate::solve::InferCtxtSelectExt as _;
-use crate::traits::normalize::normalize_with_depth;
-use crate::traits::normalize::normalize_with_depth_to;
-use crate::traits::project::ProjectAndUnifyResult;
-use crate::traits::project::ProjectionCacheKeyExt;
-use crate::traits::ProjectionCacheKey;
-use crate::traits::Unimplemented;
+use hir::def::DefKind;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Diag, EmissionGuarantee};
@@ -34,31 +15,39 @@
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_infer::infer::relate::TypeRelation;
-use rustc_infer::infer::BoundRegionConversionTime;
-use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType;
+use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::traits::TraitObligation;
use rustc_middle::bug;
-use rustc_middle::dep_graph::dep_kinds;
-use rustc_middle::dep_graph::DepNodeIndex;
+use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
+pub use rustc_middle::traits::select::*;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::error::TypeErrorToStringExt;
-use rustc_middle::ty::print::PrintTraitRefExt as _;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, PolyProjectionPredicate, Upcast};
-use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
+use rustc_middle::ty::{
+ self, GenericArgsRef, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
+ Upcast,
+};
use rustc_span::symbol::sym;
use rustc_span::Symbol;
-use std::cell::{Cell, RefCell};
-use std::cmp;
-use std::fmt::{self, Display};
-use std::iter;
-use std::ops::ControlFlow;
-
-pub use rustc_middle::traits::select::*;
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use self::EvaluationResult::*;
+use self::SelectionCandidate::*;
+use super::coherence::{self, Conflict};
+use super::project::ProjectionTermObligation;
+use super::util::closure_trait_ref_and_return_type;
+use super::{
+ const_evaluatable, project, util, wf, ImplDerivedCause, Normalized, Obligation,
+ ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
+ Selection, SelectionError, SelectionResult, TraitQueryMode,
+};
+use crate::error_reporting::InferCtxtErrorExt;
+use crate::infer::{InferCtxt, InferCtxtExt, InferOk, TypeFreshener};
+use crate::solve::InferCtxtSelectExt as _;
+use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
+use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};
+use crate::traits::{ProjectionCacheKey, Unimplemented};
mod _match;
mod candidate_assembly;
@@ -2810,6 +2799,26 @@ fn impl_or_trait_obligations(
});
}
+ // Register any outlives obligations from the trait here, cc #124336.
+ if matches!(tcx.def_kind(def_id), DefKind::Impl { of_trait: true }) {
+ for clause in tcx.impl_super_outlives(def_id).iter_instantiated(tcx, args) {
+ let clause = normalize_with_depth_to(
+ self,
+ param_env,
+ cause.clone(),
+ recursion_depth,
+ clause,
+ &mut obligations,
+ );
+ obligations.push(Obligation {
+ cause: cause.clone(),
+ recursion_depth,
+ param_env,
+ predicate: clause.as_predicate(),
+ });
+ }
+ }
+
obligations
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 3c33d13..4c8c5a2 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -10,28 +10,25 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
pub mod specialization_graph;
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::codes::*;
+use rustc_errors::{Diag, EmissionGuarantee};
+use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::DefineOpaqueTypes;
+use rustc_middle::bug;
+use rustc_middle::query::LocalCrate;
use rustc_middle::ty::print::PrintTraitRefExt as _;
+use rustc_middle::ty::{self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
+use rustc_session::lint::builtin::{COHERENCE_LEAK_CHECK, ORDER_DEPENDENT_TRAIT_OBJECTS};
+use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP};
use specialization_graph::GraphExt;
+use super::{util, SelectionContext};
use crate::error_reporting::traits::to_pretty_impl_header;
use crate::errors::NegativePositiveConflict;
use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt};
-use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{codes::*, Diag, EmissionGuarantee};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::bug;
-use rustc_middle::query::LocalCrate;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
-use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
-use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP};
-
-use super::util;
-use super::SelectionContext;
/// Information pertinent to an overlapping impl error.
#[derive(Debug)]
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index 90f2c7a..732f1b0 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -1,14 +1,13 @@
-use super::OverlapError;
-
-use crate::traits;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_macros::extension;
use rustc_middle::bug;
+pub use rustc_middle::traits::specialization_graph::*;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-pub use rustc_middle::traits::specialization_graph::*;
+use super::OverlapError;
+use crate::traits;
#[derive(Copy, Clone, Debug)]
pub enum FutureCompatOverlapErrorKind {
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 951af4b..52f8769 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -1,19 +1,19 @@
use std::collections::BTreeMap;
-use super::NormalizeExt;
-use super::{ObligationCause, PredicateObligation, SelectionContext};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Diag;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::{InferCtxt, InferOk};
+pub use rustc_infer::traits::util::*;
use rustc_middle::bug;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt, Upcast};
-use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::{
+ self, GenericArgsRef, ImplSubject, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt, Upcast,
+};
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
-pub use rustc_infer::traits::util::*;
+use super::{NormalizeExt, ObligationCause, PredicateObligation, SelectionContext};
///////////////////////////////////////////////////////////////////////////
// `TraitAliasExpander` iterator
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 4645d82..1729d8d 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -1,16 +1,18 @@
-use crate::errors::DumpVTableEntries;
-use crate::traits::{impossible_predicates, is_vtable_safe_method};
+use std::fmt::Debug;
+use std::ops::ControlFlow;
+
use rustc_hir::def_id::DefId;
use rustc_infer::traits::util::PredicateSet;
use rustc_middle::bug;
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt, Upcast, VtblEntry};
-use rustc_middle::ty::{GenericArgs, TypeVisitableExt};
+use rustc_middle::ty::{
+ self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry,
+};
use rustc_span::{sym, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
-use std::fmt::Debug;
-use std::ops::ControlFlow;
+use crate::errors::DumpVTableEntries;
+use crate::traits::{impossible_predicates, is_vtable_safe_method};
#[derive(Clone, Debug)]
pub enum VtblSegment<'tcx> {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index e77a05d..7e5fe7e 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -1,17 +1,18 @@
-use crate::infer::InferCtxt;
-use crate::traits;
+use std::iter;
+
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::bug;
use rustc_middle::ty::{
- self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable,
+ TypeVisitable, TypeVisitableExt, TypeVisitor,
};
-use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef};
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::{Span, DUMMY_SP};
-use std::iter;
+use crate::infer::InferCtxt;
+use crate::traits;
/// Returns the set of obligations needed to make `arg` well-formed.
/// If `arg` contains unresolved inference variables, this may include
/// further WF obligations. However, if `arg` IS an unresolved
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index 55abd60..add7ec5 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -5,8 +5,7 @@
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
-use rustc_middle::ty::GenericArgs;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{GenericArgs, TyCtxt};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::dropck_outlives::{
compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index fdeda34..697c839 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -12,11 +12,10 @@
mod normalize_projection_ty;
mod type_op;
+use rustc_middle::query::Providers;
pub use rustc_trait_selection::traits::query::type_op::ascribe_user_type::type_op_ascribe_user_type_with_span;
pub use type_op::type_op_prove_predicate_with_cause;
-use rustc_middle::query::Providers;
-
pub fn provide(p: &mut Providers) {
dropck_outlives::provide(p);
evaluate_obligation::provide(p);
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 06cd638..0dff475 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -4,9 +4,8 @@
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::traits::query::{
- normalize::NormalizationResult, CanonicalAliasGoal, NoSolution,
-};
+use rustc_trait_selection::traits::query::normalize::NormalizationResult;
+use rustc_trait_selection::traits::query::{CanonicalAliasGoal, NoSolution};
use rustc_trait_selection::traits::{self, ObligationCause, ScrubbedTraitError, SelectionContext};
use tracing::debug;
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index b6a59a4..5affada 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -1,9 +1,10 @@
+use std::fmt;
+
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers;
use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::{Clause, ParamEnvAnd};
-use rustc_middle::ty::{FnSig, PolyFnSig, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{Clause, FnSig, ParamEnvAnd, PolyFnSig, Ty, TyCtxt, TypeFoldable};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
@@ -14,7 +15,6 @@
use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
-use std::fmt;
pub(crate) fn provide(p: &mut Providers) {
*p = Providers {
diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs
index 3378d1c..58bd517 100644
--- a/compiler/rustc_transmute/src/layout/dfa.rs
+++ b/compiler/rustc_transmute/src/layout/dfa.rs
@@ -1,9 +1,11 @@
-use super::{nfa, Byte, Nfa, Ref};
-use crate::Map;
use std::fmt;
use std::sync::atomic::{AtomicU32, Ordering};
+
use tracing::instrument;
+use super::{nfa, Byte, Nfa, Ref};
+use crate::Map;
+
#[derive(PartialEq, Clone, Debug)]
pub(crate) struct Dfa<R>
where
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index 0377ed5..bbf1555 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -60,9 +60,10 @@ fn is_mutable(&self) -> bool {
#[cfg(feature = "rustc")]
pub mod rustc {
+ use std::fmt::{self, Write};
+
use rustc_middle::mir::Mutability;
use rustc_middle::ty::{self, Ty};
- use std::fmt::{self, Write};
/// A reference in the layout.
#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
diff --git a/compiler/rustc_transmute/src/layout/nfa.rs b/compiler/rustc_transmute/src/layout/nfa.rs
index 3c59632..5db5a8f 100644
--- a/compiler/rustc_transmute/src/layout/nfa.rs
+++ b/compiler/rustc_transmute/src/layout/nfa.rs
@@ -1,8 +1,9 @@
-use super::{Byte, Ref, Tree, Uninhabited};
-use crate::{Map, Set};
use std::fmt;
use std::sync::atomic::{AtomicU32, Ordering};
+use super::{Byte, Ref, Tree, Uninhabited};
+use crate::{Map, Set};
+
/// A non-deterministic finite automaton (NFA) that represents the layout of a type.
/// The transmutability of two given types is computed by comparing their `Nfa`s.
#[derive(PartialEq, Debug)]
@@ -86,6 +87,7 @@ pub(crate) fn from_ref(r: R) -> Self {
pub(crate) fn from_tree(tree: Tree<!, R>) -> Result<Self, Uninhabited> {
Ok(match tree {
Tree::Byte(b) => Self::from_byte(b),
+ #[cfg(bootstrap)]
Tree::Def(..) => unreachable!(),
Tree::Ref(r) => Self::from_ref(r),
Tree::Alt(alts) => {
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 865f948..5c25f91 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -1,6 +1,7 @@
-use super::{Byte, Def, Ref};
use std::ops::ControlFlow;
+use super::{Byte, Def, Ref};
+
#[cfg(test)]
mod tests;
@@ -170,24 +171,14 @@ pub(crate) fn or(self, other: Self) -> Self {
#[cfg(feature = "rustc")]
pub(crate) mod rustc {
+ use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, LayoutError, LayoutOf};
+ use rustc_middle::ty::{self, AdtDef, AdtKind, List, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
+ use rustc_span::ErrorGuaranteed;
+ use rustc_target::abi::{FieldsShape, Size, TyAndLayout, Variants};
+
use super::Tree;
use crate::layout::rustc::{Def, Ref};
- use rustc_middle::ty::layout::HasTyCtxt;
- use rustc_middle::ty::layout::LayoutCx;
- use rustc_middle::ty::layout::LayoutError;
- use rustc_middle::ty::layout::LayoutOf;
- use rustc_middle::ty::AdtDef;
- use rustc_middle::ty::AdtKind;
- use rustc_middle::ty::List;
- use rustc_middle::ty::ScalarInt;
- use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
- use rustc_span::ErrorGuaranteed;
- use rustc_target::abi::FieldsShape;
- use rustc_target::abi::Size;
- use rustc_target::abi::TyAndLayout;
- use rustc_target::abi::Variants;
-
#[derive(Debug, Copy, Clone)]
pub(crate) enum Err {
/// The layout of the type is not yet supported.
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 2b05241..31664ee 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -79,19 +79,15 @@ pub enum Reason<T> {
#[cfg(feature = "rustc")]
mod rustc {
- use super::*;
-
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::InferCtxt;
use rustc_macros::TypeVisitable;
use rustc_middle::traits::ObligationCause;
- use rustc_middle::ty::Const;
- use rustc_middle::ty::ParamEnv;
- use rustc_middle::ty::Ty;
- use rustc_middle::ty::TyCtxt;
- use rustc_middle::ty::ValTree;
+ use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt, ValTree};
use rustc_span::DUMMY_SP;
+ use super::*;
+
/// The source and destination types of a transmutation.
#[derive(TypeVisitable, Debug, Clone, Copy)]
pub struct Types<'tcx> {
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
index dee5a72..7c66a82 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs
@@ -4,11 +4,9 @@
#[cfg(test)]
mod tests;
-use crate::{
- layout::{self, dfa, Byte, Def, Dfa, Nfa, Ref, Tree, Uninhabited},
- maybe_transmutable::query_context::QueryContext,
- Answer, Condition, Map, Reason,
-};
+use crate::layout::{self, dfa, Byte, Def, Dfa, Nfa, Ref, Tree, Uninhabited};
+use crate::maybe_transmutable::query_context::QueryContext;
+use crate::{Answer, Condition, Map, Reason};
pub(crate) struct MaybeTransmutableQuery<L, C>
where
@@ -32,15 +30,12 @@ pub(crate) fn new(src: L, dst: L, assume: crate::Assume, context: C) -> Self {
// FIXME: Nix this cfg, so we can write unit tests independently of rustc
#[cfg(feature = "rustc")]
mod rustc {
+ use rustc_middle::ty::layout::{LayoutCx, LayoutOf};
+ use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+
use super::*;
use crate::layout::tree::rustc::Err;
- use rustc_middle::ty::layout::LayoutCx;
- use rustc_middle::ty::layout::LayoutOf;
- use rustc_middle::ty::ParamEnv;
- use rustc_middle::ty::Ty;
- use rustc_middle::ty::TyCtxt;
-
impl<'tcx> MaybeTransmutableQuery<Ty<'tcx>, TyCtxt<'tcx>> {
/// This method begins by converting `src` and `dst` from `Ty`s to `Tree`s,
/// then computes an answer using those trees.
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
index 1ccb6f3..9537391 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
@@ -34,9 +34,10 @@ impl QueryContext for UltraMinimal {
#[cfg(feature = "rustc")]
mod rustc {
- use super::*;
use rustc_middle::ty::{Ty, TyCtxt};
+ use super::*;
+
impl<'tcx> super::QueryContext for TyCtxt<'tcx> {
type Def = layout::rustc::Def<'tcx>;
type Ref = layout::rustc::Ref<'tcx>;
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
index 9c7abf1..c3be420 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs
@@ -1,12 +1,12 @@
+use itertools::Itertools;
+
use super::query_context::test::{Def, UltraMinimal};
use crate::maybe_transmutable::MaybeTransmutableQuery;
use crate::{layout, Reason};
-use itertools::Itertools;
mod safety {
- use crate::Answer;
-
use super::*;
+ use crate::Answer;
type Tree = layout::Tree<Def, !>;
@@ -63,9 +63,8 @@ fn src_unsafe_dst_unsafe() {
}
mod bool {
- use crate::Answer;
-
use super::*;
+ use crate::Answer;
#[test]
fn should_permit_identity_transmutation_tree() {
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 1dced9c..d90c3be 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -1,3 +1,5 @@
+use std::iter;
+
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_middle::bug;
@@ -16,8 +18,6 @@
use rustc_target::spec::abi::Abi as SpecAbi;
use tracing::debug;
-use std::iter;
-
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
}
@@ -549,7 +549,7 @@ fn fn_arg_sanity_check<'tcx>(
// With metadata. Must be unsized and not on the stack.
assert!(arg.layout.is_unsized() && !on_stack);
// Also, must not be `extern` type.
- let tail = cx.tcx.struct_tail_with_normalize(arg.layout.ty, |ty| ty, || {});
+ let tail = cx.tcx.struct_tail_for_codegen(arg.layout.ty, cx.param_env());
if matches!(tail.kind(), ty::Foreign(..)) {
// These types do not have metadata, so having `meta_attrs` is bogus.
// Conceptually, unsized arguments must be copied around, which requires dynamically
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 58f812f..2492688 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -1,20 +1,19 @@
+use std::iter;
+
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
-use rustc_middle::bug;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::query::Providers;
use rustc_middle::thir::visit;
use rustc_middle::thir::visit::Visitor;
use rustc_middle::ty::abstract_const::CastKind;
use rustc_middle::ty::{self, Expr, TyCtxt, TypeVisitableExt};
-use rustc_middle::{mir, thir};
+use rustc_middle::{bug, mir, thir};
use rustc_span::Span;
use rustc_target::abi::{VariantIdx, FIRST_VARIANT};
use tracing::{debug, instrument};
-use std::iter;
-
use crate::errors::{GenericConstantTooComplex, GenericConstantTooComplexSub};
/// Destructures array, ADT or tuple constants into the constants
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 6f71951..8812260 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,3 +1,5 @@
+use std::iter;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
@@ -6,7 +8,6 @@
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
-use std::iter;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index a2bed61..43e4913 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -6,8 +6,7 @@
use rustc_middle::query::Providers;
use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError};
use rustc_middle::ty::util::AsyncDropGlueMorphology;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgsRef, Instance, TyCtxt, TypeVisitableExt};
use rustc_span::sym;
use rustc_trait_selection::traits;
use rustc_type_ir::ClosureKind;
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 6045abc..244a6af 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,3 +1,6 @@
+use std::fmt::Debug;
+use std::iter;
+
use hir::def_id::DefId;
use rustc_hir as hir;
use rustc_index::bit_set::BitSet;
@@ -19,9 +22,6 @@
use rustc_target::abi::*;
use tracing::{debug, instrument, trace};
-use std::fmt::Debug;
-use std::iter;
-
use crate::errors::{
MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType,
};
@@ -219,9 +219,13 @@ fn layout_of_uncached<'tcx>(
// its struct tail cannot be normalized either, so try to get a
// more descriptive layout error here, which will lead to less confusing
// diagnostics.
+ //
+ // We use the raw struct tail function here to get the first tail
+ // that is an alias, which is likely the cause of the normalization
+ // error.
match tcx.try_normalize_erasing_regions(
param_env,
- tcx.struct_tail_without_normalization(pointee),
+ tcx.struct_tail_raw(pointee, |ty| ty, || {}),
) {
Ok(_) => {}
Err(better_err) => {
@@ -244,7 +248,7 @@ fn layout_of_uncached<'tcx>(
metadata
} else {
- let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
+ let unsized_part = tcx.struct_tail_for_codegen(pointee, param_env);
match unsized_part.kind() {
ty::Foreign(..) => {
@@ -733,9 +737,7 @@ fn coroutine_saved_local_eligibility(
// point, so it is no longer a candidate.
trace!(
"removing local {:?} in >1 variant ({:?}, {:?})",
- local,
- variant_index,
- idx
+ local, variant_index, idx
);
ineligible_locals.insert(*local);
assignments[*local] = Ineligible(None);
diff --git a/compiler/rustc_ty_utils/src/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index ab7d1be..2223aca 100644
--- a/compiler/rustc_ty_utils/src/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -1,12 +1,10 @@
-use rustc_middle::bug;
-use rustc_middle::ty::{
- layout::{LayoutCx, TyAndLayout},
- TyCtxt,
-};
-use rustc_target::abi::*;
-
use std::assert_matches::assert_matches;
+use rustc_middle::bug;
+use rustc_middle::ty::layout::{LayoutCx, TyAndLayout};
+use rustc_middle::ty::TyCtxt;
+use rustc_target::abi::*;
+
/// Enforce some basic invariants on layouts.
pub(super) fn sanity_check_layout<'tcx>(
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
@@ -251,7 +249,7 @@ fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: &TyAndLayou
if let Variants::Multiple { variants, .. } = &layout.variants {
for variant in variants.iter() {
// No nested "multiple".
- assert!(matches!(variant.variants, Variants::Single { .. }));
+ assert_matches!(variant.variants, Variants::Single { .. });
// Variants should have the same or a smaller size as the full thing,
// and same for alignment.
if variant.size > layout.size {
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index 205b3f2..d274a93 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -5,8 +5,7 @@
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
+use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
use rustc_session::Limit;
use rustc_span::sym;
use tracing::debug;
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 5e91320..6680b45 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,12 +1,12 @@
use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::Visitor;
-use rustc_hir::{def::DefKind, def_id::LocalDefId};
use rustc_hir::{intravisit, CRATE_HIR_ID};
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::Span;
use tracing::{instrument, trace};
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index eb6cb36..568b938 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -3,7 +3,8 @@
use rustc_ast_ir::try_visit;
use rustc_ast_ir::visit::VisitorResult;
-use rustc_hir::{def::DefKind, def_id::LocalDefId};
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::LocalDefId;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
index 241aff9..1ead7b7 100644
--- a/compiler/rustc_ty_utils/src/structural_match.rs
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -1,8 +1,7 @@
use rustc_hir::lang_items::LangItem;
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
-
-use rustc_infer::infer::TyCtxtInferExt;
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
/// This method returns true if and only if `adt_ty` itself has been marked as
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 38950c9..aba2acd 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -5,8 +5,10 @@
use rustc_index::bit_set::BitSet;
use rustc_middle::bug;
use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt, TypeVisitor};
-use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, Upcast};
+use rustc_middle::ty::{
+ self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ TypeVisitor, Upcast,
+};
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits;
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index 7e93dc2..d609e5a 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -1,12 +1,11 @@
-#![allow(clippy::derived_hash_with_manual_eq)]
+use std::fmt;
+use std::hash::Hash;
+use std::ops::Index;
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
-use std::fmt;
-use std::hash::Hash;
-use std::ops::Index;
use crate::inherent::*;
use crate::{self as ty, Interner, UniverseIndex};
@@ -141,7 +140,7 @@ pub fn expect_placeholder_index(self) -> usize {
/// Describes the "kind" of the canonical variable. This is a "kind"
/// in the type-theory sense of the term -- i.e., a "meta" type system
/// that analyzes type-like values.
-#[derive_where(Clone, Copy, Hash, Eq, Debug; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub enum CanonicalVarKind<I: Interner> {
@@ -169,21 +168,6 @@ pub enum CanonicalVarKind<I: Interner> {
PlaceholderConst(I::PlaceholderConst),
}
-// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
-impl<I: Interner> PartialEq for CanonicalVarKind<I> {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Self::Ty(l0), Self::Ty(r0)) => l0 == r0,
- (Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
- (Self::Region(l0), Self::Region(r0)) => l0 == r0,
- (Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
- (Self::Const(l0), Self::Const(r0)) => l0 == r0,
- (Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0,
- _ => std::mem::discriminant(self) == std::mem::discriminant(other),
- }
- }
-}
-
impl<I: Interner> CanonicalVarKind<I> {
pub fn universe(self) -> UniverseIndex {
match self {
diff --git a/compiler/rustc_type_ir/src/codec.rs b/compiler/rustc_type_ir/src/codec.rs
index 71f9eb0..f443f59 100644
--- a/compiler/rustc_type_ir/src/codec.rs
+++ b/compiler/rustc_type_ir/src/codec.rs
@@ -1,8 +1,8 @@
-use crate::{Interner, PredicateKind};
-
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{SpanDecoder, SpanEncoder};
+use crate::{Interner, PredicateKind};
+
/// The shorthand encoding uses an enum's variant index `usize`
/// and is offset by this value so it never matches a real variant.
/// This offset is also chosen so that the first byte is never < 0x80.
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 458ffda..7a8c612 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::derived_hash_with_manual_eq)]
+use std::fmt;
use derive_where::derive_where;
#[cfg(feature = "nightly")]
@@ -6,14 +6,11 @@
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
-use std::fmt;
use crate::{self as ty, DebruijnIndex, Interner};
-use self::ConstKind::*;
-
/// Represents a constant in Rust.
-#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ConstKind<I: Interner> {
/// A const generic parameter.
@@ -45,23 +42,6 @@ pub enum ConstKind<I: Interner> {
Expr(I::ExprConst),
}
-// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
-impl<I: Interner> PartialEq for ConstKind<I> {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Param(l0), Param(r0)) => l0 == r0,
- (Infer(l0), Infer(r0)) => l0 == r0,
- (Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
- (Placeholder(l0), Placeholder(r0)) => l0 == r0,
- (Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
- (Value(l0, l1), Value(r0, r1)) => l0 == r0 && l1 == r1,
- (Error(l0), Error(r0)) => l0 == r0,
- (Expr(l0), Expr(r0)) => l0 == r0,
- _ => false,
- }
- }
-}
-
impl<I: Interner> fmt::Debug for ConstKind<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ConstKind::*;
@@ -80,7 +60,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
}
/// An unevaluated (potentially generic) constant used in the type-system.
-#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct UnevaluatedConst<I: Interner> {
@@ -95,15 +75,6 @@ pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
}
}
-impl<I: Interner> fmt::Debug for UnevaluatedConst<I> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("UnevaluatedConst")
- .field("def", &self.def)
- .field("args", &self.args)
- .finish()
- }
-}
-
rustc_index::newtype_index! {
/// A **`const`** **v**ariable **ID**.
#[encodable]
diff --git a/compiler/rustc_type_ir/src/data_structures.rs b/compiler/rustc_type_ir/src/data_structures.rs
index 6d8ab61..4ca97c0 100644
--- a/compiler/rustc_type_ir/src/data_structures.rs
+++ b/compiler/rustc_type_ir/src/data_structures.rs
@@ -1,25 +1,20 @@
#[cfg(feature = "nightly")]
mod impl_ {
- pub use rustc_data_structures::fx::FxHashMap as HashMap;
- pub use rustc_data_structures::fx::FxHashSet as HashSet;
- pub use rustc_data_structures::fx::FxIndexMap as IndexMap;
- pub use rustc_data_structures::fx::FxIndexSet as IndexSet;
- pub use rustc_data_structures::sso::SsoHashMap;
- pub use rustc_data_structures::sso::SsoHashSet;
+ pub use rustc_data_structures::fx::{
+ FxHashMap as HashMap, FxHashSet as HashSet, FxIndexMap as IndexMap, FxIndexSet as IndexSet,
+ };
+ pub use rustc_data_structures::sso::{SsoHashMap, SsoHashSet};
pub use rustc_data_structures::stack::ensure_sufficient_stack;
pub use rustc_data_structures::sync::Lrc;
}
#[cfg(not(feature = "nightly"))]
mod impl_ {
- pub use indexmap::IndexMap;
- pub use indexmap::IndexSet;
- pub use std::collections::HashMap;
- pub use std::collections::HashMap as SsoHashMap;
- pub use std::collections::HashSet;
- pub use std::collections::HashSet as SsoHashSet;
+ pub use std::collections::{HashMap, HashMap as SsoHashMap, HashSet, HashSet as SsoHashSet};
pub use std::sync::Arc as Lrc;
+ pub use indexmap::{IndexMap, IndexSet};
+
#[inline]
pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
f()
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 7dd2f3d..f30419c 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -3,9 +3,9 @@
use smallvec::smallvec;
use crate::data_structures::HashSet;
+use crate::inherent::*;
use crate::outlives::{push_outlives_components, Component};
-use crate::{self as ty, Interner};
-use crate::{inherent::*, Upcast as _};
+use crate::{self as ty, Interner, Upcast as _};
/// "Elaboration" is the process of identifying all the predicates that
/// are implied by a source predicate. Currently, this basically means
@@ -264,15 +264,6 @@ pub fn supertraits<I: Interner>(
elaborate(cx, [trait_ref.upcast(cx)]).filter_only_self().filter_to_traits()
}
-pub fn transitive_bounds<I: Interner>(
- cx: I,
- trait_refs: impl Iterator<Item = ty::Binder<I, ty::TraitRef<I>>>,
-) -> FilterToTraits<I, Elaborator<I, I::Clause>> {
- elaborate(cx, trait_refs.map(|trait_ref| trait_ref.upcast(cx)))
- .filter_only_self()
- .filter_to_traits()
-}
-
impl<I: Interner> Elaborator<I, I::Clause> {
fn filter_to_traits(self) -> FilterToTraits<I, Self> {
FilterToTraits { _cx: PhantomData, base_iterator: self }
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index a4d8daf..d37bacc 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -45,8 +45,9 @@
//! - u.fold_with(folder)
//! ```
-use rustc_index::{Idx, IndexVec};
use std::mem;
+
+use rustc_index::{Idx, IndexVec};
use tracing::debug;
use crate::data_structures::Lrc;
@@ -90,6 +91,7 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
match self.try_fold_with(folder) {
Ok(t) => t,
+ #[cfg(bootstrap)]
Err(e) => match e {},
}
}
@@ -114,6 +116,7 @@ fn try_super_fold_with<F: FallibleTypeFolder<I>>(
fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
match self.try_super_fold_with(folder) {
Ok(t) => t,
+ #[cfg(bootstrap)]
Err(e) => match e {},
}
}
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
index 63ad36e..263ba67 100644
--- a/compiler/rustc_type_ir/src/inherent.rs
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -432,6 +432,7 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
+ UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
+ UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
+ IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
+ + Elaboratable<I>
{
fn as_clause(self) -> Option<I::Clause>;
@@ -450,6 +451,8 @@ pub trait Clause<I: Interner<Clause = Self>>:
+ UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
+ UpcastFrom<I, ty::TraitRef<I>>
+ UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
+ + UpcastFrom<I, ty::TraitPredicate<I>>
+ + UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
+ UpcastFrom<I, ty::ProjectionPredicate<I>>
+ UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
+ IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 14ebbb1..c251540 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -1,22 +1,24 @@
-use rustc_ast_ir::Movability;
-use rustc_index::bit_set::BitSet;
-use smallvec::SmallVec;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::Deref;
+use rustc_ast_ir::Movability;
+use rustc_index::bit_set::BitSet;
+use smallvec::SmallVec;
+
use crate::fold::TypeFoldable;
use crate::inherent::*;
use crate::ir_print::IrPrint;
use crate::lang_items::TraitSolverLangItem;
use crate::relate::Relate;
-use crate::search_graph;
use crate::solve::inspect::CanonicalGoalEvaluationStep;
use crate::solve::{
CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, SolverMode,
};
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{self as ty};
+use crate::{
+ search_graph, {self as ty},
+};
pub trait Interner:
Sized
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 80e970a..de41d2f 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -9,11 +9,12 @@
extern crate self as rustc_type_ir;
-#[cfg(feature = "nightly")]
-use rustc_macros::{Decodable, Encodable, HashStable_NoContext};
use std::fmt;
use std::hash::Hash;
+#[cfg(feature = "nightly")]
+use rustc_macros::{Decodable, Encodable, HashStable_NoContext};
+
// These modules are `pub` since they are not glob-imported.
#[macro_use]
pub mod visit;
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 70b7c29..c8a2102 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,16 +1,15 @@
-#![allow(clippy::derived_hash_with_manual_eq)]
+use std::fmt;
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
-use std::fmt;
use crate::{self as ty, Interner};
/// A clause is something that can appear in where bounds or be inferred
/// by implied bounds.
-#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ClauseKind<I: Interner> {
@@ -40,22 +39,6 @@ pub enum ClauseKind<I: Interner> {
ConstEvaluatable(I::Const),
}
-// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
-impl<I: Interner> PartialEq for ClauseKind<I> {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Self::Trait(l0), Self::Trait(r0)) => l0 == r0,
- (Self::RegionOutlives(l0), Self::RegionOutlives(r0)) => l0 == r0,
- (Self::TypeOutlives(l0), Self::TypeOutlives(r0)) => l0 == r0,
- (Self::Projection(l0), Self::Projection(r0)) => l0 == r0,
- (Self::ConstArgHasType(l0, l1), Self::ConstArgHasType(r0, r1)) => l0 == r0 && l1 == r1,
- (Self::WellFormed(l0), Self::WellFormed(r0)) => l0 == r0,
- (Self::ConstEvaluatable(l0), Self::ConstEvaluatable(r0)) => l0 == r0,
- _ => false,
- }
- }
-}
-
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index ef18ef1..e0b3973 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -1,15 +1,13 @@
-#![allow(clippy::derived_hash_with_manual_eq)]
+use std::fmt;
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
-use std::fmt;
-
-use crate::{DebruijnIndex, Interner};
use self::RegionKind::*;
+use crate::{DebruijnIndex, Interner};
rustc_index::newtype_index! {
/// A **region** **v**ariable **ID**.
@@ -127,7 +125,7 @@ pub struct RegionVid {}
/// [1]: https://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum RegionKind<I: Interner> {
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
@@ -179,48 +177,6 @@ pub enum RegionKind<I: Interner> {
ReError(I::ErrorGuaranteed),
}
-// This is manually implemented for `RegionKind` because `std::mem::discriminant`
-// returns an opaque value that is `PartialEq` but not `PartialOrd`
-#[inline]
-const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
- match value {
- ReEarlyParam(_) => 0,
- ReBound(_, _) => 1,
- ReLateParam(_) => 2,
- ReStatic => 3,
- ReVar(_) => 4,
- RePlaceholder(_) => 5,
- ReErased => 6,
- ReError(_) => 7,
- }
-}
-
-// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
-// This is manually implemented because a derive would require `I: PartialEq`
-impl<I: Interner> PartialEq for RegionKind<I> {
- #[inline]
- fn eq(&self, other: &RegionKind<I>) -> bool {
- regionkind_discriminant(self) == regionkind_discriminant(other)
- && match (self, other) {
- (ReEarlyParam(a_r), ReEarlyParam(b_r)) => a_r == b_r,
- (ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
- (ReLateParam(a_r), ReLateParam(b_r)) => a_r == b_r,
- (ReStatic, ReStatic) => true,
- (ReVar(a_r), ReVar(b_r)) => a_r == b_r,
- (RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
- (ReErased, ReErased) => true,
- (ReError(_), ReError(_)) => true,
- _ => {
- debug_assert!(
- false,
- "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
- );
- true
- }
- }
- }
-}
-
impl<I: Interner> fmt::Debug for RegionKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs
index e25df7a..47d5e0d 100644
--- a/compiler/rustc_type_ir/src/solve/inspect.rs
+++ b/compiler/rustc_type_ir/src/solve/inspect.rs
@@ -17,14 +17,16 @@
//!
//! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
+use std::fmt::Debug;
+use std::hash::Hash;
+
+use derive_where::derive_where;
+use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
+
use crate::solve::{
CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult,
};
use crate::{Canonical, CanonicalVarValues, Interner};
-use derive_where::derive_where;
-use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
-use std::fmt::Debug;
-use std::hash::Hash;
/// Some `data` together with information about how they relate to the input
/// of the canonical query.
diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs
index 0e49305..a999566 100644
--- a/compiler/rustc_type_ir/src/ty_info.rs
+++ b/compiler/rustc_type_ir/src/ty_info.rs
@@ -1,10 +1,11 @@
+use std::cmp::Ordering;
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+
#[cfg(feature = "nightly")]
use rustc_data_structures::fingerprint::Fingerprint;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use std::cmp::Ordering;
-use std::hash::{Hash, Hasher};
-use std::ops::Deref;
use crate::{DebruijnIndex, TypeFlags};
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 4672904..7e48f1b 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,7 +1,7 @@
-#![allow(clippy::derived_hash_with_manual_eq)]
+use std::fmt;
use derive_where::derive_where;
-
+use rustc_ast_ir::Mutability;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
@@ -9,15 +9,12 @@
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
-use std::fmt;
pub use self::closure::*;
use self::TyKind::*;
use crate::inherent::*;
use crate::{self as ty, DebruijnIndex, Interner};
-use rustc_ast_ir::Mutability;
-
mod closure;
/// Specifies how a trait object is represented.
@@ -68,7 +65,7 @@ pub fn descr(self) -> &'static str {
/// Types written by the user start out as `hir::TyKind` and get
/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
-#[derive_where(Clone, Copy, Hash, Eq; I: Interner)]
+#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum TyKind<I: Interner> {
/// The primitive boolean type. Written as `bool`.
@@ -259,92 +256,6 @@ pub fn is_primitive(&self) -> bool {
}
}
-// This is manually implemented for `TyKind` because `std::mem::discriminant`
-// returns an opaque value that is `PartialEq` but not `PartialOrd`
-#[inline]
-const fn tykind_discriminant<I: Interner>(value: &TyKind<I>) -> usize {
- match value {
- Bool => 0,
- Char => 1,
- Int(_) => 2,
- Uint(_) => 3,
- Float(_) => 4,
- Adt(_, _) => 5,
- Foreign(_) => 6,
- Str => 7,
- Array(_, _) => 8,
- Slice(_) => 9,
- RawPtr(_, _) => 10,
- Ref(_, _, _) => 11,
- FnDef(_, _) => 12,
- FnPtr(_) => 13,
- Dynamic(..) => 14,
- Closure(_, _) => 15,
- CoroutineClosure(_, _) => 16,
- Coroutine(_, _) => 17,
- CoroutineWitness(_, _) => 18,
- Never => 19,
- Tuple(_) => 20,
- Pat(_, _) => 21,
- Alias(_, _) => 22,
- Param(_) => 23,
- Bound(_, _) => 24,
- Placeholder(_) => 25,
- Infer(_) => 26,
- Error(_) => 27,
- }
-}
-
-// FIXME(GrigorenkoPV): consider not implementing PartialEq manually
-// This is manually implemented because a derive would require `I: PartialEq`
-impl<I: Interner> PartialEq for TyKind<I> {
- #[inline]
- fn eq(&self, other: &TyKind<I>) -> bool {
- // You might expect this `match` to be preceded with this:
- //
- // tykind_discriminant(self) == tykind_discriminant(other) &&
- //
- // but the data patterns in practice are such that a comparison
- // succeeds 99%+ of the time, and it's faster to omit it.
- match (self, other) {
- (Int(a_i), Int(b_i)) => a_i == b_i,
- (Uint(a_u), Uint(b_u)) => a_u == b_u,
- (Float(a_f), Float(b_f)) => a_f == b_f,
- (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (Foreign(a_d), Foreign(b_d)) => a_d == b_d,
- (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c,
- (Pat(a_t, a_c), Pat(b_t, b_c)) => a_t == b_t && a_c == b_c,
- (Slice(a_t), Slice(b_t)) => a_t == b_t,
- (RawPtr(a_t, a_m), RawPtr(b_t, b_m)) => a_t == b_t && a_m == b_m,
- (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m,
- (FnDef(a_d, a_s), FnDef(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (FnPtr(a_s), FnPtr(b_s)) => a_s == b_s,
- (Dynamic(a_p, a_r, a_repr), Dynamic(b_p, b_r, b_repr)) => {
- a_p == b_p && a_r == b_r && a_repr == b_repr
- }
- (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (CoroutineClosure(a_d, a_s), CoroutineClosure(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s,
- (Tuple(a_t), Tuple(b_t)) => a_t == b_t,
- (Alias(a_i, a_p), Alias(b_i, b_p)) => a_i == b_i && a_p == b_p,
- (Param(a_p), Param(b_p)) => a_p == b_p,
- (Bound(a_d, a_b), Bound(b_d, b_b)) => a_d == b_d && a_b == b_b,
- (Placeholder(a_p), Placeholder(b_p)) => a_p == b_p,
- (Infer(a_t), Infer(b_t)) => a_t == b_t,
- (Error(a_e), Error(b_e)) => a_e == b_e,
- (Bool, Bool) | (Char, Char) | (Str, Str) | (Never, Never) => true,
- _ => {
- debug_assert!(
- tykind_discriminant(self) != tykind_discriminant(other),
- "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}"
- );
- false
- }
- }
- }
-}
-
// This is manually implemented because a derive would require `I: Debug`
impl<I: Interner> fmt::Debug for TyKind<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index d5e114b..0ba7e2b 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -41,11 +41,12 @@
//! - u.visit_with(visitor)
//! ```
+use std::fmt;
+use std::ops::ControlFlow;
+
use rustc_ast_ir::visit::VisitorResult;
use rustc_ast_ir::{try_visit, walk_visitable_list};
use rustc_index::{Idx, IndexVec};
-use std::fmt;
-use std::ops::ControlFlow;
use crate::data_structures::Lrc;
use crate::inherent::*;
diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs
index f5b9042..2bfbfaa4 100644
--- a/compiler/rustc_type_ir_macros/src/lib.rs
+++ b/compiler/rustc_type_ir_macros/src/lib.rs
@@ -1,5 +1,6 @@
use quote::quote;
-use syn::{parse_quote, visit_mut::VisitMut};
+use syn::parse_quote;
+use syn::visit_mut::VisitMut;
use synstructure::decl_derive;
decl_derive!(
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index c003ec1..9d3b40e 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -1,15 +1,15 @@
-use crate::compiler_interface::with;
-use crate::error;
-use crate::mir::FieldIdx;
-use crate::target::{MachineInfo, MachineSize as Size};
-use crate::ty::{Align, IndexedVal, Ty, VariantIdx};
-use crate::Error;
-use crate::Opaque;
-use serde::Serialize;
use std::fmt::{self, Debug};
use std::num::NonZero;
use std::ops::RangeInclusive;
+use serde::Serialize;
+
+use crate::compiler_interface::with;
+use crate::mir::FieldIdx;
+use crate::target::{MachineInfo, MachineSize as Size};
+use crate::ty::{Align, IndexedVal, Ty, VariantIdx};
+use crate::{error, Error, Opaque};
+
/// A function ABI definition.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub struct FnAbi {
diff --git a/compiler/stable_mir/src/crate_def.rs b/compiler/stable_mir/src/crate_def.rs
index bf2b35b..2882fdf 100644
--- a/compiler/stable_mir/src/crate_def.rs
+++ b/compiler/stable_mir/src/crate_def.rs
@@ -1,9 +1,10 @@
//! Module that define a common trait for things that represent a crate definition,
//! such as, a function, a trait, an enum, and any other definitions.
+use serde::Serialize;
+
use crate::ty::{GenericArgs, Span, Ty};
use crate::{with, Crate, Symbol};
-use serde::Serialize;
/// A unique identification number for each item accessible for the current compilation unit.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)]
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index fe74532..b523e94 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -17,17 +17,16 @@
//! The goal is to eventually be published on
//! [crates.io](https://crates.io).
-use std::fmt;
use std::fmt::Debug;
-use std::io;
+use std::{fmt, io};
+
+use serde::Serialize;
use crate::compiler_interface::with;
pub use crate::crate_def::{CrateDef, CrateDefType, DefId};
pub use crate::error::*;
-use crate::mir::Body;
-use crate::mir::Mutability;
+use crate::mir::{Body, Mutability};
use crate::ty::{ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
-use serde::Serialize;
pub mod abi;
#[macro_use]
diff --git a/compiler/stable_mir/src/mir/alloc.rs b/compiler/stable_mir/src/mir/alloc.rs
index 9e0cac6..a3768f8 100644
--- a/compiler/stable_mir/src/mir/alloc.rs
+++ b/compiler/stable_mir/src/mir/alloc.rs
@@ -1,11 +1,13 @@
//! This module provides methods to retrieve allocation information, such as static variables.
+use std::io::Read;
+
+use serde::Serialize;
+
use crate::mir::mono::{Instance, StaticDef};
use crate::target::{Endian, MachineInfo};
use crate::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
use crate::{with, Error};
-use serde::Serialize;
-use std::io::Read;
/// An allocation in the SMIR global memory can be either a function pointer,
/// a static, or a "real" allocation with some data in it.
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index f7457ec..7c09fe1 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1,3 +1,7 @@
+use std::io;
+
+use serde::Serialize;
+
use crate::compiler_interface::with;
use crate::mir::pretty::function_body;
use crate::ty::{
@@ -5,8 +9,6 @@
TyConst, TyKind, VariantIdx,
};
use crate::{Error, Opaque, Span, Symbol};
-use serde::Serialize;
-use std::io;
/// The SMIR representation of a single function.
#[derive(Clone, Debug, Serialize)]
diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs
index c232933..cd02844 100644
--- a/compiler/stable_mir/src/mir/mono.rs
+++ b/compiler/stable_mir/src/mir/mono.rs
@@ -1,11 +1,13 @@
+use std::fmt::{Debug, Formatter};
+use std::io;
+
+use serde::Serialize;
+
use crate::abi::FnAbi;
use crate::crate_def::CrateDef;
use crate::mir::Body;
use crate::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
use crate::{with, CrateItem, DefId, Error, ItemKind, Opaque, Symbol};
-use serde::Serialize;
-use std::fmt::{Debug, Formatter};
-use std::io;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub enum MonoItem {
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index 18ecccb..dec0068 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -1,14 +1,13 @@
-use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
-use crate::ty::{IndexedVal, MirConst, Ty, TyConst};
-use crate::{with, Body, Mutability};
-use fmt::{Display, Formatter};
use std::fmt::Debug;
use std::io::Write;
use std::{fmt, io, iter};
-use super::{AssertMessage, BinOp, TerminatorKind};
+use fmt::{Display, Formatter};
-use super::{BorrowKind, FakeBorrowKind};
+use super::{AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind};
+use crate::mir::{Operand, Place, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents};
+use crate::ty::{IndexedVal, MirConst, Ty, TyConst};
+use crate::{with, Body, Mutability};
impl Display for Ty {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
diff --git a/compiler/stable_mir/src/target.rs b/compiler/stable_mir/src/target.rs
index 9fb5e04..32c3a2a 100644
--- a/compiler/stable_mir/src/target.rs
+++ b/compiler/stable_mir/src/target.rs
@@ -1,8 +1,9 @@
//! Provide information about the machine that this is being compiled into.
-use crate::compiler_interface::with;
use serde::Serialize;
+use crate::compiler_interface::with;
+
/// The properties of the target machine being compiled into.
#[derive(Clone, PartialEq, Eq, Serialize)]
pub struct MachineInfo {
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index fb0b8f4..2f36aa5 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -1,16 +1,16 @@
-use super::{
- mir::{Body, Mutability, Safety},
- with, DefId, Error, Symbol,
-};
+use std::fmt::{self, Debug, Display, Formatter};
+use std::ops::Range;
+
+use serde::Serialize;
+
+use super::mir::{Body, Mutability, Safety};
+use super::{with, DefId, Error, Symbol};
use crate::abi::{FnAbi, Layout};
use crate::crate_def::{CrateDef, CrateDefType};
use crate::mir::alloc::{read_target_int, read_target_uint, AllocId};
use crate::mir::mono::StaticDef;
use crate::target::MachineInfo;
use crate::{Filename, Opaque};
-use serde::Serialize;
-use std::fmt::{self, Debug, Display, Formatter};
-use std::ops::Range;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)]
pub struct Ty(usize);
diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs
index fc1da8f..72cf84a 100644
--- a/compiler/stable_mir/src/visitor.rs
+++ b/compiler/stable_mir/src/visitor.rs
@@ -1,11 +1,11 @@
use std::ops::ControlFlow;
-use crate::{ty::TyConst, Opaque};
-
use super::ty::{
Allocation, Binder, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs,
MirConst, Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst,
};
+use crate::ty::TyConst;
+use crate::Opaque;
pub trait Visitor: Sized {
type Break;
diff --git a/config.example.toml b/config.example.toml
index 45faa66..1b7de66 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -87,6 +87,9 @@
# library provided by LLVM.
#static-libstdcpp = false
+# Enable LLVM to use zstd for compression.
+#libzstd = false
+
# Whether to use Ninja to build LLVM. This runs much faster than make.
#ninja = true
@@ -472,7 +475,8 @@
# This is mostly useful for tools; if you have changes to `compiler/` or `library/` they will be ignored.
#
# Set this to "if-unchanged" to only download if the compiler and standard library have not been modified.
-# Set this to `true` to download unconditionally (useful if e.g. you are only changing doc-comments).
+# Set this to `true` to download unconditionally. This is useful if you are working on tools, doc-comments,
+# or library (you will be able to build the standard library without needing to build the compiler).
#download-rustc = false
# Number of codegen units to use for each compiler invocation. A value of 0
diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/library/Cargo.lock
similarity index 72%
rename from compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
rename to library/Cargo.lock
index 9ea53e8..b36399d 100644
--- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
+++ b/library/Cargo.lock
@@ -36,15 +36,15 @@
[[package]]
name = "allocator-api2"
-version = "0.2.16"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "cc"
-version = "1.0.97"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
+checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
[[package]]
name = "cfg-if"
@@ -58,9 +58,9 @@
[[package]]
name = "compiler_builtins"
-version = "0.1.106"
+version = "0.1.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4ab134a739bafec76aa91ccb15d519a54e569350644a1fea6528d5a0d407e22"
+checksum = "92afe7344b64cccf3662ca26d5d1c0828ab826f04206b97d856e3625e390e4b5"
dependencies = [
"cc",
"rustc-std-workspace-core",
@@ -75,24 +75,16 @@
]
[[package]]
-name = "cupid"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bad352a84b567cc38a5854e3aa8ee903cb8519a25d0b799b739bafffd1f91a1"
-dependencies = [
- "gcc",
- "rustc_version",
-]
-
-[[package]]
name = "dlmalloc"
-version = "0.2.4"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "203540e710bfadb90e5e29930baf5d10270cec1f43ab34f46f78b147b2de715a"
+checksum = "3264b043b8e977326c1ee9e723da2c1f8d09a99df52cacf00b4dbce5ac54414d"
dependencies = [
+ "cfg-if",
"compiler_builtins",
"libc",
"rustc-std-workspace-core",
+ "windows-sys",
]
[[package]]
@@ -106,12 +98,6 @@
]
[[package]]
-name = "gcc"
-version = "0.3.55"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
-
-[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -146,9 +132,9 @@
[[package]]
name = "hashbrown"
-version = "0.14.3"
+version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"allocator-api2",
"compiler_builtins",
@@ -169,18 +155,18 @@
[[package]]
name = "libc"
-version = "0.2.153"
+version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
dependencies = [
"rustc-std-workspace-core",
]
[[package]]
name = "memchr"
-version = "2.6.4"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
@@ -188,9 +174,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
"compiler_builtins",
@@ -200,9 +186,9 @@
[[package]]
name = "object"
-version = "0.36.0"
+version = "0.36.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
dependencies = [
"compiler_builtins",
"memchr",
@@ -252,9 +238,9 @@
[[package]]
name = "r-efi"
-version = "4.3.0"
+version = "4.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e244f96e03a3067f9e521d3167bd42657594cb8588c8d3a2db01545dc1af2e0"
+checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
@@ -327,30 +313,6 @@
]
[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-
-[[package]]
name = "std"
version = "0.0.0"
dependencies = [
@@ -385,7 +347,6 @@
dependencies = [
"cfg-if",
"compiler_builtins",
- "cupid",
"libc",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
@@ -412,9 +373,9 @@
[[package]]
name = "unicode-width"
-version = "0.1.11"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
@@ -453,3 +414,76 @@
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
diff --git a/library/Cargo.toml b/library/Cargo.toml
new file mode 100644
index 0000000..c4513b4
--- /dev/null
+++ b/library/Cargo.toml
@@ -0,0 +1,44 @@
+[workspace]
+resolver = "1"
+members = [
+ "std",
+ "sysroot",
+]
+
+exclude = [
+ # stdarch has its own Cargo workspace
+ "stdarch",
+]
+
+[profile.release.package.compiler_builtins]
+# For compiler-builtins we always use a high number of codegen units.
+# The goal here is to place every single intrinsic into its own object
+# file to avoid symbol clashes with the system libgcc if possible. Note
+# that this number doesn't actually produce this many object files, we
+# just don't create more than this number of object files.
+#
+# It's a bit of a bummer that we have to pass this here, unfortunately.
+# Ideally this would be specified through an env var to Cargo so Cargo
+# knows how many CGUs are for this specific crate, but for now
+# per-crate configuration isn't specifiable in the environment.
+codegen-units = 10000
+
+# These dependencies of the standard library implement symbolication for
+# backtraces on most platforms. Their debuginfo causes both linking to be slower
+# (more data to chew through) and binaries to be larger without really all that
+# much benefit. This section turns them all to down to have no debuginfo which
+# helps to improve link times a little bit.
+[profile.release.package]
+addr2line.debug = 0
+adler.debug = 0
+gimli.debug = 0
+miniz_oxide.debug = 0
+object.debug = 0
+rustc-demangle.debug = 0
+
+[patch.crates-io]
+# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
+# here
+rustc-std-workspace-core = { path = 'rustc-std-workspace-core' }
+rustc-std-workspace-alloc = { path = 'rustc-std-workspace-alloc' }
+rustc-std-workspace-std = { path = 'rustc-std-workspace-std' }
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 612452a..bdf1625 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -10,7 +10,7 @@
[dependencies]
core = { path = "../core" }
-compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.118", features = ['rustc-dep-of-std'] }
[dev-dependencies]
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
@@ -38,8 +38,8 @@
compiler-builtins-mem = ['compiler_builtins/mem']
compiler-builtins-c = ["compiler_builtins/c"]
compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
+compiler-builtins-no-f16-f128 = ["compiler_builtins/no-f16-f128"]
compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
-compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
# Make panics and failed asserts immediately abort without formatting any message
panic_immediate_abort = ["core/panic_immediate_abort"]
# Choose algorithms that are optimized for binary size instead of runtime performance
diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs
index 4fe07eb..3bddef5 100644
--- a/library/alloc/benches/btree/map.rs
+++ b/library/alloc/benches/btree/map.rs
@@ -1,7 +1,8 @@
use std::collections::BTreeMap;
use std::ops::RangeBounds;
-use rand::{seq::SliceRandom, Rng};
+use rand::seq::SliceRandom;
+use rand::Rng;
use test::{black_box, Bencher};
macro_rules! map_insert_rand_bench {
diff --git a/library/alloc/benches/linked_list.rs b/library/alloc/benches/linked_list.rs
index 29c5ad2..b9322b6 100644
--- a/library/alloc/benches/linked_list.rs
+++ b/library/alloc/benches/linked_list.rs
@@ -1,4 +1,5 @@
use std::collections::LinkedList;
+
use test::Bencher;
#[bench]
diff --git a/library/alloc/benches/string.rs b/library/alloc/benches/string.rs
index 5c95160..e0dbe80 100644
--- a/library/alloc/benches/string.rs
+++ b/library/alloc/benches/string.rs
@@ -1,4 +1,5 @@
use std::iter::repeat;
+
use test::{black_box, Bencher};
#[bench]
diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs
index 8ebfe31..13d784d 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloc/benches/vec.rs
@@ -1,5 +1,6 @@
-use rand::RngCore;
use std::iter::repeat;
+
+use rand::RngCore;
use test::{black_box, Bencher};
#[bench]
diff --git a/library/alloc/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs
index 35939f4..fb1e268 100644
--- a/library/alloc/benches/vec_deque.rs
+++ b/library/alloc/benches/vec_deque.rs
@@ -1,7 +1,6 @@
-use std::{
- collections::{vec_deque, VecDeque},
- mem,
-};
+use std::collections::{vec_deque, VecDeque};
+use std::mem;
+
use test::{black_box, Bencher};
#[bench]
diff --git a/library/alloc/benches/vec_deque_append.rs b/library/alloc/benches/vec_deque_append.rs
index 30b6e60..7c805da 100644
--- a/library/alloc/benches/vec_deque_append.rs
+++ b/library/alloc/benches/vec_deque_append.rs
@@ -1,4 +1,5 @@
-use std::{collections::VecDeque, time::Instant};
+use std::collections::VecDeque;
+use std::time::Instant;
const VECDEQUE_LEN: i32 = 100000;
const WARMUP_N: usize = 100;
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 1833a7f..db2d752 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -2,15 +2,13 @@
#![stable(feature = "alloc_module", since = "1.28.0")]
-#[cfg(not(test))]
-use core::hint;
-
-#[cfg(not(test))]
-use core::ptr::{self, NonNull};
-
#[stable(feature = "alloc_module", since = "1.28.0")]
#[doc(inline)]
pub use core::alloc::*;
+#[cfg(not(test))]
+use core::hint;
+#[cfg(not(test))]
+use core::ptr::{self, NonNull};
#[cfg(test)]
mod tests;
@@ -57,7 +55,7 @@
#[cfg(test)]
pub use std::alloc::Global;
-/// Allocate memory with the global allocator.
+/// Allocates memory with the global allocator.
///
/// This function forwards calls to the [`GlobalAlloc::alloc`] method
/// of the allocator registered with the `#[global_allocator]` attribute
@@ -101,7 +99,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
}
}
-/// Deallocate memory with the global allocator.
+/// Deallocates memory with the global allocator.
///
/// This function forwards calls to the [`GlobalAlloc::dealloc`] method
/// of the allocator registered with the `#[global_allocator]` attribute
@@ -119,7 +117,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
}
-/// Reallocate memory with the global allocator.
+/// Reallocates memory with the global allocator.
///
/// This function forwards calls to the [`GlobalAlloc::realloc`] method
/// of the allocator registered with the `#[global_allocator]` attribute
@@ -138,7 +136,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
}
-/// Allocate zero-initialized memory with the global allocator.
+/// Allocates zero-initialized memory with the global allocator.
///
/// This function forwards calls to the [`GlobalAlloc::alloc_zeroed`] method
/// of the allocator registered with the `#[global_allocator]` attribute
@@ -345,7 +343,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
}
-/// Signal a memory allocation error.
+/// Signals a memory allocation error.
///
/// Callers of memory allocation APIs wishing to cease execution
/// in response to an allocation error are encouraged to call this function,
diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs
index 1a5938f..5d6077f 100644
--- a/library/alloc/src/alloc/tests.rs
+++ b/library/alloc/src/alloc/tests.rs
@@ -1,9 +1,10 @@
use super::*;
extern crate test;
-use crate::boxed::Box;
use test::Bencher;
+use crate::boxed::Box;
+
#[test]
fn allocate_zeroed() {
unsafe {
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index 42f8a08..f86face 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -2,21 +2,20 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::hash::{Hash, Hasher};
#[cfg(not(no_global_oom_handling))]
use core::ops::{Add, AddAssign};
use core::ops::{Deref, DerefPure};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::borrow::{Borrow, BorrowMut};
+use Cow::*;
use crate::fmt;
#[cfg(not(no_global_oom_handling))]
use crate::string::String;
-use Cow::*;
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
where
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 4054303..7de4125 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -187,26 +187,26 @@
use core::any::Any;
use core::async_iter::AsyncIterator;
-use core::borrow;
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::cmp::Ordering;
use core::error::Error;
-use core::fmt;
use core::future::Future;
use core::hash::{Hash, Hasher};
use core::iter::FusedIterator;
-use core::marker::Tuple;
-use core::marker::Unsize;
+use core::marker::{Tuple, Unsize};
use core::mem::{self, SizedTypeProperties};
-use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
use core::ops::{
- CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver,
+ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
+ DerefPure, DispatchFromDyn, Receiver,
};
-use core::pin::Pin;
+use core::pin::{Pin, PinCoerceUnsized};
use core::ptr::{self, addr_of_mut, NonNull, Unique};
-use core::slice;
use core::task::{Context, Poll};
+use core::{borrow, fmt, slice};
+
+#[unstable(feature = "thin_box", issue = "92791")]
+pub use thin::ThinBox;
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
@@ -222,9 +222,6 @@
#[cfg(not(no_global_oom_handling))]
use crate::vec::Vec;
-#[unstable(feature = "thin_box", issue = "92791")]
-pub use thin::ThinBox;
-
mod thin;
/// A pointer type that uniquely owns a heap allocation of type `T`.
@@ -1176,6 +1173,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
/// ```
///
/// [memory layout]: self#memory-layout
+ #[must_use = "losing the pointer will leak memory"]
#[stable(feature = "box_raw", since = "1.4.0")]
#[inline]
pub fn into_raw(b: Self) -> *mut T {
@@ -1229,6 +1227,7 @@ pub fn into_raw(b: Self) -> *mut T {
/// ```
///
/// [memory layout]: self#memory-layout
+ #[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
#[inline]
pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) {
@@ -1268,9 +1267,11 @@ pub const fn allocator(b: &Self) -> &A {
}
/// Consumes and leaks the `Box`, returning a mutable reference,
- /// `&'a mut T`. Note that the type `T` must outlive the chosen lifetime
- /// `'a`. If the type has only static references, or none at all, then this
- /// may be chosen to be `'static`.
+ /// `&'a mut T`.
+ ///
+ /// Note that the type `T` must outlive the chosen lifetime `'a`. If the type
+ /// has only static references, or none at all, then this may be chosen to be
+ /// `'static`.
///
/// This function is mainly useful for data that lives for the remainder of
/// the program's life. Dropping the returned reference will cause a memory
@@ -1853,7 +1854,7 @@ fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
}
impl<A: Allocator> Box<dyn Any, A> {
- /// Attempt to downcast the box to a concrete type.
+ /// Attempts to downcast the box to a concrete type.
///
/// # Examples
///
@@ -1912,7 +1913,7 @@ pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
}
impl<A: Allocator> Box<dyn Any + Send, A> {
- /// Attempt to downcast the box to a concrete type.
+ /// Attempts to downcast the box to a concrete type.
///
/// # Examples
///
@@ -1971,7 +1972,7 @@ pub unsafe fn downcast_unchecked<T: Any>(self) -> Box<T, A> {
}
impl<A: Allocator> Box<dyn Any + Send + Sync, A> {
- /// Attempt to downcast the box to a concrete type.
+ /// Attempts to downcast the box to a concrete type.
///
/// # Examples
///
@@ -2725,3 +2726,6 @@ fn provide<'b>(&'b self, request: &mut core::error::Request<'b>) {
core::error::Error::provide(&**self, request);
}
}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index e9bfecb..9baded3 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -2,7 +2,6 @@
//! <https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs>
//! by matthieu-m
-use crate::alloc::{self, Layout, LayoutError};
use core::error::Error;
use core::fmt::{self, Debug, Display, Formatter};
#[cfg(not(no_global_oom_handling))]
@@ -14,8 +13,9 @@
#[cfg(not(no_global_oom_handling))]
use core::mem::SizedTypeProperties;
use core::ops::{Deref, DerefMut};
-use core::ptr::Pointee;
-use core::ptr::{self, NonNull};
+use core::ptr::{self, NonNull, Pointee};
+
+use crate::alloc::{self, Layout, LayoutError};
/// ThinBox.
///
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index fe1ff24..8870137 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -144,12 +144,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
use core::alloc::Allocator;
-use core::fmt;
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen};
use core::mem::{self, swap, ManuallyDrop};
use core::num::NonZero;
use core::ops::{Deref, DerefMut};
-use core::ptr;
+use core::{fmt, ptr};
use crate::alloc::Global;
use crate::collections::TryReserveError;
@@ -965,6 +964,7 @@ pub fn iter(&self) -> Iter<'_, T> {
}
/// Returns an iterator which retrieves elements in heap order.
+ ///
/// This method consumes the original heap.
///
/// # Examples
@@ -1361,7 +1361,7 @@ struct Hole<'a, T: 'a> {
}
impl<'a, T> Hole<'a, T> {
- /// Create a new `Hole` at index `pos`.
+ /// Creates a new `Hole` at index `pos`.
///
/// Unsafe because pos must be within the data slice.
#[inline]
@@ -1433,6 +1433,20 @@ pub struct Iter<'a, T: 'a> {
iter: slice::Iter<'a, T>,
}
+#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+impl<T> Default for Iter<'_, T> {
+ /// Creates an empty `binary_heap::Iter`.
+ ///
+ /// ```
+ /// # use std::collections::binary_heap;
+ /// let iter: binary_heap::Iter<'_, u8> = Default::default();
+ /// assert_eq!(iter.len(), 0);
+ /// ```
+ fn default() -> Self {
+ Iter { iter: Default::default() }
+ }
+}
+
#[stable(feature = "collection_debug", since = "1.17.0")]
impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs
index d4bc622..1cb07c6 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/src/collections/binary_heap/tests.rs
@@ -1,7 +1,8 @@
+use std::panic::{catch_unwind, AssertUnwindSafe};
+
use super::*;
use crate::boxed::Box;
use crate::testing::crash_test::{CrashTestDummy, Panic};
-use std::panic::{catch_unwind, AssertUnwindSafe};
#[test]
fn test_iterator() {
@@ -504,11 +505,12 @@ fn test_retain_catch_unwind() {
#[cfg(not(target_os = "emscripten"))]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn panic_safe() {
- use rand::seq::SliceRandom;
use std::cmp;
use std::panic::{self, AssertUnwindSafe};
use std::sync::atomic::{AtomicUsize, Ordering};
+ use rand::seq::SliceRandom;
+
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
#[derive(Eq, PartialEq, Ord, Clone, Debug)]
diff --git a/library/alloc/src/collections/btree/append.rs b/library/alloc/src/collections/btree/append.rs
index b6989af..4737293 100644
--- a/library/alloc/src/collections/btree/append.rs
+++ b/library/alloc/src/collections/btree/append.rs
@@ -1,8 +1,9 @@
-use super::merge_iter::MergeIterInner;
-use super::node::{self, Root};
use core::alloc::Allocator;
use core::iter::FusedIterator;
+use super::merge_iter::MergeIterInner;
+use super::node::{self, Root};
+
impl<K, V> Root<K, V> {
/// Appends all key-value pairs from the union of two ascending iterators,
/// incrementing a `length` variable along the way. The latter makes it
diff --git a/library/alloc/src/collections/btree/fix.rs b/library/alloc/src/collections/btree/fix.rs
index 91b6121..4c1e19e 100644
--- a/library/alloc/src/collections/btree/fix.rs
+++ b/library/alloc/src/collections/btree/fix.rs
@@ -1,7 +1,10 @@
-use super::map::MIN_LEN;
-use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef, Root};
use core::alloc::Allocator;
+use super::map::MIN_LEN;
+use super::node::ForceResult::*;
+use super::node::LeftOrRight::*;
+use super::node::{marker, Handle, NodeRef, Root};
+
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
/// Stocks up a possibly underfull node by merging with or stealing from a
/// sibling. If successful but at the cost of shrinking the parent node,
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 3875f61..f6f773c 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -1,4 +1,3 @@
-use crate::vec::Vec;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::error::Error;
@@ -10,20 +9,21 @@
use core::ops::{Bound, Index, RangeBounds};
use core::ptr;
-use crate::alloc::{Allocator, Global};
-
use super::borrow::DormantMutRef;
use super::dedup_sorted_iter::DedupSortedIter;
use super::navigate::{LazyLeafRange, LeafRange};
-use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root};
-use super::search::{SearchBound, SearchResult::*};
+use super::node::ForceResult::*;
+use super::node::{self, marker, Handle, NodeRef, Root};
+use super::search::SearchBound;
+use super::search::SearchResult::*;
use super::set_val::SetValZST;
+use crate::alloc::{Allocator, Global};
+use crate::vec::Vec;
mod entry;
#[stable(feature = "rust1", since = "1.0.0")]
pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry};
-
use Entry::*;
/// Minimum number of elements in a node that is not a root.
@@ -2016,6 +2016,20 @@ fn default() -> Self {
}
}
+#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+impl<K, V> Default for RangeMut<'_, K, V> {
+ /// Creates an empty `btree_map::RangeMut`.
+ ///
+ /// ```
+ /// # use std::collections::btree_map;
+ /// let iter: btree_map::RangeMut<'_, u8, u8> = Default::default();
+ /// assert_eq!(iter.count(), 0);
+ /// ```
+ fn default() -> Self {
+ RangeMut { inner: Default::default(), _marker: PhantomData }
+ }
+}
+
#[stable(feature = "map_values_mut", since = "1.10.0")]
impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
type Item = &'a mut V;
@@ -2050,6 +2064,20 @@ fn len(&self) -> usize {
#[stable(feature = "fused", since = "1.26.0")]
impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
+#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+impl<K, V> Default for ValuesMut<'_, K, V> {
+ /// Creates an empty `btree_map::ValuesMut`.
+ ///
+ /// ```
+ /// # use std::collections::btree_map;
+ /// let iter: btree_map::ValuesMut<'_, u8, u8> = Default::default();
+ /// assert_eq!(iter.count(), 0);
+ /// ```
+ fn default() -> Self {
+ ValuesMut { inner: Default::default() }
+ }
+}
+
#[stable(feature = "map_into_keys_values", since = "1.54.0")]
impl<K, V, A: Allocator + Clone> Iterator for IntoKeys<K, V, A> {
type Item = K;
@@ -2921,7 +2949,7 @@ pub fn prev(&mut self) -> Option<(&'a K, &'a V)> {
/// Returns a reference to the key and value of the next element without
/// moving the cursor.
///
- /// If the cursor is at the end of the map then `None` is returned
+ /// If the cursor is at the end of the map then `None` is returned.
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn peek_next(&self) -> Option<(&'a K, &'a V)> {
self.clone().next()
@@ -2963,7 +2991,7 @@ pub fn prev(&mut self) -> Option<(&K, &mut V)> {
/// Returns a reference to the key and value of the next element without
/// moving the cursor.
///
- /// If the cursor is at the end of the map then `None` is returned
+ /// If the cursor is at the end of the map then `None` is returned.
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn peek_next(&mut self) -> Option<(&K, &mut V)> {
let (k, v) = self.inner.peek_next()?;
@@ -3061,7 +3089,7 @@ pub fn prev(&mut self) -> Option<(&mut K, &mut V)> {
/// Returns a reference to the key and value of the next element without
/// moving the cursor.
///
- /// If the cursor is at the end of the map then `None` is returned
+ /// If the cursor is at the end of the map then `None` is returned.
#[unstable(feature = "btree_cursors", issue = "107540")]
pub fn peek_next(&mut self) -> Option<(&mut K, &mut V)> {
let current = self.current.as_mut()?;
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 66eb991..d128ad8 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -2,13 +2,12 @@
use core::marker::PhantomData;
use core::mem;
-use crate::alloc::{Allocator, Global};
+use Entry::*;
use super::super::borrow::DormantMutRef;
use super::super::node::{marker, Handle, NodeRef};
use super::BTreeMap;
-
-use Entry::*;
+use crate::alloc::{Allocator, Global};
/// A view into a single entry in a map, which may either be vacant or occupied.
///
@@ -189,6 +188,7 @@ pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
}
/// Ensures a value is in the entry by inserting, if empty, the result of the default function.
+ ///
/// This method allows for generating key-derived values for insertion by providing the default
/// function a reference to the key that was moved during the `.entry(key)` method call.
///
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index ba1f38d..ff1254a 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1,3 +1,10 @@
+use core::assert_matches::assert_matches;
+use std::iter;
+use std::ops::Bound::{Excluded, Included, Unbounded};
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering::SeqCst;
+
use super::*;
use crate::boxed::Box;
use crate::fmt::Debug;
@@ -6,11 +13,6 @@
use crate::testing::crash_test::{CrashTestDummy, Panic};
use crate::testing::ord_chaos::{Cyclic3, Governed, Governor};
use crate::testing::rng::DeterministicRng;
-use core::assert_matches::assert_matches;
-use std::iter;
-use std::ops::Bound::{Excluded, Included, Unbounded};
-use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
// Minimum number of elements to insert, to guarantee a tree with 2 levels,
// i.e., a tree who's root is an internal node at height 1, with edges to leaf nodes.
diff --git a/library/alloc/src/collections/btree/mem.rs b/library/alloc/src/collections/btree/mem.rs
index e1363d1..d738c5c 100644
--- a/library/alloc/src/collections/btree/mem.rs
+++ b/library/alloc/src/collections/btree/mem.rs
@@ -1,6 +1,4 @@
-use core::intrinsics;
-use core::mem;
-use core::ptr;
+use core::{intrinsics, mem, ptr};
/// This replaces the value behind the `v` unique reference by calling the
/// relevant function.
diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs
index 5e6a26f..f5c621e 100644
--- a/library/alloc/src/collections/btree/navigate.rs
+++ b/library/alloc/src/collections/btree/navigate.rs
@@ -1,11 +1,10 @@
use core::borrow::Borrow;
-use core::hint;
use core::ops::RangeBounds;
-use core::ptr;
+use core::{hint, ptr};
-use super::node::{marker, ForceResult::*, Handle, NodeRef};
+use super::node::ForceResult::*;
+use super::node::{marker, Handle, NodeRef};
use super::search::SearchBound;
-
use crate::alloc::Allocator;
// `front` and `back` are always both `None` or both `Some`.
pub struct LeafRange<BorrowType, K, V> {
diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs
index 0904299..c46422c 100644
--- a/library/alloc/src/collections/btree/remove.rs
+++ b/library/alloc/src/collections/btree/remove.rs
@@ -1,7 +1,10 @@
-use super::map::MIN_LEN;
-use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef};
use core::alloc::Allocator;
+use super::map::MIN_LEN;
+use super::node::ForceResult::*;
+use super::node::LeftOrRight::*;
+use super::node::{marker, Handle, NodeRef};
+
impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
/// Removes a key-value pair from the tree, and returns that pair, as well as
/// the leaf edge corresponding to that former pair. It's possible this empties
diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs
index ad3522b..1d5c927 100644
--- a/library/alloc/src/collections/btree/search.rs
+++ b/library/alloc/src/collections/btree/search.rs
@@ -2,11 +2,12 @@
use core::cmp::Ordering;
use core::ops::{Bound, RangeBounds};
-use super::node::{marker, ForceResult::*, Handle, NodeRef};
-
use SearchBound::*;
use SearchResult::*;
+use super::node::ForceResult::*;
+use super::node::{marker, Handle, NodeRef};
+
pub enum SearchBound<T> {
/// An inclusive bound to look for, just like `Bound::Included(T)`.
Included(T),
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index b0bd6ef..973e7c6 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -1,4 +1,3 @@
-use crate::vec::Vec;
use core::borrow::Borrow;
use core::cmp::Ordering::{self, Equal, Greater, Less};
use core::cmp::{max, min};
@@ -6,14 +5,14 @@
use core::hash::{Hash, Hasher};
use core::iter::{FusedIterator, Peekable};
use core::mem::ManuallyDrop;
-use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub};
+use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub};
use super::map::{BTreeMap, Keys};
use super::merge_iter::MergeIterInner;
use super::set_val::SetValZST;
use super::Recover;
-
use crate::alloc::{Allocator, Global};
+use crate::vec::Vec;
/// An ordered set based on a B-Tree.
///
@@ -1183,6 +1182,178 @@ pub const fn len(&self) -> usize {
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
+
+ /// Returns a [`Cursor`] pointing at the gap before the smallest element
+ /// greater than the given bound.
+ ///
+ /// Passing `Bound::Included(x)` will return a cursor pointing to the
+ /// gap before the smallest element greater than or equal to `x`.
+ ///
+ /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+ /// gap before the smallest element greater than `x`.
+ ///
+ /// Passing `Bound::Unbounded` will return a cursor pointing to the
+ /// gap before the smallest element in the set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeSet;
+ /// use std::ops::Bound;
+ ///
+ /// let set = BTreeSet::from([1, 2, 3, 4]);
+ ///
+ /// let cursor = set.lower_bound(Bound::Included(&2));
+ /// assert_eq!(cursor.peek_prev(), Some(&1));
+ /// assert_eq!(cursor.peek_next(), Some(&2));
+ ///
+ /// let cursor = set.lower_bound(Bound::Excluded(&2));
+ /// assert_eq!(cursor.peek_prev(), Some(&2));
+ /// assert_eq!(cursor.peek_next(), Some(&3));
+ ///
+ /// let cursor = set.lower_bound(Bound::Unbounded);
+ /// assert_eq!(cursor.peek_prev(), None);
+ /// assert_eq!(cursor.peek_next(), Some(&1));
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn lower_bound<Q: ?Sized>(&self, bound: Bound<&Q>) -> Cursor<'_, T>
+ where
+ T: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ Cursor { inner: self.map.lower_bound(bound) }
+ }
+
+ /// Returns a [`CursorMut`] pointing at the gap before the smallest element
+ /// greater than the given bound.
+ ///
+ /// Passing `Bound::Included(x)` will return a cursor pointing to the
+ /// gap before the smallest element greater than or equal to `x`.
+ ///
+ /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+ /// gap before the smallest element greater than `x`.
+ ///
+ /// Passing `Bound::Unbounded` will return a cursor pointing to the
+ /// gap before the smallest element in the set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeSet;
+ /// use std::ops::Bound;
+ ///
+ /// let mut set = BTreeSet::from([1, 2, 3, 4]);
+ ///
+ /// let mut cursor = set.lower_bound_mut(Bound::Included(&2));
+ /// assert_eq!(cursor.peek_prev(), Some(&1));
+ /// assert_eq!(cursor.peek_next(), Some(&2));
+ ///
+ /// let mut cursor = set.lower_bound_mut(Bound::Excluded(&2));
+ /// assert_eq!(cursor.peek_prev(), Some(&2));
+ /// assert_eq!(cursor.peek_next(), Some(&3));
+ ///
+ /// let mut cursor = set.lower_bound_mut(Bound::Unbounded);
+ /// assert_eq!(cursor.peek_prev(), None);
+ /// assert_eq!(cursor.peek_next(), Some(&1));
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn lower_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
+ where
+ T: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ CursorMut { inner: self.map.lower_bound_mut(bound) }
+ }
+
+ /// Returns a [`Cursor`] pointing at the gap after the greatest element
+ /// smaller than the given bound.
+ ///
+ /// Passing `Bound::Included(x)` will return a cursor pointing to the
+ /// gap after the greatest element smaller than or equal to `x`.
+ ///
+ /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+ /// gap after the greatest element smaller than `x`.
+ ///
+ /// Passing `Bound::Unbounded` will return a cursor pointing to the
+ /// gap after the greatest element in the set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeSet;
+ /// use std::ops::Bound;
+ ///
+ /// let set = BTreeSet::from([1, 2, 3, 4]);
+ ///
+ /// let cursor = set.upper_bound(Bound::Included(&3));
+ /// assert_eq!(cursor.peek_prev(), Some(&3));
+ /// assert_eq!(cursor.peek_next(), Some(&4));
+ ///
+ /// let cursor = set.upper_bound(Bound::Excluded(&3));
+ /// assert_eq!(cursor.peek_prev(), Some(&2));
+ /// assert_eq!(cursor.peek_next(), Some(&3));
+ ///
+ /// let cursor = set.upper_bound(Bound::Unbounded);
+ /// assert_eq!(cursor.peek_prev(), Some(&4));
+ /// assert_eq!(cursor.peek_next(), None);
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn upper_bound<Q: ?Sized>(&self, bound: Bound<&Q>) -> Cursor<'_, T>
+ where
+ T: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ Cursor { inner: self.map.upper_bound(bound) }
+ }
+
+ /// Returns a [`CursorMut`] pointing at the gap after the greatest element
+ /// smaller than the given bound.
+ ///
+ /// Passing `Bound::Included(x)` will return a cursor pointing to the
+ /// gap after the greatest element smaller than or equal to `x`.
+ ///
+ /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+ /// gap after the greatest element smaller than `x`.
+ ///
+ /// Passing `Bound::Unbounded` will return a cursor pointing to the
+ /// gap after the greatest element in the set.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(btree_cursors)]
+ ///
+ /// use std::collections::BTreeSet;
+ /// use std::ops::Bound;
+ ///
+ /// let mut set = BTreeSet::from([1, 2, 3, 4]);
+ ///
+ /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) };
+ /// assert_eq!(cursor.peek_prev(), Some(&3));
+ /// assert_eq!(cursor.peek_next(), Some(&4));
+ ///
+ /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) };
+ /// assert_eq!(cursor.peek_prev(), Some(&2));
+ /// assert_eq!(cursor.peek_next(), Some(&3));
+ ///
+ /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) };
+ /// assert_eq!(cursor.peek_prev(), Some(&4));
+ /// assert_eq!(cursor.peek_next(), None);
+ /// ```
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
+ where
+ T: Borrow<Q> + Ord,
+ Q: Ord,
+ {
+ CursorMut { inner: self.map.upper_bound_mut(bound) }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1817,5 +1988,414 @@ fn min(mut self) -> Option<&'a T> {
#[stable(feature = "fused", since = "1.26.0")]
impl<T: Ord> FusedIterator for Union<'_, T> {}
+/// A cursor over a `BTreeSet`.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth.
+///
+/// Cursors always point to a gap between two elements in the set, and can
+/// operate on the two immediately adjacent elements.
+///
+/// A `Cursor` is created with the [`BTreeSet::lower_bound`] and [`BTreeSet::upper_bound`] methods.
+#[derive(Clone)]
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct Cursor<'a, K: 'a> {
+ inner: super::map::Cursor<'a, K, SetValZST>,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl<K: Debug> Debug for Cursor<'_, K> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("Cursor")
+ }
+}
+
+/// A cursor over a `BTreeSet` with editing operations.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
+/// safely mutate the set during iteration. This is because the lifetime of its yielded
+/// references is tied to its own lifetime, instead of just the underlying map. This means
+/// cursors cannot yield multiple elements at once.
+///
+/// Cursors always point to a gap between two elements in the set, and can
+/// operate on the two immediately adjacent elements.
+///
+/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and [`BTreeSet::upper_bound_mut`]
+/// methods.
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global>
+{
+ inner: super::map::CursorMut<'a, K, SetValZST, A>,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl<K: Debug, A> Debug for CursorMut<'_, K, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("CursorMut")
+ }
+}
+
+/// A cursor over a `BTreeSet` with editing operations, and which allows
+/// mutating elements.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
+/// safely mutate the set during iteration. This is because the lifetime of its yielded
+/// references is tied to its own lifetime, instead of just the underlying set. This means
+/// cursors cannot yield multiple elements at once.
+///
+/// Cursors always point to a gap between two elements in the set, and can
+/// operate on the two immediately adjacent elements.
+///
+/// A `CursorMutKey` is created from a [`CursorMut`] with the
+/// [`CursorMut::with_mutable_key`] method.
+///
+/// # Safety
+///
+/// Since this cursor allows mutating elements, you must ensure that the
+/// `BTreeSet` invariants are maintained. Specifically:
+///
+/// * The newly inserted element must be unique in the tree.
+/// * All elements in the tree must remain in sorted order.
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct CursorMutKey<
+ 'a,
+ K: 'a,
+ #[unstable(feature = "allocator_api", issue = "32838")] A = Global,
+> {
+ inner: super::map::CursorMutKey<'a, K, SetValZST, A>,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl<K: Debug, A> Debug for CursorMutKey<'_, K, A> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("CursorMutKey")
+ }
+}
+
+impl<'a, K> Cursor<'a, K> {
+ /// Advances the cursor to the next gap, returning the element that it
+ /// moved over.
+ ///
+ /// If the cursor is already at the end of the set then `None` is returned
+ /// and the cursor is not moved.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn next(&mut self) -> Option<&'a K> {
+ self.inner.next().map(|(k, _)| k)
+ }
+
+ /// Advances the cursor to the previous gap, returning the element that it
+ /// moved over.
+ ///
+ /// If the cursor is already at the start of the set then `None` is returned
+ /// and the cursor is not moved.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn prev(&mut self) -> Option<&'a K> {
+ self.inner.prev().map(|(k, _)| k)
+ }
+
+ /// Returns a reference to next element without moving the cursor.
+ ///
+ /// If the cursor is at the end of the set then `None` is returned
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_next(&self) -> Option<&'a K> {
+ self.inner.peek_next().map(|(k, _)| k)
+ }
+
+ /// Returns a reference to the previous element without moving the cursor.
+ ///
+ /// If the cursor is at the start of the set then `None` is returned.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_prev(&self) -> Option<&'a K> {
+ self.inner.peek_prev().map(|(k, _)| k)
+ }
+}
+
+impl<'a, T, A> CursorMut<'a, T, A> {
+ /// Advances the cursor to the next gap, returning the element that it
+ /// moved over.
+ ///
+ /// If the cursor is already at the end of the set then `None` is returned
+ /// and the cursor is not moved.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn next(&mut self) -> Option<&T> {
+ self.inner.next().map(|(k, _)| k)
+ }
+
+ /// Advances the cursor to the previous gap, returning the element that it
+ /// moved over.
+ ///
+ /// If the cursor is already at the start of the set then `None` is returned
+ /// and the cursor is not moved.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn prev(&mut self) -> Option<&T> {
+ self.inner.prev().map(|(k, _)| k)
+ }
+
+ /// Returns a reference to the next element without moving the cursor.
+ ///
+ /// If the cursor is at the end of the set then `None` is returned.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_next(&mut self) -> Option<&T> {
+ self.inner.peek_next().map(|(k, _)| k)
+ }
+
+ /// Returns a reference to the previous element without moving the cursor.
+ ///
+ /// If the cursor is at the start of the set then `None` is returned.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_prev(&mut self) -> Option<&T> {
+ self.inner.peek_prev().map(|(k, _)| k)
+ }
+
+ /// Returns a read-only cursor pointing to the same location as the
+ /// `CursorMut`.
+ ///
+ /// The lifetime of the returned `Cursor` is bound to that of the
+ /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+ /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn as_cursor(&self) -> Cursor<'_, T> {
+ Cursor { inner: self.inner.as_cursor() }
+ }
+
+ /// Converts the cursor into a [`CursorMutKey`], which allows mutating
+ /// elements in the tree.
+ ///
+ /// # Safety
+ ///
+ /// Since this cursor allows mutating elements, you must ensure that the
+ /// `BTreeSet` invariants are maintained. Specifically:
+ ///
+ /// * The newly inserted element must be unique in the tree.
+ /// * All elements in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn with_mutable_key(self) -> CursorMutKey<'a, T, A> {
+ CursorMutKey { inner: unsafe { self.inner.with_mutable_key() } }
+ }
+}
+
+impl<'a, T, A> CursorMutKey<'a, T, A> {
+ /// Advances the cursor to the next gap, returning the element that it
+ /// moved over.
+ ///
+ /// If the cursor is already at the end of the set then `None` is returned
+ /// and the cursor is not moved.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn next(&mut self) -> Option<&mut T> {
+ self.inner.next().map(|(k, _)| k)
+ }
+
+ /// Advances the cursor to the previous gap, returning the element that it
+ /// moved over.
+ ///
+ /// If the cursor is already at the start of the set then `None` is returned
+ /// and the cursor is not moved.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn prev(&mut self) -> Option<&mut T> {
+ self.inner.prev().map(|(k, _)| k)
+ }
+
+ /// Returns a reference to the next element without moving the cursor.
+ ///
+ /// If the cursor is at the end of the set then `None` is returned
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_next(&mut self) -> Option<&mut T> {
+ self.inner.peek_next().map(|(k, _)| k)
+ }
+
+ /// Returns a reference to the previous element without moving the cursor.
+ ///
+ /// If the cursor is at the start of the set then `None` is returned.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn peek_prev(&mut self) -> Option<&mut T> {
+ self.inner.peek_prev().map(|(k, _)| k)
+ }
+
+ /// Returns a read-only cursor pointing to the same location as the
+ /// `CursorMutKey`.
+ ///
+ /// The lifetime of the returned `Cursor` is bound to that of the
+ /// `CursorMutKey`, which means it cannot outlive the `CursorMutKey` and that the
+ /// `CursorMutKey` is frozen for the lifetime of the `Cursor`.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn as_cursor(&self) -> Cursor<'_, T> {
+ Cursor { inner: self.inner.as_cursor() }
+ }
+}
+
+impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> {
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap before the
+ /// newly inserted element.
+ ///
+ /// # Safety
+ ///
+ /// You must ensure that the `BTreeSet` invariants are maintained.
+ /// Specifically:
+ ///
+ /// * The newly inserted element must be unique in the tree.
+ /// * All elements in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn insert_after_unchecked(&mut self, value: T) {
+ unsafe { self.inner.insert_after_unchecked(value, SetValZST) }
+ }
+
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap after the
+ /// newly inserted element.
+ ///
+ /// # Safety
+ ///
+ /// You must ensure that the `BTreeSet` invariants are maintained.
+ /// Specifically:
+ ///
+ /// * The newly inserted element must be unique in the tree.
+ /// * All elements in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn insert_before_unchecked(&mut self, value: T) {
+ unsafe { self.inner.insert_before_unchecked(value, SetValZST) }
+ }
+
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap before the
+ /// newly inserted element.
+ ///
+ /// If the inserted element is not greater than the element before the
+ /// cursor (if any), or if it not less than the element after the cursor (if
+ /// any), then an [`UnorderedKeyError`] is returned since this would
+ /// invalidate the [`Ord`] invariant between the elements of the set.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> {
+ self.inner.insert_after(value, SetValZST)
+ }
+
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap after the
+ /// newly inserted element.
+ ///
+ /// If the inserted element is not greater than the element before the
+ /// cursor (if any), or if it not less than the element after the cursor (if
+ /// any), then an [`UnorderedKeyError`] is returned since this would
+ /// invalidate the [`Ord`] invariant between the elements of the set.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> {
+ self.inner.insert_before(value, SetValZST)
+ }
+
+ /// Removes the next element from the `BTreeSet`.
+ ///
+ /// The element that was removed is returned. The cursor position is
+ /// unchanged (before the removed element).
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn remove_next(&mut self) -> Option<T> {
+ self.inner.remove_next().map(|(k, _)| k)
+ }
+
+ /// Removes the precending element from the `BTreeSet`.
+ ///
+ /// The element that was removed is returned. The cursor position is
+ /// unchanged (after the removed element).
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn remove_prev(&mut self) -> Option<T> {
+ self.inner.remove_prev().map(|(k, _)| k)
+ }
+}
+
+impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> {
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap before the
+ /// newly inserted element.
+ ///
+ /// # Safety
+ ///
+ /// You must ensure that the `BTreeSet` invariants are maintained.
+ /// Specifically:
+ ///
+ /// * The key of the newly inserted element must be unique in the tree.
+ /// * All elements in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn insert_after_unchecked(&mut self, value: T) {
+ unsafe { self.inner.insert_after_unchecked(value, SetValZST) }
+ }
+
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap after the
+ /// newly inserted element.
+ ///
+ /// # Safety
+ ///
+ /// You must ensure that the `BTreeSet` invariants are maintained.
+ /// Specifically:
+ ///
+ /// * The newly inserted element must be unique in the tree.
+ /// * All elements in the tree must remain in sorted order.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub unsafe fn insert_before_unchecked(&mut self, value: T) {
+ unsafe { self.inner.insert_before_unchecked(value, SetValZST) }
+ }
+
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap before the
+ /// newly inserted element.
+ ///
+ /// If the inserted element is not greater than the element before the
+ /// cursor (if any), or if it not less than the element after the cursor (if
+ /// any), then an [`UnorderedKeyError`] is returned since this would
+ /// invalidate the [`Ord`] invariant between the elements of the set.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> {
+ self.inner.insert_after(value, SetValZST)
+ }
+
+ /// Inserts a new element into the set in the gap that the
+ /// cursor is currently pointing to.
+ ///
+ /// After the insertion the cursor will be pointing at the gap after the
+ /// newly inserted element.
+ ///
+ /// If the inserted element is not greater than the element before the
+ /// cursor (if any), or if it not less than the element after the cursor (if
+ /// any), then an [`UnorderedKeyError`] is returned since this would
+ /// invalidate the [`Ord`] invariant between the elements of the set.
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> {
+ self.inner.insert_before(value, SetValZST)
+ }
+
+ /// Removes the next element from the `BTreeSet`.
+ ///
+ /// The element that was removed is returned. The cursor position is
+ /// unchanged (before the removed element).
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn remove_next(&mut self) -> Option<T> {
+ self.inner.remove_next().map(|(k, _)| k)
+ }
+
+ /// Removes the precending element from the `BTreeSet`.
+ ///
+ /// The element that was removed is returned. The cursor position is
+ /// unchanged (after the removed element).
+ #[unstable(feature = "btree_cursors", issue = "107540")]
+ pub fn remove_prev(&mut self) -> Option<T> {
+ self.inner.remove_prev().map(|(k, _)| k)
+ }
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub use super::map::UnorderedKeyError;
+
#[cfg(test)]
mod tests;
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index 48bf767..f947b61 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -1,8 +1,9 @@
+use std::ops::Bound::{Excluded, Included};
+use std::panic::{catch_unwind, AssertUnwindSafe};
+
use super::*;
use crate::testing::crash_test::{CrashTestDummy, Panic};
use crate::testing::rng::DeterministicRng;
-use std::ops::Bound::{Excluded, Included};
-use std::panic::{catch_unwind, AssertUnwindSafe};
#[test]
fn test_clone_eq() {
diff --git a/library/alloc/src/collections/btree/split.rs b/library/alloc/src/collections/btree/split.rs
index 638dc98..c188ed1 100644
--- a/library/alloc/src/collections/btree/split.rs
+++ b/library/alloc/src/collections/btree/split.rs
@@ -1,8 +1,10 @@
-use super::node::{ForceResult::*, Root};
-use super::search::SearchResult::*;
use core::alloc::Allocator;
use core::borrow::Borrow;
+use super::node::ForceResult::*;
+use super::node::Root;
+use super::search::SearchResult::*;
+
impl<K, V> Root<K, V> {
/// Calculates the length of both trees that result from splitting up
/// a given number of distinct key-value pairs.
diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs
index 077483a..0cd410c 100644
--- a/library/alloc/src/collections/linked_list.rs
+++ b/library/alloc/src/collections/linked_list.rs
@@ -13,12 +13,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
use core::cmp::Ordering;
-use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::FusedIterator;
use core::marker::PhantomData;
-use core::mem;
use core::ptr::NonNull;
+use core::{fmt, mem};
use super::SpecExtend;
use crate::alloc::{Allocator, Global};
diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs
index d3744c5..9b3c9ac 100644
--- a/library/alloc/src/collections/linked_list/tests.rs
+++ b/library/alloc/src/collections/linked_list/tests.rs
@@ -1,12 +1,12 @@
-use super::*;
-use crate::testing::crash_test::{CrashTestDummy, Panic};
-use crate::vec::Vec;
-
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::thread;
use rand::RngCore;
+use super::*;
+use crate::testing::crash_test::{CrashTestDummy, Panic};
+use crate::vec::Vec;
+
#[test]
fn test_basic() {
let mut m = LinkedList::<Box<_>>::new();
@@ -1167,9 +1167,7 @@ fn drop(&mut self) {
#[test]
fn test_allocator() {
- use core::alloc::AllocError;
- use core::alloc::Allocator;
- use core::alloc::Layout;
+ use core::alloc::{AllocError, Allocator, Layout};
use core::cell::Cell;
struct A {
diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs
index 705b815..020cf4d 100644
--- a/library/alloc/src/collections/mod.rs
+++ b/library/alloc/src/collections/mod.rs
@@ -27,33 +27,30 @@ pub mod btree_set {
pub use super::btree::set::*;
}
+use core::fmt::Display;
+
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use binary_heap::BinaryHeap;
-
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use btree_map::BTreeMap;
-
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use btree_set::BTreeSet;
-
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use linked_list::LinkedList;
-
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use vec_deque::VecDeque;
use crate::alloc::{Layout, LayoutError};
-use core::fmt::Display;
/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs
index 1373e60..44fcef4 100644
--- a/library/alloc/src/collections/vec_deque/drain.rs
+++ b/library/alloc/src/collections/vec_deque/drain.rs
@@ -4,9 +4,8 @@
use core::ptr::NonNull;
use core::{fmt, ptr};
-use crate::alloc::{Allocator, Global};
-
use super::VecDeque;
+use crate::alloc::{Allocator, Global};
/// A draining iterator over the elements of a `VecDeque`.
///
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index 4747517..7be3de1 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -1,10 +1,11 @@
use core::iter::{FusedIterator, TrustedLen};
+use core::mem::MaybeUninit;
use core::num::NonZero;
-use core::{array, fmt, mem::MaybeUninit, ops::Try, ptr};
-
-use crate::alloc::{Allocator, Global};
+use core::ops::Try;
+use core::{array, fmt, ptr};
use super::VecDeque;
+use crate::alloc::{Allocator, Global};
/// An owning iterator over the elements of a `VecDeque`.
///
@@ -120,6 +121,7 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B
{
match self.try_fold(init, |b, item| Ok::<B, !>(f(b, item))) {
Ok(b) => b,
+ #[cfg(bootstrap)]
Err(e) => match e {},
}
}
@@ -241,6 +243,7 @@ fn rfold<B, F>(mut self, init: B, mut f: F) -> B
{
match self.try_rfold(init, |b, item| Ok::<B, !>(f(b, item))) {
Ok(b) => b,
+ #[cfg(bootstrap)]
Err(e) => match e {},
}
}
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index 5a5e7f7..67b5b91 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -28,6 +28,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
+#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+impl<T> Default for Iter<'_, T> {
+ /// Creates an empty `vec_deque::Iter`.
+ ///
+ /// ```
+ /// # use std::collections::vec_deque;
+ /// let iter: vec_deque::Iter<'_, u8> = Default::default();
+ /// assert_eq!(iter.len(), 0);
+ /// ```
+ fn default() -> Self {
+ Iter { i1: Default::default(), i2: Default::default() }
+ }
+}
+
// FIXME(#26925) Remove in favor of `#[derive(Clone)]`
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Clone for Iter<'_, T> {
diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs
index 5061931..2726e3e 100644
--- a/library/alloc/src/collections/vec_deque/iter_mut.rs
+++ b/library/alloc/src/collections/vec_deque/iter_mut.rs
@@ -28,6 +28,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
+#[stable(feature = "default_iters_sequel", since = "CURRENT_RUSTC_VERSION")]
+impl<T> Default for IterMut<'_, T> {
+ /// Creates an empty `vec_deque::IterMut`.
+ ///
+ /// ```
+ /// # use std::collections::vec_deque;
+ /// let iter: vec_deque::IterMut<'_, u8> = Default::default();
+ /// assert_eq!(iter.len(), 0);
+ /// ```
+ fn default() -> Self {
+ IterMut { i1: Default::default(), i2: Default::default() }
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index a07f250..dc725ec 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -8,23 +8,19 @@
#![stable(feature = "rust1", since = "1.0.0")]
use core::cmp::{self, Ordering};
-use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::{repeat_n, repeat_with, ByRefSized};
-use core::mem::{ManuallyDrop, SizedTypeProperties};
-use core::ops::{Index, IndexMut, Range, RangeBounds};
-use core::ptr;
-use core::slice;
-
// This is used in a bunch of intra-doc links.
// FIXME: For some reason, `#[cfg(doc)]` wasn't sufficient, resulting in
// failures in linkchecker even though rustdoc built the docs just fine.
#[allow(unused_imports)]
use core::mem;
+use core::mem::{ManuallyDrop, SizedTypeProperties};
+use core::ops::{Index, IndexMut, Range, RangeBounds};
+use core::{fmt, ptr, slice};
use crate::alloc::{Allocator, Global};
-use crate::collections::TryReserveError;
-use crate::collections::TryReserveErrorKind;
+use crate::collections::{TryReserveError, TryReserveErrorKind};
use crate::raw_vec::RawVec;
use crate::vec::Vec;
diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs
index 6a89abc..a9b0fd0 100644
--- a/library/alloc/src/collections/vec_deque/spec_extend.rs
+++ b/library/alloc/src/collections/vec_deque/spec_extend.rs
@@ -1,9 +1,9 @@
-use crate::alloc::Allocator;
-use crate::vec;
use core::iter::TrustedLen;
use core::slice;
use super::VecDeque;
+use crate::alloc::Allocator;
+use crate::vec;
// Specialization trait used for VecDeque::extend
pub(super) trait SpecExtend<T, I> {
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index f1eb195..e32676a 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -3,25 +3,21 @@
#[cfg(test)]
mod tests;
+use core::borrow::Borrow;
+use core::ffi::{c_char, CStr};
+use core::num::NonZero;
+use core::slice::memchr;
+use core::str::{self, Utf8Error};
+use core::{fmt, mem, ops, ptr, slice};
+
use crate::borrow::{Cow, ToOwned};
use crate::boxed::Box;
use crate::rc::Rc;
use crate::slice::hack::into_vec;
use crate::string::String;
-use crate::vec::Vec;
-use core::borrow::Borrow;
-use core::ffi::{c_char, CStr};
-use core::fmt;
-use core::mem;
-use core::num::NonZero;
-use core::ops;
-use core::ptr;
-use core::slice;
-use core::slice::memchr;
-use core::str::{self, Utf8Error};
-
#[cfg(target_has_atomic = "ptr")]
use crate::sync::Arc;
+use crate::vec::Vec;
/// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the
/// middle.
diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs
index 9f51e17..8b7172b 100644
--- a/library/alloc/src/ffi/c_str/tests.rs
+++ b/library/alloc/src/ffi/c_str/tests.rs
@@ -1,10 +1,10 @@
-use super::*;
use core::assert_matches::assert_matches;
use core::ffi::FromBytesUntilNulError;
-use core::hash::{Hash, Hasher};
-
#[allow(deprecated)]
use core::hash::SipHasher13 as DefaultHasher;
+use core::hash::{Hash, Hasher};
+
+use super::*;
#[test]
fn c_to_rust() {
diff --git a/library/alloc/src/ffi/mod.rs b/library/alloc/src/ffi/mod.rs
index 9fc1acc..4f9dc40 100644
--- a/library/alloc/src/ffi/mod.rs
+++ b/library/alloc/src/ffi/mod.rs
@@ -80,13 +80,12 @@
#![stable(feature = "alloc_ffi", since = "1.64.0")]
-#[doc(no_inline)]
-#[stable(feature = "alloc_c_string", since = "1.64.0")]
-pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError};
-
#[doc(inline)]
#[stable(feature = "alloc_c_string", since = "1.64.0")]
pub use self::c_str::CString;
+#[doc(no_inline)]
+#[stable(feature = "alloc_c_string", since = "1.64.0")]
+pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError};
#[unstable(feature = "c_str_module", issue = "112134")]
pub mod c_str;
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index c6bba61..571fcd1 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -581,7 +581,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::Error;
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
-pub use core::fmt::FormatterFn;
+pub use core::fmt::{from_fn, FromFn};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{write, Arguments};
#[stable(feature = "rust1", since = "1.0.0")]
@@ -600,8 +600,7 @@
#[cfg(not(no_global_oom_handling))]
use crate::string;
-/// The `format` function takes an [`Arguments`] struct and returns the resulting
-/// formatted string.
+/// Takes an [`Arguments`] struct and returns the resulting formatted string.
///
/// The [`Arguments`] instance can be created with the [`format_args!`] macro.
///
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 4903607..3e44adf 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -86,6 +86,7 @@
#![warn(multiple_supertrait_upcastable)]
#![allow(internal_features)]
#![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
#![deny(ffi_unwind_calls)]
//
// Library features:
@@ -116,7 +117,6 @@
#![feature(const_pin)]
#![feature(const_refs_to_cell)]
#![feature(const_size_of_val)]
-#![feature(const_waker)]
#![feature(core_intrinsics)]
#![feature(deprecated_suggestion)]
#![feature(deref_pure_trait)]
@@ -138,6 +138,7 @@
#![feature(maybe_uninit_uninit_array_transpose)]
#![feature(panic_internals)]
#![feature(pattern)]
+#![feature(pin_coerce_unsized_trait)]
#![feature(ptr_internals)]
#![feature(ptr_metadata)]
#![feature(ptr_sub_ptr)]
@@ -165,7 +166,6 @@
//
// Language features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(c_unwind))]
#![cfg_attr(not(test), feature(coroutine_trait))]
#![cfg_attr(test, feature(panic_update_hook))]
#![cfg_attr(test, feature(test))]
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 7b7dae5..9c8fa7c 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -1,10 +1,9 @@
#![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")]
-use core::alloc::LayoutError;
-use core::cmp;
-use core::hint;
-use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
+use core::marker::PhantomData;
+use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ptr::{self, NonNull, Unique};
+use core::{cmp, hint};
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
@@ -41,6 +40,13 @@ enum AllocInit {
impl Cap {
const ZERO: Cap = unsafe { Cap(0) };
+
+ /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`.
+ ///
+ /// # Safety: cap must be <= `isize::MAX`.
+ unsafe fn new<T>(cap: usize) -> Self {
+ if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } }
+ }
}
/// A low-level utility for more ergonomically allocating, reallocating, and deallocating
@@ -52,7 +58,7 @@ impl Cap {
/// * Produces `Unique::dangling()` on zero-length allocations.
/// * Avoids freeing `Unique::dangling()`.
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics).
-/// * Guards against 32-bit systems allocating more than isize::MAX bytes.
+/// * Guards against 32-bit systems allocating more than `isize::MAX` bytes.
/// * Guards against overflowing your length.
/// * Calls `handle_alloc_error` for fallible allocations.
/// * Contains a `ptr::Unique` and thus endows the user with all related benefits.
@@ -67,7 +73,19 @@ impl Cap {
/// `Box<[T]>`, since `capacity()` won't yield the length.
#[allow(missing_debug_implementations)]
pub(crate) struct RawVec<T, A: Allocator = Global> {
- ptr: Unique<T>,
+ inner: RawVecInner<A>,
+ _marker: PhantomData<T>,
+}
+
+/// Like a `RawVec`, but only generic over the allocator, not the type.
+///
+/// As such, all the methods need the layout passed-in as a parameter.
+///
+/// Having this separation reduces the amount of code we need to monomorphize,
+/// as most operations don't need the actual type, just its layout.
+#[allow(missing_debug_implementations)]
+struct RawVecInner<A: Allocator = Global> {
+ ptr: Unique<u8>,
/// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case.
///
/// # Safety
@@ -91,8 +109,9 @@ impl<T> RawVec<T, Global> {
/// `RawVec` with capacity `usize::MAX`. Useful for implementing
/// delayed allocation.
#[must_use]
+ #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
pub const fn new() -> Self {
- Self::new_in(Global)
+ Self { inner: RawVecInner::new::<T>(), _marker: PhantomData }
}
/// Creates a `RawVec` (on the system heap) with exactly the
@@ -114,10 +133,7 @@ pub const fn new() -> Self {
#[must_use]
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
- match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global) {
- Ok(res) => res,
- Err(err) => handle_error(err),
- }
+ Self { inner: RawVecInner::with_capacity(capacity, T::LAYOUT), _marker: PhantomData }
}
/// Like `with_capacity`, but guarantees the buffer is zeroed.
@@ -125,29 +141,56 @@ pub fn with_capacity(capacity: usize) -> Self {
#[must_use]
#[inline]
pub fn with_capacity_zeroed(capacity: usize) -> Self {
- Self::with_capacity_zeroed_in(capacity, Global)
+ Self {
+ inner: RawVecInner::with_capacity_zeroed_in(capacity, Global, T::LAYOUT),
+ _marker: PhantomData,
+ }
+ }
+}
+
+impl RawVecInner<Global> {
+ #[must_use]
+ #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
+ const fn new<T>() -> Self {
+ Self::new_in(Global, core::mem::align_of::<T>())
+ }
+
+ #[cfg(not(any(no_global_oom_handling, test)))]
+ #[must_use]
+ #[inline]
+ fn with_capacity(capacity: usize, elem_layout: Layout) -> Self {
+ match Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global, elem_layout) {
+ Ok(res) => res,
+ Err(err) => handle_error(err),
+ }
+ }
+}
+
+// Tiny Vecs are dumb. Skip to:
+// - 8 if the element size is 1, because any heap allocators is likely
+// to round up a request of less than 8 bytes to at least 8 bytes.
+// - 4 if elements are moderate-sized (<= 1 KiB).
+// - 1 otherwise, to avoid wasting too much space for very short Vecs.
+const fn min_non_zero_cap(size: usize) -> usize {
+ if size == 1 {
+ 8
+ } else if size <= 1024 {
+ 4
+ } else {
+ 1
}
}
impl<T, A: Allocator> RawVec<T, A> {
- // Tiny Vecs are dumb. Skip to:
- // - 8 if the element size is 1, because any heap allocators is likely
- // to round up a request of less than 8 bytes to at least 8 bytes.
- // - 4 if elements are moderate-sized (<= 1 KiB).
- // - 1 otherwise, to avoid wasting too much space for very short Vecs.
- pub(crate) const MIN_NON_ZERO_CAP: usize = if mem::size_of::<T>() == 1 {
- 8
- } else if mem::size_of::<T>() <= 1024 {
- 4
- } else {
- 1
- };
+ #[cfg(not(no_global_oom_handling))]
+ pub(crate) const MIN_NON_ZERO_CAP: usize = min_non_zero_cap(size_of::<T>());
/// Like `new`, but parameterized over the choice of allocator for
/// the returned `RawVec`.
+ #[inline]
+ #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
pub const fn new_in(alloc: A) -> Self {
- // `cap: 0` means "unallocated". zero-sized types are ignored.
- Self { ptr: Unique::dangling(), cap: Cap::ZERO, alloc }
+ Self { inner: RawVecInner::new_in(alloc, align_of::<T>()), _marker: PhantomData }
}
/// Like `with_capacity`, but parameterized over the choice of
@@ -155,9 +198,9 @@ pub const fn new_in(alloc: A) -> Self {
#[cfg(not(no_global_oom_handling))]
#[inline]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
- match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc) {
- Ok(res) => res,
- Err(err) => handle_error(err),
+ Self {
+ inner: RawVecInner::with_capacity_in(capacity, alloc, T::LAYOUT),
+ _marker: PhantomData,
}
}
@@ -165,7 +208,10 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
/// allocator for the returned `RawVec`.
#[inline]
pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserveError> {
- Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc)
+ match RawVecInner::try_with_capacity_in(capacity, alloc, T::LAYOUT) {
+ Ok(inner) => Ok(Self { inner, _marker: PhantomData }),
+ Err(e) => Err(e),
+ }
}
/// Like `with_capacity_zeroed`, but parameterized over the choice
@@ -173,9 +219,9 @@ pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, TryReserv
#[cfg(not(no_global_oom_handling))]
#[inline]
pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
- match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc) {
- Ok(res) => res,
- Err(err) => handle_error(err),
+ Self {
+ inner: RawVecInner::with_capacity_zeroed_in(capacity, alloc, T::LAYOUT),
+ _marker: PhantomData,
}
}
@@ -201,45 +247,7 @@ pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>], A> {
let me = ManuallyDrop::new(self);
unsafe {
let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
- Box::from_raw_in(slice, ptr::read(&me.alloc))
- }
- }
-
- fn try_allocate_in(
- capacity: usize,
- init: AllocInit,
- alloc: A,
- ) -> Result<Self, TryReserveError> {
- // Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
-
- if T::IS_ZST || capacity == 0 {
- Ok(Self::new_in(alloc))
- } else {
- // We avoid `unwrap_or_else` here because it bloats the amount of
- // LLVM IR generated.
- let layout = match Layout::array::<T>(capacity) {
- Ok(layout) => layout,
- Err(_) => return Err(CapacityOverflow.into()),
- };
-
- if let Err(err) = alloc_guard(layout.size()) {
- return Err(err);
- }
-
- let result = match init {
- AllocInit::Uninitialized => alloc.allocate(layout),
- #[cfg(not(no_global_oom_handling))]
- AllocInit::Zeroed => alloc.allocate_zeroed(layout),
- };
- let ptr = match result {
- Ok(ptr) => ptr,
- Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()),
- };
-
- // Allocators currently return a `NonNull<[u8]>` whose length
- // matches the size requested. If that ever changes, the capacity
- // here should change to `ptr.len() / mem::size_of::<T>()`.
- Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc })
+ Box::from_raw_in(slice, ptr::read(&me.inner.alloc))
}
}
@@ -255,8 +263,15 @@ fn try_allocate_in(
/// guaranteed.
#[inline]
pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self {
- let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } };
- Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc }
+ // SAFETY: Precondition passed to the caller
+ unsafe {
+ let ptr = ptr.cast();
+ let capacity = Cap::new::<T>(capacity);
+ Self {
+ inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc),
+ _marker: PhantomData,
+ }
+ }
}
/// A convenience method for hoisting the non-null precondition out of [`RawVec::from_raw_parts_in`].
@@ -265,9 +280,13 @@ pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, alloc: A) -> Self
///
/// See [`RawVec::from_raw_parts_in`].
#[inline]
- pub(crate) unsafe fn from_nonnull_in(ptr: NonNull<T>, capacity: usize, alloc: A) -> Self {
- let cap = if T::IS_ZST { Cap::ZERO } else { unsafe { Cap(capacity) } };
- Self { ptr: Unique::from(ptr), cap, alloc }
+ pub unsafe fn from_nonnull_in(ptr: NonNull<T>, capacity: usize, alloc: A) -> Self {
+ // SAFETY: Precondition passed to the caller
+ unsafe {
+ let ptr = ptr.cast();
+ let capacity = Cap::new::<T>(capacity);
+ Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData }
+ }
}
/// Gets a raw pointer to the start of the allocation. Note that this is
@@ -275,43 +294,26 @@ pub(crate) unsafe fn from_nonnull_in(ptr: NonNull<T>, capacity: usize, alloc: A)
/// be careful.
#[inline]
pub fn ptr(&self) -> *mut T {
- self.ptr.as_ptr()
+ self.inner.ptr()
}
#[inline]
pub fn non_null(&self) -> NonNull<T> {
- NonNull::from(self.ptr)
+ self.inner.non_null()
}
/// Gets the capacity of the allocation.
///
/// This will always be `usize::MAX` if `T` is zero-sized.
- #[inline(always)]
+ #[inline]
pub fn capacity(&self) -> usize {
- if T::IS_ZST { usize::MAX } else { self.cap.0 }
+ self.inner.capacity(size_of::<T>())
}
/// Returns a shared reference to the allocator backing this `RawVec`.
+ #[inline]
pub fn allocator(&self) -> &A {
- &self.alloc
- }
-
- fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
- if T::IS_ZST || self.cap.0 == 0 {
- None
- } else {
- // We could use Layout::array here which ensures the absence of isize and usize overflows
- // and could hypothetically handle differences between stride and size, but this memory
- // has already been allocated so we know it can't overflow and currently Rust does not
- // support such types. So we can do better by skipping some checks and avoid an unwrap.
- const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
- unsafe {
- let align = mem::align_of::<T>();
- let size = mem::size_of::<T>().unchecked_mul(self.cap.0);
- let layout = Layout::from_size_align_unchecked(size, align);
- Some((self.ptr.cast().into(), layout))
- }
- }
+ self.inner.allocator()
}
/// Ensures that the buffer contains at least enough space to hold `len +
@@ -336,24 +338,7 @@ fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
#[cfg(not(no_global_oom_handling))]
#[inline]
pub fn reserve(&mut self, len: usize, additional: usize) {
- // Callers expect this function to be very cheap when there is already sufficient capacity.
- // Therefore, we move all the resizing and error-handling logic from grow_amortized and
- // handle_reserve behind a call, while making sure that this function is likely to be
- // inlined as just a comparison and a call if the comparison fails.
- #[cold]
- fn do_reserve_and_handle<T, A: Allocator>(
- slf: &mut RawVec<T, A>,
- len: usize,
- additional: usize,
- ) {
- if let Err(err) = slf.grow_amortized(len, additional) {
- handle_error(err);
- }
- }
-
- if self.needs_to_grow(len, additional) {
- do_reserve_and_handle(self, len, additional);
- }
+ self.inner.reserve(len, additional, T::LAYOUT)
}
/// A specialized version of `self.reserve(len, 1)` which requires the
@@ -361,21 +346,12 @@ fn do_reserve_and_handle<T, A: Allocator>(
#[cfg(not(no_global_oom_handling))]
#[inline(never)]
pub fn grow_one(&mut self) {
- if let Err(err) = self.grow_amortized(self.cap.0, 1) {
- handle_error(err);
- }
+ self.inner.grow_one(T::LAYOUT)
}
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
- if self.needs_to_grow(len, additional) {
- self.grow_amortized(len, additional)?;
- }
- unsafe {
- // Inform the optimizer that the reservation has succeeded or wasn't needed
- hint::assert_unchecked(!self.needs_to_grow(len, additional));
- }
- Ok(())
+ self.inner.try_reserve(len, additional, T::LAYOUT)
}
/// Ensures that the buffer contains at least enough space to hold `len +
@@ -397,9 +373,7 @@ pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryRe
/// Aborts on OOM.
#[cfg(not(no_global_oom_handling))]
pub fn reserve_exact(&mut self, len: usize, additional: usize) {
- if let Err(err) = self.try_reserve_exact(len, additional) {
- handle_error(err);
- }
+ self.inner.reserve_exact(len, additional, T::LAYOUT)
}
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
@@ -408,14 +382,7 @@ pub fn try_reserve_exact(
len: usize,
additional: usize,
) -> Result<(), TryReserveError> {
- if self.needs_to_grow(len, additional) {
- self.grow_exact(len, additional)?;
- }
- unsafe {
- // Inform the optimizer that the reservation has succeeded or wasn't needed
- hint::assert_unchecked(!self.needs_to_grow(len, additional));
- }
- Ok(())
+ self.inner.try_reserve_exact(len, additional, T::LAYOUT)
}
/// Shrinks the buffer down to the specified capacity. If the given amount
@@ -431,22 +398,230 @@ pub fn try_reserve_exact(
#[cfg(not(no_global_oom_handling))]
#[inline]
pub fn shrink_to_fit(&mut self, cap: usize) {
- if let Err(err) = self.shrink(cap) {
- handle_error(err);
- }
+ self.inner.shrink_to_fit(cap, T::LAYOUT)
}
}
-impl<T, A: Allocator> RawVec<T, A> {
- /// Returns if the buffer needs to grow to fulfill the needed extra capacity.
- /// Mainly used to make inlining reserve-calls possible without inlining `grow`.
- fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
- additional > self.capacity().wrapping_sub(len)
+unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
+ /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
+ fn drop(&mut self) {
+ // SAFETY: We are in a Drop impl, self.inner will not be used again.
+ unsafe { self.inner.deallocate(T::LAYOUT) }
+ }
+}
+
+impl<A: Allocator> RawVecInner<A> {
+ #[inline]
+ #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")]
+ const fn new_in(alloc: A, align: usize) -> Self {
+ let ptr = unsafe { core::mem::transmute(align) };
+ // `cap: 0` means "unallocated". zero-sized types are ignored.
+ Self { ptr, cap: Cap::ZERO, alloc }
}
- /// # Safety:
- ///
- /// `cap` must not exceed `isize::MAX`.
+ #[cfg(not(no_global_oom_handling))]
+ #[inline]
+ fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self {
+ match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) {
+ Ok(this) => {
+ unsafe {
+ // Make it more obvious that a subsquent Vec::reserve(capacity) will not allocate.
+ hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout));
+ }
+ this
+ }
+ Err(err) => handle_error(err),
+ }
+ }
+
+ #[inline]
+ fn try_with_capacity_in(
+ capacity: usize,
+ alloc: A,
+ elem_layout: Layout,
+ ) -> Result<Self, TryReserveError> {
+ Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout)
+ }
+
+ #[cfg(not(no_global_oom_handling))]
+ #[inline]
+ fn with_capacity_zeroed_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self {
+ match Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc, elem_layout) {
+ Ok(res) => res,
+ Err(err) => handle_error(err),
+ }
+ }
+
+ fn try_allocate_in(
+ capacity: usize,
+ init: AllocInit,
+ alloc: A,
+ elem_layout: Layout,
+ ) -> Result<Self, TryReserveError> {
+ // We avoid `unwrap_or_else` here because it bloats the amount of
+ // LLVM IR generated.
+ let layout = match layout_array(capacity, elem_layout) {
+ Ok(layout) => layout,
+ Err(_) => return Err(CapacityOverflow.into()),
+ };
+
+ // Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
+ if layout.size() == 0 {
+ return Ok(Self::new_in(alloc, elem_layout.align()));
+ }
+
+ if let Err(err) = alloc_guard(layout.size()) {
+ return Err(err);
+ }
+
+ let result = match init {
+ AllocInit::Uninitialized => alloc.allocate(layout),
+ #[cfg(not(no_global_oom_handling))]
+ AllocInit::Zeroed => alloc.allocate_zeroed(layout),
+ };
+ let ptr = match result {
+ Ok(ptr) => ptr,
+ Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()),
+ };
+
+ // Allocators currently return a `NonNull<[u8]>` whose length
+ // matches the size requested. If that ever changes, the capacity
+ // here should change to `ptr.len() / mem::size_of::<T>()`.
+ Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc })
+ }
+
+ #[inline]
+ unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self {
+ Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc }
+ }
+
+ #[inline]
+ unsafe fn from_nonnull_in(ptr: NonNull<u8>, cap: Cap, alloc: A) -> Self {
+ Self { ptr: Unique::from(ptr), cap, alloc }
+ }
+
+ #[inline]
+ fn ptr<T>(&self) -> *mut T {
+ self.non_null::<T>().as_ptr()
+ }
+
+ #[inline]
+ fn non_null<T>(&self) -> NonNull<T> {
+ self.ptr.cast().into()
+ }
+
+ #[inline]
+ fn capacity(&self, elem_size: usize) -> usize {
+ if elem_size == 0 { usize::MAX } else { self.cap.0 }
+ }
+
+ #[inline]
+ fn allocator(&self) -> &A {
+ &self.alloc
+ }
+
+ #[inline]
+ fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull<u8>, Layout)> {
+ if elem_layout.size() == 0 || self.cap.0 == 0 {
+ None
+ } else {
+ // We could use Layout::array here which ensures the absence of isize and usize overflows
+ // and could hypothetically handle differences between stride and size, but this memory
+ // has already been allocated so we know it can't overflow and currently Rust does not
+ // support such types. So we can do better by skipping some checks and avoid an unwrap.
+ unsafe {
+ let alloc_size = elem_layout.size().unchecked_mul(self.cap.0);
+ let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align());
+ Some((self.ptr.into(), layout))
+ }
+ }
+ }
+
+ #[cfg(not(no_global_oom_handling))]
+ #[inline]
+ fn reserve(&mut self, len: usize, additional: usize, elem_layout: Layout) {
+ // Callers expect this function to be very cheap when there is already sufficient capacity.
+ // Therefore, we move all the resizing and error-handling logic from grow_amortized and
+ // handle_reserve behind a call, while making sure that this function is likely to be
+ // inlined as just a comparison and a call if the comparison fails.
+ #[cold]
+ fn do_reserve_and_handle<A: Allocator>(
+ slf: &mut RawVecInner<A>,
+ len: usize,
+ additional: usize,
+ elem_layout: Layout,
+ ) {
+ if let Err(err) = slf.grow_amortized(len, additional, elem_layout) {
+ handle_error(err);
+ }
+ }
+
+ if self.needs_to_grow(len, additional, elem_layout) {
+ do_reserve_and_handle(self, len, additional, elem_layout);
+ }
+ }
+
+ #[cfg(not(no_global_oom_handling))]
+ #[inline]
+ fn grow_one(&mut self, elem_layout: Layout) {
+ if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) {
+ handle_error(err);
+ }
+ }
+
+ fn try_reserve(
+ &mut self,
+ len: usize,
+ additional: usize,
+ elem_layout: Layout,
+ ) -> Result<(), TryReserveError> {
+ if self.needs_to_grow(len, additional, elem_layout) {
+ self.grow_amortized(len, additional, elem_layout)?;
+ }
+ unsafe {
+ // Inform the optimizer that the reservation has succeeded or wasn't needed
+ hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout));
+ }
+ Ok(())
+ }
+
+ #[cfg(not(no_global_oom_handling))]
+ fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) {
+ if let Err(err) = self.try_reserve_exact(len, additional, elem_layout) {
+ handle_error(err);
+ }
+ }
+
+ fn try_reserve_exact(
+ &mut self,
+ len: usize,
+ additional: usize,
+ elem_layout: Layout,
+ ) -> Result<(), TryReserveError> {
+ if self.needs_to_grow(len, additional, elem_layout) {
+ self.grow_exact(len, additional, elem_layout)?;
+ }
+ unsafe {
+ // Inform the optimizer that the reservation has succeeded or wasn't needed
+ hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout));
+ }
+ Ok(())
+ }
+
+ #[cfg(not(no_global_oom_handling))]
+ #[inline]
+ fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) {
+ if let Err(err) = self.shrink(cap, elem_layout) {
+ handle_error(err);
+ }
+ }
+
+ #[inline]
+ fn needs_to_grow(&self, len: usize, additional: usize, elem_layout: Layout) -> bool {
+ additional > self.capacity(elem_layout.size()).wrapping_sub(len)
+ }
+
+ #[inline]
unsafe fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) {
// Allocators currently return a `NonNull<[u8]>` whose length matches
// the size requested. If that ever changes, the capacity here should
@@ -455,18 +630,16 @@ unsafe fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) {
self.cap = unsafe { Cap(cap) };
}
- // This method is usually instantiated many times. So we want it to be as
- // small as possible, to improve compile times. But we also want as much of
- // its contents to be statically computable as possible, to make the
- // generated code run faster. Therefore, this method is carefully written
- // so that all of the code that depends on `T` is within it, while as much
- // of the code that doesn't depend on `T` as possible is in functions that
- // are non-generic over `T`.
- fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
+ fn grow_amortized(
+ &mut self,
+ len: usize,
+ additional: usize,
+ elem_layout: Layout,
+ ) -> Result<(), TryReserveError> {
// This is ensured by the calling contexts.
debug_assert!(additional > 0);
- if T::IS_ZST {
+ if elem_layout.size() == 0 {
// Since we return a capacity of `usize::MAX` when `elem_size` is
// 0, getting to here necessarily means the `RawVec` is overfull.
return Err(CapacityOverflow.into());
@@ -478,33 +651,34 @@ fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), TryRes
// This guarantees exponential growth. The doubling cannot overflow
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
let cap = cmp::max(self.cap.0 * 2, required_cap);
- let cap = cmp::max(Self::MIN_NON_ZERO_CAP, cap);
+ let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
- let new_layout = Layout::array::<T>(cap);
+ let new_layout = layout_array(cap, elem_layout)?;
- // `finish_grow` is non-generic over `T`.
- let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?;
- // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than isize::MAX items
+ let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?;
+ // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
+
unsafe { self.set_ptr_and_cap(ptr, cap) };
Ok(())
}
- // The constraints on this method are much the same as those on
- // `grow_amortized`, but this method is usually instantiated less often so
- // it's less critical.
- fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
- if T::IS_ZST {
+ fn grow_exact(
+ &mut self,
+ len: usize,
+ additional: usize,
+ elem_layout: Layout,
+ ) -> Result<(), TryReserveError> {
+ if elem_layout.size() == 0 {
// Since we return a capacity of `usize::MAX` when the type size is
// 0, getting to here necessarily means the `RawVec` is overfull.
return Err(CapacityOverflow.into());
}
let cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
- let new_layout = Layout::array::<T>(cap);
+ let new_layout = layout_array(cap, elem_layout)?;
- // `finish_grow` is non-generic over `T`.
- let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?;
- // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than isize::MAX items
+ let ptr = finish_grow(new_layout, self.current_memory(elem_layout), &mut self.alloc)?;
+ // SAFETY: finish_grow would have resulted in a capacity overflow if we tried to allocate more than `isize::MAX` items
unsafe {
self.set_ptr_and_cap(ptr, cap);
}
@@ -513,10 +687,10 @@ fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserve
#[cfg(not(no_global_oom_handling))]
#[inline]
- fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
- assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity");
+ fn shrink(&mut self, cap: usize, elem_layout: Layout) -> Result<(), TryReserveError> {
+ assert!(cap <= self.capacity(elem_layout.size()), "Tried to shrink to a larger capacity");
// SAFETY: Just checked this isn't trying to grow
- unsafe { self.shrink_unchecked(cap) }
+ unsafe { self.shrink_unchecked(cap, elem_layout) }
}
/// `shrink`, but without the capacity check.
@@ -530,23 +704,27 @@ fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> {
/// # Safety
/// `cap <= self.capacity()`
#[cfg(not(no_global_oom_handling))]
- unsafe fn shrink_unchecked(&mut self, cap: usize) -> Result<(), TryReserveError> {
- let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
- // See current_memory() why this assert is here
- const { assert!(mem::size_of::<T>() % mem::align_of::<T>() == 0) };
+ unsafe fn shrink_unchecked(
+ &mut self,
+ cap: usize,
+ elem_layout: Layout,
+ ) -> Result<(), TryReserveError> {
+ let (ptr, layout) =
+ if let Some(mem) = self.current_memory(elem_layout) { mem } else { return Ok(()) };
// If shrinking to 0, deallocate the buffer. We don't reach this point
// for the T::IS_ZST case since current_memory() will have returned
// None.
if cap == 0 {
unsafe { self.alloc.deallocate(ptr, layout) };
- self.ptr = Unique::dangling();
+ self.ptr =
+ unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) };
self.cap = Cap::ZERO;
} else {
let ptr = unsafe {
- // `Layout::array` cannot overflow here because it would have
+ // Layout cannot overflow here because it would have
// overflowed earlier when capacity was larger.
- let new_size = mem::size_of::<T>().unchecked_mul(cap);
+ let new_size = elem_layout.size().unchecked_mul(cap);
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
self.alloc
.shrink(ptr, layout, new_layout)
@@ -559,24 +737,32 @@ unsafe fn shrink_unchecked(&mut self, cap: usize) -> Result<(), TryReserveError>
}
Ok(())
}
+
+ /// # Safety
+ ///
+ /// This function deallocates the owned allocation, but does not update `ptr` or `cap` to
+ /// prevent double-free or use-after-free. Essentially, do not do anything with the caller
+ /// after this function returns.
+ /// Ideally this function would take `self` by move, but it cannot because it exists to be
+ /// called from a `Drop` impl.
+ unsafe fn deallocate(&mut self, elem_layout: Layout) {
+ if let Some((ptr, layout)) = self.current_memory(elem_layout) {
+ unsafe {
+ self.alloc.deallocate(ptr, layout);
+ }
+ }
+ }
}
-// This function is outside `RawVec` to minimize compile times. See the comment
-// above `RawVec::grow_amortized` for details. (The `A` parameter isn't
-// significant, because the number of different `A` types seen in practice is
-// much smaller than the number of `T` types.)
#[inline(never)]
fn finish_grow<A>(
- new_layout: Result<Layout, LayoutError>,
+ new_layout: Layout,
current_memory: Option<(NonNull<u8>, Layout)>,
alloc: &mut A,
) -> Result<NonNull<[u8]>, TryReserveError>
where
A: Allocator,
{
- // Check for the error here to minimize the size of `RawVec::grow_*`.
- let new_layout = new_layout.map_err(|_| CapacityOverflow)?;
-
alloc_guard(new_layout.size())?;
let memory = if let Some((ptr, old_layout)) = current_memory {
@@ -593,15 +779,6 @@ fn finish_grow<A>(
memory.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () }.into())
}
-unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec<T, A> {
- /// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
- fn drop(&mut self) {
- if let Some((ptr, layout)) = self.current_memory() {
- unsafe { self.alloc.deallocate(ptr, layout) }
- }
- }
-}
-
// Central function for reserve error handling.
#[cfg(not(no_global_oom_handling))]
#[cold]
@@ -628,3 +805,8 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
Ok(())
}
}
+
+#[inline]
+fn layout_array(cap: usize, elem_layout: Layout) -> Result<Layout, TryReserveError> {
+ elem_layout.repeat(cap).map(|(layout, _pad)| layout).map_err(|_| CapacityOverflow.into())
+}
diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs
index 4194be5..d78ded1 100644
--- a/library/alloc/src/raw_vec/tests.rs
+++ b/library/alloc/src/raw_vec/tests.rs
@@ -1,7 +1,8 @@
-use super::*;
use core::mem::size_of;
use std::cell::Cell;
+use super::*;
+
#[test]
fn allocator_param() {
use crate::alloc::AllocError;
@@ -42,9 +43,9 @@ unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
let a = BoundedAlloc { fuel: Cell::new(500) };
let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
- assert_eq!(v.alloc.fuel.get(), 450);
+ assert_eq!(v.inner.alloc.fuel.get(), 450);
v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
- assert_eq!(v.alloc.fuel.get(), 250);
+ assert_eq!(v.inner.alloc.fuel.get(), 250);
}
#[test]
@@ -85,7 +86,7 @@ fn reserve_does_not_overallocate() {
fn zst_sanity<T>(v: &RawVec<T>) {
assert_eq!(v.capacity(), usize::MAX);
assert_eq!(v.ptr(), core::ptr::Unique::<T>::dangling().as_ptr());
- assert_eq!(v.current_memory(), None);
+ assert_eq!(v.inner.current_memory(T::LAYOUT), None);
}
#[test]
@@ -105,22 +106,11 @@ fn zst() {
let v: RawVec<ZST> = RawVec::with_capacity_in(100, Global);
zst_sanity(&v);
- let v: RawVec<ZST> = RawVec::try_allocate_in(0, AllocInit::Uninitialized, Global).unwrap();
- zst_sanity(&v);
-
- let v: RawVec<ZST> = RawVec::try_allocate_in(100, AllocInit::Uninitialized, Global).unwrap();
- zst_sanity(&v);
-
- let mut v: RawVec<ZST> =
- RawVec::try_allocate_in(usize::MAX, AllocInit::Uninitialized, Global).unwrap();
+ let mut v: RawVec<ZST> = RawVec::with_capacity_in(usize::MAX, Global);
zst_sanity(&v);
// Check all these operations work as expected with zero-sized elements.
- assert!(!v.needs_to_grow(100, usize::MAX - 100));
- assert!(v.needs_to_grow(101, usize::MAX - 100));
- zst_sanity(&v);
-
v.reserve(100, usize::MAX - 100);
//v.reserve(101, usize::MAX - 100); // panics, in `zst_reserve_panic` below
zst_sanity(&v);
@@ -137,12 +127,12 @@ fn zst() {
assert_eq!(v.try_reserve_exact(101, usize::MAX - 100), cap_err);
zst_sanity(&v);
- assert_eq!(v.grow_amortized(100, usize::MAX - 100), cap_err);
- assert_eq!(v.grow_amortized(101, usize::MAX - 100), cap_err);
+ assert_eq!(v.inner.grow_amortized(100, usize::MAX - 100, ZST::LAYOUT), cap_err);
+ assert_eq!(v.inner.grow_amortized(101, usize::MAX - 100, ZST::LAYOUT), cap_err);
zst_sanity(&v);
- assert_eq!(v.grow_exact(100, usize::MAX - 100), cap_err);
- assert_eq!(v.grow_exact(101, usize::MAX - 100), cap_err);
+ assert_eq!(v.inner.grow_exact(100, usize::MAX - 100, ZST::LAYOUT), cap_err);
+ assert_eq!(v.inner.grow_exact(101, usize::MAX - 100, ZST::LAYOUT), cap_err);
zst_sanity(&v);
}
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index bfe3ea2..bdee061 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -241,20 +241,12 @@
#![stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(test))]
-use crate::boxed::Box;
-#[cfg(test)]
-use std::boxed::Box;
-
use core::any::Any;
-use core::borrow;
use core::cell::Cell;
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::cmp::Ordering;
-use core::fmt;
use core::hash::{Hash, Hasher};
-use core::hint;
use core::intrinsics::abort;
#[cfg(not(no_global_oom_handling))]
use core::iter;
@@ -264,14 +256,20 @@
use core::panic::{RefUnwindSafe, UnwindSafe};
#[cfg(not(no_global_oom_handling))]
use core::pin::Pin;
+use core::pin::PinCoerceUnsized;
use core::ptr::{self, drop_in_place, NonNull};
#[cfg(not(no_global_oom_handling))]
use core::slice::from_raw_parts_mut;
+use core::{borrow, fmt, hint};
+#[cfg(test)]
+use std::boxed::Box;
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
use crate::alloc::{AllocError, Allocator, Global, Layout};
use crate::borrow::{Cow, ToOwned};
+#[cfg(not(test))]
+use crate::boxed::Box;
#[cfg(not(no_global_oom_handling))]
use crate::string::String;
#[cfg(not(no_global_oom_handling))]
@@ -439,7 +437,7 @@ pub fn new(value: T) -> Rc<T> {
/// }
///
/// impl Gadget {
- /// /// Construct a reference counted Gadget.
+ /// /// Constructs a reference counted Gadget.
/// fn new() -> Rc<Self> {
/// // `me` is a `Weak<Gadget>` pointing at the new allocation of the
/// // `Rc` we're constructing.
@@ -449,7 +447,7 @@ pub fn new(value: T) -> Rc<T> {
/// })
/// }
///
- /// /// Return a reference counted pointer to Self.
+ /// /// Returns a reference counted pointer to Self.
/// fn me(&self) -> Rc<Self> {
/// self.me.upgrade().unwrap()
/// }
@@ -1375,6 +1373,7 @@ pub fn into_raw(this: Self) -> *const T {
/// let x = unsafe { Rc::from_raw_in(ptr, alloc) };
/// assert_eq!(&*x, "hello");
/// ```
+ #[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn into_raw_with_allocator(this: Self) -> (*const T, A) {
let this = mem::ManuallyDrop::new(this);
@@ -1900,7 +1899,7 @@ pub fn unwrap_or_clone(this: Self) -> T {
}
impl<A: Allocator> Rc<dyn Any, A> {
- /// Attempt to downcast the `Rc<dyn Any>` to a concrete type.
+ /// Attempts to downcast the `Rc<dyn Any>` to a concrete type.
///
/// # Examples
///
@@ -2179,6 +2178,12 @@ fn deref(&self) -> &T {
}
}
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Rc<T, A> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
+
#[unstable(feature = "deref_pure_trait", issue = "87121")]
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
@@ -2586,7 +2591,7 @@ fn from(t: T) -> Self {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T: Clone> From<&[T]> for Rc<[T]> {
- /// Allocate a reference-counted slice and fill it by cloning `v`'s items.
+ /// Allocates a reference-counted slice and fills it by cloning `v`'s items.
///
/// # Example
///
@@ -2605,7 +2610,7 @@ fn from(v: &[T]) -> Rc<[T]> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl From<&str> for Rc<str> {
- /// Allocate a reference-counted string slice and copy `v` into it.
+ /// Allocates a reference-counted string slice and copies `v` into it.
///
/// # Example
///
@@ -2624,7 +2629,7 @@ fn from(v: &str) -> Rc<str> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl From<String> for Rc<str> {
- /// Allocate a reference-counted string slice and copy `v` into it.
+ /// Allocates a reference-counted string slice and copies `v` into it.
///
/// # Example
///
@@ -2662,7 +2667,7 @@ fn from(v: Box<T, A>) -> Rc<T, A> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T, A: Allocator> From<Vec<T, A>> for Rc<[T], A> {
- /// Allocate a reference-counted slice and move `v`'s items into it.
+ /// Allocates a reference-counted slice and moves `v`'s items into it.
///
/// # Example
///
@@ -2695,8 +2700,8 @@ impl<'a, B> From<Cow<'a, B>> for Rc<B>
B: ToOwned + ?Sized,
Rc<B>: From<&'a B> + From<B::Owned>,
{
- /// Create a reference-counted pointer from
- /// a clone-on-write pointer by copying its content.
+ /// Creates a reference-counted pointer from a clone-on-write pointer by
+ /// copying its content.
///
/// # Example
///
@@ -3110,6 +3115,7 @@ pub fn into_raw(self) -> *const T {
///
/// [`from_raw_in`]: Weak::from_raw_in
/// [`as_ptr`]: Weak::as_ptr
+ #[must_use = "losing the pointer will leak memory"]
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn into_raw_with_allocator(self) -> (*const T, A) {
@@ -3526,7 +3532,7 @@ fn as_ref(&self) -> &T {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized, A: Allocator> Unpin for Rc<T, A> {}
-/// Get the offset within an `RcBox` for the payload behind a pointer.
+/// Gets the offset within an `RcBox` for the payload behind a pointer.
///
/// # Safety
///
@@ -3692,6 +3698,9 @@ fn deref(&self) -> &T {
}
}
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueRc<T> {}
+
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
fn deref_mut(&mut self) -> &mut T {
@@ -3734,7 +3743,7 @@ struct UniqueRcUninit<T: ?Sized, A: Allocator> {
#[cfg(not(no_global_oom_handling))]
impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
- /// Allocate a RcBox with layout suitable to contain `for_value` or a clone of it.
+ /// Allocates a RcBox with layout suitable to contain `for_value` or a clone of it.
fn new(for_value: &T, alloc: A) -> UniqueRcUninit<T, A> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index 5e2e4be..84e8b32 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -1,8 +1,8 @@
-use super::*;
-
use std::cell::RefCell;
use std::clone::Clone;
+use super::*;
+
#[test]
fn test_clone() {
let x = Rc::new(RefCell::new(5));
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index c7960b3..9d70487 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -78,7 +78,6 @@
// N.B., see the `hack` module in this file for more details.
#[cfg(test)]
pub use hack::into_vec;
-
// HACK(japaric) needed for the implementation of `Vec::clone` during testing
// N.B., see the `hack` module in this file for more details.
#[cfg(test)]
@@ -179,15 +178,25 @@ impl<T> [T] {
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case.
///
- /// If `T: Ord` does not implement a total order the resulting order is unspecified. All
- /// original elements will remain in the slice and any possible modifications via interior
- /// mutability are observed in the input. Same is true if `T: Ord` panics.
+ /// If the implementation of [`Ord`] for `T` does not implement a [total order] the resulting
+ /// order of elements in the slice is unspecified. All original elements will remain in the
+ /// slice and any possible modifications via interior mutability are observed in the input. Same
+ /// is true if the implementation of [`Ord`] for `T` panics.
///
/// When applicable, unstable sorting is preferred because it is generally faster than stable
/// sorting and it doesn't allocate auxiliary memory. See
/// [`sort_unstable`](slice::sort_unstable). The exception are partially sorted slices, which
/// may be better served with `slice::sort`.
///
+ /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require
+ /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the
+ /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with
+ /// `slice::sort_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a [total
+ /// order] users can sort slices containing floating-point values. Alternatively, if all values
+ /// in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`] forms a
+ /// [total order], it's possible to sort the slice with `sort_by(|a, b|
+ /// a.partial_cmp(b).unwrap())`.
+ ///
/// # Current implementation
///
/// The current implementation is based on [driftsort] by Orson Peters and Lukas Bergdoll, which
@@ -199,18 +208,21 @@ impl<T> [T] {
/// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
/// clamps at `self.len() / 2`.
///
- /// If `T: Ord` does not implement a total order, the implementation may panic.
+ /// # Panics
+ ///
+ /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order].
///
/// # Examples
///
/// ```
- /// let mut v = [-5, 4, 1, -3, 2];
+ /// let mut v = [4, -5, 1, -3, 2];
///
/// v.sort();
- /// assert!(v == [-5, -3, 1, 2, 4]);
+ /// assert_eq!(v, [-5, -3, 1, 2, 4]);
/// ```
///
/// [driftsort]: https://github.com/Voultapher/driftsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -222,30 +234,19 @@ pub fn sort(&mut self)
stable_sort(self, T::lt);
}
- /// Sorts the slice with a comparator function, preserving initial order of equal elements.
+ /// Sorts the slice with a comparison function, preserving initial order of equal elements.
///
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*n* \* log(*n*))
/// worst-case.
///
- /// The comparator function should define a total ordering for the elements in the slice. If the
- /// ordering is not total, the order of the elements is unspecified.
+ /// If the comparison function `compare` does not implement a [total order] the resulting order
+ /// of elements in the slice is unspecified. All original elements will remain in the slice and
+ /// any possible modifications via interior mutability are observed in the input. Same is true
+ /// if `compare` panics.
///
- /// If the comparator function does not implement a total order the resulting order is
- /// unspecified. All original elements will remain in the slice and any possible modifications
- /// via interior mutability are observed in the input. Same is true if the comparator function
- /// panics. A total order (for all `a`, `b` and `c`):
- ///
- /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and
- /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
- ///
- /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use
- /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.
- ///
- /// ```
- /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0];
- /// floats.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
- /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]);
- /// ```
+ /// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor
+ /// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and
+ /// examples see the [`Ord`] documentation.
///
/// # Current implementation
///
@@ -258,21 +259,24 @@ pub fn sort(&mut self)
/// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
/// clamps at `self.len() / 2`.
///
- /// If `T: Ord` does not implement a total order, the implementation may panic.
+ /// # Panics
+ ///
+ /// May panic if `compare` does not implement a [total order].
///
/// # Examples
///
/// ```
- /// let mut v = [5, 4, 1, 3, 2];
+ /// let mut v = [4, -5, 1, -3, 2];
/// v.sort_by(|a, b| a.cmp(b));
- /// assert!(v == [1, 2, 3, 4, 5]);
+ /// assert_eq!(v, [-5, -3, 1, 2, 4]);
///
/// // reverse sorting
/// v.sort_by(|a, b| b.cmp(a));
- /// assert!(v == [5, 4, 3, 2, 1]);
+ /// assert_eq!(v, [4, 2, 1, -3, -5]);
/// ```
///
/// [driftsort]: https://github.com/Voultapher/driftsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -289,9 +293,10 @@ pub fn sort_by<F>(&mut self, mut compare: F)
/// This sort is stable (i.e., does not reorder equal elements) and *O*(*m* \* *n* \* log(*n*))
/// worst-case, where the key function is *O*(*m*).
///
- /// If `K: Ord` does not implement a total order the resulting order is unspecified.
- /// All original elements will remain in the slice and any possible modifications via interior
- /// mutability are observed in the input. Same is true if `K: Ord` panics.
+ /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
+ /// order of elements in the slice is unspecified. All original elements will remain in the
+ /// slice and any possible modifications via interior mutability are observed in the input. Same
+ /// is true if the implementation of [`Ord`] for `K` panics.
///
/// # Current implementation
///
@@ -304,18 +309,21 @@ pub fn sort_by<F>(&mut self, mut compare: F)
/// handled without allocation, medium sized slices allocate `self.len()` and beyond that it
/// clamps at `self.len() / 2`.
///
- /// If `K: Ord` does not implement a total order, the implementation may panic.
+ /// # Panics
+ ///
+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
///
/// # Examples
///
/// ```
- /// let mut v = [-5i32, 4, 1, -3, 2];
+ /// let mut v = [4i32, -5, 1, -3, 2];
///
/// v.sort_by_key(|k| k.abs());
- /// assert!(v == [1, 2, -3, 4, -5]);
+ /// assert_eq!(v, [1, 2, -3, 4, -5]);
/// ```
///
/// [driftsort]: https://github.com/Voultapher/driftsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
@@ -337,9 +345,10 @@ pub fn sort_by_key<K, F>(&mut self, mut f: F)
/// storage to remember the results of key evaluation. The order of calls to the key function is
/// unspecified and may change in future versions of the standard library.
///
- /// If `K: Ord` does not implement a total order the resulting order is unspecified.
- /// All original elements will remain in the slice and any possible modifications via interior
- /// mutability are observed in the input. Same is true if `K: Ord` panics.
+ /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
+ /// order of elements in the slice is unspecified. All original elements will remain in the
+ /// slice and any possible modifications via interior mutability are observed in the input. Same
+ /// is true if the implementation of [`Ord`] for `K` panics.
///
/// For simple key functions (e.g., functions that are property accesses or basic operations),
/// [`sort_by_key`](slice::sort_by_key) is likely to be faster.
@@ -356,16 +365,22 @@ pub fn sort_by_key<K, F>(&mut self, mut f: F)
/// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the
/// length of the slice.
///
+ /// # Panics
+ ///
+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
+ ///
/// # Examples
///
/// ```
- /// let mut v = [-5i32, 4, 32, -3, 2];
+ /// let mut v = [4i32, -5, 1, -3, 2, 10];
///
+ /// // Strings are sorted by lexicographical order.
/// v.sort_by_cached_key(|k| k.to_string());
- /// assert!(v == [-3, -5, 2, 32, 4]);
+ /// assert_eq!(v, [-3, -5, 1, 10, 2, 4]);
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[cfg(not(no_global_oom_handling))]
#[rustc_allow_incoherent_impl]
#[stable(feature = "slice_sort_by_cached_key", since = "1.34.0")]
diff --git a/library/alloc/src/slice/tests.rs b/library/alloc/src/slice/tests.rs
index 0b972a1..786704c 100644
--- a/library/alloc/src/slice/tests.rs
+++ b/library/alloc/src/slice/tests.rs
@@ -1,18 +1,21 @@
+use core::cell::Cell;
+use core::cmp::Ordering::{self, Equal, Greater, Less};
+use core::convert::identity;
+use core::sync::atomic::AtomicUsize;
+use core::sync::atomic::Ordering::Relaxed;
+use core::{fmt, mem};
+use std::panic;
+
+use rand::distributions::Standard;
+use rand::prelude::*;
+use rand::{Rng, RngCore};
+
use crate::borrow::ToOwned;
use crate::rc::Rc;
use crate::string::ToString;
use crate::test_helpers::test_rng;
use crate::vec::Vec;
-use core::cell::Cell;
-use core::cmp::Ordering::{self, Equal, Greater, Less};
-use core::convert::identity;
-use core::fmt;
-use core::mem;
-use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
-use rand::{distributions::Standard, prelude::*, Rng, RngCore};
-use std::panic;
-
macro_rules! do_test {
($input:ident, $func:ident) => {
let len = $input.len();
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 94053ef..d7fba3a 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -9,19 +9,9 @@
use core::borrow::{Borrow, BorrowMut};
use core::iter::FusedIterator;
-use core::mem;
-use core::ptr;
-use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
-use core::unicode::conversions;
-
-use crate::borrow::ToOwned;
-use crate::boxed::Box;
-use crate::slice::{Concat, Join, SliceIndex};
-use crate::string::String;
-use crate::vec::Vec;
-
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::pattern;
+use core::str::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
#[stable(feature = "encode_utf16", since = "1.8.0")]
pub use core::str::EncodeUtf16;
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
@@ -55,6 +45,14 @@
pub use core::str::{RSplitTerminator, SplitTerminator};
#[stable(feature = "utf8_chunks", since = "1.79.0")]
pub use core::str::{Utf8Chunk, Utf8Chunks};
+use core::unicode::conversions;
+use core::{mem, ptr};
+
+use crate::borrow::ToOwned;
+use crate::boxed::Box;
+use crate::slice::{Concat, Join, SliceIndex};
+use crate::string::String;
+use crate::vec::Vec;
/// Note: `str` in `Concat<str>` is not meaningful here.
/// This type parameter of the trait only exists to enable another impl.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 0ff6616..1242308 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -43,8 +43,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
use core::error::Error;
-use core::fmt;
-use core::hash;
#[cfg(not(no_global_oom_handling))]
use core::iter::from_fn;
use core::iter::FusedIterator;
@@ -55,9 +53,8 @@
#[cfg(not(no_global_oom_handling))]
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{self, Range, RangeBounds};
-use core::ptr;
-use core::slice;
use core::str::pattern::Pattern;
+use core::{fmt, hash, ptr, slice};
#[cfg(not(no_global_oom_handling))]
use crate::alloc::Allocator;
@@ -903,7 +900,7 @@ pub fn from_utf16be_lossy(v: &[u8]) -> String {
/// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) };
/// assert_eq!(rebuilt, "hello");
/// ```
- #[must_use = "`self` will be dropped if the result is not used"]
+ #[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
pub fn into_raw_parts(self) -> (*mut u8, usize, usize) {
self.vec.into_raw_parts()
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index c36b8f6..2c0d19b 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -9,13 +9,10 @@
//! `#[cfg(target_has_atomic = "ptr")]`.
use core::any::Any;
-use core::borrow;
#[cfg(not(no_global_oom_handling))]
use core::clone::CloneToUninit;
use core::cmp::Ordering;
-use core::fmt;
use core::hash::{Hash, Hasher};
-use core::hint;
use core::intrinsics::abort;
#[cfg(not(no_global_oom_handling))]
use core::iter;
@@ -23,12 +20,13 @@
use core::mem::{self, align_of_val_raw, ManuallyDrop};
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
use core::panic::{RefUnwindSafe, UnwindSafe};
-use core::pin::Pin;
+use core::pin::{Pin, PinCoerceUnsized};
use core::ptr::{self, NonNull};
#[cfg(not(no_global_oom_handling))]
use core::slice::from_raw_parts_mut;
use core::sync::atomic;
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use core::{borrow, fmt, hint};
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
@@ -428,7 +426,7 @@ pub fn new(data: T) -> Arc<T> {
/// }
///
/// impl Gadget {
- /// /// Construct a reference counted Gadget.
+ /// /// Constructs a reference counted Gadget.
/// fn new() -> Arc<Self> {
/// // `me` is a `Weak<Gadget>` pointing at the new allocation of the
/// // `Arc` we're constructing.
@@ -438,7 +436,7 @@ pub fn new(data: T) -> Arc<T> {
/// })
/// }
///
- /// /// Return a reference counted pointer to Self.
+ /// /// Returns a reference counted pointer to Self.
/// fn me(&self) -> Arc<Self> {
/// self.me.upgrade().unwrap()
/// }
@@ -2144,6 +2142,12 @@ fn deref(&self) -> &T {
}
}
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Arc<T, A> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
+
#[unstable(feature = "deref_pure_trait", issue = "87121")]
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
@@ -2531,7 +2535,7 @@ fn drop(&mut self) {
}
impl<A: Allocator> Arc<dyn Any + Send + Sync, A> {
- /// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
+ /// Attempts to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
///
/// # Examples
///
@@ -3545,7 +3549,7 @@ fn from(t: T) -> Self {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T: Clone> From<&[T]> for Arc<[T]> {
- /// Allocate a reference-counted slice and fill it by cloning `v`'s items.
+ /// Allocates a reference-counted slice and fills it by cloning `v`'s items.
///
/// # Example
///
@@ -3564,7 +3568,7 @@ fn from(v: &[T]) -> Arc<[T]> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl From<&str> for Arc<str> {
- /// Allocate a reference-counted `str` and copy `v` into it.
+ /// Allocates a reference-counted `str` and copies `v` into it.
///
/// # Example
///
@@ -3583,7 +3587,7 @@ fn from(v: &str) -> Arc<str> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl From<String> for Arc<str> {
- /// Allocate a reference-counted `str` and copy `v` into it.
+ /// Allocates a reference-counted `str` and copies `v` into it.
///
/// # Example
///
@@ -3621,7 +3625,7 @@ fn from(v: Box<T, A>) -> Arc<T, A> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "shared_from_slice", since = "1.21.0")]
impl<T, A: Allocator + Clone> From<Vec<T, A>> for Arc<[T], A> {
- /// Allocate a reference-counted slice and move `v`'s items into it.
+ /// Allocates a reference-counted slice and moves `v`'s items into it.
///
/// # Example
///
@@ -3654,8 +3658,8 @@ impl<'a, B> From<Cow<'a, B>> for Arc<B>
B: ToOwned + ?Sized,
Arc<B>: From<&'a B> + From<B::Owned>,
{
- /// Create an atomically reference-counted pointer from
- /// a clone-on-write pointer by copying its content.
+ /// Creates an atomically reference-counted pointer from a clone-on-write
+ /// pointer by copying its content.
///
/// # Example
///
@@ -3811,7 +3815,7 @@ fn as_ref(&self) -> &T {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized, A: Allocator> Unpin for Arc<T, A> {}
-/// Get the offset within an `ArcInner` for the payload behind a pointer.
+/// Gets the offset within an `ArcInner` for the payload behind a pointer.
///
/// # Safety
///
@@ -3833,7 +3837,7 @@ fn data_offset_align(align: usize) -> usize {
layout.size() + layout.padding_needed_for(align)
}
-/// A unique owning pointer to a [`ArcInner`] **that does not imply the contents are initialized,**
+/// A unique owning pointer to an [`ArcInner`] **that does not imply the contents are initialized,**
/// but will deallocate it (without dropping the value) when dropped.
///
/// This is a helper for [`Arc::make_mut()`] to ensure correct cleanup on panic.
@@ -3846,7 +3850,7 @@ struct UniqueArcUninit<T: ?Sized, A: Allocator> {
#[cfg(not(no_global_oom_handling))]
impl<T: ?Sized, A: Allocator> UniqueArcUninit<T, A> {
- /// Allocate a ArcInner with layout suitable to contain `for_value` or a clone of it.
+ /// Allocates an ArcInner with layout suitable to contain `for_value` or a clone of it.
fn new(for_value: &T, alloc: A) -> UniqueArcUninit<T, A> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 1b123aa..d6b3de8 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -1,5 +1,3 @@
-use super::*;
-
use std::clone::Clone;
use std::mem::MaybeUninit;
use std::option::Option::None;
@@ -9,6 +7,8 @@
use std::sync::Mutex;
use std::thread;
+use super::*;
+
struct Canary(*mut AtomicUsize);
impl Drop for Canary {
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
index a3fa658..27589ae 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -7,14 +7,14 @@
//! This may be detected at compile time using
//! `#[cfg(target_has_atomic = "ptr")]`.
-use crate::rc::Rc;
use core::mem::ManuallyDrop;
-use core::task::{LocalWaker, RawWaker, RawWakerVTable};
-
-#[cfg(target_has_atomic = "ptr")]
-use crate::sync::Arc;
#[cfg(target_has_atomic = "ptr")]
use core::task::Waker;
+use core::task::{LocalWaker, RawWaker, RawWakerVTable};
+
+use crate::rc::Rc;
+#[cfg(target_has_atomic = "ptr")]
+use crate::sync::Arc;
/// The implementation of waking a task on an executor.
///
diff --git a/library/alloc/src/testing/crash_test.rs b/library/alloc/src/testing/crash_test.rs
index ff72f99..684bac6 100644
--- a/library/alloc/src/testing/crash_test.rs
+++ b/library/alloc/src/testing/crash_test.rs
@@ -1,6 +1,8 @@
-use crate::fmt::Debug; // the `Debug` trait is the only thing we use from `crate::fmt`
use std::cmp::Ordering;
-use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering::SeqCst;
+
+use crate::fmt::Debug; // the `Debug` trait is the only thing we use from `crate::fmt`
/// A blueprint for crash test dummy instances that monitor particular events.
/// Some instances may be configured to panic at some point.
diff --git a/library/alloc/src/tests.rs b/library/alloc/src/tests.rs
index ab256ce..b95d11c 100644
--- a/library/alloc/src/tests.rs
+++ b/library/alloc/src/tests.rs
@@ -2,7 +2,6 @@
use core::any::Any;
use core::ops::Deref;
-
use std::boxed::Box;
#[test]
diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs
index 3fe8324..c180917 100644
--- a/library/alloc/src/vec/cow.rs
+++ b/library/alloc/src/vec/cow.rs
@@ -1,6 +1,5 @@
-use crate::borrow::Cow;
-
use super::Vec;
+use crate::borrow::Cow;
#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs
index f0b6375..9362cef 100644
--- a/library/alloc/src/vec/drain.rs
+++ b/library/alloc/src/vec/drain.rs
@@ -1,4 +1,3 @@
-use crate::alloc::{Allocator, Global};
use core::fmt;
use core::iter::{FusedIterator, TrustedLen};
use core::mem::{self, ManuallyDrop, SizedTypeProperties};
@@ -6,6 +5,7 @@
use core::slice::{self};
use super::Vec;
+use crate::alloc::{Allocator, Global};
/// A draining iterator for `Vec<T>`.
///
diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs
index 118cfdb..72d51e8 100644
--- a/library/alloc/src/vec/extract_if.rs
+++ b/library/alloc/src/vec/extract_if.rs
@@ -1,8 +1,7 @@
-use crate::alloc::{Allocator, Global};
-use core::ptr;
-use core::slice;
+use core::{ptr, slice};
use super::Vec;
+use crate::alloc::{Allocator, Global};
/// An iterator which uses a closure to determine if an element should be removed.
///
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index 0dc193d..d119e6c 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -155,9 +155,7 @@
//! vec.truncate(write_idx);
//! ```
-use crate::alloc::{handle_alloc_error, Global};
-use core::alloc::Allocator;
-use core::alloc::Layout;
+use core::alloc::{Allocator, Layout};
use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, SizedTypeProperties};
@@ -165,6 +163,7 @@
use core::ptr;
use super::{InPlaceDrop, InPlaceDstDataSrcBufDrop, SpecFromIter, SpecFromIterNested, Vec};
+use crate::alloc::{handle_alloc_error, Global};
const fn in_place_collectible<DEST, SRC>(
step_merge: Option<NonZero<usize>>,
diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs
index 4050c25..27f7597 100644
--- a/library/alloc/src/vec/in_place_drop.rs
+++ b/library/alloc/src/vec/in_place_drop.rs
@@ -1,6 +1,5 @@
use core::marker::PhantomData;
-use core::ptr::NonNull;
-use core::ptr::{self, drop_in_place};
+use core::ptr::{self, drop_in_place, NonNull};
use core::slice::{self};
use crate::alloc::Global;
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 10f62e4..fad8aba 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -1,11 +1,3 @@
-#[cfg(not(no_global_oom_handling))]
-use super::AsVecIntoIter;
-use crate::alloc::{Allocator, Global};
-#[cfg(not(no_global_oom_handling))]
-use crate::collections::VecDeque;
-use crate::raw_vec::RawVec;
-use core::array;
-use core::fmt;
use core::iter::{
FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen,
TrustedRandomAccessNoCoerce,
@@ -17,6 +9,14 @@
use core::ops::Deref;
use core::ptr::{self, NonNull};
use core::slice::{self};
+use core::{array, fmt};
+
+#[cfg(not(no_global_oom_handling))]
+use super::AsVecIntoIter;
+use crate::alloc::{Allocator, Global};
+#[cfg(not(no_global_oom_handling))]
+use crate::collections::VecDeque;
+use crate::raw_vec::RawVec;
macro non_null {
(mut $place:expr, $t:ident) => {{
@@ -114,8 +114,9 @@ fn as_raw_mut_slice(&mut self) -> *mut [T] {
}
/// Drops remaining elements and relinquishes the backing allocation.
- /// This method guarantees it won't panic before relinquishing
- /// the backing allocation.
+ ///
+ /// This method guarantees it won't panic before relinquishing the backing
+ /// allocation.
///
/// This is roughly equivalent to the following, but more efficient
///
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index f63a6dd..b4e0bc5 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -66,15 +66,14 @@
use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};
+#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
+pub use self::extract_if::ExtractIf;
use crate::alloc::{Allocator, Global};
use crate::borrow::{Cow, ToOwned};
use crate::boxed::Box;
use crate::collections::TryReserveError;
use crate::raw_vec::RawVec;
-#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
-pub use self::extract_if::ExtractIf;
-
mod extract_if;
#[cfg(not(no_global_oom_handling))]
@@ -879,6 +878,7 @@ pub(crate) unsafe fn from_nonnull_in(
/// };
/// assert_eq!(rebuilt, [4294967295, 0, 1]);
/// ```
+ #[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
let mut me = ManuallyDrop::new(self);
@@ -922,6 +922,7 @@ pub fn into_raw_parts(self) -> (*mut T, usize, usize) {
/// };
/// assert_eq!(rebuilt, [4294967295, 0, 1]);
/// ```
+ #[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
// #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")]
pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) {
@@ -1711,6 +1712,12 @@ pub fn retain_mut<F>(&mut self, mut f: F)
F: FnMut(&mut T) -> bool,
{
let original_len = self.len();
+
+ if original_len == 0 {
+ // Empty case: explicit return allows better optimization, vs letting compiler infer it
+ return;
+ }
+
// Avoid double drop if the drop guard is not executed,
// since we may make some holes during the process.
unsafe { self.set_len(0) };
@@ -2373,9 +2380,11 @@ pub fn resize_with<F>(&mut self, new_len: usize, f: F)
}
/// Consumes and leaks the `Vec`, returning a mutable reference to the contents,
- /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime
- /// `'a`. If the type has only static references, or none at all, then this
- /// may be chosen to be `'static`.
+ /// `&'a mut [T]`.
+ ///
+ /// Note that the type `T` must outlive the chosen lifetime `'a`. If the type
+ /// has only static references, or none at all, then this may be chosen to be
+ /// `'static`.
///
/// As of Rust 1.57, this method does not reallocate or shrink the `Vec`,
/// so the leaked allocation may include unused capacity that is not part
@@ -3359,7 +3368,7 @@ fn as_mut(&mut self) -> &mut [T] {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> From<&[T]> for Vec<T> {
- /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+ /// Allocates a `Vec<T>` and fills it by cloning `s`'s items.
///
/// # Examples
///
@@ -3379,7 +3388,7 @@ fn from(s: &[T]) -> Vec<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_mut", since = "1.19.0")]
impl<T: Clone> From<&mut [T]> for Vec<T> {
- /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+ /// Allocates a `Vec<T>` and fills it by cloning `s`'s items.
///
/// # Examples
///
@@ -3399,7 +3408,7 @@ fn from(s: &mut [T]) -> Vec<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array_ref", since = "1.74.0")]
impl<T: Clone, const N: usize> From<&[T; N]> for Vec<T> {
- /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+ /// Allocates a `Vec<T>` and fills it by cloning `s`'s items.
///
/// # Examples
///
@@ -3414,7 +3423,7 @@ fn from(s: &mut [T]) -> Vec<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array_ref", since = "1.74.0")]
impl<T: Clone, const N: usize> From<&mut [T; N]> for Vec<T> {
- /// Allocate a `Vec<T>` and fill it by cloning `s`'s items.
+ /// Allocates a `Vec<T>` and fills it by cloning `s`'s items.
///
/// # Examples
///
@@ -3429,7 +3438,7 @@ fn from(s: &mut [T]) -> Vec<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array", since = "1.44.0")]
impl<T, const N: usize> From<[T; N]> for Vec<T> {
- /// Allocate a `Vec<T>` and move `s`'s items into it.
+ /// Allocates a `Vec<T>` and moves `s`'s items into it.
///
/// # Examples
///
@@ -3452,7 +3461,7 @@ impl<'a, T> From<Cow<'a, [T]>> for Vec<T>
where
[T]: ToOwned<Owned = Vec<T>>,
{
- /// Convert a clone-on-write slice into a vector.
+ /// Converts a clone-on-write slice into a vector.
///
/// If `s` already owns a `Vec<T>`, it will be returned directly.
/// If `s` is borrowing a slice, a new `Vec<T>` will be allocated and
@@ -3475,7 +3484,7 @@ fn from(s: Cow<'a, [T]>) -> Vec<T> {
#[cfg(not(test))]
#[stable(feature = "vec_from_box", since = "1.18.0")]
impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
- /// Convert a boxed slice into a vector by transferring ownership of
+ /// Converts a boxed slice into a vector by transferring ownership of
/// the existing heap allocation.
///
/// # Examples
@@ -3494,7 +3503,7 @@ fn from(s: Box<[T], A>) -> Self {
#[cfg(not(test))]
#[stable(feature = "box_from_vec", since = "1.20.0")]
impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
- /// Convert a vector into a boxed slice.
+ /// Converts a vector into a boxed slice.
///
/// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`].
///
@@ -3522,7 +3531,7 @@ fn from(v: Vec<T, A>) -> Self {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl From<&str> for Vec<u8> {
- /// Allocate a `Vec<u8>` and fill it with a UTF-8 string.
+ /// Allocates a `Vec<u8>` and fills it with a UTF-8 string.
///
/// # Examples
///
diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs
index b0cf725..5e620c4 100644
--- a/library/alloc/src/vec/partial_eq.rs
+++ b/library/alloc/src/vec/partial_eq.rs
@@ -1,9 +1,8 @@
+use super::Vec;
use crate::alloc::Allocator;
#[cfg(not(no_global_oom_handling))]
use crate::borrow::Cow;
-use super::Vec;
-
macro_rules! __impl_slice_eq1 {
([$($vars:tt)*] $lhs:ty, $rhs:ty $(where $ty:ty: $bound:ident)?, #[$stability:meta]) => {
#[$stability]
diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs
index e2f865d..7085bce 100644
--- a/library/alloc/src/vec/spec_extend.rs
+++ b/library/alloc/src/vec/spec_extend.rs
@@ -1,8 +1,8 @@
-use crate::alloc::Allocator;
use core::iter::TrustedLen;
use core::slice::{self};
use super::{IntoIter, Vec};
+use crate::alloc::Allocator;
// Specialization trait used for Vec::extend
pub(super) trait SpecExtend<T, I> {
diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs
index 01a6db1..96d701e 100644
--- a/library/alloc/src/vec/spec_from_elem.rs
+++ b/library/alloc/src/vec/spec_from_elem.rs
@@ -1,10 +1,9 @@
use core::ptr;
+use super::{IsZero, Vec};
use crate::alloc::Allocator;
use crate::raw_vec::RawVec;
-use super::{IsZero, Vec};
-
// Specialization trait used for Vec::from_elem
pub(super) trait SpecFromElem: Sized {
fn from_elem<A: Allocator>(elem: Self, n: usize, alloc: A) -> Vec<Self, A>;
diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs
index f915ebb..77f7761 100644
--- a/library/alloc/src/vec/spec_from_iter_nested.rs
+++ b/library/alloc/src/vec/spec_from_iter_nested.rs
@@ -1,10 +1,8 @@
-use core::cmp;
use core::iter::TrustedLen;
-use core::ptr;
-
-use crate::raw_vec::RawVec;
+use core::{cmp, ptr};
use super::{SpecExtend, Vec};
+use crate::raw_vec::RawVec;
/// Another specialization trait for Vec::from_iter
/// necessary to manually prioritize overlapping specializations
diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs
index 852fdcc..9e36377 100644
--- a/library/alloc/src/vec/splice.rs
+++ b/library/alloc/src/vec/splice.rs
@@ -1,8 +1,8 @@
-use crate::alloc::{Allocator, Global};
use core::ptr::{self};
use core::slice::{self};
use super::{Drain, Vec};
+use crate::alloc::{Allocator, Global};
/// A splicing iterator for `Vec`.
///
diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs
index c37a80d..dc27c57 100644
--- a/library/alloc/tests/arc.rs
+++ b/library/alloc/tests/arc.rs
@@ -227,3 +227,17 @@ fn make_mut_unsized() {
assert_eq!(*data, [11, 21, 31]);
assert_eq!(*other_data, [110, 20, 30]);
}
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+ use alloc::sync::Arc;
+ use core::pin::Pin;
+
+ pub trait MyTrait {}
+ impl MyTrait for String {}
+
+ // Pin coercion should work for Arc
+ pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> {
+ arg
+ }
+}
diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs
index 4cacee0..faee64b 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloc/tests/boxed.rs
@@ -179,3 +179,40 @@ fn by_ref(&self) -> &Self
self
}
}
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+ use alloc::boxed::Box;
+ use core::pin::Pin;
+
+ trait MyTrait {
+ fn action(&self) -> &str;
+ }
+ impl MyTrait for String {
+ fn action(&self) -> &str {
+ &*self
+ }
+ }
+ struct MyStruct;
+ impl MyTrait for MyStruct {
+ fn action(&self) -> &str {
+ "MyStruct"
+ }
+ }
+
+ // Pin coercion should work for Box
+ fn pin_box<T: MyTrait + 'static>(arg: Pin<Box<T>>) -> Pin<Box<dyn MyTrait>> {
+ arg
+ }
+
+ #[test]
+ fn pin_coerce_unsized_box() {
+ let my_string = "my string";
+ let a_string = Box::pin(String::from(my_string));
+ let pin_box_str = pin_box(a_string);
+ assert_eq!(pin_box_str.as_ref().action(), my_string);
+ let a_struct = Box::pin(MyStruct);
+ let pin_box_struct = pin_box(a_struct);
+ assert_eq!(pin_box_struct.as_ref().action(), "MyStruct");
+ }
+}
diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs
index ab275ac..71a3a14 100644
--- a/library/alloc/tests/btree_set_hash.rs
+++ b/library/alloc/tests/btree_set_hash.rs
@@ -1,6 +1,7 @@
-use crate::hash;
use std::collections::BTreeSet;
+use crate::hash;
+
#[test]
fn test_hash() {
let mut x = BTreeSet::new();
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 89538f2..3d4add6 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -40,6 +40,7 @@
#![feature(drain_keep_rest)]
#![feature(local_waker)]
#![feature(vec_pop_if)]
+#![feature(unique_rc_arc)]
#![allow(internal_features)]
#![deny(fuzzy_provenance_casts)]
#![deny(unsafe_op_in_unsafe_fn)]
diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs
index 499740e..29dbdcf 100644
--- a/library/alloc/tests/rc.rs
+++ b/library/alloc/tests/rc.rs
@@ -205,3 +205,20 @@ fn hmm<'a>(val: &'a mut Weak<&'a str>) -> Weak<&'a str> {
// `val` dropped here while still borrowed
// borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
}
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+ use alloc::rc::{Rc, UniqueRc};
+ use core::pin::Pin;
+
+ pub trait MyTrait {}
+ impl MyTrait for String {}
+
+ // Pin coercion should work for Rc
+ pub fn pin_rc(arg: Pin<Rc<String>>) -> Pin<Rc<dyn MyTrait>> {
+ arg
+ }
+ pub fn pin_unique_rc(arg: Pin<UniqueRc<String>>) -> Pin<UniqueRc<dyn MyTrait>> {
+ arg
+ }
+}
diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs
index c0f7a11..df5a8af 100644
--- a/library/alloc/tests/slice.rs
+++ b/library/alloc/tests/slice.rs
@@ -1,9 +1,7 @@
use std::cmp::Ordering::{Equal, Greater, Less};
use std::convert::identity;
-use std::fmt;
-use std::mem;
-use std::panic;
use std::rc::Rc;
+use std::{fmt, mem, panic};
fn square(n: usize) -> usize {
n * n
@@ -911,8 +909,7 @@ fn assert_tight_size_hints(mut it: impl Iterator, which: Bounds, ctx: impl fmt::
// become maximally long, so the size_hint upper bounds are tight
((|_| true) as fn(&_) -> _, Bounds::Upper),
] {
- use assert_tight_size_hints as a;
- use format_args as f;
+ use {assert_tight_size_hints as a, format_args as f};
a(v.split(p), b, "split");
a(v.split_mut(p), b, "split_mut");
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index de5d399..a6b1fe5 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -165,7 +165,8 @@ fn test_join_for_different_lengths_with_long_separator() {
#[test]
fn test_join_issue_80335() {
- use core::{borrow::Borrow, cell::Cell};
+ use core::borrow::Borrow;
+ use core::cell::Cell;
struct WeirdBorrow {
state: Cell<bool>,
diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs
index e20ceae..c5bc418 100644
--- a/library/alloc/tests/string.rs
+++ b/library/alloc/tests/string.rs
@@ -2,11 +2,9 @@
use std::borrow::Cow;
use std::cell::Cell;
use std::collections::TryReserveErrorKind::*;
-use std::ops::Bound;
use std::ops::Bound::*;
-use std::ops::RangeBounds;
-use std::panic;
-use std::str;
+use std::ops::{Bound, RangeBounds};
+use std::{panic, str};
pub trait IntoCow<'a, B: ?Sized>
where
diff --git a/library/alloc/tests/task.rs b/library/alloc/tests/task.rs
index 034039a..390dec1 100644
--- a/library/alloc/tests/task.rs
+++ b/library/alloc/tests/task.rs
@@ -4,7 +4,7 @@
use core::task::{LocalWaker, Waker};
#[test]
-#[cfg_attr(miri, should_panic)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it fails
+#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
fn test_waker_will_wake_clone() {
struct NoopWaker;
@@ -20,7 +20,7 @@ fn wake(self: Arc<Self>) {}
}
#[test]
-#[cfg_attr(miri, should_panic)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it fails
+#[cfg_attr(miri, ignore)] // `will_wake` doesn't guarantee that this test will work, and indeed on Miri it can fail
fn test_local_waker_will_wake_clone() {
struct NoopWaker;
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 71d7989..fd2ddbf 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -8,15 +8,14 @@
use std::cell::Cell;
use std::collections::TryReserveErrorKind::*;
use std::fmt::Debug;
-use std::hint;
use std::iter::InPlaceIterable;
-use std::mem;
use std::mem::{size_of, swap};
use std::ops::Bound::*;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::rc::Rc;
use std::sync::atomic::{AtomicU32, Ordering};
use std::vec::{Drain, IntoIter};
+use std::{hint, mem};
struct DropCounter<'a> {
count: &'a mut u32,
@@ -2572,7 +2571,8 @@ fn test_into_flattened_size_overflow() {
#[test]
fn test_box_zero_allocator() {
- use core::{alloc::AllocError, cell::RefCell};
+ use core::alloc::AllocError;
+ use core::cell::RefCell;
use std::collections::HashSet;
// Track ZST allocations and ensure that they all have a matching free.
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs
index cea5de4..db97212 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloc/tests/vec_deque.rs
@@ -1,16 +1,17 @@
use core::num::NonZero;
use std::assert_matches::assert_matches;
+use std::collections::vec_deque::Drain;
use std::collections::TryReserveErrorKind::*;
-use std::collections::{vec_deque::Drain, VecDeque};
+use std::collections::VecDeque;
use std::fmt::Debug;
use std::ops::Bound::*;
use std::panic::{catch_unwind, AssertUnwindSafe};
-use crate::hash;
-
use Taggy::*;
use Taggypar::*;
+use crate::hash;
+
#[test]
fn test_simple() {
let mut d = VecDeque::new();
diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs
index 8b516dd..c41d826 100644
--- a/library/alloc/tests/vec_deque_alloc_error.rs
+++ b/library/alloc/tests/vec_deque_alloc_error.rs
@@ -1,11 +1,9 @@
#![feature(alloc_error_hook, allocator_api)]
-use std::{
- alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System},
- collections::VecDeque,
- panic::{catch_unwind, AssertUnwindSafe},
- ptr::NonNull,
-};
+use std::alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System};
+use std::collections::VecDeque;
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::ptr::NonNull;
#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
diff --git a/library/core/benches/any.rs b/library/core/benches/any.rs
index 53099b7..f6be41b 100644
--- a/library/core/benches/any.rs
+++ b/library/core/benches/any.rs
@@ -1,4 +1,5 @@
use core::any::*;
+
use test::{black_box, Bencher};
#[bench]
diff --git a/library/core/benches/array.rs b/library/core/benches/array.rs
index d8cc44d..b1a41a0 100644
--- a/library/core/benches/array.rs
+++ b/library/core/benches/array.rs
@@ -1,5 +1,4 @@
-use test::black_box;
-use test::Bencher;
+use test::{black_box, Bencher};
macro_rules! map_array {
($func_name:ident, $start_item: expr, $map_item: expr, $arr_size: expr) => {
diff --git a/library/core/benches/ascii.rs b/library/core/benches/ascii.rs
index 71ec9fe..61bf8bb 100644
--- a/library/core/benches/ascii.rs
+++ b/library/core/benches/ascii.rs
@@ -64,8 +64,8 @@ fn $name(bencher: &mut Bencher) {
}
use std::fmt::Write;
-use test::black_box;
-use test::Bencher;
+
+use test::{black_box, Bencher};
const ASCII_CASE_MASK: u8 = 0b0010_0000;
diff --git a/library/core/benches/ascii/is_ascii.rs b/library/core/benches/ascii/is_ascii.rs
index a42a1dc..05f60a4 100644
--- a/library/core/benches/ascii/is_ascii.rs
+++ b/library/core/benches/ascii/is_ascii.rs
@@ -1,6 +1,6 @@
+use test::{black_box, Bencher};
+
use super::{LONG, MEDIUM, SHORT};
-use test::black_box;
-use test::Bencher;
macro_rules! benches {
($( fn $name: ident($arg: ident: &[u8]) $body: block )+) => {
diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs
index d1cdb12..906d7ac 100644
--- a/library/core/benches/fmt.rs
+++ b/library/core/benches/fmt.rs
@@ -1,5 +1,6 @@
use std::fmt::{self, Write as FmtWrite};
use std::io::{self, Write as IoWrite};
+
use test::{black_box, Bencher};
#[bench]
diff --git a/library/core/benches/hash/sip.rs b/library/core/benches/hash/sip.rs
index 725c864..8e8c07b 100644
--- a/library/core/benches/hash/sip.rs
+++ b/library/core/benches/hash/sip.rs
@@ -1,6 +1,7 @@
#![allow(deprecated)]
use core::hash::*;
+
use test::{black_box, Bencher};
fn hash_bytes<H: Hasher>(mut s: H, x: &[u8]) -> u64 {
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index c1cec5e..24469ba 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -3,6 +3,7 @@
use core::mem;
use core::num::Wrapping;
use core::ops::Range;
+
use test::{black_box, Bencher};
#[bench]
diff --git a/library/core/benches/num/flt2dec/mod.rs b/library/core/benches/num/flt2dec/mod.rs
index b1a9fc5..6c7de5d 100644
--- a/library/core/benches/num/flt2dec/mod.rs
+++ b/library/core/benches/num/flt2dec/mod.rs
@@ -3,9 +3,9 @@
mod grisu;
}
-use core::num::flt2dec::MAX_SIG_DIGITS;
-use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
+use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS};
use std::io::Write;
+
use test::{black_box, Bencher};
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/core/benches/num/flt2dec/strategy/dragon.rs
index babedc6..4526697 100644
--- a/library/core/benches/num/flt2dec/strategy/dragon.rs
+++ b/library/core/benches/num/flt2dec/strategy/dragon.rs
@@ -1,7 +1,8 @@
-use super::super::*;
use core::num::flt2dec::strategy::dragon::*;
use std::mem::MaybeUninit;
+use super::super::*;
+
#[bench]
fn bench_small_shortest(b: &mut Bencher) {
let decoded = decode_finite(3.141592f64);
diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs
index b5bddb2..d20f9b0 100644
--- a/library/core/benches/num/flt2dec/strategy/grisu.rs
+++ b/library/core/benches/num/flt2dec/strategy/grisu.rs
@@ -1,7 +1,8 @@
-use super::super::*;
use core::num::flt2dec::strategy::grisu::*;
use std::mem::MaybeUninit;
+use super::super::*;
+
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
match decode(v).1 {
FullDecoded::Finite(decoded) => decoded,
diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs
index 4922ee1..c1dc3a3 100644
--- a/library/core/benches/num/mod.rs
+++ b/library/core/benches/num/mod.rs
@@ -4,6 +4,7 @@
mod int_pow;
use std::str::FromStr;
+
use test::{black_box, Bencher};
const ASCII_NUMBERS: [&str; 19] = [
diff --git a/library/core/benches/ops.rs b/library/core/benches/ops.rs
index 0a2be8a2..3d0b330 100644
--- a/library/core/benches/ops.rs
+++ b/library/core/benches/ops.rs
@@ -1,4 +1,5 @@
use core::ops::*;
+
use test::Bencher;
// Overhead of dtors
diff --git a/library/core/benches/pattern.rs b/library/core/benches/pattern.rs
index 480ac6f..0d60b00 100644
--- a/library/core/benches/pattern.rs
+++ b/library/core/benches/pattern.rs
@@ -1,5 +1,4 @@
-use test::black_box;
-use test::Bencher;
+use test::{black_box, Bencher};
#[bench]
fn starts_with_char(b: &mut Bencher) {
diff --git a/library/core/benches/slice.rs b/library/core/benches/slice.rs
index 8f87a21..2741dbd 100644
--- a/library/core/benches/slice.rs
+++ b/library/core/benches/slice.rs
@@ -1,6 +1,6 @@
use core::ptr::NonNull;
-use test::black_box;
-use test::Bencher;
+
+use test::{black_box, Bencher};
enum Cache {
L1,
diff --git a/library/core/benches/str.rs b/library/core/benches/str.rs
index 0f14809..a8178f9 100644
--- a/library/core/benches/str.rs
+++ b/library/core/benches/str.rs
@@ -1,4 +1,5 @@
use std::str;
+
use test::{black_box, Bencher};
mod char_count;
diff --git a/library/core/benches/str/char_count.rs b/library/core/benches/str/char_count.rs
index 25d9b2e..b87ad0f 100644
--- a/library/core/benches/str/char_count.rs
+++ b/library/core/benches/str/char_count.rs
@@ -1,6 +1,7 @@
-use super::corpora::*;
use test::{black_box, Bencher};
+use super::corpora::*;
+
macro_rules! define_benches {
($( fn $name: ident($arg: ident: &str) $body: block )+) => {
define_benches!(mod en_tiny, en::TINY, $($name $arg $body)+);
diff --git a/library/core/benches/str/debug.rs b/library/core/benches/str/debug.rs
index cb91169..6dbf4e9 100644
--- a/library/core/benches/str/debug.rs
+++ b/library/core/benches/str/debug.rs
@@ -4,6 +4,7 @@
//! we should still try to minimize those calls over time rather than regress them.
use std::fmt::{self, Write};
+
use test::{black_box, Bencher};
#[derive(Default)]
diff --git a/library/core/benches/str/iter.rs b/library/core/benches/str/iter.rs
index 58ae71f..f6e73e4 100644
--- a/library/core/benches/str/iter.rs
+++ b/library/core/benches/str/iter.rs
@@ -1,6 +1,7 @@
-use super::corpora;
use test::{black_box, Bencher};
+use super::corpora;
+
#[bench]
fn chars_advance_by_1000(b: &mut Bencher) {
b.iter(|| black_box(corpora::ru::LARGE).chars().advance_by(1000));
diff --git a/library/core/src/alloc/global.rs b/library/core/src/alloc/global.rs
index 8df3ace..a6f799c 100644
--- a/library/core/src/alloc/global.rs
+++ b/library/core/src/alloc/global.rs
@@ -1,6 +1,5 @@
use crate::alloc::Layout;
-use crate::cmp;
-use crate::ptr;
+use crate::{cmp, ptr};
/// A memory allocator that can be registered as the standard library’s default
/// through the `#[global_allocator]` attribute.
@@ -118,7 +117,7 @@
/// having side effects.
#[stable(feature = "global_alloc", since = "1.28.0")]
pub unsafe trait GlobalAlloc {
- /// Allocate memory as described by the given `layout`.
+ /// Allocates memory as described by the given `layout`.
///
/// Returns a pointer to newly-allocated memory,
/// or null to indicate allocation failure.
@@ -153,7 +152,7 @@ pub unsafe trait GlobalAlloc {
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn alloc(&self, layout: Layout) -> *mut u8;
- /// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
+ /// Deallocates the block of memory at the given `ptr` pointer with the given `layout`.
///
/// # Safety
///
@@ -200,7 +199,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
ptr
}
- /// Shrink or grow a block of memory to the given `new_size` in bytes.
+ /// Shrinks or grows a block of memory to the given `new_size` in bytes.
/// The block is described by the given `ptr` pointer and `layout`.
///
/// If this returns a non-null pointer, then ownership of the memory block
@@ -232,7 +231,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
/// * `new_size` must be greater than zero.
///
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
- /// must not overflow isize (i.e., the rounded value must be less than or
+ /// must not overflow `isize` (i.e., the rounded value must be less than or
/// equal to `isize::MAX`).
///
/// (Extension subtraits might provide more specific bounds on
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index e96a414..549a4bc 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -4,11 +4,9 @@
// collections, resulting in having to optimize down excess IR multiple times.
// Your performance intuition is useless. Run perf.
-use crate::cmp;
use crate::error::Error;
-use crate::fmt;
-use crate::mem;
use crate::ptr::{Alignment, NonNull};
+use crate::{cmp, fmt, mem};
// While this function is used in one place and its implementation
// could be inlined, the previous attempts to do so made rustc
@@ -26,7 +24,7 @@ const fn size_align<T>() -> (usize, usize) {
/// You build a `Layout` up as an input to give to an allocator.
///
/// All layouts have an associated size and a power-of-two alignment. The size, when rounded up to
-/// the nearest multiple of `align`, does not overflow isize (i.e., the rounded value will always be
+/// the nearest multiple of `align`, does not overflow `isize` (i.e., the rounded value will always be
/// less than or equal to `isize::MAX`).
///
/// (Note that layouts are *not* required to have non-zero size,
@@ -61,7 +59,7 @@ impl Layout {
/// * `align` must be a power of two,
///
/// * `size`, when rounded up to the nearest multiple of `align`,
- /// must not overflow isize (i.e., the rounded value must be
+ /// must not overflow `isize` (i.e., the rounded value must be
/// less than or equal to `isize::MAX`).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index 1c8e667..aa841db 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -17,10 +17,8 @@
)]
#[allow(deprecated, deprecated_in_future)]
pub use self::layout::LayoutErr;
-
#[stable(feature = "alloc_layout_error", since = "1.50.0")]
pub use self::layout::LayoutError;
-
use crate::error::Error;
use crate::fmt;
use crate::ptr::{self, NonNull};
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 59f3b68..58107b1 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -86,9 +86,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::fmt;
-use crate::hash;
-use crate::intrinsics;
+use crate::{fmt, hash, intrinsics};
///////////////////////////////////////////////////////////////////////////////
// Any trait
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index 31d6bc3..d681bd1 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -4,6 +4,15 @@
#[stable(feature = "simd_arch", since = "1.27.0")]
pub use crate::core_arch::arch::*;
+#[cfg(bootstrap)]
+#[allow(dead_code)]
+#[unstable(feature = "sha512_sm_x86", issue = "126624")]
+fn dummy() {
+ // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs
+ // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a
+ // library feature until bootstrap gets bumped
+}
+
/// Inline assembly.
///
/// Refer to [Rust By Example] for a usage guide and the [reference] for
diff --git a/library/core/src/array/ascii.rs b/library/core/src/array/ascii.rs
index 3fea9a4..05797b0 100644
--- a/library/core/src/array/ascii.rs
+++ b/library/core/src/array/ascii.rs
@@ -2,7 +2,7 @@
#[cfg(not(test))]
impl<const N: usize> [u8; N] {
- /// Converts this array of bytes into a array of ASCII characters,
+ /// Converts this array of bytes into an array of ASCII characters,
/// or returns `None` if any of the characters is non-ASCII.
///
/// # Examples
@@ -29,7 +29,7 @@
}
}
- /// Converts this array of bytes into a array of ASCII characters,
+ /// Converts this array of bytes into an array of ASCII characters,
/// without checking whether they're valid.
///
/// # Safety
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 3585bf0..2d19e48 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -1,14 +1,11 @@
//! Defines the `IntoIter` owned iterator for arrays.
+use crate::intrinsics::transmute_unchecked;
+use crate::iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce};
+use crate::mem::MaybeUninit;
use crate::num::NonZero;
-use crate::{
- fmt,
- intrinsics::transmute_unchecked,
- iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce},
- mem::MaybeUninit,
- ops::{IndexRange, Range},
- ptr,
-};
+use crate::ops::{IndexRange, Range};
+use crate::{fmt, ptr};
/// A by-value [array] iterator.
#[stable(feature = "array_value_iter", since = "1.51.0")]
@@ -47,8 +44,10 @@ pub struct IntoIter<T, const N: usize> {
type IntoIter = IntoIter<T, N>;
/// Creates a consuming iterator, that is, one that moves each value out of
- /// the array (from start to end). The array cannot be used after calling
- /// this unless `T` implements `Copy`, so the whole array is copied.
+ /// the array (from start to end).
+ ///
+ /// The array cannot be used after calling this unless `T` implements
+ /// `Copy`, so the whole array is copied.
///
/// Arrays have special behavior when calling `.into_iter()` prior to the
/// 2021 edition -- see the [array] Editions section for more information.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 8285c64..61c713c 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -23,7 +23,6 @@
mod iter;
pub(crate) use drain::drain_array_with;
-
#[stable(feature = "array_value_iter", since = "1.51.0")]
pub use iter::IntoIter;
@@ -890,6 +889,7 @@ pub unsafe fn push_unchecked(&mut self, item: T) {
}
impl<T> Drop for Guard<'_, T> {
+ #[inline]
fn drop(&mut self) {
debug_assert!(self.initialized <= self.array_mut.len());
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index e9f4d0f..5b3711b 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -9,10 +9,9 @@
#![stable(feature = "core_ascii", since = "1.26.0")]
-use crate::escape;
-use crate::fmt;
use crate::iter::FusedIterator;
use crate::num::NonZero;
+use crate::{escape, fmt};
mod ascii_char;
#[unstable(feature = "ascii_char", issue = "110998")]
diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs
index 34a05ac..375358d 100644
--- a/library/core/src/ascii/ascii_char.rs
+++ b/library/core/src/ascii/ascii_char.rs
@@ -3,7 +3,7 @@
//! suggestions from rustc if you get anything slightly wrong in here, and overall
//! helps with clarity as we're also referring to `char` intentionally in here.
-use crate::fmt::{self, Write};
+use crate::fmt;
use crate::mem::transmute;
/// One of the 128 Unicode characters from U+0000 through U+007F,
@@ -583,9 +583,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[unstable(feature = "ascii_char", issue = "110998")]
impl fmt::Debug for AsciiChar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[inline]
- fn backslash(a: AsciiChar) -> ([AsciiChar; 4], u8) {
- ([AsciiChar::ReverseSolidus, a, AsciiChar::Null, AsciiChar::Null], 2)
+ use AsciiChar::{Apostrophe, Null, ReverseSolidus as Backslash};
+
+ fn backslash(a: AsciiChar) -> ([AsciiChar; 6], usize) {
+ ([Apostrophe, Backslash, a, Apostrophe, Null, Null], 4)
}
let (buf, len) = match self {
@@ -595,24 +596,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
AsciiChar::LineFeed => backslash(AsciiChar::SmallN),
AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus),
AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe),
- _ => {
- let byte = self.to_u8();
- if !byte.is_ascii_control() {
- ([*self, AsciiChar::Null, AsciiChar::Null, AsciiChar::Null], 1)
- } else {
- const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
+ _ if self.to_u8().is_ascii_control() => {
+ const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
- let hi = HEX_DIGITS[usize::from(byte >> 4)];
- let lo = HEX_DIGITS[usize::from(byte & 0xf)];
- ([AsciiChar::ReverseSolidus, AsciiChar::SmallX, hi, lo], 4)
- }
+ let byte = self.to_u8();
+ let hi = HEX_DIGITS[usize::from(byte >> 4)];
+ let lo = HEX_DIGITS[usize::from(byte & 0xf)];
+ ([Apostrophe, Backslash, AsciiChar::SmallX, hi, lo, Apostrophe], 6)
}
+ _ => ([Apostrophe, *self, Apostrophe, Null, Null, Null], 3),
};
- f.write_char('\'')?;
- for byte in &buf[..len as usize] {
- f.write_str(byte.as_str())?;
- }
- f.write_char('\'')
+ f.write_str(buf[..len].as_str())
}
}
diff --git a/library/core/src/asserting.rs b/library/core/src/asserting.rs
index 212b637..3015aa5 100644
--- a/library/core/src/asserting.rs
+++ b/library/core/src/asserting.rs
@@ -9,10 +9,8 @@
#![doc(hidden)]
#![unstable(feature = "generic_assert_internals", issue = "44838")]
-use crate::{
- fmt::{Debug, Formatter},
- marker::PhantomData,
-};
+use crate::fmt::{Debug, Formatter};
+use crate::marker::PhantomData;
// ***** TryCapture - Generic *****
diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs
index a0ffb6d..069c50c 100644
--- a/library/core/src/async_iter/async_iter.rs
+++ b/library/core/src/async_iter/async_iter.rs
@@ -18,7 +18,7 @@ pub trait AsyncIterator {
/// The type of items yielded by the async iterator.
type Item;
- /// Attempt to pull out the next value of this async iterator, registering the
+ /// Attempts to pull out the next value of this async iterator, registering the
/// current task for wakeup if the value is not yet available, and returning
/// `None` if the async iterator is exhausted.
///
@@ -139,7 +139,7 @@ pub fn async_gen_ready(t: T) -> Self {
pub const FINISHED: Self = Poll::Ready(None);
}
-/// Convert something into an async iterator
+/// Converts something into an async iterator
#[unstable(feature = "async_iterator", issue = "79024")]
pub trait IntoAsyncIterator {
/// The type of the item yielded by the iterator
diff --git a/library/core/src/async_iter/from_iter.rs b/library/core/src/async_iter/from_iter.rs
index 3180187..f4e10bd 100644
--- a/library/core/src/async_iter/from_iter.rs
+++ b/library/core/src/async_iter/from_iter.rs
@@ -1,6 +1,5 @@
-use crate::pin::Pin;
-
use crate::async_iter::AsyncIterator;
+use crate::pin::Pin;
use crate::task::{Context, Poll};
/// An async iterator that was created from iterator.
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index b3189f1..d860f34 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -255,6 +255,7 @@
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
+use crate::pin::PinCoerceUnsized;
use crate::ptr::{self, NonNull};
mod lazy;
@@ -427,7 +428,9 @@ pub fn set(&self, val: T) {
}
/// Swaps the values of two `Cell`s.
- /// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference.
+ ///
+ /// The difference with `std::mem::swap` is that this function doesn't
+ /// require a `&mut` reference.
///
/// # Panics
///
@@ -1579,7 +1582,7 @@ pub fn map_split<U: ?Sized, V: ?Sized, F>(orig: Ref<'b, T>, f: F) -> (Ref<'b, U>
)
}
- /// Convert into a reference to the underlying data.
+ /// Converts into a reference to the underlying data.
///
/// The underlying `RefCell` can never be mutably borrowed from again and will always appear
/// already immutably borrowed. It is not a good idea to leak more than a constant number of
@@ -1747,7 +1750,7 @@ pub fn map_split<U: ?Sized, V: ?Sized, F>(
)
}
- /// Convert into a mutable reference to the underlying data.
+ /// Converts into a mutable reference to the underlying data.
///
/// The underlying `RefCell` can not be borrowed from again and will always appear already
/// mutably borrowed, making the returned reference the only to the interior.
@@ -1879,7 +1882,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
///
/// If you have a reference `&T`, then normally in Rust the compiler performs optimizations based on
/// the knowledge that `&T` points to immutable data. Mutating that data, for example through an
-/// alias or by transmuting an `&T` into an `&mut T`, is considered undefined behavior.
+/// alias or by transmuting a `&T` into a `&mut T`, is considered undefined behavior.
/// `UnsafeCell<T>` opts-out of the immutability guarantee for `&T`: a shared reference
/// `&UnsafeCell<T>` may point to data that is being mutated. This is called "interior mutability".
///
@@ -1936,7 +1939,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// to have multiple `&mut UnsafeCell<T>` aliases. That is, `UnsafeCell` is a wrapper
/// designed to have a special interaction with _shared_ accesses (_i.e._, through an
/// `&UnsafeCell<_>` reference); there is no magic whatsoever when dealing with _exclusive_
-/// accesses (_e.g._, through an `&mut UnsafeCell<_>`): neither the cell nor the wrapped value
+/// accesses (_e.g._, through a `&mut UnsafeCell<_>`): neither the cell nor the wrapped value
/// may be aliased for the duration of that `&mut` borrow.
/// This is showcased by the [`.get_mut()`] accessor, which is a _safe_ getter that yields
/// a `&mut T`.
@@ -2394,3 +2397,21 @@ fn assert_coerce_unsized(
let _: Cell<&dyn Send> = c;
let _: RefCell<&dyn Send> = d;
}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for SyncUnsafeCell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<'b, T: ?Sized> PinCoerceUnsized for RefMut<'b, T> {}
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index 21452d4..6ec1d2a 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -1,8 +1,7 @@
+use super::UnsafeCell;
use crate::ops::Deref;
use crate::{fmt, mem};
-use super::UnsafeCell;
-
enum State<T, F> {
Uninit(F),
Init(T),
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index 872b4da..097fa86 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -1,6 +1,5 @@
use crate::cell::UnsafeCell;
-use crate::fmt;
-use crate::mem;
+use crate::{fmt, mem};
/// A cell which can nominally be written to only once.
///
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 4186565..41a1966 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1,12 +1,11 @@
//! impl char {}
+use super::*;
use crate::slice;
use crate::str::from_utf8_unchecked_mut;
use crate::unicode::printable::is_printable;
use crate::unicode::{self, conversions};
-use super::*;
-
impl char {
/// The lowest valid code point a `char` can have, `'\0'`.
///
@@ -223,10 +222,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
/// assert_eq!('❤', c);
/// ```
#[stable(feature = "assoc_char_funcs", since = "1.52.0")]
- #[rustc_const_stable(
- feature = "const_char_from_u32_unchecked",
- since = "CURRENT_RUSTC_VERSION"
- )]
+ #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
#[must_use]
#[inline]
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 37c27ec..e6574ac 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -42,14 +42,13 @@
#[rustfmt::skip]
use crate::ascii;
+pub(crate) use self::methods::EscapeDebugExtArgs;
use crate::error::Error;
use crate::escape;
use crate::fmt::{self, Write};
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::num::NonZero;
-pub(crate) use self::methods::EscapeDebugExtArgs;
-
// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
@@ -126,7 +125,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`].
/// instead.
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
-#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
#[must_use]
#[inline]
pub const unsafe fn from_u32_unchecked(i: u32) -> char {
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index cff7587..a1ed993 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -246,15 +246,14 @@
)]
#[rustc_diagnostic_item = "PartialEq"]
pub trait PartialEq<Rhs: ?Sized = Self> {
- /// This method tests for `self` and `other` values to be equal, and is used
- /// by `==`.
+ /// Tests for `self` and `other` values to be equal, and is used by `==`.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "cmp_partialeq_eq"]
fn eq(&self, other: &Rhs) -> bool;
- /// This method tests for `!=`. The default implementation is almost always
- /// sufficient, and should not be overridden without very good reason.
+ /// Tests for `!=`. The default implementation is almost always sufficient,
+ /// and should not be overridden without very good reason.
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1163,7 +1162,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
#[rustc_diagnostic_item = "cmp_partialord_cmp"]
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
- /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ /// Tests less than (for `self` and `other`) and is used by the `<` operator.
///
/// # Examples
///
@@ -1180,8 +1179,8 @@ fn lt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Less))
}
- /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
- /// operator.
+ /// Tests less than or equal to (for `self` and `other`) and is used by the
+ /// `<=` operator.
///
/// # Examples
///
@@ -1198,7 +1197,8 @@ fn le(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Less | Equal))
}
- /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ /// Tests greater than (for `self` and `other`) and is used by the `>`
+ /// operator.
///
/// # Examples
///
@@ -1215,8 +1215,8 @@ fn gt(&self, other: &Rhs) -> bool {
matches!(self.partial_cmp(other), Some(Greater))
}
- /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
- /// operator.
+ /// Tests greater than or equal to (for `self` and `other`) and is used by
+ /// the `>=` operator.
///
/// # Examples
///
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 86c4ea9..0246d06 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -208,7 +208,7 @@ macro_rules! impl_try_from_unbounded {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
- /// Try to create the target number type from a source
+ /// Tries to create the target number type from a source
/// number type. This returns an error if the source value
/// is outside of the range of the target type.
#[inline]
@@ -226,7 +226,7 @@ macro_rules! impl_try_from_lower_bounded {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
- /// Try to create the target number type from a source
+ /// Tries to create the target number type from a source
/// number type. This returns an error if the source value
/// is outside of the range of the target type.
#[inline]
@@ -248,7 +248,7 @@ macro_rules! impl_try_from_upper_bounded {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
- /// Try to create the target number type from a source
+ /// Tries to create the target number type from a source
/// number type. This returns an error if the source value
/// is outside of the range of the target type.
#[inline]
@@ -270,7 +270,7 @@ macro_rules! impl_try_from_both_bounded {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
- /// Try to create the target number type from a source
+ /// Tries to create the target number type from a source
/// number type. This returns an error if the source value
/// is outside of the range of the target type.
#[inline]
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 4524b35..5cacedc 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -103,6 +103,7 @@
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
pub trait Default: Sized {
/// Returns the "default value" for a type.
///
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 19b7bb4..6cc9184 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -1,5 +1,5 @@
#![doc = include_str!("error.md")]
-#![stable(feature = "error_in_core", since = "CURRENT_RUSTC_VERSION")]
+#![stable(feature = "error_in_core", since = "1.81.0")]
#[cfg(test)]
mod tests;
@@ -30,7 +30,7 @@
#[rustc_has_incoherent_inherent_impls]
#[allow(multiple_supertrait_upcastable)]
pub trait Error: Debug + Display {
- /// The lower-level source of this error, if any.
+ /// Returns the lower-level source of this error, if any.
///
/// # Examples
///
@@ -121,7 +121,7 @@ fn cause(&self) -> Option<&dyn Error> {
self.source()
}
- /// Provides type based access to context intended for error reports.
+ /// Provides type-based access to context intended for error reports.
///
/// Used in conjunction with [`Request::provide_value`] and [`Request::provide_ref`] to extract
/// references to member variables from `dyn Error` trait objects.
@@ -353,7 +353,7 @@ pub fn sources(&self) -> Source<'_> {
}
}
-/// Request a value of type `T` from the given `impl Error`.
+/// Requests a value of type `T` from the given `impl Error`.
///
/// # Examples
///
@@ -376,7 +376,7 @@ pub fn request_value<'a, T>(err: &'a (impl Error + ?Sized)) -> Option<T>
request_by_type_tag::<'a, tags::Value<T>>(err)
}
-/// Request a reference of type `T` from the given `impl Error`.
+/// Requests a reference of type `T` from the given `impl Error`.
///
/// # Examples
///
@@ -510,7 +510,7 @@ fn request_by_type_tag<'a, I>(err: &'a (impl Error + ?Sized)) -> Option<I::Reifi
pub struct Request<'a>(Tagged<dyn Erased<'a> + 'a>);
impl<'a> Request<'a> {
- /// Provide a value or other type with only static lifetimes.
+ /// Provides a value or other type with only static lifetimes.
///
/// # Examples
///
@@ -544,7 +544,7 @@ pub fn provide_value<T>(&mut self, value: T) -> &mut Self
self.provide::<tags::Value<T>>(value)
}
- /// Provide a value or other type with only static lifetimes computed using a closure.
+ /// Provides a value or other type with only static lifetimes computed using a closure.
///
/// # Examples
///
@@ -578,7 +578,7 @@ pub fn provide_value_with<T>(&mut self, fulfil: impl FnOnce() -> T) -> &mut Self
self.provide_with::<tags::Value<T>>(fulfil)
}
- /// Provide a reference. The referee type must be bounded by `'static`,
+ /// Provides a reference. The referee type must be bounded by `'static`,
/// but may be unsized.
///
/// # Examples
@@ -610,7 +610,7 @@ pub fn provide_ref<T: ?Sized + 'static>(&mut self, value: &'a T) -> &mut Self {
self.provide::<tags::Ref<tags::MaybeSizedValue<T>>>(value)
}
- /// Provide a reference computed using a closure. The referee type
+ /// Provides a reference computed using a closure. The referee type
/// must be bounded by `'static`, but may be unsized.
///
/// # Examples
@@ -652,7 +652,7 @@ pub fn provide_ref_with<T: ?Sized + 'static>(
self.provide_with::<tags::Ref<tags::MaybeSizedValue<T>>>(fulfil)
}
- /// Provide a value with the given `Type` tag.
+ /// Provides a value with the given `Type` tag.
fn provide<I>(&mut self, value: I::Reified) -> &mut Self
where
I: tags::Type<'a>,
@@ -663,7 +663,7 @@ fn provide<I>(&mut self, value: I::Reified) -> &mut Self
self
}
- /// Provide a value with the given `Type` tag, using a closure to prevent unnecessary work.
+ /// Provides a value with the given `Type` tag, using a closure to prevent unnecessary work.
fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self
where
I: tags::Type<'a>,
@@ -674,13 +674,13 @@ fn provide_with<I>(&mut self, fulfil: impl FnOnce() -> I::Reified) -> &mut Self
self
}
- /// Check if the `Request` would be satisfied if provided with a
+ /// Checks if the `Request` would be satisfied if provided with a
/// value of the specified type. If the type does not match or has
/// already been provided, returns false.
///
/// # Examples
///
- /// Check if an `u8` still needs to be provided and then provides
+ /// Checks if a `u8` still needs to be provided and then provides
/// it.
///
/// ```rust
@@ -761,13 +761,14 @@ pub fn would_be_satisfied_by_value_of<T>(&self) -> bool
self.would_be_satisfied_by::<tags::Value<T>>()
}
- /// Check if the `Request` would be satisfied if provided with a
- /// reference to a value of the specified type. If the type does
- /// not match or has already been provided, returns false.
+ /// Checks if the `Request` would be satisfied if provided with a
+ /// reference to a value of the specified type.
+ ///
+ /// If the type does not match or has already been provided, returns false.
///
/// # Examples
///
- /// Check if a `&str` still needs to be provided and then provides
+ /// Checks if a `&str` still needs to be provided and then provides
/// it.
///
/// ```rust
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index ae42ae3..22084dc 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -3,16 +3,11 @@
use crate::cmp::Ordering;
use crate::error::Error;
use crate::ffi::c_char;
-use crate::fmt;
-use crate::intrinsics;
use crate::iter::FusedIterator;
use crate::marker::PhantomData;
-use crate::ops;
-use crate::ptr::addr_of;
-use crate::ptr::NonNull;
-use crate::slice;
+use crate::ptr::{addr_of, NonNull};
use crate::slice::memchr;
-use crate::str;
+use crate::{fmt, intrinsics, ops, slice, str};
// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link
// depends on where the item is being documented. however, since this is libcore, we can't
@@ -277,7 +272,7 @@ impl CStr {
#[inline] // inline is necessary for codegen to see strlen.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
// SAFETY: The caller has provided a pointer that points to a valid C
// string with a NUL terminator less than `isize::MAX` from `ptr`.
@@ -539,7 +534,7 @@ const fn as_non_null_ptr(&self) -> NonNull<c_char> {
#[must_use]
#[doc(alias("len", "strlen"))]
#[stable(feature = "cstr_count_bytes", since = "1.79.0")]
- #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "CURRENT_RUSTC_VERSION")]
+ #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
pub const fn count_bytes(&self) -> usize {
self.inner.len() - 1
}
@@ -734,7 +729,7 @@ fn as_ref(&self) -> &CStr {
/// located within `isize::MAX` from `ptr`.
#[inline]
#[unstable(feature = "cstr_internals", issue = "none")]
-#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
#[rustc_allow_const_fn_unstable(const_eval_select)]
const unsafe fn strlen(ptr: *const c_char) -> usize {
const fn strlen_ct(s: *const c_char) -> usize {
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 93426b9..ec1f905 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -9,19 +9,16 @@
#![stable(feature = "core_ffi", since = "1.30.0")]
#![allow(non_camel_case_types)]
-use crate::fmt;
-
-#[doc(no_inline)]
-#[stable(feature = "core_c_str", since = "1.64.0")]
-pub use self::c_str::FromBytesWithNulError;
-
-#[doc(no_inline)]
-#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
-pub use self::c_str::FromBytesUntilNulError;
-
#[doc(inline)]
#[stable(feature = "core_c_str", since = "1.64.0")]
pub use self::c_str::CStr;
+#[doc(no_inline)]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+pub use self::c_str::FromBytesUntilNulError;
+#[doc(no_inline)]
+#[stable(feature = "core_c_str", since = "1.64.0")]
+pub use self::c_str::FromBytesWithNulError;
+use crate::fmt;
#[unstable(feature = "c_str_module", issue = "112134")]
pub mod c_str;
diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs
index f4c7462..3a224e4 100644
--- a/library/core/src/ffi/va_list.rs
+++ b/library/core/src/ffi/va_list.rs
@@ -3,7 +3,6 @@
//! Better known as "varargs".
use crate::ffi::c_void;
-
#[allow(unused_imports)]
use crate::fmt;
use crate::marker::PhantomData;
@@ -162,7 +161,7 @@ pub struct VaList<'a, 'f: 'a> {
windows,
))]
impl<'f> VaListImpl<'f> {
- /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
+ /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
@@ -182,7 +181,7 @@ pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
not(windows),
))]
impl<'f> VaListImpl<'f> {
- /// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
+ /// Converts a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
VaList { inner: self, _marker: PhantomData }
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 794ca18..467fa17 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -1018,7 +1018,8 @@ fn is_pretty(&self) -> bool {
}
}
-/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
+/// Creates a type whose [`fmt::Debug`] and [`fmt::Display`] impls are provided with the function
+/// `f`.
///
/// # Examples
///
@@ -1030,17 +1031,25 @@ fn is_pretty(&self) -> bool {
/// assert_eq!(format!("{}", value), "a");
/// assert_eq!(format!("{:?}", value), "'a'");
///
-/// let wrapped = fmt::FormatterFn(|f| write!(f, "{value:?}"));
+/// let wrapped = fmt::from_fn(|f| write!(f, "{value:?}"));
/// assert_eq!(format!("{}", wrapped), "'a'");
/// assert_eq!(format!("{:?}", wrapped), "'a'");
/// ```
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
-pub struct FormatterFn<F>(pub F)
+pub fn from_fn<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result>(f: F) -> FromFn<F> {
+ FromFn(f)
+}
+
+/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
+///
+/// Created with [`from_fn`].
+#[unstable(feature = "debug_closure_helpers", issue = "117729")]
+pub struct FromFn<F>(F)
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
-impl<F> fmt::Debug for FormatterFn<F>
+impl<F> fmt::Debug for FromFn<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
{
@@ -1050,7 +1059,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
#[unstable(feature = "debug_closure_helpers", issue = "117729")]
-impl<F> fmt::Display for FormatterFn<F>
+impl<F> fmt::Display for FromFn<F>
where
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
{
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 80c45fc..20ea035 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -1,7 +1,6 @@
use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp};
use crate::mem::MaybeUninit;
-use crate::num::flt2dec;
-use crate::num::fmt as numfmt;
+use crate::num::{flt2dec, fmt as numfmt};
#[doc(hidden)]
trait GeneralFormat: PartialOrd {
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 25ab5b2..485ad4a 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -4,13 +4,10 @@
use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
use crate::char::EscapeDebugExtArgs;
-use crate::iter;
use crate::marker::PhantomData;
-use crate::mem;
use crate::num::fmt as numfmt;
use crate::ops::Deref;
-use crate::result;
-use crate::str;
+use crate::{iter, mem, result, str};
mod builders;
#[cfg(not(no_fp_fmt_parse))]
@@ -36,12 +33,11 @@ pub enum Alignment {
Center,
}
+#[unstable(feature = "debug_closure_helpers", issue = "117729")]
+pub use self::builders::{from_fn, FromFn};
#[stable(feature = "debug_builders", since = "1.2.0")]
pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
-#[unstable(feature = "debug_closure_helpers", issue = "117729")]
-pub use self::builders::FormatterFn;
-
/// The type returned by formatter methods.
///
/// # Examples
@@ -354,7 +350,7 @@ pub fn new_v1<const P: usize, const A: usize>(
Arguments { pieces, fmt: None, args }
}
- /// This function is used to specify nonstandard formatting parameters.
+ /// Specifies nonstandard formatting parameters.
///
/// An `rt::UnsafeArg` is required because the following invariants must be held
/// in order for this function to be safe:
@@ -396,7 +392,7 @@ pub fn estimated_capacity(&self) -> usize {
}
impl<'a> Arguments<'a> {
- /// Get the formatted string, if it has no arguments to be formatted at runtime.
+ /// Gets the formatted string, if it has no arguments to be formatted at runtime.
///
/// This can be used to avoid allocations in some cases.
///
@@ -1129,8 +1125,8 @@ pub trait UpperExp {
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}
-/// The `write` function takes an output stream, and an `Arguments` struct
-/// that can be precompiled with the `format_args!` macro.
+/// Takes an output stream and an `Arguments` struct that can be precompiled with
+/// the `format_args!` macro.
///
/// The arguments will be formatted according to the specified format string
/// into the output stream provided.
@@ -1257,7 +1253,7 @@ fn new(fill: char, padding: usize) -> PostPadding {
PostPadding { fill, padding }
}
- /// Write this post padding.
+ /// Writes this post padding.
pub(crate) fn write(self, f: &mut Formatter<'_>) -> Result {
for _ in 0..self.padding {
f.buf.write_char(self.fill)?;
@@ -1398,9 +1394,10 @@ fn write_prefix(f: &mut Formatter<'_>, sign: Option<char>, prefix: Option<&str>)
}
}
- /// This function takes a string slice and emits it to the internal buffer
- /// after applying the relevant formatting flags specified. The flags
- /// recognized for generic strings are:
+ /// Takes a string slice and emits it to the internal buffer after applying
+ /// the relevant formatting flags specified.
+ ///
+ /// The flags recognized for generic strings are:
///
/// * width - the minimum width of what to emit
/// * fill/align - what to emit and where to emit it if the string
@@ -1474,9 +1471,10 @@ pub fn pad(&mut self, s: &str) -> Result {
}
}
- /// Write the pre-padding and return the unwritten post-padding. Callers are
- /// responsible for ensuring post-padding is written after the thing that is
- /// being padded.
+ /// Writes the pre-padding and returns the unwritten post-padding.
+ ///
+ /// Callers are responsible for ensuring post-padding is written after the
+ /// thing that is being padded.
pub(crate) fn padding(
&mut self,
padding: usize,
@@ -1503,6 +1501,7 @@ pub(crate) fn padding(
}
/// Takes the formatted parts and applies the padding.
+ ///
/// Assumes that the caller already has rendered the parts with required precision,
/// so that `self.precision` can be ignored.
///
@@ -1655,7 +1654,7 @@ pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {
}
}
- /// Flags for formatting
+ /// Returns flags for formatting.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(
@@ -1667,7 +1666,7 @@ pub fn flags(&self) -> u32 {
self.flags
}
- /// Character used as 'fill' whenever there is alignment.
+ /// Returns the character used as 'fill' whenever there is alignment.
///
/// # Examples
///
@@ -1700,7 +1699,7 @@ pub fn fill(&self) -> char {
self.fill
}
- /// Flag indicating what form of alignment was requested.
+ /// Returns a flag indicating what form of alignment was requested.
///
/// # Examples
///
@@ -1740,7 +1739,7 @@ pub fn align(&self) -> Option<Alignment> {
}
}
- /// Optionally specified integer width that the output should be.
+ /// Returns the optionally specified integer width that the output should be.
///
/// # Examples
///
@@ -1770,8 +1769,8 @@ pub fn width(&self) -> Option<usize> {
self.width
}
- /// Optionally specified precision for numeric types. Alternatively, the
- /// maximum width for string types.
+ /// Returns the optionally specified precision for numeric types.
+ /// Alternatively, the maximum width for string types.
///
/// # Examples
///
@@ -1967,8 +1966,9 @@ pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {
builders::debug_struct_new(self, name)
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_struct_fields_finish` is more general, but this is faster for 1 field.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_struct_fields_finish` is more general, but this is
+ /// faster for 1 field.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_struct_field1_finish<'b>(
@@ -1982,8 +1982,9 @@ pub fn debug_struct_field1_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_struct_fields_finish` is more general, but this is faster for 2 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_struct_fields_finish` is more general, but this is
+ /// faster for 2 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_struct_field2_finish<'b>(
@@ -2000,8 +2001,9 @@ pub fn debug_struct_field2_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_struct_fields_finish` is more general, but this is faster for 3 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_struct_fields_finish` is more general, but this is
+ /// faster for 3 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_struct_field3_finish<'b>(
@@ -2021,8 +2023,9 @@ pub fn debug_struct_field3_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_struct_fields_finish` is more general, but this is faster for 4 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_struct_fields_finish` is more general, but this is
+ /// faster for 4 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_struct_field4_finish<'b>(
@@ -2045,8 +2048,9 @@ pub fn debug_struct_field4_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_struct_fields_finish` is more general, but this is faster for 5 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_struct_fields_finish` is more general, but this is
+ /// faster for 5 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_struct_field5_finish<'b>(
@@ -2072,7 +2076,7 @@ pub fn debug_struct_field5_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller binaries.
/// For the cases not covered by `debug_struct_field[12345]_finish`.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
@@ -2121,8 +2125,9 @@ pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {
builders::debug_tuple_new(self, name)
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_tuple_fields_finish` is more general, but this is faster for 1 field.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_tuple_fields_finish` is more general, but this is faster
+ /// for 1 field.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_tuple_field1_finish<'b>(&'b mut self, name: &str, value1: &dyn Debug) -> Result {
@@ -2131,8 +2136,9 @@ pub fn debug_tuple_field1_finish<'b>(&'b mut self, name: &str, value1: &dyn Debu
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_tuple_fields_finish` is more general, but this is faster for 2 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_tuple_fields_finish` is more general, but this is faster
+ /// for 2 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_tuple_field2_finish<'b>(
@@ -2147,8 +2153,9 @@ pub fn debug_tuple_field2_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_tuple_fields_finish` is more general, but this is faster for 3 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_tuple_fields_finish` is more general, but this is faster
+ /// for 3 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_tuple_field3_finish<'b>(
@@ -2165,8 +2172,9 @@ pub fn debug_tuple_field3_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_tuple_fields_finish` is more general, but this is faster for 4 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_tuple_fields_finish` is more general, but this is faster
+ /// for 4 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_tuple_field4_finish<'b>(
@@ -2185,8 +2193,9 @@ pub fn debug_tuple_field4_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// `debug_tuple_fields_finish` is more general, but this is faster for 5 fields.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. `debug_tuple_fields_finish` is more general, but this is faster
+ /// for 5 fields.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_tuple_field5_finish<'b>(
@@ -2207,8 +2216,8 @@ pub fn debug_tuple_field5_finish<'b>(
builder.finish()
}
- /// Used to shrink `derive(Debug)` code, for faster compilation and smaller binaries.
- /// For the cases not covered by `debug_tuple_field[12345]_finish`.
+ /// Shrinks `derive(Debug)` code, for faster compilation and smaller
+ /// binaries. For the cases not covered by `debug_tuple_field[12345]_finish`.
#[doc(hidden)]
#[unstable(feature = "fmt_helpers_for_derive", issue = "none")]
pub fn debug_tuple_fields_finish<'b>(
@@ -2496,8 +2505,9 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
}
}
-/// Since the formatting will be identical for all pointer types, use a non-monomorphized
-/// implementation for the actual formatting to reduce the amount of codegen work needed.
+/// Since the formatting will be identical for all pointer types, uses a
+/// non-monomorphized implementation for the actual formatting to reduce the
+/// amount of codegen work needed.
///
/// This uses `ptr_addr: usize` and not `ptr: *const ()` to be able to use this for
/// `fn(...) -> ...` without using [problematic] "Oxford Casts".
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index 3a5a5af..e7726da 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -1,12 +1,9 @@
//! Integer and floating-point number formatting
-use crate::fmt;
use crate::mem::MaybeUninit;
use crate::num::fmt as numfmt;
use crate::ops::{Div, Rem, Sub};
-use crate::ptr;
-use crate::slice;
-use crate::str;
+use crate::{fmt, ptr, slice, str};
#[doc(hidden)]
trait DisplayInt:
diff --git a/library/core/src/future/async_drop.rs b/library/core/src/future/async_drop.rs
index 63193bb..8971a2c 100644
--- a/library/core/src/future/async_drop.rs
+++ b/library/core/src/future/async_drop.rs
@@ -205,7 +205,7 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
}
}
-/// Construct a chain of two futures, which awaits them sequentially as
+/// Constructs a chain of two futures, which awaits them sequentially as
/// a future.
#[lang = "async_drop_chain"]
async fn chain<F, G>(first: F, last: G)
@@ -235,8 +235,8 @@ async fn chain<F, G>(first: F, last: G)
///
/// # Safety
///
-/// User should carefully manage returned future, since it would
-/// try creating an immutable referece from `this` and get pointee's
+/// Users should carefully manage the returned future, since it would
+/// try creating an immutable reference from `this` and get pointee's
/// discriminant.
// FIXME(zetanumbers): Send and Sync impls
#[lang = "async_drop_either"]
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index c80cfdc..ca1c2d1 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -38,7 +38,7 @@ pub trait Future {
#[lang = "future_output"]
type Output;
- /// Attempt to resolve the future to a final value, registering
+ /// Attempts to resolve the future to a final value, registering
/// the current task for wakeup if the value is not yet available.
///
/// # Return value
diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs
index eb5a9b7..aa546b9 100644
--- a/library/core/src/future/into_future.rs
+++ b/library/core/src/future/into_future.rs
@@ -40,7 +40,7 @@
/// }
///
/// impl Multiply {
-/// /// Construct a new instance of `Multiply`.
+/// /// Constructs a new instance of `Multiply`.
/// pub fn new(num: u16, factor: u16) -> Self {
/// Self { num, factor }
/// }
@@ -89,7 +89,7 @@
/// ```rust
/// use std::future::IntoFuture;
///
-/// /// Convert the output of a future to a string.
+/// /// Converts the output of a future to a string.
/// async fn fut_to_string<Fut>(fut: Fut) -> String
/// where
/// Fut: IntoFuture,
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 3a1451a..d188f1c 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -20,25 +20,21 @@
mod poll_fn;
mod ready;
-#[stable(feature = "futures_api", since = "1.36.0")]
-pub use self::future::Future;
-
-#[unstable(feature = "future_join", issue = "91642")]
-pub use self::join::join;
-
+#[unstable(feature = "async_drop", issue = "126482")]
+pub use async_drop::{async_drop, async_drop_in_place, AsyncDrop, AsyncDropInPlace};
#[stable(feature = "into_future", since = "1.64.0")]
pub use into_future::IntoFuture;
-
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub use pending::{pending, Pending};
+#[stable(feature = "future_poll_fn", since = "1.64.0")]
+pub use poll_fn::{poll_fn, PollFn};
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
pub use ready::{ready, Ready};
-#[stable(feature = "future_poll_fn", since = "1.64.0")]
-pub use poll_fn::{poll_fn, PollFn};
-
-#[unstable(feature = "async_drop", issue = "126482")]
-pub use async_drop::{async_drop, async_drop_in_place, AsyncDrop, AsyncDropInPlace};
+#[stable(feature = "futures_api", since = "1.36.0")]
+pub use self::future::Future;
+#[unstable(feature = "future_join", issue = "91642")]
+pub use self::join::join;
/// This type is needed because:
///
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index da73446..061690e 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -83,17 +83,14 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::fmt;
-use crate::marker;
-
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::sip::SipHasher;
-
#[unstable(feature = "hashmap_internals", issue = "none")]
#[allow(deprecated)]
#[doc(hidden)]
pub use self::sip::SipHasher13;
+use crate::{fmt, marker};
mod sip;
@@ -806,10 +803,8 @@ fn eq(&self, _other: &BuildHasherDefault<H>) -> bool {
impl<H> Eq for BuildHasherDefault<H> {}
mod impls {
- use crate::mem;
- use crate::slice;
-
use super::*;
+ use crate::{mem, slice};
macro_rules! impl_write {
($(($ty:ident, $meth:ident),)*) => {$(
diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs
index 0d1ac64..17f2caa 100644
--- a/library/core/src/hash/sip.rs
+++ b/library/core/src/hash/sip.rs
@@ -2,10 +2,8 @@
#![allow(deprecated)] // the types in this module are deprecated
-use crate::cmp;
use crate::marker::PhantomData;
-use crate::mem;
-use crate::ptr;
+use crate::{cmp, mem, ptr};
/// An implementation of SipHash 1-3.
///
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index b3e36e6..6ca5e53 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -3,8 +3,7 @@
//! Hints to compiler that affects how code should be emitted or optimized.
//! Hints may be compile time or runtime.
-use crate::intrinsics;
-use crate::ub_checks;
+use crate::{intrinsics, ub_checks};
/// Informs the compiler that the site which is calling this function is not
/// reachable, possibly enabling further optimizations.
@@ -195,8 +194,8 @@
#[track_caller]
#[inline(always)]
#[doc(alias = "assume")]
-#[stable(feature = "hint_assert_unchecked", since = "CURRENT_RUSTC_VERSION")]
-#[rustc_const_stable(feature = "hint_assert_unchecked", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "hint_assert_unchecked", since = "1.81.0")]
+#[rustc_const_stable(feature = "hint_assert_unchecked", since = "1.81.0")]
pub const unsafe fn assert_unchecked(cond: bool) {
// SAFETY: The caller promised `cond` is true.
unsafe {
diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs
index bf53b22..fe4fa80 100644
--- a/library/core/src/internal_macros.rs
+++ b/library/core/src/internal_macros.rs
@@ -80,7 +80,7 @@ fn $method(&mut self, other: &$u) {
}
}
-/// Create a zero-size type similar to a closure type, but named.
+/// Creates a zero-size type similar to a closure type, but named.
macro_rules! impl_fn_for_zst {
($(
$( #[$attr: meta] )*
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index c4c6388..bd99e90 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -63,10 +63,8 @@
)]
#![allow(missing_docs)]
-use crate::marker::DiscriminantKind;
-use crate::marker::Tuple;
-use crate::ptr;
-use crate::ub_checks;
+use crate::marker::{DiscriminantKind, Tuple};
+use crate::{ptr, ub_checks};
pub mod mir;
pub mod simd;
@@ -1010,6 +1008,34 @@ pub const fn unlikely(b: bool) -> bool {
b
}
+/// Returns either `true_val` or `false_val` depending on condition `b` with a
+/// hint to the compiler that this condition is unlikely to be correctly
+/// predicted by a CPU's branch predictor (e.g. a binary search).
+///
+/// This is otherwise functionally equivalent to `if b { true_val } else { false_val }`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// This intrinsic does not have a stable counterpart.
+#[cfg(not(bootstrap))]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[miri::intrinsic_fallback_is_spec]
+#[inline]
+pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
+ if b { true_val } else { false_val }
+}
+
+#[cfg(bootstrap)]
+#[inline]
+pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
+ if b { true_val } else { false_val }
+}
+
extern "rust-intrinsic" {
/// Executes a breakpoint trap, for inspection by a debugger.
///
@@ -1017,45 +1043,6 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_nounwind]
pub fn breakpoint();
- #[cfg(bootstrap)]
- #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
- #[rustc_safe_intrinsic]
- #[rustc_nounwind]
- pub fn size_of<T>() -> usize;
-
- #[cfg(bootstrap)]
- #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
- #[rustc_safe_intrinsic]
- #[rustc_nounwind]
- pub fn min_align_of<T>() -> usize;
-
- #[cfg(bootstrap)]
- #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
- #[rustc_nounwind]
- pub fn pref_align_of<T>() -> usize;
-
- #[cfg(bootstrap)]
- #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
- #[rustc_nounwind]
- pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
-
- #[cfg(bootstrap)]
- #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
- #[rustc_nounwind]
- pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
-
- #[cfg(bootstrap)]
- #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
- #[rustc_safe_intrinsic]
- #[rustc_nounwind]
- pub fn type_name<T: ?Sized>() -> &'static str;
-
- #[cfg(bootstrap)]
- #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
- #[rustc_safe_intrinsic]
- #[rustc_nounwind]
- pub fn type_id<T: ?Sized + 'static>() -> u128;
-
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
/// This will statically either panic, or do nothing.
///
@@ -1252,7 +1239,7 @@ pub const fn unlikely(b: bool) -> bool {
/// - If the code actually wants to work on the address the pointer points to, it can use `as`
/// casts or [`ptr.addr()`][pointer::addr].
///
- /// Turning a `*mut T` into an `&mut T`:
+ /// Turning a `*mut T` into a `&mut T`:
///
/// ```
/// let ptr: *mut i32 = &mut 0;
@@ -1264,7 +1251,7 @@ pub const fn unlikely(b: bool) -> bool {
/// let ref_casted = unsafe { &mut *ptr };
/// ```
///
- /// Turning an `&mut T` into an `&mut U`:
+ /// Turning a `&mut T` into a `&mut U`:
///
/// ```
/// let ptr = &mut 0;
@@ -1277,7 +1264,7 @@ pub const fn unlikely(b: bool) -> bool {
/// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
/// ```
///
- /// Turning an `&str` into a `&[u8]`:
+ /// Turning a `&str` into a `&[u8]`:
///
/// ```
/// // this is not a good way to do this.
@@ -1363,7 +1350,7 @@ pub const fn unlikely(b: bool) -> bool {
/// }
///
/// // This gets rid of the type safety problems; `&mut *` will *only* give
- /// // you an `&mut T` from an `&mut T` or `*mut T`.
+ /// // you a `&mut T` from a `&mut T` or `*mut T`.
/// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
/// -> (&mut [T], &mut [T]) {
/// let len = slice.len();
@@ -1541,6 +1528,12 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"]
pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
+ /// Returns the square root of an `f16`
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::sqrt`](../../std/primitive.f16.html#method.sqrt)
+ #[rustc_nounwind]
+ pub fn sqrtf16(x: f16) -> f16;
/// Returns the square root of an `f32`
///
/// The stabilized version of this intrinsic is
@@ -1553,6 +1546,12 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::sqrt`](../../std/primitive.f64.html#method.sqrt)
#[rustc_nounwind]
pub fn sqrtf64(x: f64) -> f64;
+ /// Returns the square root of an `f128`
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::sqrt`](../../std/primitive.f128.html#method.sqrt)
+ #[rustc_nounwind]
+ pub fn sqrtf128(x: f128) -> f128;
/// Raises an `f16` to an integer power.
///
@@ -1579,6 +1578,12 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_nounwind]
pub fn powif128(a: f128, x: i32) -> f128;
+ /// Returns the sine of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::sin`](../../std/primitive.f16.html#method.sin)
+ #[rustc_nounwind]
+ pub fn sinf16(x: f16) -> f16;
/// Returns the sine of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1591,7 +1596,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::sin`](../../std/primitive.f64.html#method.sin)
#[rustc_nounwind]
pub fn sinf64(x: f64) -> f64;
+ /// Returns the sine of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::sin`](../../std/primitive.f128.html#method.sin)
+ #[rustc_nounwind]
+ pub fn sinf128(x: f128) -> f128;
+ /// Returns the cosine of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::cos`](../../std/primitive.f16.html#method.cos)
+ #[rustc_nounwind]
+ pub fn cosf16(x: f16) -> f16;
/// Returns the cosine of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1604,7 +1621,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::cos`](../../std/primitive.f64.html#method.cos)
#[rustc_nounwind]
pub fn cosf64(x: f64) -> f64;
+ /// Returns the cosine of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::cos`](../../std/primitive.f128.html#method.cos)
+ #[rustc_nounwind]
+ pub fn cosf128(x: f128) -> f128;
+ /// Raises an `f16` to an `f16` power.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::powf`](../../std/primitive.f16.html#method.powf)
+ #[rustc_nounwind]
+ pub fn powf16(a: f16, x: f16) -> f16;
/// Raises an `f32` to an `f32` power.
///
/// The stabilized version of this intrinsic is
@@ -1617,7 +1646,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::powf`](../../std/primitive.f64.html#method.powf)
#[rustc_nounwind]
pub fn powf64(a: f64, x: f64) -> f64;
+ /// Raises an `f128` to an `f128` power.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::powf`](../../std/primitive.f128.html#method.powf)
+ #[rustc_nounwind]
+ pub fn powf128(a: f128, x: f128) -> f128;
+ /// Returns the exponential of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::exp`](../../std/primitive.f16.html#method.exp)
+ #[rustc_nounwind]
+ pub fn expf16(x: f16) -> f16;
/// Returns the exponential of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1630,7 +1671,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::exp`](../../std/primitive.f64.html#method.exp)
#[rustc_nounwind]
pub fn expf64(x: f64) -> f64;
+ /// Returns the exponential of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::exp`](../../std/primitive.f128.html#method.exp)
+ #[rustc_nounwind]
+ pub fn expf128(x: f128) -> f128;
+ /// Returns 2 raised to the power of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::exp2`](../../std/primitive.f16.html#method.exp2)
+ #[rustc_nounwind]
+ pub fn exp2f16(x: f16) -> f16;
/// Returns 2 raised to the power of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1643,7 +1696,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::exp2`](../../std/primitive.f64.html#method.exp2)
#[rustc_nounwind]
pub fn exp2f64(x: f64) -> f64;
+ /// Returns 2 raised to the power of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::exp2`](../../std/primitive.f128.html#method.exp2)
+ #[rustc_nounwind]
+ pub fn exp2f128(x: f128) -> f128;
+ /// Returns the natural logarithm of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::ln`](../../std/primitive.f16.html#method.ln)
+ #[rustc_nounwind]
+ pub fn logf16(x: f16) -> f16;
/// Returns the natural logarithm of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1656,7 +1721,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::ln`](../../std/primitive.f64.html#method.ln)
#[rustc_nounwind]
pub fn logf64(x: f64) -> f64;
+ /// Returns the natural logarithm of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::ln`](../../std/primitive.f128.html#method.ln)
+ #[rustc_nounwind]
+ pub fn logf128(x: f128) -> f128;
+ /// Returns the base 10 logarithm of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::log10`](../../std/primitive.f16.html#method.log10)
+ #[rustc_nounwind]
+ pub fn log10f16(x: f16) -> f16;
/// Returns the base 10 logarithm of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1669,7 +1746,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::log10`](../../std/primitive.f64.html#method.log10)
#[rustc_nounwind]
pub fn log10f64(x: f64) -> f64;
+ /// Returns the base 10 logarithm of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::log10`](../../std/primitive.f128.html#method.log10)
+ #[rustc_nounwind]
+ pub fn log10f128(x: f128) -> f128;
+ /// Returns the base 2 logarithm of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::log2`](../../std/primitive.f16.html#method.log2)
+ #[rustc_nounwind]
+ pub fn log2f16(x: f16) -> f16;
/// Returns the base 2 logarithm of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1682,7 +1771,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::log2`](../../std/primitive.f64.html#method.log2)
#[rustc_nounwind]
pub fn log2f64(x: f64) -> f64;
+ /// Returns the base 2 logarithm of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::log2`](../../std/primitive.f128.html#method.log2)
+ #[rustc_nounwind]
+ pub fn log2f128(x: f128) -> f128;
+ /// Returns `a * b + c` for `f16` values.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add)
+ #[rustc_nounwind]
+ pub fn fmaf16(a: f16, b: f16, c: f16) -> f16;
/// Returns `a * b + c` for `f32` values.
///
/// The stabilized version of this intrinsic is
@@ -1695,7 +1796,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add)
#[rustc_nounwind]
pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
+ /// Returns `a * b + c` for `f128` values.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add)
+ #[rustc_nounwind]
+ pub fn fmaf128(a: f128, b: f128, c: f128) -> f128;
+ /// Returns the absolute value of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::abs`](../../std/primitive.f16.html#method.abs)
+ #[rustc_nounwind]
+ pub fn fabsf16(x: f16) -> f16;
/// Returns the absolute value of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1708,7 +1821,25 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::abs`](../../std/primitive.f64.html#method.abs)
#[rustc_nounwind]
pub fn fabsf64(x: f64) -> f64;
+ /// Returns the absolute value of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::abs`](../../std/primitive.f128.html#method.abs)
+ #[rustc_nounwind]
+ pub fn fabsf128(x: f128) -> f128;
+ /// Returns the minimum of two `f16` values.
+ ///
+ /// Note that, unlike most intrinsics, this is safe to call;
+ /// it does not require an `unsafe` block.
+ /// Therefore, implementations must not require the user to uphold
+ /// any safety invariants.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::min`]
+ #[rustc_safe_intrinsic]
+ #[rustc_nounwind]
+ pub fn minnumf16(x: f16, y: f16) -> f16;
/// Returns the minimum of two `f32` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
@@ -1733,6 +1864,31 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn minnumf64(x: f64, y: f64) -> f64;
+ /// Returns the minimum of two `f128` values.
+ ///
+ /// Note that, unlike most intrinsics, this is safe to call;
+ /// it does not require an `unsafe` block.
+ /// Therefore, implementations must not require the user to uphold
+ /// any safety invariants.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::min`]
+ #[rustc_safe_intrinsic]
+ #[rustc_nounwind]
+ pub fn minnumf128(x: f128, y: f128) -> f128;
+
+ /// Returns the maximum of two `f16` values.
+ ///
+ /// Note that, unlike most intrinsics, this is safe to call;
+ /// it does not require an `unsafe` block.
+ /// Therefore, implementations must not require the user to uphold
+ /// any safety invariants.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::max`]
+ #[rustc_safe_intrinsic]
+ #[rustc_nounwind]
+ pub fn maxnumf16(x: f16, y: f16) -> f16;
/// Returns the maximum of two `f32` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
@@ -1757,7 +1913,25 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn maxnumf64(x: f64, y: f64) -> f64;
+ /// Returns the maximum of two `f128` values.
+ ///
+ /// Note that, unlike most intrinsics, this is safe to call;
+ /// it does not require an `unsafe` block.
+ /// Therefore, implementations must not require the user to uphold
+ /// any safety invariants.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::max`]
+ #[rustc_safe_intrinsic]
+ #[rustc_nounwind]
+ pub fn maxnumf128(x: f128, y: f128) -> f128;
+ /// Copies the sign from `y` to `x` for `f16` values.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
+ #[rustc_nounwind]
+ pub fn copysignf16(x: f16, y: f16) -> f16;
/// Copies the sign from `y` to `x` for `f32` values.
///
/// The stabilized version of this intrinsic is
@@ -1770,7 +1944,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign)
#[rustc_nounwind]
pub fn copysignf64(x: f64, y: f64) -> f64;
+ /// Copies the sign from `y` to `x` for `f128` values.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
+ #[rustc_nounwind]
+ pub fn copysignf128(x: f128, y: f128) -> f128;
+ /// Returns the largest integer less than or equal to an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::floor`](../../std/primitive.f16.html#method.floor)
+ #[rustc_nounwind]
+ pub fn floorf16(x: f16) -> f16;
/// Returns the largest integer less than or equal to an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1783,7 +1969,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::floor`](../../std/primitive.f64.html#method.floor)
#[rustc_nounwind]
pub fn floorf64(x: f64) -> f64;
+ /// Returns the largest integer less than or equal to an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::floor`](../../std/primitive.f128.html#method.floor)
+ #[rustc_nounwind]
+ pub fn floorf128(x: f128) -> f128;
+ /// Returns the smallest integer greater than or equal to an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
+ #[rustc_nounwind]
+ pub fn ceilf16(x: f16) -> f16;
/// Returns the smallest integer greater than or equal to an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1796,7 +1994,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
#[rustc_nounwind]
pub fn ceilf64(x: f64) -> f64;
+ /// Returns the smallest integer greater than or equal to an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
+ #[rustc_nounwind]
+ pub fn ceilf128(x: f128) -> f128;
+ /// Returns the integer part of an `f16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
+ #[rustc_nounwind]
+ pub fn truncf16(x: f16) -> f16;
/// Returns the integer part of an `f32`.
///
/// The stabilized version of this intrinsic is
@@ -1809,7 +2019,25 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
#[rustc_nounwind]
pub fn truncf64(x: f64) -> f64;
+ /// Returns the integer part of an `f128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
+ #[rustc_nounwind]
+ pub fn truncf128(x: f128) -> f128;
+ /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust,
+ /// so this rounds half-way cases to the number with an even least significant digit.
+ ///
+ /// May raise an inexact floating-point exception if the argument is not an integer.
+ /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+ /// cannot actually be utilized from Rust code.
+ /// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
+ #[rustc_nounwind]
+ pub fn rintf16(x: f16) -> f16;
/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit.
///
@@ -1834,7 +2062,25 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
#[rustc_nounwind]
pub fn rintf64(x: f64) -> f64;
+ /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
+ /// so this rounds half-way cases to the number with an even least significant digit.
+ ///
+ /// May raise an inexact floating-point exception if the argument is not an integer.
+ /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+ /// cannot actually be utilized from Rust code.
+ /// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
+ #[rustc_nounwind]
+ pub fn rintf128(x: f128) -> f128;
+ /// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust,
+ /// so this rounds half-way cases to the number with an even least significant digit.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ #[rustc_nounwind]
+ pub fn nearbyintf16(x: f16) -> f16;
/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust,
/// so this rounds half-way cases to the number with an even least significant digit.
///
@@ -1847,7 +2093,19 @@ pub const fn unlikely(b: bool) -> bool {
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
pub fn nearbyintf64(x: f64) -> f64;
+ /// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust,
+ /// so this rounds half-way cases to the number with an even least significant digit.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ #[rustc_nounwind]
+ pub fn nearbyintf128(x: f128) -> f128;
+ /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f16::round`](../../std/primitive.f16.html#method.round)
+ #[rustc_nounwind]
+ pub fn roundf16(x: f16) -> f16;
/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
///
/// The stabilized version of this intrinsic is
@@ -1860,7 +2118,19 @@ pub const fn unlikely(b: bool) -> bool {
/// [`f64::round`](../../std/primitive.f64.html#method.round)
#[rustc_nounwind]
pub fn roundf64(x: f64) -> f64;
+ /// Returns the nearest integer to an `f128`. Rounds half-way cases away from zero.
+ ///
+ /// The stabilized version of this intrinsic is
+ /// [`f128::round`](../../std/primitive.f128.html#method.round)
+ #[rustc_nounwind]
+ pub fn roundf128(x: f128) -> f128;
+ /// Returns the nearest integer to an `f16`. Rounds half-way cases to the number
+ /// with an even least significant digit.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ #[rustc_nounwind]
+ pub fn roundevenf16(x: f16) -> f16;
/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number
/// with an even least significant digit.
///
@@ -1873,6 +2143,12 @@ pub const fn unlikely(b: bool) -> bool {
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
pub fn roundevenf64(x: f64) -> f64;
+ /// Returns the nearest integer to an `f128`. Rounds half-way cases to the number
+ /// with an even least significant digit.
+ ///
+ /// This intrinsic does not have a stable counterpart.
+ #[rustc_nounwind]
+ pub fn roundevenf128(x: f128) -> f128;
/// Float addition that allows optimizations based on algebraic rules.
/// May assume inputs are finite.
@@ -1944,7 +2220,7 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_safe_intrinsic]
pub fn frem_algebraic<T: Copy>(a: T, b: T) -> T;
- /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range
+ /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range
/// (<https://github.com/rust-lang/rust/issues/10184>)
///
/// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
@@ -2385,12 +2661,6 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_nounwind]
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
- #[cfg(bootstrap)]
- #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
- #[rustc_safe_intrinsic]
- #[rustc_nounwind]
- pub fn variant_count<T>() -> usize;
-
/// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
/// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
///
@@ -2405,12 +2675,12 @@ pub const fn unlikely(b: bool) -> bool {
#[rustc_nounwind]
pub fn catch_unwind(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32;
- /// Emits a `!nontemporal` store according to LLVM (see their docs).
- /// Probably will never become stable.
+ /// Emits a `nontemporal` store, which gives a hint to the CPU that the data should not be held
+ /// in cache. Except for performance, this is fully equivalent to `ptr.write(val)`.
///
- /// Do NOT use this intrinsic; "nontemporal" operations do not exist in our memory model!
- /// It exists to support current stdarch, but the plan is to change stdarch and remove this intrinsic.
- /// See <https://github.com/rust-lang/rust/issues/114582> for some more discussion.
+ /// Not all architectures provide such an operation. For instance, x86 does not: while `MOVNT`
+ /// exists, that operation is *not* equivalent to `ptr.write(val)` (`MOVNT` writes can be reordered
+ /// in ways that are not allowed for regular writes).
#[rustc_nounwind]
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
@@ -2455,11 +2725,13 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 {
///
/// # Safety
///
- /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carry a
- /// pointer value.
+ /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized.
/// Note that this is a stricter criterion than just the *values* being
/// fully-initialized: if `T` has padding, it's UB to call this intrinsic.
///
+ /// At compile-time, it is furthermore UB to call this if any of the bytes
+ /// in `*a` or `*b` have provenance.
+ ///
/// (The implementation is allowed to branch on the results of comparisons,
/// which is UB if any of their inputs are `undef`.)
#[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
@@ -2768,7 +3040,6 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize {
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const fn size_of<T>() -> usize {
unreachable!()
}
@@ -2786,7 +3057,6 @@ pub const fn size_of<T>() -> usize {
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const fn min_align_of<T>() -> usize {
unreachable!()
}
@@ -2800,7 +3070,6 @@ pub const fn min_align_of<T>() -> usize {
#[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const unsafe fn pref_align_of<T>() -> usize {
unreachable!()
}
@@ -2819,7 +3088,6 @@ pub const fn min_align_of<T>() -> usize {
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const fn variant_count<T>() -> usize {
unreachable!()
}
@@ -2836,7 +3104,6 @@ pub const fn variant_count<T>() -> usize {
#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
unreachable!()
}
@@ -2853,7 +3120,6 @@ pub const fn variant_count<T>() -> usize {
#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
unreachable!()
}
@@ -2871,7 +3137,6 @@ pub const fn variant_count<T>() -> usize {
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const fn type_name<T: ?Sized>() -> &'static str {
unreachable!()
}
@@ -2891,7 +3156,6 @@ pub const fn type_name<T: ?Sized>() -> &'static str {
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
pub const fn type_id<T: ?Sized + 'static>() -> u128 {
unreachable!()
}
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 1daf1d7..c7cec39 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -247,6 +247,8 @@
//! otherwise branch.
//! - [`Call`] has an associated function as well, with special syntax:
//! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`.
+//! - [`TailCall`] does not have a return destination or next block, so its syntax is just
+//! `TailCall(function(arg1, arg2, ...))`.
#![unstable(
feature = "custom_mir",
@@ -276,8 +278,7 @@ pub enum UnwindTerminateReason {
InCleanup,
}
-pub use UnwindTerminateReason::Abi as ReasonAbi;
-pub use UnwindTerminateReason::InCleanup as ReasonInCleanup;
+pub use UnwindTerminateReason::{Abi as ReasonAbi, InCleanup as ReasonInCleanup};
macro_rules! define {
($name:literal, $( #[ $meta:meta ] )* fn $($sig:tt)*) => {
@@ -351,6 +352,12 @@ fn Drop<T>(place: T, goto: ReturnToArg, unwind_action: UnwindActionArg)
/// - [`UnwindCleanup`]
fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg)
);
+define!("mir_tail_call",
+ /// Call a function.
+ ///
+ /// The argument must be of the form `fun(arg1, arg2, ...)`.
+ fn TailCall<T>(call: T)
+);
define!("mir_unwind_resume",
/// A terminator that resumes the unwinding.
fn UnwindResume()
diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs
index 0c21e6f..221724d 100644
--- a/library/core/src/intrinsics/simd.rs
+++ b/library/core/src/intrinsics/simd.rs
@@ -3,7 +3,7 @@
//! In this module, a "vector" is any `repr(simd)` type.
extern "rust-intrinsic" {
- /// Insert an element into a vector, returning the updated vector.
+ /// Inserts an element into a vector, returning the updated vector.
///
/// `T` must be a vector with element type `U`.
///
@@ -13,7 +13,7 @@
#[rustc_nounwind]
pub fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
- /// Extract an element from a vector.
+ /// Extracts an element from a vector.
///
/// `T` must be a vector with element type `U`.
///
@@ -23,25 +23,25 @@
#[rustc_nounwind]
pub fn simd_extract<T, U>(x: T, idx: u32) -> U;
- /// Add two simd vectors elementwise.
+ /// Adds two simd vectors elementwise.
///
/// `T` must be a vector of integer or floating point primitive types.
#[rustc_nounwind]
pub fn simd_add<T>(x: T, y: T) -> T;
- /// Subtract `rhs` from `lhs` elementwise.
+ /// Subtracts `rhs` from `lhs` elementwise.
///
/// `T` must be a vector of integer or floating point primitive types.
#[rustc_nounwind]
pub fn simd_sub<T>(lhs: T, rhs: T) -> T;
- /// Multiply two simd vectors elementwise.
+ /// Multiplies two simd vectors elementwise.
///
/// `T` must be a vector of integer or floating point primitive types.
#[rustc_nounwind]
pub fn simd_mul<T>(x: T, y: T) -> T;
- /// Divide `lhs` by `rhs` elementwise.
+ /// Divides `lhs` by `rhs` elementwise.
///
/// `T` must be a vector of integer or floating point primitive types.
///
@@ -51,7 +51,7 @@
#[rustc_nounwind]
pub fn simd_div<T>(lhs: T, rhs: T) -> T;
- /// Remainder of two vectors elementwise
+ /// Returns remainder of two vectors elementwise.
///
/// `T` must be a vector of integer or floating point primitive types.
///
@@ -61,9 +61,9 @@
#[rustc_nounwind]
pub fn simd_rem<T>(lhs: T, rhs: T) -> T;
- /// Elementwise vector left shift, with UB on overflow.
+ /// Shifts vector left elementwise, with UB on overflow.
///
- /// Shift `lhs` left by `rhs`, shifting in sign bits for signed types.
+ /// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types.
///
/// `T` must be a vector of integer primitive types.
///
@@ -73,11 +73,11 @@
#[rustc_nounwind]
pub fn simd_shl<T>(lhs: T, rhs: T) -> T;
- /// Elementwise vector right shift, with UB on overflow.
+ /// Shifts vector right elementwise, with UB on overflow.
///
/// `T` must be a vector of integer primitive types.
///
- /// Shift `lhs` right by `rhs`, shifting in sign bits for signed types.
+ /// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types.
///
/// # Safety
///
@@ -85,25 +85,25 @@
#[rustc_nounwind]
pub fn simd_shr<T>(lhs: T, rhs: T) -> T;
- /// Elementwise vector "and".
+ /// "Ands" vectors elementwise.
///
/// `T` must be a vector of integer primitive types.
#[rustc_nounwind]
pub fn simd_and<T>(x: T, y: T) -> T;
- /// Elementwise vector "or".
+ /// "Ors" vectors elementwise.
///
/// `T` must be a vector of integer primitive types.
#[rustc_nounwind]
pub fn simd_or<T>(x: T, y: T) -> T;
- /// Elementwise vector "exclusive or".
+ /// "Exclusive ors" vectors elementwise.
///
/// `T` must be a vector of integer primitive types.
#[rustc_nounwind]
pub fn simd_xor<T>(x: T, y: T) -> T;
- /// Numerically cast a vector, elementwise.
+ /// Numerically casts a vector, elementwise.
///
/// `T` and `U` must be vectors of integer or floating point primitive types, and must have the
/// same length.
@@ -124,7 +124,7 @@
#[rustc_nounwind]
pub fn simd_cast<T, U>(x: T) -> U;
- /// Numerically cast a vector, elementwise.
+ /// Numerically casts a vector, elementwise.
///
/// `T` and `U` be a vectors of integer or floating point primitive types, and must have the
/// same length.
@@ -138,7 +138,7 @@
#[rustc_nounwind]
pub fn simd_as<T, U>(x: T) -> U;
- /// Elementwise negation of a vector.
+ /// Negates a vector elementwise.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -146,13 +146,13 @@
#[rustc_nounwind]
pub fn simd_neg<T>(x: T) -> T;
- /// Elementwise absolute value of a vector.
+ /// Returns absolute value of a vector, elementwise.
///
/// `T` must be a vector of floating-point primitive types.
#[rustc_nounwind]
pub fn simd_fabs<T>(x: T) -> T;
- /// Elementwise minimum of two vectors.
+ /// Returns the minimum of two vectors, elementwise.
///
/// `T` must be a vector of floating-point primitive types.
///
@@ -160,7 +160,7 @@
#[rustc_nounwind]
pub fn simd_fmin<T>(x: T, y: T) -> T;
- /// Elementwise maximum of two vectors.
+ /// Returns the maximum of two vectors, elementwise.
///
/// `T` must be a vector of floating-point primitive types.
///
@@ -228,7 +228,7 @@
#[rustc_nounwind]
pub fn simd_ge<T, U>(x: T, y: T) -> U;
- /// Shuffle two vectors by const indices.
+ /// Shuffles two vectors by const indices.
///
/// `T` must be a vector.
///
@@ -243,7 +243,7 @@
#[rustc_nounwind]
pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
- /// Read a vector of pointers.
+ /// Reads a vector of pointers.
///
/// `T` must be a vector.
///
@@ -263,7 +263,7 @@
#[rustc_nounwind]
pub fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
- /// Write to a vector of pointers.
+ /// Writes to a vector of pointers.
///
/// `T` must be a vector.
///
@@ -286,7 +286,7 @@
#[rustc_nounwind]
pub fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
- /// Read a vector of pointers.
+ /// Reads a vector of pointers.
///
/// `T` must be a vector.
///
@@ -308,7 +308,7 @@
#[rustc_nounwind]
pub fn simd_masked_load<V, U, T>(mask: V, ptr: U, val: T) -> T;
- /// Write to a vector of pointers.
+ /// Writes to a vector of pointers.
///
/// `T` must be a vector.
///
@@ -329,13 +329,13 @@
#[rustc_nounwind]
pub fn simd_masked_store<V, U, T>(mask: V, ptr: U, val: T);
- /// Add two simd vectors elementwise, with saturation.
+ /// Adds two simd vectors elementwise, with saturation.
///
/// `T` must be a vector of integer primitive types.
#[rustc_nounwind]
pub fn simd_saturating_add<T>(x: T, y: T) -> T;
- /// Subtract two simd vectors elementwise, with saturation.
+ /// Subtracts two simd vectors elementwise, with saturation.
///
/// `T` must be a vector of integer primitive types.
///
@@ -343,7 +343,7 @@
#[rustc_nounwind]
pub fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
- /// Add elements within a vector from left to right.
+ /// Adds elements within a vector from left to right.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -353,7 +353,7 @@
#[rustc_nounwind]
pub fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
- /// Add elements within a vector in arbitrary order. May also be re-associated with
+ /// Adds elements within a vector in arbitrary order. May also be re-associated with
/// unordered additions on the inputs/outputs.
///
/// `T` must be a vector of integer or floating-point primitive types.
@@ -362,7 +362,7 @@
#[rustc_nounwind]
pub fn simd_reduce_add_unordered<T, U>(x: T) -> U;
- /// Multiply elements within a vector from left to right.
+ /// Multiplies elements within a vector from left to right.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -372,7 +372,7 @@
#[rustc_nounwind]
pub fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
- /// Multiply elements within a vector in arbitrary order. May also be re-associated with
+ /// Multiplies elements within a vector in arbitrary order. May also be re-associated with
/// unordered additions on the inputs/outputs.
///
/// `T` must be a vector of integer or floating-point primitive types.
@@ -381,7 +381,7 @@
#[rustc_nounwind]
pub fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
- /// Check if all mask values are true.
+ /// Checks if all mask values are true.
///
/// `T` must be a vector of integer primitive types.
///
@@ -390,7 +390,7 @@
#[rustc_nounwind]
pub fn simd_reduce_all<T>(x: T) -> bool;
- /// Check if any mask value is true.
+ /// Checks if any mask value is true.
///
/// `T` must be a vector of integer primitive types.
///
@@ -399,7 +399,7 @@
#[rustc_nounwind]
pub fn simd_reduce_any<T>(x: T) -> bool;
- /// Return the maximum element of a vector.
+ /// Returns the maximum element of a vector.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -409,7 +409,7 @@
#[rustc_nounwind]
pub fn simd_reduce_max<T, U>(x: T) -> U;
- /// Return the minimum element of a vector.
+ /// Returns the minimum element of a vector.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -419,7 +419,7 @@
#[rustc_nounwind]
pub fn simd_reduce_min<T, U>(x: T) -> U;
- /// Logical "and" all elements together.
+ /// Logical "ands" all elements together.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -427,7 +427,7 @@
#[rustc_nounwind]
pub fn simd_reduce_and<T, U>(x: T) -> U;
- /// Logical "or" all elements together.
+ /// Logical "ors" all elements together.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -435,7 +435,7 @@
#[rustc_nounwind]
pub fn simd_reduce_or<T, U>(x: T) -> U;
- /// Logical "exclusive or" all elements together.
+ /// Logical "exclusive ors" all elements together.
///
/// `T` must be a vector of integer or floating-point primitive types.
///
@@ -443,7 +443,7 @@
#[rustc_nounwind]
pub fn simd_reduce_xor<T, U>(x: T) -> U;
- /// Truncate an integer vector to a bitmask.
+ /// Truncates an integer vector to a bitmask.
///
/// `T` must be an integer vector.
///
@@ -479,7 +479,7 @@
#[rustc_nounwind]
pub fn simd_bitmask<T, U>(x: T) -> U;
- /// Select elements from a mask.
+ /// Selects elements from a mask.
///
/// `M` must be an integer vector.
///
@@ -494,7 +494,7 @@
#[rustc_nounwind]
pub fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
- /// Select elements from a bitmask.
+ /// Selects elements from a bitmask.
///
/// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`.
///
@@ -511,7 +511,8 @@
#[rustc_nounwind]
pub fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
- /// Elementwise calculates the offset from a pointer vector, potentially wrapping.
+ /// Calculates the offset from a pointer vector elementwise, potentially
+ /// wrapping.
///
/// `T` must be a vector of pointers.
///
@@ -521,13 +522,13 @@
#[rustc_nounwind]
pub fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
- /// Cast a vector of pointers.
+ /// Casts a vector of pointers.
///
/// `T` and `U` must be vectors of pointers with the same number of elements.
#[rustc_nounwind]
pub fn simd_cast_ptr<T, U>(ptr: T) -> U;
- /// Expose a vector of pointers as a vector of addresses.
+ /// Exposes a vector of pointers as a vector of addresses.
///
/// `T` must be a vector of pointers.
///
@@ -535,7 +536,7 @@
#[rustc_nounwind]
pub fn simd_expose_provenance<T, U>(ptr: T) -> U;
- /// Create a vector of pointers from a vector of addresses.
+ /// Creates a vector of pointers from a vector of addresses.
///
/// `T` must be a vector of `usize`.
///
@@ -543,56 +544,56 @@
#[rustc_nounwind]
pub fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
- /// Swap bytes of each element.
+ /// Swaps bytes of each element.
///
/// `T` must be a vector of integers.
#[rustc_nounwind]
pub fn simd_bswap<T>(x: T) -> T;
- /// Reverse bits of each element.
+ /// Reverses bits of each element.
///
/// `T` must be a vector of integers.
#[rustc_nounwind]
pub fn simd_bitreverse<T>(x: T) -> T;
- /// Count the leading zeros of each element.
+ /// Counts the leading zeros of each element.
///
/// `T` must be a vector of integers.
#[rustc_nounwind]
pub fn simd_ctlz<T>(x: T) -> T;
- /// Count the number of ones in each element.
+ /// Counts the number of ones in each element.
///
/// `T` must be a vector of integers.
#[rustc_nounwind]
pub fn simd_ctpop<T>(x: T) -> T;
- /// Count the trailing zeros of each element.
+ /// Counts the trailing zeros of each element.
///
/// `T` must be a vector of integers.
#[rustc_nounwind]
pub fn simd_cttz<T>(x: T) -> T;
- /// Round up each element to the next highest integer-valued float.
+ /// Rounds up each element to the next highest integer-valued float.
///
/// `T` must be a vector of floats.
#[rustc_nounwind]
pub fn simd_ceil<T>(x: T) -> T;
- /// Round down each element to the next lowest integer-valued float.
+ /// Rounds down each element to the next lowest integer-valued float.
///
/// `T` must be a vector of floats.
#[rustc_nounwind]
pub fn simd_floor<T>(x: T) -> T;
- /// Round each element to the closest integer-valued float.
+ /// Rounds each element to the closest integer-valued float.
/// Ties are resolved by rounding away from 0.
///
/// `T` must be a vector of floats.
#[rustc_nounwind]
pub fn simd_round<T>(x: T) -> T;
- /// Return the integer part of each element as an integer-valued float.
+ /// Returns the integer part of each element as an integer-valued float.
/// In other words, non-integer values are truncated towards zero.
///
/// `T` must be a vector of floats.
diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs
index d497da3..dbc60aa 100644
--- a/library/core/src/io/borrowed_buf.rs
+++ b/library/core/src/io/borrowed_buf.rs
@@ -44,7 +44,7 @@ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
}
}
-/// Create a new `BorrowedBuf` from a fully initialized slice.
+/// Creates a new `BorrowedBuf` from a fully initialized slice.
impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> {
#[inline]
fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> {
@@ -59,7 +59,7 @@ fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> {
}
}
-/// Create a new `BorrowedBuf` from an uninitialized buffer.
+/// Creates a new `BorrowedBuf` from an uninitialized buffer.
///
/// Use `set_init` if part of the buffer is known to be already initialized.
impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> {
@@ -174,7 +174,7 @@ pub struct BorrowedCursor<'a> {
}
impl<'a> BorrowedCursor<'a> {
- /// Reborrow this cursor by cloning it with a smaller lifetime.
+ /// Reborrows this cursor by cloning it with a smaller lifetime.
///
/// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is
/// not accessible while the new cursor exists.
@@ -247,7 +247,7 @@ pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { self.buf.buf.get_unchecked_mut(self.buf.filled..) }
}
- /// Advance the cursor by asserting that `n` bytes have been filled.
+ /// Advances the cursor by asserting that `n` bytes have been filled.
///
/// After advancing, the `n` bytes are no longer accessible via the cursor and can only be
/// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
@@ -268,7 +268,7 @@ pub fn advance(&mut self, n: usize) -> &mut Self {
self
}
- /// Advance the cursor by asserting that `n` bytes have been filled.
+ /// Advances the cursor by asserting that `n` bytes have been filled.
///
/// After advancing, the `n` bytes are no longer accessible via the cursor and can only be
/// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs
index 1a106ef..aea6d64 100644
--- a/library/core/src/iter/adapters/cloned.rs
+++ b/library/core/src/iter/adapters/cloned.rs
@@ -1,9 +1,9 @@
-use crate::iter::adapters::{
- zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
-};
+use core::num::NonZero;
+
+use crate::iter::adapters::zip::try_get_unchecked;
+use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
use crate::ops::Try;
-use core::num::NonZero;
/// An iterator that clones the elements of an underlying iterator.
///
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
index d772e7b..23e4e25 100644
--- a/library/core/src/iter/adapters/copied.rs
+++ b/library/core/src/iter/adapters/copied.rs
@@ -1,9 +1,7 @@
-use crate::iter::adapters::{
- zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
-};
+use crate::iter::adapters::zip::try_get_unchecked;
+use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
-use crate::mem::MaybeUninit;
-use crate::mem::SizedTypeProperties;
+use crate::mem::{MaybeUninit, SizedTypeProperties};
use crate::num::NonZero;
use crate::ops::Try;
use crate::{array, ptr};
diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs
index b35ed84..6cb1a3a 100644
--- a/library/core/src/iter/adapters/cycle.rs
+++ b/library/core/src/iter/adapters/cycle.rs
@@ -1,5 +1,6 @@
+use crate::iter::FusedIterator;
use crate::num::NonZero;
-use crate::{iter::FusedIterator, ops::Try};
+use crate::ops::Try;
/// An iterator that repeats endlessly.
///
diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs
index 7adbabf..ac15e37 100644
--- a/library/core/src/iter/adapters/enumerate.rs
+++ b/library/core/src/iter/adapters/enumerate.rs
@@ -1,6 +1,5 @@
-use crate::iter::adapters::{
- zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
-};
+use crate::iter::adapters::zip::try_get_unchecked;
+use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen};
use crate::num::NonZero;
use crate::ops::Try;
diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs
index ba49070..dd08cd6 100644
--- a/library/core/src/iter/adapters/filter.rs
+++ b/library/core/src/iter/adapters/filter.rs
@@ -1,11 +1,13 @@
-use crate::fmt;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused};
-use crate::num::NonZero;
-use crate::ops::Try;
use core::array;
use core::mem::MaybeUninit;
use core::ops::ControlFlow;
+use crate::fmt;
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
+use crate::num::NonZero;
+use crate::ops::Try;
+
/// An iterator that filters the elements of `iter` with `predicate`.
///
/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index 2126619..914ef61 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -1,4 +1,5 @@
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused};
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
use crate::mem::{ManuallyDrop, MaybeUninit};
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 145c9d3..0023b46 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -1,13 +1,11 @@
use crate::iter::adapters::SourceIter;
use crate::iter::{
- Cloned, Copied, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, TrustedFused,
- TrustedLen,
+ Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, Once,
+ OnceWith, TrustedFused, TrustedLen,
};
-use crate::iter::{Empty, Once, OnceWith};
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
-use crate::result;
-use crate::{array, fmt, option};
+use crate::{array, fmt, option, result};
/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs
index 1c4656a..0e2a68a 100644
--- a/library/core/src/iter/adapters/inspect.rs
+++ b/library/core/src/iter/adapters/inspect.rs
@@ -1,5 +1,6 @@
use crate::fmt;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused};
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
use crate::num::NonZero;
use crate::ops::Try;
diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs
index 6e163e2..007c2d5 100644
--- a/library/core/src/iter/adapters/map.rs
+++ b/library/core/src/iter/adapters/map.rs
@@ -1,7 +1,6 @@
use crate::fmt;
-use crate::iter::adapters::{
- zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
-};
+use crate::iter::adapters::zip::try_get_unchecked;
+use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, UncheckedIterator};
use crate::num::NonZero;
use crate::ops::Try;
diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs
index 9ad5004..4e73279 100644
--- a/library/core/src/iter/adapters/map_while.rs
+++ b/library/core/src/iter/adapters/map_while.rs
@@ -1,5 +1,6 @@
use crate::fmt;
-use crate::iter::{adapters::SourceIter, InPlaceIterable};
+use crate::iter::adapters::SourceIter;
+use crate::iter::InPlaceIterable;
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
diff --git a/library/core/src/iter/adapters/map_windows.rs b/library/core/src/iter/adapters/map_windows.rs
index 1827751..cb13023 100644
--- a/library/core/src/iter/adapters/map_windows.rs
+++ b/library/core/src/iter/adapters/map_windows.rs
@@ -1,9 +1,6 @@
-use crate::{
- fmt,
- iter::FusedIterator,
- mem::{self, MaybeUninit},
- ptr,
-};
+use crate::iter::FusedIterator;
+use crate::mem::{self, MaybeUninit};
+use crate::{fmt, ptr};
/// An iterator over the mapped windows of another iterator.
///
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index 1bde448..96158c4 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -28,6 +28,32 @@
mod take_while;
mod zip;
+#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
+pub use self::array_chunks::ArrayChunks;
+#[unstable(feature = "std_internals", issue = "none")]
+pub use self::by_ref_sized::ByRefSized;
+#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
+pub use self::chain::chain;
+#[stable(feature = "iter_cloned", since = "1.1.0")]
+pub use self::cloned::Cloned;
+#[stable(feature = "iter_copied", since = "1.36.0")]
+pub use self::copied::Copied;
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
+pub use self::flatten::Flatten;
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+pub use self::intersperse::{Intersperse, IntersperseWith};
+#[stable(feature = "iter_map_while", since = "1.57.0")]
+pub use self::map_while::MapWhile;
+#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")]
+pub use self::map_windows::MapWindows;
+#[stable(feature = "iterator_step_by", since = "1.28.0")]
+pub use self::step_by::StepBy;
+#[stable(feature = "iter_zip", since = "1.59.0")]
+pub use self::zip::zip;
+#[unstable(feature = "trusted_random_access", issue = "none")]
+pub use self::zip::TrustedRandomAccess;
+#[unstable(feature = "trusted_random_access", issue = "none")]
+pub use self::zip::TrustedRandomAccessNoCoerce;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::{
chain::Chain, cycle::Cycle, enumerate::Enumerate, filter::Filter, filter_map::FilterMap,
@@ -35,45 +61,6 @@
scan::Scan, skip::Skip, skip_while::SkipWhile, take::Take, take_while::TakeWhile, zip::Zip,
};
-#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
-pub use self::array_chunks::ArrayChunks;
-
-#[unstable(feature = "std_internals", issue = "none")]
-pub use self::by_ref_sized::ByRefSized;
-
-#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
-pub use self::chain::chain;
-
-#[stable(feature = "iter_cloned", since = "1.1.0")]
-pub use self::cloned::Cloned;
-
-#[stable(feature = "iterator_step_by", since = "1.28.0")]
-pub use self::step_by::StepBy;
-
-#[stable(feature = "iterator_flatten", since = "1.29.0")]
-pub use self::flatten::Flatten;
-
-#[stable(feature = "iter_copied", since = "1.36.0")]
-pub use self::copied::Copied;
-
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-pub use self::intersperse::{Intersperse, IntersperseWith};
-
-#[stable(feature = "iter_map_while", since = "1.57.0")]
-pub use self::map_while::MapWhile;
-
-#[unstable(feature = "iter_map_windows", reason = "recently added", issue = "87155")]
-pub use self::map_windows::MapWindows;
-
-#[unstable(feature = "trusted_random_access", issue = "none")]
-pub use self::zip::TrustedRandomAccess;
-
-#[unstable(feature = "trusted_random_access", issue = "none")]
-pub use self::zip::TrustedRandomAccessNoCoerce;
-
-#[stable(feature = "iter_zip", since = "1.59.0")]
-pub use self::zip::zip;
-
/// This trait provides transitive access to source-stage in an iterator-adapter pipeline
/// under the conditions that
/// * the iterator source `S` itself implements `SourceIter<Source = S>`
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index 65ba429..a11b73c 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -1,4 +1,5 @@
-use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen};
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, TrustedLen};
use crate::ops::{ControlFlow, Try};
/// An iterator with a `peek()` that returns an optional reference to the next
diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs
index d261a53..7ba7ed2 100644
--- a/library/core/src/iter/adapters/scan.rs
+++ b/library/core/src/iter/adapters/scan.rs
@@ -1,5 +1,6 @@
use crate::fmt;
-use crate::iter::{adapters::SourceIter, InPlaceIterable};
+use crate::iter::adapters::SourceIter;
+use crate::iter::InPlaceIterable;
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs
index f51a2c3..8ba2e2a 100644
--- a/library/core/src/iter/adapters/skip.rs
+++ b/library/core/src/iter/adapters/skip.rs
@@ -1,8 +1,8 @@
use crate::intrinsics::unlikely;
use crate::iter::adapters::zip::try_get_unchecked;
-use crate::iter::TrustedFused;
+use crate::iter::adapters::SourceIter;
use crate::iter::{
- adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess,
+ FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess,
TrustedRandomAccessNoCoerce,
};
use crate::num::NonZero;
diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs
index 8001e6e..8ae453e 100644
--- a/library/core/src/iter/adapters/skip_while.rs
+++ b/library/core/src/iter/adapters/skip_while.rs
@@ -1,5 +1,6 @@
use crate::fmt;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused};
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
use crate::num::NonZero;
use crate::ops::Try;
diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs
index abdf2f4..72eb72a 100644
--- a/library/core/src/iter/adapters/step_by.rs
+++ b/library/core/src/iter/adapters/step_by.rs
@@ -1,9 +1,7 @@
-use crate::{
- intrinsics,
- iter::{from_fn, TrustedLen, TrustedRandomAccess},
- num::NonZero,
- ops::{Range, Try},
-};
+use crate::intrinsics;
+use crate::iter::{from_fn, TrustedLen, TrustedRandomAccess};
+use crate::num::NonZero;
+use crate::ops::{Range, Try};
/// An iterator for stepping iterators by a custom amount.
///
@@ -414,9 +412,9 @@ fn nth_back<I: DoubleEndedIterator>(
/// These only work for unsigned types, and will need to be reworked
/// if you want to use it to specialize on signed types.
///
-/// Currently these are only implemented for integers up to usize due to
-/// correctness issues around ExactSizeIterator impls on 16bit platforms.
-/// And since ExactSizeIterator is a prerequisite for backwards iteration
+/// Currently these are only implemented for integers up to `usize` due to
+/// correctness issues around `ExactSizeIterator` impls on 16bit platforms.
+/// And since `ExactSizeIterator` is a prerequisite for backwards iteration
/// and we must consistently specialize backwards and forwards iteration
/// that makes the situation complicated enough that it's not covered
/// for now.
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 6870c67..297dd0a 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -1,8 +1,6 @@
use crate::cmp;
-use crate::iter::{
- adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused, TrustedLen,
- TrustedRandomAccess,
-};
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess};
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs
index d3f09ab..06028ea 100644
--- a/library/core/src/iter/adapters/take_while.rs
+++ b/library/core/src/iter/adapters/take_while.rs
@@ -1,5 +1,6 @@
use crate::fmt;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedFused};
+use crate::iter::adapters::SourceIter;
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
use crate::num::NonZero;
use crate::ops::{ControlFlow, Try};
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 2e885f0..0c38811 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -1,7 +1,8 @@
use crate::cmp;
use crate::fmt::{self, Debug};
-use crate::iter::{FusedIterator, TrustedFused};
-use crate::iter::{InPlaceIterable, SourceIter, TrustedLen, UncheckedIterator};
+use crate::iter::{
+ FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, UncheckedIterator,
+};
use crate::num::NonZero;
/// An iterator that iterates two other iterators simultaneously.
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 921c75c..1f2bf49 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -380,56 +380,9 @@ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
};
}
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::traits::Iterator;
-
-#[unstable(
- feature = "step_trait",
- reason = "likely to be replaced by finer-grained traits",
- issue = "42168"
-)]
-pub use self::range::Step;
-
-#[unstable(
- feature = "iter_from_coroutine",
- issue = "43122",
- reason = "coroutines are unstable"
-)]
-pub use self::sources::from_coroutine;
-#[stable(feature = "iter_empty", since = "1.2.0")]
-pub use self::sources::{empty, Empty};
-#[stable(feature = "iter_from_fn", since = "1.34.0")]
-pub use self::sources::{from_fn, FromFn};
-#[stable(feature = "iter_once", since = "1.2.0")]
-pub use self::sources::{once, Once};
-#[stable(feature = "iter_once_with", since = "1.43.0")]
-pub use self::sources::{once_with, OnceWith};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::sources::{repeat, Repeat};
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
-pub use self::sources::{repeat_n, RepeatN};
-#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
-pub use self::sources::{repeat_with, RepeatWith};
-#[stable(feature = "iter_successors", since = "1.34.0")]
-pub use self::sources::{successors, Successors};
-
-#[stable(feature = "fused", since = "1.26.0")]
-pub use self::traits::FusedIterator;
-#[unstable(issue = "none", feature = "inplace_iteration")]
-pub use self::traits::InPlaceIterable;
-#[unstable(issue = "none", feature = "trusted_fused")]
-pub use self::traits::TrustedFused;
-#[unstable(feature = "trusted_len", issue = "37572")]
-pub use self::traits::TrustedLen;
-#[unstable(feature = "trusted_step", issue = "85731")]
-pub use self::traits::TrustedStep;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::traits::{
- DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
-};
-
#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")]
pub use self::adapters::chain;
+pub(crate) use self::adapters::try_process;
#[stable(feature = "iter_zip", since = "1.59.0")]
pub use self::adapters::zip;
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
@@ -461,9 +414,51 @@ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
};
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
pub use self::adapters::{Intersperse, IntersperseWith};
-
-pub(crate) use self::adapters::try_process;
+#[unstable(
+ feature = "step_trait",
+ reason = "likely to be replaced by finer-grained traits",
+ issue = "42168"
+)]
+pub use self::range::Step;
+#[unstable(
+ feature = "iter_from_coroutine",
+ issue = "43122",
+ reason = "coroutines are unstable"
+)]
+pub use self::sources::from_coroutine;
+#[stable(feature = "iter_empty", since = "1.2.0")]
+pub use self::sources::{empty, Empty};
+#[stable(feature = "iter_from_fn", since = "1.34.0")]
+pub use self::sources::{from_fn, FromFn};
+#[stable(feature = "iter_once", since = "1.2.0")]
+pub use self::sources::{once, Once};
+#[stable(feature = "iter_once_with", since = "1.43.0")]
+pub use self::sources::{once_with, OnceWith};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::sources::{repeat, Repeat};
+#[unstable(feature = "iter_repeat_n", issue = "104434")]
+pub use self::sources::{repeat_n, RepeatN};
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+pub use self::sources::{repeat_with, RepeatWith};
+#[stable(feature = "iter_successors", since = "1.34.0")]
+pub use self::sources::{successors, Successors};
+#[stable(feature = "fused", since = "1.26.0")]
+pub use self::traits::FusedIterator;
+#[unstable(issue = "none", feature = "inplace_iteration")]
+pub use self::traits::InPlaceIterable;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::traits::Iterator;
+#[unstable(issue = "none", feature = "trusted_fused")]
+pub use self::traits::TrustedFused;
+#[unstable(feature = "trusted_len", issue = "37572")]
+pub use self::traits::TrustedLen;
+#[unstable(feature = "trusted_step", issue = "85731")]
+pub use self::traits::TrustedStep;
pub(crate) use self::traits::UncheckedIterator;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::traits::{
+ DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
+};
mod adapters;
mod range;
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 644a169..da4f68a 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,13 +1,12 @@
+use super::{
+ FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep,
+};
use crate::ascii::Char as AsciiChar;
use crate::mem;
use crate::net::{Ipv4Addr, Ipv6Addr};
use crate::num::NonZero;
use crate::ops::{self, Try};
-use super::{
- FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep,
-};
-
// Safety: All invariants are upheld.
macro_rules! unsafe_impl_trusted_step {
($($type:ty)*) => {$(
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 56c1f86..6a94051 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -8,33 +8,25 @@
mod repeat_with;
mod successors;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::repeat::{repeat, Repeat};
-
#[stable(feature = "iter_empty", since = "1.2.0")]
pub use self::empty::{empty, Empty};
-
-#[stable(feature = "iter_once", since = "1.2.0")]
-pub use self::once::{once, Once};
-
-#[unstable(feature = "iter_repeat_n", issue = "104434")]
-pub use self::repeat_n::{repeat_n, RepeatN};
-
-#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
-pub use self::repeat_with::{repeat_with, RepeatWith};
-
-#[stable(feature = "iter_from_fn", since = "1.34.0")]
-pub use self::from_fn::{from_fn, FromFn};
-
#[unstable(
feature = "iter_from_coroutine",
issue = "43122",
reason = "coroutines are unstable"
)]
pub use self::from_coroutine::from_coroutine;
-
-#[stable(feature = "iter_successors", since = "1.34.0")]
-pub use self::successors::{successors, Successors};
-
+#[stable(feature = "iter_from_fn", since = "1.34.0")]
+pub use self::from_fn::{from_fn, FromFn};
+#[stable(feature = "iter_once", since = "1.2.0")]
+pub use self::once::{once, Once};
#[stable(feature = "iter_once_with", since = "1.43.0")]
pub use self::once_with::{once_with, OnceWith};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::repeat::{repeat, Repeat};
+#[unstable(feature = "iter_repeat_n", issue = "104434")]
+pub use self::repeat_n::{repeat_n, RepeatN};
+#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
+pub use self::repeat_with::{repeat_with, RepeatWith};
+#[stable(feature = "iter_successors", since = "1.34.0")]
+pub use self::successors::{successors, Successors};
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 438e046..3c3acce 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -1,6 +1,5 @@
-use crate::fmt;
use crate::iter::{FusedIterator, TrustedLen};
-use crate::marker;
+use crate::{fmt, marker};
/// Creates an iterator that yields nothing.
///
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 8390dab..4c4ae39 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -114,19 +114,12 @@ impl<A: Clone> Iterator for RepeatN<A> {
#[inline]
fn next(&mut self) -> Option<A> {
- if self.count == 0 {
- return None;
- }
-
- self.count -= 1;
- Some(if self.count == 0 {
- // SAFETY: the check above ensured that the count used to be non-zero,
- // so element hasn't been dropped yet, and we just lowered the count to
- // zero so it won't be dropped later, and thus it's okay to take it here.
- unsafe { ManuallyDrop::take(&mut self.element) }
+ if self.count > 0 {
+ // SAFETY: Just checked it's not empty
+ unsafe { Some(self.next_unchecked()) }
} else {
- A::clone(&self.element)
- })
+ None
+ }
}
#[inline]
@@ -194,4 +187,18 @@ impl<A: Clone> FusedIterator for RepeatN<A> {}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
#[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
-impl<A: Clone> UncheckedIterator for RepeatN<A> {}
+impl<A: Clone> UncheckedIterator for RepeatN<A> {
+ #[inline]
+ unsafe fn next_unchecked(&mut self) -> Self::Item {
+ // SAFETY: The caller promised the iterator isn't empty
+ self.count = unsafe { self.count.unchecked_sub(1) };
+ if self.count == 0 {
+ // SAFETY: the check above ensured that the count used to be non-zero,
+ // so element hasn't been dropped yet, and we just lowered the count to
+ // zero so it won't be dropped later, and thus it's okay to take it here.
+ unsafe { ManuallyDrop::take(&mut self.element) }
+ } else {
+ A::clone(&self.element)
+ }
+ }
+}
diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs
index 7f7b2c7..36bc403 100644
--- a/library/core/src/iter/sources/successors.rs
+++ b/library/core/src/iter/sources/successors.rs
@@ -1,4 +1,5 @@
-use crate::{fmt, iter::FusedIterator};
+use crate::fmt;
+use crate::iter::FusedIterator;
/// Creates a new iterator where each successive item is computed based on the preceding one.
///
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index f9c7eb8..c97cd04 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -15,8 +15,8 @@
label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
)]
pub trait Sum<A = Self>: Sized {
- /// Method which takes an iterator and generates `Self` from the elements by
- /// "summing up" the items.
+ /// Takes an iterator and generates `Self` from the elements by "summing up"
+ /// the items.
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
}
@@ -36,8 +36,8 @@ pub trait Sum<A = Self>: Sized {
label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
)]
pub trait Product<A = Self>: Sized {
- /// Method which takes an iterator and generates `Self` from the elements by
- /// multiplying the items.
+ /// Takes an iterator and generates `Self` from the elements by multiplying
+ /// the items.
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
fn product<I: Iterator<Item = A>>(iter: I) -> Self;
}
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index c85a61a..50a2d95 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1,19 +1,14 @@
+use super::super::{
+ try_process, ArrayChunks, ByRefSized, Chain, Cloned, Copied, Cycle, Enumerate, Filter,
+ FilterMap, FlatMap, Flatten, Fuse, Inspect, Intersperse, IntersperseWith, Map, MapWhile,
+ MapWindows, Peekable, Product, Rev, Scan, Skip, SkipWhile, StepBy, Sum, Take, TakeWhile,
+ TrustedRandomAccessNoCoerce, Zip,
+};
use crate::array;
use crate::cmp::{self, Ordering};
use crate::num::NonZero;
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
-use super::super::try_process;
-use super::super::ByRefSized;
-use super::super::TrustedRandomAccessNoCoerce;
-use super::super::{ArrayChunks, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
-use super::super::{FlatMap, Flatten};
-use super::super::{
- Inspect, Map, MapWhile, MapWindows, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take,
- TakeWhile,
-};
-use super::super::{Intersperse, IntersperseWith, Product, Sum, Zip};
-
fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
/// A trait for dealing with iterators.
diff --git a/library/core/src/iter/traits/mod.rs b/library/core/src/iter/traits/mod.rs
index d4c9cc4..b330e9f 100644
--- a/library/core/src/iter/traits/mod.rs
+++ b/library/core/src/iter/traits/mod.rs
@@ -6,6 +6,13 @@
mod marker;
mod unchecked_iterator;
+#[unstable(issue = "none", feature = "inplace_iteration")]
+pub use self::marker::InPlaceIterable;
+#[unstable(issue = "none", feature = "trusted_fused")]
+pub use self::marker::TrustedFused;
+#[unstable(feature = "trusted_step", issue = "85731")]
+pub use self::marker::TrustedStep;
+pub(crate) use self::unchecked_iterator::UncheckedIterator;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::{
accum::{Product, Sum},
@@ -15,12 +22,3 @@
iterator::Iterator,
marker::{FusedIterator, TrustedLen},
};
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-pub use self::marker::InPlaceIterable;
-#[unstable(issue = "none", feature = "trusted_fused")]
-pub use self::marker::TrustedFused;
-#[unstable(feature = "trusted_step", issue = "85731")]
-pub use self::marker::TrustedStep;
-
-pub(crate) use self::unchecked_iterator::UncheckedIterator;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 9f0055d..07daa32 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -103,9 +103,11 @@
#![deny(ffi_unwind_calls)]
// Do not check link redundancy on bootstraping phase
#![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
//
// Library features:
// tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(offset_of_nested))]
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
#![feature(char_indices_offset)]
@@ -162,7 +164,6 @@
#![feature(const_ub_checks)]
#![feature(const_unicode_case_lookup)]
#![feature(const_unsafecell_get_mut)]
-#![feature(const_waker)]
#![feature(coverage_attribute)]
#![feature(do_not_recommend)]
#![feature(duration_consts_float)]
@@ -172,7 +173,6 @@
#![feature(isqrt)]
#![feature(link_cfg)]
#![feature(offset_of_enum)]
-#![feature(offset_of_nested)]
#![feature(panic_internals)]
#![feature(ptr_alignment_type)]
#![feature(ptr_metadata)]
@@ -192,8 +192,7 @@
//
// Language features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(c_unwind))]
-#![cfg_attr(bootstrap, feature(effects))]
+#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![feature(abi_unadjusted)]
#![feature(adt_const_params)]
#![feature(allow_internal_unsafe)]
@@ -227,7 +226,6 @@
#![feature(link_llvm_intrinsics)]
#![feature(macro_metavar_expr)]
#![feature(marker_trait_attr)]
-#![feature(min_exhaustive_patterns)]
#![feature(min_specialization)]
#![feature(multiple_supertrait_upcastable)]
#![feature(must_not_suspend)]
@@ -262,9 +260,11 @@
#![feature(powerpc_target_feature)]
#![feature(riscv_target_feature)]
#![feature(rtm_target_feature)]
+#![feature(sha512_sm_x86)]
#![feature(sse4a_target_feature)]
#![feature(tbm_target_feature)]
#![feature(wasm_target_feature)]
+#![feature(x86_amx_intrinsics)]
// tidy-alphabetical-end
// allow using `core::` in intra-doc links
@@ -391,7 +391,7 @@ pub mod assert_matches {
pub mod option;
pub mod panic;
pub mod panicking;
-#[unstable(feature = "core_pattern_types", issue = "none")]
+#[unstable(feature = "core_pattern_types", issue = "123646")]
pub mod pat;
pub mod pin;
#[unstable(feature = "new_range_api", issue = "125687")]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 0d4ca4d..ac51a40 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -14,6 +14,12 @@ macro_rules! panic {
/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
///
+/// Assertions are always checked in both debug and release builds, and cannot
+/// be disabled. See [`debug_assert_eq!`] for assertions that are disabled in
+/// release builds by default.
+///
+/// [`debug_assert_eq!`]: crate::debug_assert_eq
+///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
@@ -64,6 +70,12 @@ macro_rules! assert_eq {
/// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
///
+/// Assertions are always checked in both debug and release builds, and cannot
+/// be disabled. See [`debug_assert_ne!`] for assertions that are disabled in
+/// release builds by default.
+///
+/// [`debug_assert_ne!`]: crate::debug_assert_ne
+///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
@@ -122,6 +134,12 @@ macro_rules! assert_ne {
/// optional if guard can be used to add additional checks that must be true for the matched value,
/// otherwise this macro will panic.
///
+/// Assertions are always checked in both debug and release builds, and cannot
+/// be disabled. See [`debug_assert_matches!`] for assertions that are disabled in
+/// release builds by default.
+///
+/// [`debug_assert_matches!`]: crate::assert_matches::debug_assert_matches
+///
/// On panic, this macro will print the value of the expression with its debug representation.
///
/// Like [`assert!`], this macro has a second form, where a custom panic message can be provided.
@@ -633,7 +651,7 @@ macro_rules! write {
};
}
-/// Write formatted data into a buffer, with a newline appended.
+/// Writes formatted data into a buffer, with a newline appended.
///
/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index cf428e3..6a83ec2 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -9,8 +9,7 @@
use crate::cell::UnsafeCell;
use crate::cmp;
use crate::fmt::Debug;
-use crate::hash::Hash;
-use crate::hash::Hasher;
+use crate::hash::{Hash, Hasher};
/// Implements a given marker trait for multiple types at the same time.
///
@@ -871,7 +870,7 @@ impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
///
/// *However*, you cannot use [`mem::replace`] on `!Unpin` data which is *pinned* by being wrapped
/// inside a [`Pin<Ptr>`] pointing at it. This is because you cannot (safely) use a
-/// [`Pin<Ptr>`] to get an `&mut T` to its pointee value, which you would need to call
+/// [`Pin<Ptr>`] to get a `&mut T` to its pointee value, which you would need to call
/// [`mem::replace`], and *that* is what makes this system work.
///
/// So this, for example, can only be done on types implementing `Unpin`:
@@ -1061,7 +1060,6 @@ pub trait FnPtr: Copy + Clone {
}
/// Derive macro generating impls of traits related to smart pointers.
-#[cfg(not(bootstrap))]
#[rustc_builtin_macro]
#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)]
#[unstable(feature = "derive_smart_pointer", issue = "123430")]
@@ -1079,7 +1077,6 @@ pub trait FnPtr: Copy + Clone {
reason = "internal module for implementing effects"
)]
#[allow(missing_debug_implementations)] // these unit structs don't need `Debug` impls.
-#[cfg(not(bootstrap))]
pub mod effects {
#[lang = "EffectsNoRuntime"]
pub struct NoRuntime;
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 997f088..00c8370 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -118,10 +118,12 @@ pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
}
impl<T: ?Sized> ManuallyDrop<T> {
- /// Manually drops the contained value. This is exactly equivalent to calling
- /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless
- /// the contained value is a packed struct, the destructor will be called in-place
- /// without moving the value, and thus can be used to safely drop [pinned] data.
+ /// Manually drops the contained value.
+ ///
+ /// This is exactly equivalent to calling [`ptr::drop_in_place`] with a
+ /// pointer to the contained value. As such, unless the contained value is a
+ /// packed struct, the destructor will be called in-place without moving the
+ /// value, and thus can be used to safely drop [pinned] data.
///
/// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
///
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index dd40f57..f920ab1 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -1,9 +1,6 @@
use crate::any::type_name;
-use crate::fmt;
-use crate::intrinsics;
use crate::mem::{self, ManuallyDrop};
-use crate::ptr;
-use crate::slice;
+use crate::{fmt, intrinsics, ptr, slice};
/// A wrapper type to construct uninitialized instances of `T`.
///
@@ -310,7 +307,7 @@ pub const fn uninit() -> MaybeUninit<T> {
MaybeUninit { uninit: () }
}
- /// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
+ /// Creates a new array of `MaybeUninit<T>` items, in an uninitialized state.
///
/// Note: in a future Rust version this method may become unnecessary
/// when Rust allows
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 9bb4ba9..7a9ca40 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -5,13 +5,9 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::clone;
-use crate::cmp;
-use crate::fmt;
-use crate::hash;
-use crate::intrinsics;
+use crate::alloc::Layout;
use crate::marker::DiscriminantKind;
-use crate::ptr;
+use crate::{clone, cmp, fmt, hash, intrinsics, ptr};
mod manually_drop;
#[stable(feature = "manually_drop", since = "1.20.0")]
@@ -1243,6 +1239,10 @@ pub trait SizedTypeProperties: Sized {
#[doc(hidden)]
#[unstable(feature = "sized_type_properties", issue = "none")]
const IS_ZST: bool = size_of::<Self>() == 0;
+
+ #[doc(hidden)]
+ #[unstable(feature = "sized_type_properties", issue = "none")]
+ const LAYOUT: Layout = Layout::new::<Self>();
}
#[doc(hidden)]
#[unstable(feature = "sized_type_properties", issue = "none")]
@@ -1326,7 +1326,8 @@ impl<T> SizedTypeProperties for T {}
/// # Examples
///
/// ```
-/// #![feature(offset_of_enum, offset_of_nested)]
+/// # #![cfg_attr(bootstrap, feature(offset_of_nested))]
+/// #![feature(offset_of_enum)]
///
/// use std::mem;
/// #[repr(C)]
diff --git a/library/core/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs
index 6619c85..bab84a9 100644
--- a/library/core/src/net/display_buffer.rs
+++ b/library/core/src/net/display_buffer.rs
@@ -1,6 +1,5 @@
-use crate::fmt;
use crate::mem::MaybeUninit;
-use crate::str;
+use crate::{fmt, str};
/// Used for slow path in `Display` implementations when alignment is required.
pub struct DisplayBuffer<const SIZE: usize> {
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index c11a508..3e036b8 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1,11 +1,10 @@
+use super::display_buffer::DisplayBuffer;
use crate::cmp::Ordering;
use crate::fmt::{self, Write};
use crate::iter;
use crate::mem::transmute;
use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
-use super::display_buffer::DisplayBuffer;
-
/// An IP address, either IPv4 or IPv6.
///
/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
@@ -406,8 +405,8 @@ pub const fn is_ipv6(&self) -> bool {
matches!(self, IpAddr::V6(_))
}
- /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 address, otherwise it
- /// returns `self` as-is.
+ /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6
+ /// address, otherwise returns `self` as-is.
///
/// # Examples
///
@@ -549,7 +548,7 @@ pub const fn from_bits(bits: u32) -> Ipv4Addr {
#[stable(feature = "ip_constructors", since = "1.30.0")]
pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
- /// An IPv4 address representing the broadcast address: `255.255.255.255`
+ /// An IPv4 address representing the broadcast address: `255.255.255.255`.
///
/// # Examples
///
@@ -686,10 +685,10 @@ pub const fn is_link_local(&self) -> bool {
/// Returns [`true`] if the address appears to be globally reachable
/// as specified by the [IANA IPv4 Special-Purpose Address Registry].
- /// Whether or not an address is practically reachable will depend on your network configuration.
///
- /// Most IPv4 addresses are globally reachable;
- /// unless they are specifically defined as *not* globally reachable.
+ /// Whether or not an address is practically reachable will depend on your
+ /// network configuration. Most IPv4 addresses are globally reachable, unless
+ /// they are specifically defined as *not* globally reachable.
///
/// Non-exhaustive list of notable addresses that are not globally reachable:
///
@@ -802,8 +801,10 @@ pub const fn is_shared(&self) -> bool {
}
/// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
- /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
- /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+ /// network devices benchmarking.
+ ///
+ /// This range is defined in [IETF RFC 2544] as `192.18.0.0` through
+ /// `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
///
/// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
/// [errata 423]: https://www.rfc-editor.org/errata/eid423
@@ -827,10 +828,12 @@ pub const fn is_benchmarking(&self) -> bool {
self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
}
- /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
- /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
- /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
- /// it is obviously not reserved for future use.
+ /// Returns [`true`] if this address is reserved by IANA for future use.
+ ///
+ /// [IETF RFC 1112] defines the block of reserved addresses as `240.0.0.0/4`.
+ /// This range normally includes the broadcast address `255.255.255.255`, but
+ /// this implementation explicitly excludes it, since it is obviously not
+ /// reserved for future use.
///
/// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
///
@@ -1328,7 +1331,7 @@ pub const fn from_bits(bits: u128) -> Ipv6Addr {
#[stable(feature = "ip_constructors", since = "1.30.0")]
pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
- /// An IPv6 address representing the unspecified address: `::`
+ /// An IPv6 address representing the unspecified address: `::`.
///
/// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages.
///
@@ -1424,10 +1427,10 @@ pub const fn is_loopback(&self) -> bool {
/// Returns [`true`] if the address appears to be globally reachable
/// as specified by the [IANA IPv6 Special-Purpose Address Registry].
- /// Whether or not an address is practically reachable will depend on your network configuration.
///
- /// Most IPv6 addresses are globally reachable;
- /// unless they are specifically defined as *not* globally reachable.
+ /// Whether or not an address is practically reachable will depend on your
+ /// network configuration. Most IPv6 addresses are globally reachable, unless
+ /// they are specifically defined as *not* globally reachable.
///
/// Non-exhaustive list of notable addresses that are not globally reachable:
/// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
@@ -1879,8 +1882,8 @@ pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
}
}
- /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped address, otherwise it
- /// returns self wrapped in an `IpAddr::V6`.
+ /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped address,
+ /// otherwise returns self wrapped in an `IpAddr::V6`.
///
/// # Examples
///
@@ -1919,7 +1922,7 @@ pub const fn to_canonical(&self) -> IpAddr {
}
}
-/// Write an Ipv6Addr, conforming to the canonical style described by
+/// Writes an Ipv6Addr, conforming to the canonical style described by
/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Ipv6Addr {
@@ -1962,7 +1965,7 @@ struct Span {
longest
};
- /// Write a colon-separated part of the address
+ /// Writes a colon-separated part of the address.
#[inline]
fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
if let Some((first, tail)) = chunk.split_first() {
diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs
index deea821..a8ec71f 100644
--- a/library/core/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -68,7 +68,7 @@ fn peek_char(&self) -> Option<char> {
self.state.first().map(|&b| char::from(b))
}
- /// Read the next character from the input
+ /// Reads the next character from the input
fn read_char(&mut self) -> Option<char> {
self.state.split_first().map(|(&b, tail)| {
self.state = tail;
@@ -77,7 +77,7 @@ fn read_char(&mut self) -> Option<char> {
}
#[must_use]
- /// Read the next character from the input if it matches the target.
+ /// Reads the next character from the input if it matches the target.
fn read_given_char(&mut self, target: char) -> Option<()> {
self.read_atomically(|p| {
p.read_char().and_then(|c| if c == target { Some(()) } else { None })
@@ -165,7 +165,7 @@ fn read_number<T: ReadNumberHelper + TryFrom<u32>>(
}
}
- /// Read an IPv4 address.
+ /// Reads an IPv4 address.
fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
self.read_atomically(|p| {
let mut groups = [0; 4];
@@ -182,7 +182,7 @@ fn read_ipv4_addr(&mut self) -> Option<Ipv4Addr> {
})
}
- /// Read an IPv6 Address.
+ /// Reads an IPv6 address.
fn read_ipv6_addr(&mut self) -> Option<Ipv6Addr> {
/// Read a chunk of an IPv6 address into `groups`. Returns the number
/// of groups read, along with a bool indicating if an embedded
@@ -249,12 +249,12 @@ fn read_groups(p: &mut Parser<'_>, groups: &mut [u16]) -> (usize, bool) {
})
}
- /// Read an IP Address, either IPv4 or IPv6.
+ /// Reads an IP address, either IPv4 or IPv6.
fn read_ip_addr(&mut self) -> Option<IpAddr> {
self.read_ipv4_addr().map(IpAddr::V4).or_else(move || self.read_ipv6_addr().map(IpAddr::V6))
}
- /// Read a `:` followed by a port in base 10.
+ /// Reads a `:` followed by a port in base 10.
fn read_port(&mut self) -> Option<u16> {
self.read_atomically(|p| {
p.read_given_char(':')?;
@@ -262,7 +262,7 @@ fn read_port(&mut self) -> Option<u16> {
})
}
- /// Read a `%` followed by a scope ID in base 10.
+ /// Reads a `%` followed by a scope ID in base 10.
fn read_scope_id(&mut self) -> Option<u32> {
self.read_atomically(|p| {
p.read_given_char('%')?;
@@ -270,7 +270,7 @@ fn read_scope_id(&mut self) -> Option<u32> {
})
}
- /// Read an IPv4 address with a port.
+ /// Reads an IPv4 address with a port.
fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
self.read_atomically(|p| {
let ip = p.read_ipv4_addr()?;
@@ -279,7 +279,7 @@ fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
})
}
- /// Read an IPv6 address with a port.
+ /// Reads an IPv6 address with a port.
fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
self.read_atomically(|p| {
p.read_given_char('[')?;
@@ -292,7 +292,7 @@ fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
})
}
- /// Read an IP address with a port
+ /// Reads an IP address with a port.
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
self.read_socket_addr_v4()
.map(SocketAddr::V4)
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index c24d8f5..4e33917 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -1,8 +1,7 @@
+use super::display_buffer::DisplayBuffer;
use crate::fmt::{self, Write};
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-use super::display_buffer::DisplayBuffer;
-
/// An internet socket address, either IPv4 or IPv6.
///
/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs
index d2a21b6..2a47c89 100644
--- a/library/core/src/num/bignum.rs
+++ b/library/core/src/num/bignum.rs
@@ -145,8 +145,7 @@ pub fn bit_length(&self) -> usize {
/// Adds `other` to itself and returns its own mutable reference.
pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name {
- use crate::cmp;
- use crate::iter;
+ use crate::{cmp, iter};
let mut sz = cmp::max(self.size, other.size);
let mut carry = false;
@@ -181,8 +180,7 @@ pub fn add_small(&mut self, other: $ty) -> &mut $name {
/// Subtracts `other` from itself and returns its own mutable reference.
pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name {
- use crate::cmp;
- use crate::iter;
+ use crate::{cmp, iter};
let sz = cmp::max(self.size, other.size);
let mut noborrow = true;
diff --git a/library/core/src/num/dec2flt/common.rs b/library/core/src/num/dec2flt/common.rs
index c85727b..4dadf40 100644
--- a/library/core/src/num/dec2flt/common.rs
+++ b/library/core/src/num/dec2flt/common.rs
@@ -2,10 +2,10 @@
/// Helper methods to process immutable bytes.
pub(crate) trait ByteSlice {
- /// Read 8 bytes as a 64-bit integer in little-endian order.
+ /// Reads 8 bytes as a 64-bit integer in little-endian order.
fn read_u64(&self) -> u64;
- /// Write a 64-bit integer as 8 bytes in little-endian order.
+ /// Writes a 64-bit integer as 8 bytes in little-endian order.
fn write_u64(&mut self, value: u64);
/// Calculate the offset of a slice from another.
diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs
index 1c9d689..da57aa9 100644
--- a/library/core/src/num/dec2flt/float.rs
+++ b/library/core/src/num/dec2flt/float.rs
@@ -81,7 +81,7 @@ pub trait RawFloat:
// Maximum mantissa for the fast-path (`1 << 53` for f64).
const MAX_MANTISSA_FAST_PATH: u64 = 2_u64 << Self::MANTISSA_EXPLICIT_BITS;
- /// Convert integer into float through an as cast.
+ /// Converts integer into float through an as cast.
/// This is only called in the fast-path algorithm, and therefore
/// will not lose precision, since the value will always have
/// only if the value is <= Self::MAX_MANTISSA_FAST_PATH.
@@ -90,7 +90,7 @@ pub trait RawFloat:
/// Performs a raw transmutation from an integer.
fn from_u64_bits(v: u64) -> Self;
- /// Get a small power-of-ten for fast-path multiplication.
+ /// Gets a small power-of-ten for fast-path multiplication.
fn pow10_fast_path(exponent: usize) -> Self;
/// Returns the category that this number falls into.
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 9aac233..87bfd0d 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -75,15 +75,14 @@
issue = "none"
)]
-use crate::error::Error;
-use crate::fmt;
-use crate::str::FromStr;
-
use self::common::BiasedFp;
use self::float::RawFloat;
use self::lemire::compute_float;
use self::parse::{parse_inf_nan, parse_number};
use self::slow::parse_long_mantissa;
+use crate::error::Error;
+use crate::fmt;
+use crate::str::FromStr;
mod common;
mod decimal;
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 05dc1e9..0c04f47 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -234,24 +234,20 @@ impl f128 {
/// This constant isn't guaranteed to equal to any specific NaN bitpattern,
/// and the stability of its representation over Rust versions
/// and target platforms isn't guaranteed.
- #[cfg(not(bootstrap))]
#[allow(clippy::eq_op)]
#[rustc_diagnostic_item = "f128_nan"]
#[unstable(feature = "f128", issue = "116909")]
pub const NAN: f128 = 0.0_f128 / 0.0_f128;
/// Infinity (∞).
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
pub const INFINITY: f128 = 1.0_f128 / 0.0_f128;
/// Negative infinity (−∞).
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128;
/// Sign bit
- #[cfg(not(bootstrap))]
pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
/// Exponent mask
@@ -261,11 +257,9 @@ impl f128 {
pub(crate) const MAN_MASK: u128 = 0x0000_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
/// Minimum representable positive value (min subnormal)
- #[cfg(not(bootstrap))]
const TINY_BITS: u128 = 0x1;
/// Minimum representable negative value (min negative subnormal)
- #[cfg(not(bootstrap))]
const NEG_TINY_BITS: u128 = Self::TINY_BITS | Self::SIGN_MASK;
/// Returns `true` if this value is NaN.
@@ -284,7 +278,6 @@ impl f128 {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
pub const fn is_nan(self) -> bool {
@@ -295,7 +288,6 @@ pub const fn is_nan(self) -> bool {
// concerns about portability, so this implementation is for
// private use internally.
#[inline]
- #[cfg(not(bootstrap))]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub(crate) const fn abs_private(self) -> f128 {
// SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
@@ -326,7 +318,6 @@ pub(crate) const fn abs_private(self) -> f128 {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_infinite(self) -> bool {
@@ -354,7 +345,6 @@ pub const fn is_infinite(self) -> bool {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_finite(self) -> bool {
@@ -389,7 +379,6 @@ pub const fn is_finite(self) -> bool {
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_subnormal(self) -> bool {
@@ -422,7 +411,6 @@ pub const fn is_subnormal(self) -> bool {
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_normal(self) -> bool {
@@ -448,7 +436,6 @@ pub const fn is_normal(self) -> bool {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn classify(self) -> FpCategory {
@@ -557,7 +544,6 @@ pub fn is_sign_negative(self) -> bool {
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_up(self) -> Self {
@@ -612,7 +598,6 @@ pub fn next_up(self) -> Self {
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_down(self) -> Self {
@@ -649,7 +634,6 @@ pub fn next_down(self) -> Self {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn recip(self) -> Self {
@@ -670,7 +654,6 @@ pub fn recip(self) -> Self {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_degrees(self) -> Self {
@@ -694,7 +677,6 @@ pub fn to_degrees(self) -> Self {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_radians(self) -> f128 {
@@ -704,6 +686,182 @@ pub fn to_radians(self) -> f128 {
self * RADS_PER_DEG
}
+ /// Returns the maximum of the two numbers, ignoring NaN.
+ ///
+ /// If one of the arguments is NaN, then the other argument is returned.
+ /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
+ /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
+ /// This also matches the behavior of libm’s fmax.
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # // Using aarch64 because `reliable_f128_math` is needed
+ /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
+ ///
+ /// let x = 1.0f128;
+ /// let y = 2.0f128;
+ ///
+ /// assert_eq!(x.max(y), y);
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn max(self, other: f128) -> f128 {
+ intrinsics::maxnumf128(self, other)
+ }
+
+ /// Returns the minimum of the two numbers, ignoring NaN.
+ ///
+ /// If one of the arguments is NaN, then the other argument is returned.
+ /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
+ /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
+ /// This also matches the behavior of libm’s fmin.
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # // Using aarch64 because `reliable_f128_math` is needed
+ /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
+ ///
+ /// let x = 1.0f128;
+ /// let y = 2.0f128;
+ ///
+ /// assert_eq!(x.min(y), x);
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn min(self, other: f128) -> f128 {
+ intrinsics::minnumf128(self, other)
+ }
+
+ /// Returns the maximum of the two numbers, propagating NaN.
+ ///
+ /// This returns NaN when *either* argument is NaN, as opposed to
+ /// [`f128::max`] which only returns NaN when *both* arguments are NaN.
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// #![feature(float_minimum_maximum)]
+ /// # // Using aarch64 because `reliable_f128_math` is needed
+ /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
+ ///
+ /// let x = 1.0f128;
+ /// let y = 2.0f128;
+ ///
+ /// assert_eq!(x.maximum(y), y);
+ /// assert!(x.maximum(f128::NAN).is_nan());
+ /// # }
+ /// ```
+ ///
+ /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
+ /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
+ /// Note that this follows the semantics specified in IEEE 754-2019.
+ ///
+ /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
+ /// operand is conserved; see [explanation of NaN as a special value](f128) for more info.
+ #[inline]
+ #[unstable(feature = "f128", issue = "116909")]
+ // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn maximum(self, other: f128) -> f128 {
+ if self > other {
+ self
+ } else if other > self {
+ other
+ } else if self == other {
+ if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
+ } else {
+ self + other
+ }
+ }
+
+ /// Returns the minimum of the two numbers, propagating NaN.
+ ///
+ /// This returns NaN when *either* argument is NaN, as opposed to
+ /// [`f128::min`] which only returns NaN when *both* arguments are NaN.
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// #![feature(float_minimum_maximum)]
+ /// # // Using aarch64 because `reliable_f128_math` is needed
+ /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
+ ///
+ /// let x = 1.0f128;
+ /// let y = 2.0f128;
+ ///
+ /// assert_eq!(x.minimum(y), x);
+ /// assert!(x.minimum(f128::NAN).is_nan());
+ /// # }
+ /// ```
+ ///
+ /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
+ /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
+ /// Note that this follows the semantics specified in IEEE 754-2019.
+ ///
+ /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
+ /// operand is conserved; see [explanation of NaN as a special value](f128) for more info.
+ #[inline]
+ #[unstable(feature = "f128", issue = "116909")]
+ // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn minimum(self, other: f128) -> f128 {
+ if self < other {
+ self
+ } else if other < self {
+ other
+ } else if self == other {
+ if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
+ } else {
+ // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ self + other
+ }
+ }
+
+ /// Calculates the middle point of `self` and `rhs`.
+ ///
+ /// This returns NaN when *either* argument is NaN or if a combination of
+ /// +inf and -inf is provided as arguments.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// #![feature(num_midpoint)]
+ /// # // Using aarch64 because `reliable_f128_math` is needed
+ /// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
+ ///
+ /// assert_eq!(1f128.midpoint(4.0), 2.5);
+ /// assert_eq!((-5.5f128).midpoint(8.0), 1.25);
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f128", issue = "116909")]
+ // #[unstable(feature = "num_midpoint", issue = "110840")]
+ pub fn midpoint(self, other: f128) -> f128 {
+ const LO: f128 = f128::MIN_POSITIVE * 2.;
+ const HI: f128 = f128::MAX / 2.;
+
+ let (a, b) = (self, other);
+ let abs_a = a.abs_private();
+ let abs_b = b.abs_private();
+
+ if abs_a <= HI && abs_b <= HI {
+ // Overflow is impossible
+ (a + b) / 2.
+ } else if abs_a < LO {
+ // Not safe to halve `a` (would underflow)
+ a + (b / 2.)
+ } else if abs_b < LO {
+ // Not safe to halve `b` (would underflow)
+ (a / 2.) + b
+ } else {
+ // Safe to halve `a` and `b`
+ (a / 2.) + (b / 2.)
+ }
+ }
+
/// Rounds toward zero and converts to any primitive integer type,
/// assuming that the value is finite and fits in that type.
///
@@ -898,7 +1056,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
intrinsics::const_eval_select((v,), ct_u128_to_f128, rt_u128_to_f128)
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// big-endian (network) byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -924,7 +1082,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
self.to_bits().to_be_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// little-endian byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -950,7 +1108,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
self.to_bits().to_le_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// native byte order.
///
/// As the target platform's native endianness is used, portable code
@@ -987,7 +1145,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
self.to_bits().to_ne_bytes()
}
- /// Create a floating point value from its representation as a byte array in big endian.
+ /// Creates a floating point value from its representation as a byte array in big endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1014,7 +1172,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
Self::from_bits(u128::from_be_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in little endian.
+ /// Creates a floating point value from its representation as a byte array in little endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1041,7 +1199,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
Self::from_bits(u128::from_le_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in native endian.
+ /// Creates a floating point value from its representation as a byte array in native endian.
///
/// As the target platform's native endianness is used, portable code
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
@@ -1078,7 +1236,7 @@ fn rt_u128_to_f128(x: u128) -> f128 {
Self::from_bits(u128::from_ne_bytes(bytes))
}
- /// Return the ordering between `self` and `other`.
+ /// Returns the ordering between `self` and `other`.
///
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
@@ -1141,7 +1299,6 @@ fn rt_u128_to_f128(x: u128) -> f128 {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
let mut left = self.to_bits() as i128;
@@ -1201,7 +1358,6 @@ pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn clamp(mut self, min: f128, max: f128) -> f128 {
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 2a8ede9..e5b1148 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -229,24 +229,20 @@ impl f16 {
/// This constant isn't guaranteed to equal to any specific NaN bitpattern,
/// and the stability of its representation over Rust versions
/// and target platforms isn't guaranteed.
- #[cfg(not(bootstrap))]
#[allow(clippy::eq_op)]
#[rustc_diagnostic_item = "f16_nan"]
#[unstable(feature = "f16", issue = "116909")]
pub const NAN: f16 = 0.0_f16 / 0.0_f16;
/// Infinity (∞).
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
pub const INFINITY: f16 = 1.0_f16 / 0.0_f16;
/// Negative infinity (−∞).
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;
/// Sign bit
- #[cfg(not(bootstrap))]
pub(crate) const SIGN_MASK: u16 = 0x8000;
/// Exponent mask
@@ -256,11 +252,9 @@ impl f16 {
pub(crate) const MAN_MASK: u16 = 0x03ff;
/// Minimum representable positive value (min subnormal)
- #[cfg(not(bootstrap))]
const TINY_BITS: u16 = 0x1;
/// Minimum representable negative value (min negative subnormal)
- #[cfg(not(bootstrap))]
const NEG_TINY_BITS: u16 = Self::TINY_BITS | Self::SIGN_MASK;
/// Returns `true` if this value is NaN.
@@ -278,7 +272,6 @@ impl f16 {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
pub const fn is_nan(self) -> bool {
@@ -289,7 +282,6 @@ pub const fn is_nan(self) -> bool {
// concerns about portability, so this implementation is for
// private use internally.
#[inline]
- #[cfg(not(bootstrap))]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub(crate) const fn abs_private(self) -> f16 {
// SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
@@ -317,7 +309,6 @@ pub(crate) const fn abs_private(self) -> f16 {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_infinite(self) -> bool {
@@ -344,7 +335,6 @@ pub const fn is_infinite(self) -> bool {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_finite(self) -> bool {
@@ -377,7 +367,6 @@ pub const fn is_finite(self) -> bool {
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_subnormal(self) -> bool {
@@ -408,7 +397,6 @@ pub const fn is_subnormal(self) -> bool {
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn is_normal(self) -> bool {
@@ -433,7 +421,6 @@ pub const fn is_normal(self) -> bool {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
pub const fn classify(self) -> FpCategory {
@@ -478,7 +465,6 @@ pub const fn classify(self) -> FpCategory {
/// but getting floats correct is important for not accidentally leaking const eval
/// runtime-deviating logic which may or may not be acceptable.
#[inline]
- #[cfg(not(bootstrap))]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
const unsafe fn partial_classify(self) -> FpCategory {
// SAFETY: The caller is not asking questions for which this will tell lies.
@@ -593,7 +579,6 @@ pub fn is_sign_negative(self) -> bool {
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_up(self) -> Self {
@@ -648,7 +633,6 @@ pub fn next_up(self) -> Self {
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_down(self) -> Self {
@@ -685,7 +669,6 @@ pub fn next_down(self) -> Self {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn recip(self) -> Self {
@@ -706,7 +689,6 @@ pub fn recip(self) -> Self {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_degrees(self) -> Self {
@@ -730,7 +712,6 @@ pub fn to_degrees(self) -> Self {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_radians(self) -> f16 {
@@ -739,6 +720,177 @@ pub fn to_radians(self) -> f16 {
self * RADS_PER_DEG
}
+ /// Returns the maximum of the two numbers, ignoring NaN.
+ ///
+ /// If one of the arguments is NaN, then the other argument is returned.
+ /// This follows the IEEE 754-2008 semantics for maxNum, except for handling of signaling NaNs;
+ /// this function handles all NaNs the same way and avoids maxNum's problems with associativity.
+ /// This also matches the behavior of libm’s fmax.
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
+ ///
+ /// let x = 1.0f16;
+ /// let y = 2.0f16;
+ ///
+ /// assert_eq!(x.max(y), y);
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn max(self, other: f16) -> f16 {
+ intrinsics::maxnumf16(self, other)
+ }
+
+ /// Returns the minimum of the two numbers, ignoring NaN.
+ ///
+ /// If one of the arguments is NaN, then the other argument is returned.
+ /// This follows the IEEE 754-2008 semantics for minNum, except for handling of signaling NaNs;
+ /// this function handles all NaNs the same way and avoids minNum's problems with associativity.
+ /// This also matches the behavior of libm’s fmin.
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
+ ///
+ /// let x = 1.0f16;
+ /// let y = 2.0f16;
+ ///
+ /// assert_eq!(x.min(y), x);
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn min(self, other: f16) -> f16 {
+ intrinsics::minnumf16(self, other)
+ }
+
+ /// Returns the maximum of the two numbers, propagating NaN.
+ ///
+ /// This returns NaN when *either* argument is NaN, as opposed to
+ /// [`f16::max`] which only returns NaN when *both* arguments are NaN.
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// #![feature(float_minimum_maximum)]
+ /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
+ ///
+ /// let x = 1.0f16;
+ /// let y = 2.0f16;
+ ///
+ /// assert_eq!(x.maximum(y), y);
+ /// assert!(x.maximum(f16::NAN).is_nan());
+ /// # }
+ /// ```
+ ///
+ /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater
+ /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
+ /// Note that this follows the semantics specified in IEEE 754-2019.
+ ///
+ /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
+ /// operand is conserved; see [explanation of NaN as a special value](f16) for more info.
+ #[inline]
+ #[unstable(feature = "f16", issue = "116909")]
+ // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn maximum(self, other: f16) -> f16 {
+ if self > other {
+ self
+ } else if other > self {
+ other
+ } else if self == other {
+ if self.is_sign_positive() && other.is_sign_negative() { self } else { other }
+ } else {
+ self + other
+ }
+ }
+
+ /// Returns the minimum of the two numbers, propagating NaN.
+ ///
+ /// This returns NaN when *either* argument is NaN, as opposed to
+ /// [`f16::min`] which only returns NaN when *both* arguments are NaN.
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// #![feature(float_minimum_maximum)]
+ /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
+ ///
+ /// let x = 1.0f16;
+ /// let y = 2.0f16;
+ ///
+ /// assert_eq!(x.minimum(y), x);
+ /// assert!(x.minimum(f16::NAN).is_nan());
+ /// # }
+ /// ```
+ ///
+ /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser
+ /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0.
+ /// Note that this follows the semantics specified in IEEE 754-2019.
+ ///
+ /// Also note that "propagation" of NaNs here doesn't necessarily mean that the bitpattern of a NaN
+ /// operand is conserved; see [explanation of NaN as a special value](f16) for more info.
+ #[inline]
+ #[unstable(feature = "f16", issue = "116909")]
+ // #[unstable(feature = "float_minimum_maximum", issue = "91079")]
+ #[must_use = "this returns the result of the comparison, without modifying either input"]
+ pub fn minimum(self, other: f16) -> f16 {
+ if self < other {
+ self
+ } else if other < self {
+ other
+ } else if self == other {
+ if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
+ } else {
+ // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
+ self + other
+ }
+ }
+
+ /// Calculates the middle point of `self` and `rhs`.
+ ///
+ /// This returns NaN when *either* argument is NaN or if a combination of
+ /// +inf and -inf is provided as arguments.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// #![feature(num_midpoint)]
+ /// # #[cfg(target_arch = "aarch64")] { // FIXME(f16_F128): rust-lang/rust#123885
+ ///
+ /// assert_eq!(1f16.midpoint(4.0), 2.5);
+ /// assert_eq!((-5.5f16).midpoint(8.0), 1.25);
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f16", issue = "116909")]
+ // #[unstable(feature = "num_midpoint", issue = "110840")]
+ pub fn midpoint(self, other: f16) -> f16 {
+ const LO: f16 = f16::MIN_POSITIVE * 2.;
+ const HI: f16 = f16::MAX / 2.;
+
+ let (a, b) = (self, other);
+ let abs_a = a.abs_private();
+ let abs_b = b.abs_private();
+
+ if abs_a <= HI && abs_b <= HI {
+ // Overflow is impossible
+ (a + b) / 2.
+ } else if abs_a < LO {
+ // Not safe to halve `a` (would underflow)
+ a + (b / 2.)
+ } else if abs_b < LO {
+ // Not safe to halve `b` (would underflow)
+ (a / 2.) + b
+ } else {
+ // Safe to halve `a` and `b`
+ (a / 2.) + (b / 2.)
+ }
+ }
+
/// Rounds toward zero and converts to any primitive integer type,
/// assuming that the value is finite and fits in that type.
///
@@ -933,7 +1085,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
intrinsics::const_eval_select((v,), ct_u16_to_f16, rt_u16_to_f16)
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// big-endian (network) byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -958,7 +1110,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
self.to_bits().to_be_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// little-endian byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -983,7 +1135,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
self.to_bits().to_le_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// native byte order.
///
/// As the target platform's native endianness is used, portable code
@@ -1021,7 +1173,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
self.to_bits().to_ne_bytes()
}
- /// Create a floating point value from its representation as a byte array in big endian.
+ /// Creates a floating point value from its representation as a byte array in big endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1044,7 +1196,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
Self::from_bits(u16::from_be_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in little endian.
+ /// Creates a floating point value from its representation as a byte array in little endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1067,7 +1219,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
Self::from_bits(u16::from_le_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in native endian.
+ /// Creates a floating point value from its representation as a byte array in native endian.
///
/// As the target platform's native endianness is used, portable code
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
@@ -1101,7 +1253,7 @@ fn rt_u16_to_f16(x: u16) -> f16 {
Self::from_bits(u16::from_ne_bytes(bytes))
}
- /// Return the ordering between `self` and `other`.
+ /// Returns the ordering between `self` and `other`.
///
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
@@ -1167,7 +1319,6 @@ fn rt_u16_to_f16(x: u16) -> f16 {
/// ```
#[inline]
#[must_use]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
let mut left = self.to_bits() as i16;
@@ -1226,7 +1377,6 @@ pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn clamp(mut self, min: f16, max: f16) -> f16 {
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index b9c84a6..7710e23 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -721,11 +721,13 @@ const fn classify_bits(b: u32) -> FpCategory {
}
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
- /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any
- /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
- /// the bit pattern of NaNs are conserved over arithmetic operations, the result of
- /// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
- /// See [explanation of NaN as a special value](f32) for more info.
+ /// positive sign bit and positive infinity.
+ ///
+ /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
+ /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
+ /// conserved over arithmetic operations, the result of `is_sign_positive` on
+ /// a NaN might produce an unexpected result in some cases. See [explanation
+ /// of NaN as a special value](f32) for more info.
///
/// ```
/// let f = 7.0_f32;
@@ -743,11 +745,13 @@ pub const fn is_sign_positive(self) -> bool {
}
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
- /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any
- /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
- /// the bit pattern of NaNs are conserved over arithmetic operations, the result of
- /// `is_sign_negative` on a NaN might produce an unexpected result in some cases.
- /// See [explanation of NaN as a special value](f32) for more info.
+ /// negative sign bit and negative infinity.
+ ///
+ /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
+ /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
+ /// conserved over arithmetic operations, the result of `is_sign_negative` on
+ /// a NaN might produce an unexpected result in some cases. See [explanation
+ /// of NaN as a special value](f32) for more info.
///
/// ```
/// let f = 7.0f32;
@@ -793,6 +797,7 @@ pub const fn is_sign_negative(self) -> bool {
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
+ #[inline]
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_up(self) -> Self {
@@ -841,6 +846,7 @@ pub const fn next_up(self) -> Self {
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
+ #[inline]
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_down(self) -> Self {
@@ -1038,6 +1044,7 @@ pub fn minimum(self, other: f32) -> f32 {
/// assert_eq!(1f32.midpoint(4.0), 2.5);
/// assert_eq!((-5.5f32).midpoint(8.0), 1.25);
/// ```
+ #[inline]
#[unstable(feature = "num_midpoint", issue = "110840")]
pub fn midpoint(self, other: f32) -> f32 {
cfg_if! {
@@ -1066,13 +1073,13 @@ pub fn midpoint(self, other: f32) -> f32 {
// Overflow is impossible
(a + b) / 2.
} else if abs_a < LO {
- // Not safe to halve a
+ // Not safe to halve `a` (would underflow)
a + (b / 2.)
} else if abs_b < LO {
- // Not safe to halve b
+ // Not safe to halve `b` (would underflow)
(a / 2.) + b
} else {
- // Not safe to halve a and b
+ // Safe to halve `a` and `b`
(a / 2.) + (b / 2.)
}
}
@@ -1274,7 +1281,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
intrinsics::const_eval_select((v,), ct_u32_to_f32, rt_u32_to_f32)
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// big-endian (network) byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -1295,7 +1302,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
self.to_bits().to_be_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// little-endian byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -1316,7 +1323,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
self.to_bits().to_le_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// native byte order.
///
/// As the target platform's native endianness is used, portable code
@@ -1350,7 +1357,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
self.to_bits().to_ne_bytes()
}
- /// Create a floating point value from its representation as a byte array in big endian.
+ /// Creates a floating point value from its representation as a byte array in big endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1369,7 +1376,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
Self::from_bits(u32::from_be_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in little endian.
+ /// Creates a floating point value from its representation as a byte array in little endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1388,7 +1395,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
Self::from_bits(u32::from_le_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in native endian.
+ /// Creates a floating point value from its representation as a byte array in native endian.
///
/// As the target platform's native endianness is used, portable code
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
@@ -1418,7 +1425,7 @@ fn rt_u32_to_f32(x: u32) -> f32 {
Self::from_bits(u32::from_ne_bytes(bytes))
}
- /// Return the ordering between `self` and `other`.
+ /// Returns the ordering between `self` and `other`.
///
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index f8e4555..a89859b 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -711,11 +711,13 @@ const fn classify_bits(b: u64) -> FpCategory {
}
/// Returns `true` if `self` has a positive sign, including `+0.0`, NaNs with
- /// positive sign bit and positive infinity. Note that IEEE 754 doesn't assign any
- /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
- /// the bit pattern of NaNs are conserved over arithmetic operations, the result of
- /// `is_sign_positive` on a NaN might produce an unexpected result in some cases.
- /// See [explanation of NaN as a special value](f32) for more info.
+ /// positive sign bit and positive infinity.
+ ///
+ /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
+ /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
+ /// conserved over arithmetic operations, the result of `is_sign_positive` on
+ /// a NaN might produce an unexpected result in some cases. See [explanation
+ /// of NaN as a special value](f32) for more info.
///
/// ```
/// let f = 7.0_f64;
@@ -742,11 +744,13 @@ pub fn is_positive(self) -> bool {
}
/// Returns `true` if `self` has a negative sign, including `-0.0`, NaNs with
- /// negative sign bit and negative infinity. Note that IEEE 754 doesn't assign any
- /// meaning to the sign bit in case of a NaN, and as Rust doesn't guarantee that
- /// the bit pattern of NaNs are conserved over arithmetic operations, the result of
- /// `is_sign_negative` on a NaN might produce an unexpected result in some cases.
- /// See [explanation of NaN as a special value](f32) for more info.
+ /// negative sign bit and negative infinity.
+ ///
+ /// Note that IEEE 754 doesn't assign any meaning to the sign bit in case of
+ /// a NaN, and as Rust doesn't guarantee that the bit pattern of NaNs are
+ /// conserved over arithmetic operations, the result of `is_sign_negative` on
+ /// a NaN might produce an unexpected result in some cases. See [explanation
+ /// of NaN as a special value](f32) for more info.
///
/// ```
/// let f = 7.0_f64;
@@ -801,6 +805,7 @@ pub fn is_negative(self) -> bool {
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
+ #[inline]
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_up(self) -> Self {
@@ -849,6 +854,7 @@ pub const fn next_up(self) -> Self {
/// [`INFINITY`]: Self::INFINITY
/// [`MIN`]: Self::MIN
/// [`MAX`]: Self::MAX
+ #[inline]
#[unstable(feature = "float_next_up_down", issue = "91399")]
#[rustc_const_unstable(feature = "float_next_up_down", issue = "91399")]
pub const fn next_down(self) -> Self {
@@ -1047,6 +1053,7 @@ pub fn minimum(self, other: f64) -> f64 {
/// assert_eq!(1f64.midpoint(4.0), 2.5);
/// assert_eq!((-5.5f64).midpoint(8.0), 1.25);
/// ```
+ #[inline]
#[unstable(feature = "num_midpoint", issue = "110840")]
pub fn midpoint(self, other: f64) -> f64 {
const LO: f64 = f64::MIN_POSITIVE * 2.;
@@ -1060,13 +1067,13 @@ pub fn midpoint(self, other: f64) -> f64 {
// Overflow is impossible
(a + b) / 2.
} else if abs_a < LO {
- // Not safe to halve a
+ // Not safe to halve `a` (would underflow)
a + (b / 2.)
} else if abs_b < LO {
- // Not safe to halve b
+ // Not safe to halve `b` (would underflow)
(a / 2.) + b
} else {
- // Not safe to halve a and b
+ // Safe to halve `a` and `b`
(a / 2.) + (b / 2.)
}
}
@@ -1252,7 +1259,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
intrinsics::const_eval_select((v,), ct_u64_to_f64, rt_u64_to_f64)
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// big-endian (network) byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -1273,7 +1280,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
self.to_bits().to_be_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// little-endian byte order.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
@@ -1294,7 +1301,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
self.to_bits().to_le_bytes()
}
- /// Return the memory representation of this floating point number as a byte array in
+ /// Returns the memory representation of this floating point number as a byte array in
/// native byte order.
///
/// As the target platform's native endianness is used, portable code
@@ -1328,7 +1335,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
self.to_bits().to_ne_bytes()
}
- /// Create a floating point value from its representation as a byte array in big endian.
+ /// Creates a floating point value from its representation as a byte array in big endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1347,7 +1354,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
Self::from_bits(u64::from_be_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in little endian.
+ /// Creates a floating point value from its representation as a byte array in little endian.
///
/// See [`from_bits`](Self::from_bits) for some discussion of the
/// portability of this operation (there are almost no issues).
@@ -1366,7 +1373,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
Self::from_bits(u64::from_le_bytes(bytes))
}
- /// Create a floating point value from its representation as a byte array in native endian.
+ /// Creates a floating point value from its representation as a byte array in native endian.
///
/// As the target platform's native endianness is used, portable code
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
@@ -1396,7 +1403,7 @@ fn rt_u64_to_f64(rt: u64) -> f64 {
Self::from_bits(u64::from_ne_bytes(bytes))
}
- /// Return the ordering between `self` and `other`.
+ /// Returns the ordering between `self` and `other`.
///
/// Unlike the standard partial comparison between floating point numbers,
/// this comparison always produces an ordering in accordance to
diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs
index 1ff2e8c..7d923a2 100644
--- a/library/core/src/num/flt2dec/mod.rs
+++ b/library/core/src/num/flt2dec/mod.rs
@@ -123,7 +123,6 @@
)]
pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
-
use super::fmt::{Formatted, Part};
use crate::mem::MaybeUninit;
diff --git a/library/core/src/num/flt2dec/strategy/dragon.rs b/library/core/src/num/flt2dec/strategy/dragon.rs
index 71b14d0..f8db637 100644
--- a/library/core/src/num/flt2dec/strategy/dragon.rs
+++ b/library/core/src/num/flt2dec/strategy/dragon.rs
@@ -6,56 +6,57 @@
use crate::cmp::Ordering;
use crate::mem::MaybeUninit;
-
-use crate::num::bignum::Big32x40 as Big;
-use crate::num::bignum::Digit32 as Digit;
+use crate::num::bignum::{Big32x40 as Big, Digit32 as Digit};
use crate::num::flt2dec::estimator::estimate_scaling_factor;
use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
static POW10: [Digit; 10] =
[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
-static TWOPOW10: [Digit; 10] =
- [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000];
-
-// precalculated arrays of `Digit`s for 10^(2^n)
-static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2];
-static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee];
-static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
-static POW10TO128: [Digit; 14] = [
- 0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da,
- 0xa6337f19, 0xe91f2603, 0x24e,
+// precalculated arrays of `Digit`s for 5^(2^n).
+static POW5TO16: [Digit; 2] = [0x86f26fc1, 0x23];
+static POW5TO32: [Digit; 3] = [0x85acef81, 0x2d6d415b, 0x4ee];
+static POW5TO64: [Digit; 5] = [0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
+static POW5TO128: [Digit; 10] = [
+ 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19,
+ 0xe91f2603, 0x24e,
];
-static POW10TO256: [Digit; 27] = [
- 0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70,
- 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17,
- 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7,
+static POW5TO256: [Digit; 19] = [
+ 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e,
+ 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7,
+ 0xf46eeddc, 0x5fdcefce, 0x553f7,
];
#[doc(hidden)]
pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big {
debug_assert!(n < 512);
+ // Save ourself the left shift for the smallest cases.
+ if n < 8 {
+ return x.mul_small(POW10[n & 7]);
+ }
+ // Multiply by the powers of 5 and shift the 2s in at the end.
+ // This keeps the intermediate products smaller and faster.
if n & 7 != 0 {
- x.mul_small(POW10[n & 7]);
+ x.mul_small(POW10[n & 7] >> (n & 7));
}
if n & 8 != 0 {
- x.mul_small(POW10[8]);
+ x.mul_small(POW10[8] >> 8);
}
if n & 16 != 0 {
- x.mul_digits(&POW10TO16);
+ x.mul_digits(&POW5TO16);
}
if n & 32 != 0 {
- x.mul_digits(&POW10TO32);
+ x.mul_digits(&POW5TO32);
}
if n & 64 != 0 {
- x.mul_digits(&POW10TO64);
+ x.mul_digits(&POW5TO64);
}
if n & 128 != 0 {
- x.mul_digits(&POW10TO128);
+ x.mul_digits(&POW5TO128);
}
if n & 256 != 0 {
- x.mul_digits(&POW10TO256);
+ x.mul_digits(&POW5TO256);
}
- x
+ x.mul_pow2(n)
}
fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big {
@@ -64,7 +65,7 @@ fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big {
x.div_rem_small(POW10[largest]);
n -= largest;
}
- x.div_rem_small(TWOPOW10[n]);
+ x.div_rem_small(POW10[n] << 1);
x
}
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 591ae58..dd88e85 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2197,10 +2197,11 @@ pub const fn wrapping_pow(self, mut exp: u32) -> Self {
acc.wrapping_mul(base)
}
- /// Calculates `self` + `rhs`
+ /// Calculates `self` + `rhs`.
///
- /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would
- /// occur. If an overflow would have occurred then the wrapped value is returned.
+ /// Returns a tuple of the addition along with a boolean indicating
+ /// whether an arithmetic overflow would occur. If an overflow would have
+ /// occurred then the wrapped value is returned.
///
/// # Examples
///
@@ -2278,7 +2279,7 @@ pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
(c, b != d)
}
- /// Calculates `self` + `rhs` with an unsigned `rhs`
+ /// Calculates `self` + `rhs` with an unsigned `rhs`.
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
@@ -3391,7 +3392,7 @@ pub const fn is_positive(self) -> bool { self > 0 }
#[inline(always)]
pub const fn is_negative(self) -> bool { self < 0 }
- /// Return the memory representation of this integer as a byte array in
+ /// Returns the memory representation of this integer as a byte array in
/// big-endian (network) byte order.
///
#[doc = $to_xe_bytes_doc]
@@ -3411,7 +3412,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
self.to_be().to_ne_bytes()
}
- /// Return the memory representation of this integer as a byte array in
+ /// Returns the memory representation of this integer as a byte array in
/// little-endian byte order.
///
#[doc = $to_xe_bytes_doc]
@@ -3431,7 +3432,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
self.to_le().to_ne_bytes()
}
- /// Return the memory representation of this integer as a byte array in
+ /// Returns the memory representation of this integer as a byte array in
/// native byte order.
///
/// As the target platform's native endianness is used, portable code
@@ -3469,7 +3470,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
unsafe { mem::transmute(self) }
}
- /// Create an integer value from its representation as a byte array in
+ /// Creates an integer value from its representation as a byte array in
/// big endian.
///
#[doc = $from_xe_bytes_doc]
@@ -3498,7 +3499,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
Self::from_be(Self::from_ne_bytes(bytes))
}
- /// Create an integer value from its representation as a byte array in
+ /// Creates an integer value from its representation as a byte array in
/// little endian.
///
#[doc = $from_xe_bytes_doc]
@@ -3527,7 +3528,7 @@ pub const fn is_negative(self) -> bool { self < 0 }
Self::from_le(Self::from_ne_bytes(bytes))
}
- /// Create an integer value from its memory representation as a byte
+ /// Creates an integer value from its memory representation as a byte
/// array in native endianness.
///
/// As the target platform's native endianness is used, portable code
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index e342a73..309e1ba 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -2,11 +2,9 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::ascii;
-use crate::intrinsics;
-use crate::mem;
use crate::str::FromStr;
use crate::ub_checks::assert_unsafe_precondition;
+use crate::{ascii, intrinsics, mem};
// Used because the `?` operator is not allowed in a const context.
macro_rules! try_opt {
@@ -48,39 +46,31 @@ macro_rules! unlikely {
mod saturating;
mod wrapping;
-#[stable(feature = "saturating_int_impl", since = "1.74.0")]
-pub use saturating::Saturating;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use wrapping::Wrapping;
-
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(no_fp_fmt_parse))]
pub use dec2flt::ParseFloatError;
-
+#[stable(feature = "int_error_matching", since = "1.55.0")]
+pub use error::IntErrorKind;
#[stable(feature = "rust1", since = "1.0.0")]
pub use error::ParseIntError;
-
+#[stable(feature = "try_from", since = "1.34.0")]
+pub use error::TryFromIntError;
+#[stable(feature = "generic_nonzero", since = "1.79.0")]
+pub use nonzero::NonZero;
#[unstable(
feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
pub use nonzero::ZeroablePrimitive;
-
-#[stable(feature = "generic_nonzero", since = "1.79.0")]
-pub use nonzero::NonZero;
-
#[stable(feature = "signed_nonzero", since = "1.34.0")]
pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
-
#[stable(feature = "nonzero", since = "1.28.0")]
pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
-
-#[stable(feature = "try_from", since = "1.34.0")]
-pub use error::TryFromIntError;
-
-#[stable(feature = "int_error_matching", since = "1.55.0")]
-pub use error::IntErrorKind;
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
+pub use saturating::Saturating;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use wrapping::Wrapping;
macro_rules! usize_isize_to_xe_bytes_doc {
() => {
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 64985e2..c6e9c24 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -1,18 +1,13 @@
//! Definitions of integer that is known not to equal zero.
+use super::{IntErrorKind, ParseIntError};
use crate::cmp::Ordering;
-use crate::fmt;
use crate::hash::{Hash, Hasher};
-use crate::hint;
-use crate::intrinsics;
use crate::marker::{Freeze, StructuralPartialEq};
use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign};
use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::ptr;
use crate::str::FromStr;
-use crate::ub_checks;
-
-use super::{IntErrorKind, ParseIntError};
+use crate::{fmt, hint, intrinsics, ptr, ub_checks};
/// A marker trait for primitive types which can be zero.
///
diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs
index d040539e..3f4791e 100644
--- a/library/core/src/num/saturating.rs
+++ b/library/core/src/num/saturating.rs
@@ -1,10 +1,10 @@
//! Definitions of `Saturating<T>`.
use crate::fmt;
-use crate::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign};
-use crate::ops::{BitXor, BitXorAssign, Div, DivAssign};
-use crate::ops::{Mul, MulAssign, Neg, Not, Rem, RemAssign};
-use crate::ops::{Sub, SubAssign};
+use crate::ops::{
+ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
+ Mul, MulAssign, Neg, Not, Rem, RemAssign, Sub, SubAssign,
+};
/// Provides intentionally-saturating arithmetic on `T`.
///
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index dec4444..a2e17fa 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -950,10 +950,10 @@ pub const fn checked_div(self, rhs: Self) -> Option<Self> {
}
/// Strict integer division. Computes `self / rhs`.
- /// Strict division on unsigned types is just normal division.
- /// There's no way overflow could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the strict operations.
+ ///
+ /// Strict division on unsigned types is just normal division. There's no
+ /// way overflow could ever happen. This function exists so that all
+ /// operations are accounted for in the strict operations.
///
/// # Panics
///
@@ -1009,12 +1009,11 @@ pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
}
/// Strict Euclidean division. Computes `self.div_euclid(rhs)`.
- /// Strict division on unsigned types is just normal division.
- /// There's no way overflow could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the strict operations.
- /// Since, for the positive integers, all common
- /// definitions of division are equal, this
+ ///
+ /// Strict division on unsigned types is just normal division. There's no
+ /// way overflow could ever happen. This function exists so that all
+ /// operations are accounted for in the strict operations. Since, for the
+ /// positive integers, all common definitions of division are equal, this
/// is exactly equal to `self.strict_div(rhs)`.
///
/// # Panics
@@ -1072,11 +1071,11 @@ pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
}
/// Strict integer remainder. Computes `self % rhs`.
- /// Strict remainder calculation on unsigned types is
- /// just the regular remainder calculation.
- /// There's no way overflow could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the strict operations.
+ ///
+ /// Strict remainder calculation on unsigned types is just the regular
+ /// remainder calculation. There's no way overflow could ever happen.
+ /// This function exists so that all operations are accounted for in the
+ /// strict operations.
///
/// # Panics
///
@@ -1132,14 +1131,13 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
}
/// Strict Euclidean modulo. Computes `self.rem_euclid(rhs)`.
- /// Strict modulo calculation on unsigned types is
- /// just the regular remainder calculation.
- /// There's no way overflow could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the strict operations.
- /// Since, for the positive integers, all common
- /// definitions of division are equal, this
- /// is exactly equal to `self.strict_rem(rhs)`.
+ ///
+ /// Strict modulo calculation on unsigned types is just the regular
+ /// remainder calculation. There's no way overflow could ever happen.
+ /// This function exists so that all operations are accounted for in the
+ /// strict operations. Since, for the positive integers, all common
+ /// definitions of division are equal, this is exactly equal to
+ /// `self.strict_rem(rhs)`.
///
/// # Panics
///
@@ -1916,10 +1914,10 @@ pub const fn wrapping_mul(self, rhs: Self) -> Self {
}
/// Wrapping (modular) division. Computes `self / rhs`.
- /// Wrapped division on unsigned types is just normal division.
- /// There's no way wrapping could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the wrapping operations.
+ ///
+ /// Wrapped division on unsigned types is just normal division. There's
+ /// no way wrapping could ever happen. This function exists so that all
+ /// operations are accounted for in the wrapping operations.
///
/// # Panics
///
@@ -1943,13 +1941,12 @@ pub const fn wrapping_div(self, rhs: Self) -> Self {
}
/// Wrapping Euclidean division. Computes `self.div_euclid(rhs)`.
- /// Wrapped division on unsigned types is just normal division.
- /// There's no way wrapping could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the wrapping operations.
- /// Since, for the positive integers, all common
- /// definitions of division are equal, this
- /// is exactly equal to `self.wrapping_div(rhs)`.
+ ///
+ /// Wrapped division on unsigned types is just normal division. There's
+ /// no way wrapping could ever happen. This function exists so that all
+ /// operations are accounted for in the wrapping operations. Since, for
+ /// the positive integers, all common definitions of division are equal,
+ /// this is exactly equal to `self.wrapping_div(rhs)`.
///
/// # Panics
///
@@ -1973,11 +1970,11 @@ pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
}
/// Wrapping (modular) remainder. Computes `self % rhs`.
- /// Wrapped remainder calculation on unsigned types is
- /// just the regular remainder calculation.
- /// There's no way wrapping could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the wrapping operations.
+ ///
+ /// Wrapped remainder calculation on unsigned types is just the regular
+ /// remainder calculation. There's no way wrapping could ever happen.
+ /// This function exists so that all operations are accounted for in the
+ /// wrapping operations.
///
/// # Panics
///
@@ -2001,14 +1998,13 @@ pub const fn wrapping_rem(self, rhs: Self) -> Self {
}
/// Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`.
- /// Wrapped modulo calculation on unsigned types is
- /// just the regular remainder calculation.
- /// There's no way wrapping could ever happen.
- /// This function exists, so that all operations
- /// are accounted for in the wrapping operations.
- /// Since, for the positive integers, all common
- /// definitions of division are equal, this
- /// is exactly equal to `self.wrapping_rem(rhs)`.
+ ///
+ /// Wrapped modulo calculation on unsigned types is just the regular
+ /// remainder calculation. There's no way wrapping could ever happen.
+ /// This function exists so that all operations are accounted for in the
+ /// wrapping operations. Since, for the positive integers, all common
+ /// definitions of division are equal, this is exactly equal to
+ /// `self.wrapping_rem(rhs)`.
///
/// # Panics
///
@@ -2164,7 +2160,7 @@ pub const fn wrapping_pow(self, mut exp: u32) -> Self {
acc.wrapping_mul(base)
}
- /// Calculates `self` + `rhs`
+ /// Calculates `self` + `rhs`.
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
@@ -2238,7 +2234,7 @@ pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
(c, b || d)
}
- /// Calculates `self` + `rhs` with a signed `rhs`
+ /// Calculates `self` + `rhs` with a signed `rhs`.
///
/// Returns a tuple of the addition along with a boolean indicating
/// whether an arithmetic overflow would occur. If an overflow would
@@ -2857,6 +2853,35 @@ pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
}
}
+ /// Returns `true` if `self` is an integer multiple of `rhs`, and false otherwise.
+ ///
+ /// This function is equivalent to `self % rhs == 0`, except that it will not panic
+ /// for `rhs == 0`. Instead, `0.is_multiple_of(0) == true`, and for any non-zero `n`,
+ /// `n.is_multiple_of(0) == false`.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(unsigned_is_multiple_of)]
+ #[doc = concat!("assert!(6_", stringify!($SelfT), ".is_multiple_of(2));")]
+ #[doc = concat!("assert!(!5_", stringify!($SelfT), ".is_multiple_of(2));")]
+ ///
+ #[doc = concat!("assert!(0_", stringify!($SelfT), ".is_multiple_of(0));")]
+ #[doc = concat!("assert!(!6_", stringify!($SelfT), ".is_multiple_of(0));")]
+ /// ```
+ #[unstable(feature = "unsigned_is_multiple_of", issue = "128101")]
+ #[must_use]
+ #[inline]
+ #[rustc_inherit_overflow_checks]
+ pub const fn is_multiple_of(self, rhs: Self) -> bool {
+ match rhs {
+ 0 => self == 0,
+ _ => self % rhs == 0,
+ }
+ }
+
/// Returns `true` if and only if `self == 2^k` for some `k`.
///
/// # Examples
@@ -2970,7 +2995,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
self.one_less_than_next_power_of_two().wrapping_add(1)
}
- /// Return the memory representation of this integer as a byte array in
+ /// Returns the memory representation of this integer as a byte array in
/// big-endian (network) byte order.
///
#[doc = $to_xe_bytes_doc]
@@ -2990,7 +3015,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
self.to_be().to_ne_bytes()
}
- /// Return the memory representation of this integer as a byte array in
+ /// Returns the memory representation of this integer as a byte array in
/// little-endian byte order.
///
#[doc = $to_xe_bytes_doc]
@@ -3010,7 +3035,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
self.to_le().to_ne_bytes()
}
- /// Return the memory representation of this integer as a byte array in
+ /// Returns the memory representation of this integer as a byte array in
/// native byte order.
///
/// As the target platform's native endianness is used, portable code
@@ -3048,7 +3073,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
unsafe { mem::transmute(self) }
}
- /// Create a native endian integer value from its representation
+ /// Creates a native endian integer value from its representation
/// as a byte array in big endian.
///
#[doc = $from_xe_bytes_doc]
@@ -3077,7 +3102,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
Self::from_be(Self::from_ne_bytes(bytes))
}
- /// Create a native endian integer value from its representation
+ /// Creates a native endian integer value from its representation
/// as a byte array in little endian.
///
#[doc = $from_xe_bytes_doc]
@@ -3106,7 +3131,7 @@ pub const fn wrapping_next_power_of_two(self) -> Self {
Self::from_le(Self::from_ne_bytes(bytes))
}
- /// Create a native endian integer value from its memory representation
+ /// Creates a native endian integer value from its memory representation
/// as a byte array in native endianness.
///
/// As the target platform's native endianness is used, portable code
diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs
index 16f0b6d..1ac6d316 100644
--- a/library/core/src/num/wrapping.rs
+++ b/library/core/src/num/wrapping.rs
@@ -1,10 +1,10 @@
//! Definitions of `Wrapping<T>`.
use crate::fmt;
-use crate::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign};
-use crate::ops::{BitXor, BitXorAssign, Div, DivAssign};
-use crate::ops::{Mul, MulAssign, Neg, Not, Rem, RemAssign};
-use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
+use crate::ops::{
+ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
+ Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
+};
/// Provides intentionally-wrapped arithmetic on `T`.
///
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index e10c438..a2709c6 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -238,7 +238,7 @@ pub fn map_continue<T, F>(self, f: F) -> ControlFlow<B, T>
/// They have mediocre names and non-obvious semantics, so aren't
/// currently on a path to potential stabilization.
impl<R: ops::Try> ControlFlow<R, R::Output> {
- /// Create a `ControlFlow` from any type implementing `Try`.
+ /// Creates a `ControlFlow` from any type implementing `Try`.
#[inline]
pub(crate) fn from_try(r: R) -> Self {
match R::branch(r) {
@@ -247,7 +247,7 @@ pub(crate) fn from_try(r: R) -> Self {
}
}
- /// Convert a `ControlFlow` into any type implementing `Try`;
+ /// Converts a `ControlFlow` into any type implementing `Try`.
#[inline]
pub(crate) fn into_try(self) -> R {
match self {
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index 753f14c..13df888 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -76,7 +76,7 @@ pub trait Coroutine<R = ()> {
/// values which are allowed to be returned each time a coroutine yields.
/// For example an iterator-as-a-coroutine would likely have this type as
/// `T`, the type being iterated over.
- #[cfg_attr(not(bootstrap), lang = "coroutine_yield")]
+ #[lang = "coroutine_yield"]
type Yield;
/// The type of value this coroutine returns.
@@ -85,7 +85,7 @@ pub trait Coroutine<R = ()> {
/// `return` statement or implicitly as the last expression of a coroutine
/// literal. For example futures would use this as `Result<T, E>` as it
/// represents a completed future.
- #[cfg_attr(not(bootstrap), lang = "coroutine_return")]
+ #[lang = "coroutine_return"]
type Return;
/// Resumes the execution of this coroutine.
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 9849410..f0d2c76 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -282,7 +282,7 @@ fn deref_mut(&mut self) -> &mut T {
/// FIXME(deref_patterns): The precise semantics are undecided; the rough idea is that
/// successive calls to `deref`/`deref_mut` without intermediate mutation should be
/// idempotent, in the sense that they return the same value as far as pattern-matching
-/// is concerned. Calls to `deref`/`deref_mut`` must leave the pointer itself likewise
+/// is concerned. Calls to `deref`/`deref_mut` must leave the pointer itself likewise
/// unchanged.
#[unstable(feature = "deref_pure_trait", issue = "87121")]
#[lang = "deref_pure"]
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index 36ae581..c6083a1 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -171,12 +171,13 @@
/// still be live when `T` gets dropped. The exact details of this analysis are not yet
/// stably guaranteed and **subject to change**. Currently, the analysis works as follows:
/// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if
-/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`]
-/// and [`ManuallyDrop`] are considered to never have a destructor, no matter their field type.
+/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`],
+/// arrays of length 0 and [`ManuallyDrop`] are considered to never have a destructor, no matter
+/// their field type.
/// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`,
/// recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of
/// owned types is determined by recursively traversing `T`:
-/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (including arrays of
+/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (excluding arrays of
/// length 0).
/// - Stop at reference and raw pointer types as well as function pointers and function items;
/// they do not own anything.
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 7bcfaad..98d41b7 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -156,65 +156,44 @@
pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub};
#[stable(feature = "op_assign_traits", since = "1.8.0")]
pub use self::arith::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
-
+#[unstable(feature = "async_fn_traits", issue = "none")]
+pub use self::async_function::{AsyncFn, AsyncFnMut, AsyncFnOnce};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
#[stable(feature = "op_assign_traits", since = "1.8.0")]
pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::deref::{Deref, DerefMut};
-
-#[unstable(feature = "deref_pure_trait", issue = "87121")]
-pub use self::deref::DerefPure;
-
-#[unstable(feature = "receiver_trait", issue = "none")]
-pub use self::deref::Receiver;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::drop::Drop;
-
-pub(crate) use self::drop::fallback_surface_drop;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::function::{Fn, FnMut, FnOnce};
-
-#[unstable(feature = "async_fn_traits", issue = "none")]
-pub use self::async_function::{AsyncFn, AsyncFnMut, AsyncFnOnce};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::index::{Index, IndexMut};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
-
-pub(crate) use self::index_range::IndexRange;
-
-#[stable(feature = "inclusive_range", since = "1.26.0")]
-pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
-
-#[unstable(feature = "one_sided_range", issue = "69780")]
-pub use self::range::OneSidedRange;
-
-#[unstable(feature = "try_trait_v2", issue = "84277")]
-pub use self::try_trait::{FromResidual, Try};
-
-#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
-pub use self::try_trait::Yeet;
-
-#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
-pub use self::try_trait::Residual;
-
-pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit};
-
-#[unstable(feature = "coroutine_trait", issue = "43122")]
-pub use self::coroutine::{Coroutine, CoroutineState};
-
-#[unstable(feature = "coerce_unsized", issue = "18598")]
-pub use self::unsize::CoerceUnsized;
-
-#[unstable(feature = "dispatch_from_dyn", issue = "none")]
-pub use self::unsize::DispatchFromDyn;
-
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
pub use self::control_flow::ControlFlow;
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+pub use self::coroutine::{Coroutine, CoroutineState};
+#[unstable(feature = "deref_pure_trait", issue = "87121")]
+pub use self::deref::DerefPure;
+#[unstable(feature = "receiver_trait", issue = "none")]
+pub use self::deref::Receiver;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::deref::{Deref, DerefMut};
+pub(crate) use self::drop::fallback_surface_drop;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::drop::Drop;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::function::{Fn, FnMut, FnOnce};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::index::{Index, IndexMut};
+pub(crate) use self::index_range::IndexRange;
+#[unstable(feature = "one_sided_range", issue = "69780")]
+pub use self::range::OneSidedRange;
+#[stable(feature = "inclusive_range", since = "1.26.0")]
+pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
+#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+pub use self::try_trait::Residual;
+#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
+pub use self::try_trait::Yeet;
+pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit};
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+pub use self::try_trait::{FromResidual, Try};
+#[unstable(feature = "coerce_unsized", issue = "18598")]
+pub use self::unsize::CoerceUnsized;
+#[unstable(feature = "dispatch_from_dyn", issue = "none")]
+pub use self::unsize::DispatchFromDyn;
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index d93cb8d..6c89c81 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -557,13 +557,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::iter::{self, FusedIterator, TrustedLen};
+use crate::ops::{self, ControlFlow, Deref, DerefMut};
use crate::panicking::{panic, panic_display};
use crate::pin::Pin;
-use crate::{
- cmp, convert, hint, mem,
- ops::{self, ControlFlow, Deref, DerefMut},
- slice,
-};
+use crate::{cmp, convert, hint, mem, slice};
/// The `Option` type. See [the module level documentation](self) for more.
#[derive(Copy, Eq, Debug, Hash)]
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 37c338d..6c5236e 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -6,16 +6,15 @@
mod panic_info;
mod unwind_safe;
-use crate::any::Any;
-
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use self::location::Location;
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use self::panic_info::PanicInfo;
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
pub use self::panic_info::PanicMessage;
#[stable(feature = "catch_unwind", since = "1.9.0")]
pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
+use crate::any::Any;
#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
@@ -160,7 +159,7 @@ pub unsafe trait PanicPayload: crate::fmt::Display {
/// Just borrow the contents.
fn get(&mut self) -> &(dyn Any + Send);
- /// Try to borrow the contents as `&str`, if possible without doing any allocations.
+ /// Tries to borrow the contents as `&str`, if possible without doing any allocations.
fn as_str(&mut self) -> Option<&str> {
None
}
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index 6bbb9c3..e4d0c89 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -24,7 +24,7 @@ pub struct PanicInfo<'a> {
/// that were given to the `panic!()` macro.
///
/// See [`PanicInfo::message`].
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
pub struct PanicMessage<'a> {
message: fmt::Arguments<'a>,
}
@@ -57,7 +57,7 @@ pub(crate) fn new(
/// }
/// ```
#[must_use]
- #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "panic_info_message", since = "1.81.0")]
pub fn message(&self) -> PanicMessage<'_> {
PanicMessage { message: self.message }
}
@@ -152,7 +152,7 @@ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
}
impl<'a> PanicMessage<'a> {
- /// Get the formatted message, if it has no arguments to be formatted at runtime.
+ /// Gets the formatted message, if it has no arguments to be formatted at runtime.
///
/// This can be used to avoid allocations in some cases.
///
@@ -164,7 +164,7 @@ impl<'a> PanicMessage<'a> {
/// For most cases with placeholders, this function will return `None`.
///
/// See [`fmt::Arguments::as_str`] for details.
- #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "panic_info_message", since = "1.81.0")]
#[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
#[must_use]
#[inline]
@@ -173,7 +173,7 @@ pub const fn as_str(&self) -> Option<&'static str> {
}
}
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
impl Display for PanicMessage<'_> {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -181,7 +181,7 @@ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
impl fmt::Debug for PanicMessage<'_> {
#[inline]
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 97fb1d6..7affe63 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -294,10 +294,11 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
)
}
-/// Panic because we cannot unwind out of a function.
+/// Panics because we cannot unwind out of a function.
///
/// This is a separate function to avoid the codesize impact of each crate containing the string to
/// pass to `panic_nounwind`.
+///
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
@@ -309,10 +310,11 @@ fn panic_cannot_unwind() -> ! {
panic_nounwind("panic in a function that cannot unwind")
}
-/// Panic because we are unwinding out of a destructor during cleanup.
+/// Panics because we are unwinding out of a destructor during cleanup.
///
/// This is a separate function to avoid the codesize impact of each crate containing the string to
/// pass to `panic_nounwind`.
+///
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs
index a10c459..1f89d96 100644
--- a/library/core/src/pat.rs
+++ b/library/core/src/pat.rs
@@ -6,7 +6,7 @@
/// ```
#[macro_export]
#[rustc_builtin_macro(pattern_type)]
-#[unstable(feature = "core_pattern_type", issue = "none")]
+#[unstable(feature = "core_pattern_type", issue = "123646")]
macro_rules! pattern_type {
($($arg:tt)*) => {
/* compiler built-in */
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 0d2aa30..0569b8b 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -421,7 +421,7 @@
//! }
//!
//! impl Unmovable {
-//! /// Create a new `Unmovable`.
+//! /// Creates a new `Unmovable`.
//! ///
//! /// To ensure the data doesn't move we place it on the heap behind a pinning Box.
//! /// Note that the data is pinned, but the `Pin<Box<Self>>` which is pinning it can
@@ -920,11 +920,8 @@
#![stable(feature = "pin", since = "1.33.0")]
-use crate::cmp;
-use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver};
-
#[allow(unused_imports)]
use crate::{
cell::{RefCell, UnsafeCell},
@@ -932,6 +929,7 @@
marker::PhantomPinned,
mem, ptr,
};
+use crate::{cmp, fmt};
/// A pointer which pins its pointee in place.
///
@@ -1168,7 +1166,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
}
impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
- /// Construct a new `Pin<Ptr>` around a pointer to some data of a type that
+ /// Constructs a new `Pin<Ptr>` around a pointer to some data of a type that
/// implements [`Unpin`].
///
/// Unlike `Pin::new_unchecked`, this method is safe because the pointer
@@ -1223,7 +1221,7 @@ pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
}
impl<Ptr: Deref> Pin<Ptr> {
- /// Construct a new `Pin<Ptr>` around a reference to some data of a type that
+ /// Constructs a new `Pin<Ptr>` around a reference to some data of a type that
/// may or may not implement [`Unpin`].
///
/// If `pointer` dereferences to an [`Unpin`] type, [`Pin::new`] should be used
@@ -1569,7 +1567,7 @@ pub const fn get_mut(self) -> &'a mut T
self.__pointer
}
- /// Construct a new pin by mapping the interior value.
+ /// Constructs a new pin by mapping the interior value.
///
/// For example, if you wanted to get a `Pin` of a field of something,
/// you could use this to get access to that field in one line of code.
@@ -1602,7 +1600,7 @@ pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U>
}
impl<T: ?Sized> Pin<&'static T> {
- /// Get a pinning reference from a `&'static` reference.
+ /// Gets a pinning reference from a `&'static` reference.
///
/// This is safe because `T` is borrowed immutably for the `'static` lifetime, which
/// never ends.
@@ -1639,8 +1637,8 @@ pub fn as_deref_mut(self) -> Pin<&'a mut Ptr::Target> {
//
// We need to ensure that two things hold for that to be the case:
//
- // 1) Once we give out a `Pin<&mut Ptr::Target>`, an `&mut Ptr::Target` will not be given out.
- // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk of violating
+ // 1) Once we give out a `Pin<&mut Ptr::Target>`, a `&mut Ptr::Target` will not be given out.
+ // 2) By giving out a `Pin<&mut Ptr::Target>`, we do not risk violating
// `Pin<&mut Pin<Ptr>>`
//
// The existence of `Pin<Ptr>` is sufficient to guarantee #1: since we already have a
@@ -1656,7 +1654,7 @@ pub fn as_deref_mut(self) -> Pin<&'a mut Ptr::Target> {
}
impl<T: ?Sized> Pin<&'static mut T> {
- /// Get a pinning mutable reference from a static mutable reference.
+ /// Gets a pinning mutable reference from a static mutable reference.
///
/// This is safe because `T` is borrowed for the `'static` lifetime, which
/// never ends.
@@ -1717,10 +1715,56 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// for other reasons, though, so we just need to take care not to allow such
// impls to land in std.
#[stable(feature = "pin", since = "1.33.0")]
-impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr> where Ptr: CoerceUnsized<U> {}
+impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr>
+where
+ Ptr: CoerceUnsized<U> + PinCoerceUnsized,
+ U: PinCoerceUnsized,
+{
+}
#[stable(feature = "pin", since = "1.33.0")]
-impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U> {}
+impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>
+where
+ Ptr: DispatchFromDyn<U> + PinCoerceUnsized,
+ U: PinCoerceUnsized,
+{
+}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+/// Trait that indicates that this is a pointer or a wrapper for one, where
+/// unsizing can be performed on the pointee when it is pinned.
+///
+/// # Safety
+///
+/// If this type implements `Deref`, then the concrete type returned by `deref`
+/// and `deref_mut` must not change without a modification. The following
+/// operations are not considered modifications:
+///
+/// * Moving the pointer.
+/// * Performing unsizing coercions on the pointer.
+/// * Performing dynamic dispatch with the pointer.
+/// * Calling `deref` or `deref_mut` on the pointer.
+///
+/// The concrete type of a trait object is the type that the vtable corresponds
+/// to. The concrete type of a slice is an array of the same element type and
+/// the length specified in the metadata. The concrete type of a sized type
+/// is the type itself.
+pub unsafe trait PinCoerceUnsized {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: PinCoerceUnsized> PinCoerceUnsized for Pin<T> {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for *const T {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
///
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 5989bcb..09ebef8 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1244,6 +1244,9 @@ mod prim_f64 {}
/// actually implement it. For x86-64 and AArch64, ISA support is not even specified,
/// so it will always be a software implementation significantly slower than `f64`.
///
+/// _Note: `f128` support is incomplete. Many platforms will not be able to link math functions. On
+/// x86 in particular, these functions do link but their results are always incorrect._
+///
/// *[See also the `std::f128::consts` module](crate::f128::consts).*
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 3e7933e..93bbd92 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -61,7 +61,7 @@ pub const fn cast<U>(self) -> *const U {
self as _
}
- /// Use the pointer value in a new pointer of another type.
+ /// Uses the pointer value in a new pointer of another type.
///
/// In case `meta` is a (fat) pointer to an unsized type, this operation
/// will ignore the pointer part, whereas for (thin) pointers to sized
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 06f205c..ccc9f87 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -2,8 +2,7 @@
use crate::fmt;
use crate::hash::{Hash, Hasher};
-use crate::intrinsics::aggregate_raw_ptr;
-use crate::intrinsics::ptr_metadata;
+use crate::intrinsics::{aggregate_raw_ptr, ptr_metadata};
use crate::marker::Freeze;
use crate::ptr::NonNull;
@@ -81,7 +80,7 @@ pub trait Pointee {
// NOTE: don’t stabilize this before trait aliases are stable in the language?
pub trait Thin = Pointee<Metadata = ()>;
-/// Extract the metadata component of a pointer.
+/// Extracts the metadata component of a pointer.
///
/// Values of type `*mut T`, `&T`, or `&mut T` can be passed directly to this function
/// as they implicitly coerce to `*const T`.
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 9b0aa2e..25d8f4a 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -196,9 +196,9 @@
//! * The **provenance** it has, defining the memory it has permission to access.
//! Provenance can be absent, in which case the pointer does not have permission to access any memory.
//!
-//! Under Strict Provenance, a usize *cannot* accurately represent a pointer, and converting from
-//! a pointer to a usize is generally an operation which *only* extracts the address. It is
-//! therefore *impossible* to construct a valid pointer from a usize because there is no way
+//! Under Strict Provenance, a `usize` *cannot* accurately represent a pointer, and converting from
+//! a pointer to a `usize` is generally an operation which *only* extracts the address. It is
+//! therefore *impossible* to construct a valid pointer from a `usize` because there is no way
//! to restore the address-space and provenance. In other words, pointer-integer-pointer
//! roundtrips are not possible (in the sense that the resulting pointer is not dereferenceable).
//!
@@ -234,16 +234,16 @@
//!
//! Most code needs no changes to conform to strict provenance, as the only really concerning
//! operation that *wasn't* obviously already Undefined Behaviour is casts from usize to a
-//! pointer. For code which *does* cast a usize to a pointer, the scope of the change depends
+//! pointer. For code which *does* cast a `usize` to a pointer, the scope of the change depends
//! on exactly what you're doing.
//!
-//! In general, you just need to make sure that if you want to convert a usize address to a
+//! In general, you just need to make sure that if you want to convert a `usize` address to a
//! pointer and then use that pointer to read/write memory, you need to keep around a pointer
//! that has sufficient provenance to perform that read/write itself. In this way all of your
//! casts from an address to a pointer are essentially just applying offsets/indexing.
//!
//! This is generally trivial to do for simple cases like tagged pointers *as long as you
-//! represent the tagged pointer as an actual pointer and not a usize*. For instance:
+//! represent the tagged pointer as an actual pointer and not a `usize`*. For instance:
//!
//! ```
//! #![feature(strict_provenance)]
@@ -409,13 +409,9 @@
#![allow(clippy::not_unsafe_ptr_arg_deref)]
use crate::cmp::Ordering;
-use crate::fmt;
-use crate::hash;
-use crate::intrinsics;
use crate::marker::FnPtr;
-use crate::ub_checks;
-
use crate::mem::{self, MaybeUninit};
+use crate::{fmt, hash, intrinsics, ub_checks};
mod alignment;
#[unstable(feature = "ptr_alignment_type", issue = "102070")]
@@ -423,12 +419,10 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
-pub use crate::intrinsics::copy_nonoverlapping;
-
+pub use crate::intrinsics::copy;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
-pub use crate::intrinsics::copy;
-
+pub use crate::intrinsics::copy_nonoverlapping;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
pub use crate::intrinsics::write_bytes;
@@ -606,7 +600,7 @@ pub const fn null_mut<T: ?Sized + Thin>() -> *mut T {
/// Without provenance, this pointer is not associated with any actual allocation. Such a
/// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but
/// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers are
-/// little more than a usize address in disguise.
+/// little more than a `usize` address in disguise.
///
/// This is different from `addr as *const T`, which creates a pointer that picks up a previously
/// exposed provenance. See [`with_exposed_provenance`] for more details on that operation.
@@ -650,7 +644,7 @@ pub const fn dangling<T>() -> *const T {
/// Without provenance, this pointer is not associated with any actual allocation. Such a
/// no-provenance pointer may be used for zero-sized memory accesses (if suitably aligned), but
/// non-zero-sized memory accesses with a no-provenance pointer are UB. No-provenance pointers are
-/// little more than a usize address in disguise.
+/// little more than a `usize` address in disguise.
///
/// This is different from `addr as *mut T`, which creates a pointer that picks up a previously
/// exposed provenance. See [`with_exposed_provenance_mut`] for more details on that operation.
@@ -687,7 +681,7 @@ pub const fn dangling_mut<T>() -> *mut T {
without_provenance_mut(mem::align_of::<T>())
}
-/// Convert an address back to a pointer, picking up a previously 'exposed' provenance.
+/// Converts an address back to a pointer, picking up a previously 'exposed' provenance.
///
/// This is a more rigorously specified alternative to `addr as *const T`. The provenance of the
/// returned pointer is that of *any* pointer that was previously exposed by passing it to
@@ -735,7 +729,7 @@ pub fn with_exposed_provenance<T>(addr: usize) -> *const T
addr as *const T
}
-/// Convert an address back to a mutable pointer, picking up a previously 'exposed' provenance.
+/// Converts an address back to a mutable pointer, picking up a previously 'exposed' provenance.
///
/// This is a more rigorously specified alternative to `addr as *mut T`. The provenance of the
/// returned pointer is that of *any* pointer that was previously passed to
@@ -775,7 +769,7 @@ pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T
addr as *mut T
}
-/// Convert a reference to a raw pointer.
+/// Converts a reference to a raw pointer.
///
/// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T` (except for the caveat noted below),
/// but is a bit safer since it will never silently change type or mutability, in particular if the
@@ -786,7 +780,7 @@ pub fn with_exposed_provenance_mut<T>(addr: usize) -> *mut T
///
/// The caller must also ensure that the memory the pointer (non-transitively) points to is never
/// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If
-/// you need to mutate the pointee, use [`from_mut`]`. Specifically, to turn a mutable reference `m:
+/// you need to mutate the pointee, use [`from_mut`]. Specifically, to turn a mutable reference `m:
/// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be
/// used for mutation.
///
@@ -832,7 +826,7 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
r
}
-/// Convert a mutable reference to a raw pointer.
+/// Converts a mutable reference to a raw pointer.
///
/// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T` (except for the caveat noted
/// below), but is a bit safer since it will never silently change type or mutability, in particular
@@ -1468,7 +1462,7 @@ macro_rules! attempt_swap_as_chunks {
///
/// # Examples
///
-/// Read a usize value from a byte buffer:
+/// Read a `usize` value from a byte buffer:
///
/// ```
/// use std::mem;
@@ -1679,7 +1673,7 @@ macro_rules! attempt_swap_as_chunks {
///
/// # Examples
///
-/// Write a usize value to a byte buffer:
+/// Write a `usize` value to a byte buffer:
///
/// ```
/// use std::mem;
@@ -2014,7 +2008,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
let y = cttz_nonzero(a);
if x < y { x } else { y }
};
- // SAFETY: gcdpow has an upper-bound that’s at most the number of bits in a usize.
+ // SAFETY: gcdpow has an upper-bound that’s at most the number of bits in a `usize`.
let gcd = unsafe { unchecked_shl(1usize, gcdpow) };
// SAFETY: gcd is always greater or equal to 1.
if addr & unsafe { unchecked_sub(gcd, 1) } == 0 {
@@ -2213,7 +2207,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
-/// Create a `const` raw pointer to a place, without creating an intermediate reference.
+/// Creates a `const` raw pointer to a place, without creating an intermediate reference.
///
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
/// and points to initialized data. For cases where those requirements do not hold,
@@ -2287,7 +2281,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
&raw const $place
}
-/// Create a `mut` raw pointer to a place, without creating an intermediate reference.
+/// Creates a `mut` raw pointer to a place, without creating an intermediate reference.
///
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
/// and points to initialized data. For cases where those requirements do not hold,
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 904d6c6..bcf9b88 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -60,7 +60,7 @@ pub const fn cast<U>(self) -> *mut U {
self as _
}
- /// Use the pointer value in a new pointer of another type.
+ /// Uses the pointer value in a new pointer of another type.
///
/// In case `meta` is a (fat) pointer to an unsized type, this operation
/// will ignore the pointer part, whereas for (thin) pointers to sized
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 796c85d..d6be37a 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1,15 +1,13 @@
use crate::cmp::Ordering;
-use crate::fmt;
-use crate::hash;
-use crate::intrinsics;
use crate::marker::Unsize;
use crate::mem::{MaybeUninit, SizedTypeProperties};
use crate::num::NonZero;
use crate::ops::{CoerceUnsized, DispatchFromDyn};
-use crate::ptr;
+use crate::pin::PinCoerceUnsized;
use crate::ptr::Unique;
use crate::slice::{self, SliceIndex};
use crate::ub_checks::assert_unsafe_precondition;
+use crate::{fmt, hash, intrinsics, ptr};
/// `*mut T` but non-zero and [covariant].
///
@@ -1171,9 +1169,7 @@ pub unsafe fn replace(self, src: T) -> T
/// `align`.
///
/// If it is not possible to align the pointer, the implementation returns
- /// `usize::MAX`. It is permissible for the implementation to *always*
- /// return `usize::MAX`. Only your algorithm's performance can depend
- /// on getting a usable offset here, not its correctness.
+ /// `usize::MAX`.
///
/// The offset is expressed in number of `T` elements, and not bytes.
///
@@ -1181,6 +1177,15 @@ pub unsafe fn replace(self, src: T) -> T
/// beyond the allocation that the pointer points into. It is up to the caller to ensure that
/// the returned offset is correct in all terms other than alignment.
///
+ /// When this is called during compile-time evaluation (which is unstable), the implementation
+ /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
+ /// actual alignment of pointers is not known yet during compile-time, so an offset with
+ /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
+ /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
+ /// known, so the execution has to be correct for either choice. It is therefore impossible to
+ /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
+ /// for unstable APIs.)
+ ///
/// # Panics
///
/// The function panics if `align` is not a power-of-two.
@@ -1727,6 +1732,9 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Uns
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for NonNull<T> {}
+
#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized> fmt::Debug for NonNull<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index b74d691..4810ebe 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -1,6 +1,7 @@
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::pin::PinCoerceUnsized;
use crate::ptr::NonNull;
/// A wrapper around a raw non-null `*mut T` that indicates that the possessor
@@ -166,6 +167,9 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsiz
#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for Unique<T> {}
+
#[unstable(feature = "ptr_internals", issue = "none")]
impl<T: ?Sized> fmt::Debug for Unique<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index bfbbf12..408972c 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -25,15 +25,13 @@
pub mod legacy;
#[doc(inline)]
-pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive};
-
+pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
use Bound::{Excluded, Included, Unbounded};
#[doc(inline)]
pub use crate::iter::Step;
-
#[doc(inline)]
-pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
+pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive};
/// A (half-open) range bounded inclusively below and exclusively above
/// (`start..end` in a future edition).
@@ -72,7 +70,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
}
impl<Idx: Step> Range<Idx> {
- /// Create an iterator over the elements within this range.
+ /// Creates an iterator over the elements within this range.
///
/// Shorthand for `.clone().into_iter()`
///
@@ -292,7 +290,7 @@ pub fn is_empty(&self) -> bool {
}
impl<Idx: Step> RangeInclusive<Idx> {
- /// Create an iterator over the elements within this range.
+ /// Creates an iterator over the elements within this range.
///
/// Shorthand for `.clone().into_iter()`
///
@@ -408,7 +406,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
}
impl<Idx: Step> RangeFrom<Idx> {
- /// Create an iterator over the elements within this range.
+ /// Creates an iterator over the elements within this range.
///
/// Shorthand for `.clone().into_iter()`
///
diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs
index 2b7db47..4935280 100644
--- a/library/core/src/range/iter.rs
+++ b/library/core/src/range/iter.rs
@@ -1,9 +1,8 @@
-use crate::num::NonZero;
-use crate::range::{legacy, Range, RangeFrom, RangeInclusive};
-
use crate::iter::{
FusedIterator, Step, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep,
};
+use crate::num::NonZero;
+use crate::range::{legacy, Range, RangeFrom, RangeInclusive};
/// By-value [`Range`] iterator.
#[unstable(feature = "new_range_api", issue = "125687")]
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index bf444d2..d1ea52f 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -1,12 +1,10 @@
//! Operations on ASCII `[u8]`.
-use crate::ascii;
-use crate::fmt::{self, Write};
-use crate::iter;
-use crate::mem;
-use crate::ops;
use core::ascii::EscapeDefault;
+use crate::fmt::{self, Write};
+use crate::{ascii, iter, mem, ops};
+
#[cfg(not(test))]
impl [u8] {
/// Checks if all bytes in this slice are within the ASCII range.
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 5bee4d5..d19d0ea 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -1,12 +1,10 @@
//! Comparison traits for `[T]`.
+use super::{from_raw_parts, memchr};
use crate::cmp::{self, BytewiseEq, Ordering};
use crate::intrinsics::compare_bytes;
use crate::mem;
-use super::from_raw_parts;
-use super::memchr;
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> PartialEq<[U]> for [T]
where
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 2624a44..de1492e 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,9 +1,8 @@
//! Indexing implementations for `[T]`.
use crate::intrinsics::const_eval_select;
-use crate::ops;
-use crate::range;
use crate::ub_checks::assert_unsafe_precondition;
+use crate::{ops, range};
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, I> ops::Index<I> for [T]
@@ -214,6 +213,7 @@ pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
/// Returns a pointer to the output at this location, without
/// performing any bounds checking.
+ ///
/// Calling this method with an out-of-bounds index or a dangling `slice` pointer
/// is *[undefined behavior]* even if the resulting pointer is not used.
///
@@ -223,6 +223,7 @@ pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
/// Returns a mutable pointer to the output at this location, without
/// performing any bounds checking.
+ ///
/// Calling this method with an out-of-bounds index or a dangling `slice` pointer
/// is *[undefined behavior]* even if the resulting pointer is not used.
///
@@ -802,13 +803,13 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
}
}
-/// Performs bounds-checking of a range.
+/// Performs bounds checking of a range.
///
/// This method is similar to [`Index::index`] for slices, but it returns a
/// [`Range`] equivalent to `range`. You can use this method to turn any range
/// into `start` and `end` values.
///
-/// `bounds` is the range of the slice to use for bounds-checking. It should
+/// `bounds` is the range of the slice to use for bounds checking. It should
/// be a [`RangeTo`] range that ends at the length of the slice.
///
/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
@@ -898,7 +899,7 @@ pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
ops::Range { start, end }
}
-/// Performs bounds-checking of a range without panicking.
+/// Performs bounds checking of a range without panicking.
///
/// This is a version of [`range()`] that returns [`None`] instead of panicking.
///
@@ -951,7 +952,8 @@ pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<
if start > end || end > len { None } else { Some(ops::Range { start, end }) }
}
-/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
+/// Converts a pair of `ops::Bound`s into `ops::Range` without performing any
+/// bounds checking or (in debug) overflow checking.
pub(crate) fn into_range_unchecked(
len: usize,
(start, end): (ops::Bound<usize>, ops::Bound<usize>),
@@ -970,7 +972,7 @@ pub(crate) fn into_range_unchecked(
start..end
}
-/// Convert pair of `ops::Bound`s into `ops::Range`.
+/// Converts pair of `ops::Bound`s into `ops::Range`.
/// Returns `None` on overflowing indices.
pub(crate) fn into_range(
len: usize,
@@ -995,7 +997,7 @@ pub(crate) fn into_range(
Some(start..end)
}
-/// Convert pair of `ops::Bound`s into `ops::Range`.
+/// Converts pair of `ops::Bound`s into `ops::Range`.
/// Panics on overflowing indices.
pub(crate) fn into_slice_range(
len: usize,
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 504676c..62b170a 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -3,8 +3,7 @@
#[macro_use] // import iterator! and forward_iterator!
mod macros;
-use crate::cmp;
-use crate::fmt;
+use super::{from_raw_parts, from_raw_parts_mut};
use crate::hint::assert_unchecked;
use crate::iter::{
FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, UncheckedIterator,
@@ -13,8 +12,7 @@
use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZero;
use crate::ptr::{self, without_provenance, without_provenance_mut, NonNull};
-
-use super::{from_raw_parts, from_raw_parts_mut};
+use crate::{cmp, fmt};
#[stable(feature = "boxed_slice_into_iter", since = "1.80.0")]
impl<T> !Iterator for [T] {}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 8b50262..c761577 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -7,16 +7,13 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::cmp::Ordering::{self, Equal, Greater, Less};
-use crate::fmt;
-use crate::hint;
-use crate::intrinsics::{exact_div, unchecked_sub};
+use crate::intrinsics::{exact_div, select_unpredictable, unchecked_sub};
use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZero;
use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
-use crate::ptr;
use crate::simd::{self, Simd};
-use crate::slice;
use crate::ub_checks::assert_unsafe_precondition;
+use crate::{fmt, hint, ptr, slice};
#[unstable(
feature = "slice_internals",
@@ -31,6 +28,7 @@
issue = "none",
reason = "exposed from core to be reused in std;"
)]
+#[doc(hidden)]
pub mod sort;
mod ascii;
@@ -44,52 +42,38 @@
#[unstable(feature = "str_internals", issue = "none")]
#[doc(hidden)]
pub use ascii::is_ascii_simple;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use iter::{Chunks, ChunksMut, Windows};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use iter::{Iter, IterMut};
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use iter::{RSplitN, RSplitNMut, Split, SplitMut, SplitN, SplitNMut};
-
-#[stable(feature = "slice_rsplit", since = "1.27.0")]
-pub use iter::{RSplit, RSplitMut};
-
-#[stable(feature = "chunks_exact", since = "1.31.0")]
-pub use iter::{ChunksExact, ChunksExactMut};
-
-#[stable(feature = "rchunks", since = "1.31.0")]
-pub use iter::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
-
-#[unstable(feature = "array_chunks", issue = "74985")]
-pub use iter::{ArrayChunks, ArrayChunksMut};
-
-#[unstable(feature = "array_windows", issue = "75027")]
-pub use iter::ArrayWindows;
-
-#[stable(feature = "slice_group_by", since = "1.77.0")]
-pub use iter::{ChunkBy, ChunkByMut};
-
-#[stable(feature = "split_inclusive", since = "1.51.0")]
-pub use iter::{SplitInclusive, SplitInclusiveMut};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use raw::{from_raw_parts, from_raw_parts_mut};
-
-#[stable(feature = "from_ref", since = "1.28.0")]
-pub use raw::{from_mut, from_ref};
-
-#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
-pub use raw::{from_mut_ptr_range, from_ptr_range};
-
-#[stable(feature = "slice_get_slice", since = "1.28.0")]
-pub use index::SliceIndex;
-
-#[unstable(feature = "slice_range", issue = "76393")]
-pub use index::{range, try_range};
-
#[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
pub use ascii::EscapeAscii;
+#[stable(feature = "slice_get_slice", since = "1.28.0")]
+pub use index::SliceIndex;
+#[unstable(feature = "slice_range", issue = "76393")]
+pub use index::{range, try_range};
+#[unstable(feature = "array_windows", issue = "75027")]
+pub use iter::ArrayWindows;
+#[unstable(feature = "array_chunks", issue = "74985")]
+pub use iter::{ArrayChunks, ArrayChunksMut};
+#[stable(feature = "slice_group_by", since = "1.77.0")]
+pub use iter::{ChunkBy, ChunkByMut};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use iter::{Chunks, ChunksMut, Windows};
+#[stable(feature = "chunks_exact", since = "1.31.0")]
+pub use iter::{ChunksExact, ChunksExactMut};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use iter::{Iter, IterMut};
+#[stable(feature = "rchunks", since = "1.31.0")]
+pub use iter::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
+#[stable(feature = "slice_rsplit", since = "1.27.0")]
+pub use iter::{RSplit, RSplitMut};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use iter::{RSplitN, RSplitNMut, Split, SplitMut, SplitN, SplitNMut};
+#[stable(feature = "split_inclusive", since = "1.51.0")]
+pub use iter::{SplitInclusive, SplitInclusiveMut};
+#[stable(feature = "from_ref", since = "1.28.0")]
+pub use raw::{from_mut, from_ref};
+#[unstable(feature = "slice_from_ptr_range", issue = "89792")]
+pub use raw::{from_mut_ptr_range, from_ptr_range};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use raw::{from_raw_parts, from_raw_parts_mut};
/// Calculates the direction and split point of a one-sided range.
///
@@ -321,7 +305,7 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
if let [.., last] = self { Some(last) } else { None }
}
- /// Return an array reference to the first `N` items in the slice.
+ /// Returns an array reference to the first `N` items in the slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
///
@@ -350,7 +334,7 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
}
}
- /// Return a mutable array reference to the first `N` items in the slice.
+ /// Returns a mutable array reference to the first `N` items in the slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
///
@@ -381,7 +365,7 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
}
}
- /// Return an array reference to the first `N` items in the slice and the remaining slice.
+ /// Returns an array reference to the first `N` items in the slice and the remaining slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
///
@@ -413,7 +397,7 @@ pub const fn last_mut(&mut self) -> Option<&mut T> {
}
}
- /// Return a mutable array reference to the first `N` items in the slice and the remaining
+ /// Returns a mutable array reference to the first `N` items in the slice and the remaining
/// slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
@@ -451,7 +435,7 @@ pub const fn split_first_chunk_mut<const N: usize>(
}
}
- /// Return an array reference to the last `N` items in the slice and the remaining slice.
+ /// Returns an array reference to the last `N` items in the slice and the remaining slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
///
@@ -483,7 +467,7 @@ pub const fn split_first_chunk_mut<const N: usize>(
}
}
- /// Return a mutable array reference to the last `N` items in the slice and the remaining
+ /// Returns a mutable array reference to the last `N` items in the slice and the remaining
/// slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
@@ -521,7 +505,7 @@ pub const fn split_last_chunk_mut<const N: usize>(
}
}
- /// Return an array reference to the last `N` items in the slice.
+ /// Returns an array reference to the last `N` items in the slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
///
@@ -539,7 +523,7 @@ pub const fn split_last_chunk_mut<const N: usize>(
/// ```
#[inline]
#[stable(feature = "slice_first_last_chunk", since = "1.77.0")]
- #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")]
+ #[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")]
pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> {
if self.len() < N {
None
@@ -554,7 +538,7 @@ pub const fn split_last_chunk_mut<const N: usize>(
}
}
- /// Return a mutable array reference to the last `N` items in the slice.
+ /// Returns a mutable array reference to the last `N` items in the slice.
///
/// If the slice is not at least `N` in length, this will return `None`.
///
@@ -828,7 +812,7 @@ pub const fn as_ptr_range(&self) -> Range<*const T> {
// - Both pointers are part of the same object, as pointing directly
// past the object also counts.
//
- // - The size of the slice is never larger than isize::MAX bytes, as
+ // - The size of the slice is never larger than `isize::MAX` bytes, as
// noted here:
// - https://github.com/rust-lang/unsafe-code-guidelines/issues/102#issuecomment-473340447
// - https://doc.rust-lang.org/reference/behavior-considered-undefined.html
@@ -839,7 +823,7 @@ pub const fn as_ptr_range(&self) -> Range<*const T> {
// - There is no wrapping around involved, as slices do not wrap past
// the end of the address space.
//
- // See the documentation of pointer::add.
+ // See the documentation of [`pointer::add`].
let end = unsafe { start.add(self.len()) };
start..end
}
@@ -2787,41 +2771,54 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
where
F: FnMut(&'a T) -> Ordering,
{
- // INVARIANTS:
- // - 0 <= left <= left + size = right <= self.len()
- // - f returns Less for everything in self[..left]
- // - f returns Greater for everything in self[right..]
let mut size = self.len();
- let mut left = 0;
- let mut right = size;
- while left < right {
- let mid = left + size / 2;
+ if size == 0 {
+ return Err(0);
+ }
+ let mut base = 0usize;
- // SAFETY: the while condition means `size` is strictly positive, so
- // `size/2 < size`. Thus `left + size/2 < left + size`, which
- // coupled with the `left + size <= self.len()` invariant means
- // we have `left + size/2 < self.len()`, and this is in-bounds.
+ // This loop intentionally doesn't have an early exit if the comparison
+ // returns Equal. We want the number of loop iterations to depend *only*
+ // on the size of the input slice so that the CPU can reliably predict
+ // the loop count.
+ while size > 1 {
+ let half = size / 2;
+ let mid = base + half;
+
+ // SAFETY: the call is made safe by the following inconstants:
+ // - `mid >= 0`: by definition
+ // - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...`
let cmp = f(unsafe { self.get_unchecked(mid) });
- // This control flow produces conditional moves, which results in
- // fewer branches and instructions than if/else or matching on
- // cmp::Ordering.
- // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx.
- left = if cmp == Less { mid + 1 } else { left };
- right = if cmp == Greater { mid } else { right };
- if cmp == Equal {
- // SAFETY: same as the `get_unchecked` above
- unsafe { hint::assert_unchecked(mid < self.len()) };
- return Ok(mid);
- }
+ // Binary search interacts poorly with branch prediction, so force
+ // the compiler to use conditional moves if supported by the target
+ // architecture.
+ base = select_unpredictable(cmp == Greater, base, mid);
- size = right - left;
+ // This is imprecise in the case where `size` is odd and the
+ // comparison returns Greater: the mid element still gets included
+ // by `size` even though it's known to be larger than the element
+ // being searched for.
+ //
+ // This is fine though: we gain more performance by keeping the
+ // loop iteration count invariant (and thus predictable) than we
+ // lose from considering one additional element.
+ size -= half;
}
- // SAFETY: directly true from the overall invariant.
- // Note that this is `<=`, unlike the assume in the `Ok` path.
- unsafe { hint::assert_unchecked(left <= self.len()) };
- Err(left)
+ // SAFETY: base is always in [0, size) because base <= mid.
+ let cmp = f(unsafe { self.get_unchecked(base) });
+ if cmp == Equal {
+ // SAFETY: same as the `get_unchecked` above.
+ unsafe { hint::assert_unchecked(base < self.len()) };
+ Ok(base)
+ } else {
+ let result = base + (cmp == Less) as usize;
+ // SAFETY: same as the `get_unchecked` above.
+ // Note that this is `<=`, unlike the assume in the `Ok` path.
+ unsafe { hint::assert_unchecked(result <= self.len()) };
+ Err(result)
+ }
}
/// Binary searches this slice with a key extraction function.
@@ -2884,9 +2881,19 @@ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize
/// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not
/// allocate), and *O*(*n* \* log(*n*)) worst-case.
///
- /// If `T: Ord` does not implement a total order the resulting order is unspecified. All
- /// original elements will remain in the slice and any possible modifications via interior
- /// mutability are observed in the input. Same is true if `T: Ord` panics.
+ /// If the implementation of [`Ord`] for `T` does not implement a [total order] the resulting
+ /// order of elements in the slice is unspecified. All original elements will remain in the
+ /// slice and any possible modifications via interior mutability are observed in the input. Same
+ /// is true if the implementation of [`Ord`] for `T` panics.
+ ///
+ /// Sorting types that only implement [`PartialOrd`] such as [`f32`] and [`f64`] require
+ /// additional precautions. For example, `f32::NAN != f32::NAN`, which doesn't fulfill the
+ /// reflexivity requirement of [`Ord`]. By using an alternative comparison function with
+ /// `slice::sort_unstable_by` such as [`f32::total_cmp`] or [`f64::total_cmp`] that defines a
+ /// [total order] users can sort slices containing floating-point values. Alternatively, if all
+ /// values in the slice are guaranteed to be in a subset for which [`PartialOrd::partial_cmp`]
+ /// forms a [total order], it's possible to sort the slice with `sort_unstable_by(|a, b|
+ /// a.partial_cmp(b).unwrap())`.
///
/// # Current implementation
///
@@ -2898,18 +2905,21 @@ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize
/// It is typically faster than stable sorting, except in a few special cases, e.g., when the
/// slice is partially sorted.
///
- /// If `T: Ord` does not implement a total order, the implementation may panic.
+ /// # Panics
+ ///
+ /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order].
///
/// # Examples
///
/// ```
- /// let mut v = [-5, 4, 1, -3, 2];
+ /// let mut v = [4, -5, 1, -3, 2];
///
/// v.sort_unstable();
- /// assert!(v == [-5, -3, 1, 2, 4]);
+ /// assert_eq!(v, [-5, -3, 1, 2, 4]);
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[stable(feature = "sort_unstable", since = "1.20.0")]
#[inline]
pub fn sort_unstable(&mut self)
@@ -2919,31 +2929,20 @@ pub fn sort_unstable(&mut self)
sort::unstable::sort(self, &mut T::lt);
}
- /// Sorts the slice with a comparator function, **without** preserving the initial order of
+ /// Sorts the slice with a comparison function, **without** preserving the initial order of
/// equal elements.
///
/// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not
/// allocate), and *O*(*n* \* log(*n*)) worst-case.
///
- /// The comparator function should define a total ordering for the elements in the slice. If the
- /// ordering is not total, the order of the elements is unspecified.
+ /// If the comparison function `compare` does not implement a [total order] the resulting order
+ /// of elements in the slice is unspecified. All original elements will remain in the slice and
+ /// any possible modifications via interior mutability are observed in the input. Same is true
+ /// if `compare` panics.
///
- /// If the comparator function does not implement a total order the resulting order is
- /// unspecified. All original elements will remain in the slice and any possible modifications
- /// via interior mutability are observed in the input. Same is true if the comparator function
- /// panics. A total order (for all `a`, `b` and `c`):
- ///
- /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and
- /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
- ///
- /// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use
- /// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.
- ///
- /// ```
- /// let mut floats = [5f64, 4.0, 1.0, 3.0, 2.0];
- /// floats.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
- /// assert_eq!(floats, [1.0, 2.0, 3.0, 4.0, 5.0]);
- /// ```
+ /// For example `|a, b| (a - b).cmp(a)` is a comparison function that is neither transitive nor
+ /// reflexive nor total, `a < b < c < a` with `a = 1, b = 2, c = 3`. For more information and
+ /// examples see the [`Ord`] documentation.
///
/// # Current implementation
///
@@ -2955,21 +2954,24 @@ pub fn sort_unstable(&mut self)
/// It is typically faster than stable sorting, except in a few special cases, e.g., when the
/// slice is partially sorted.
///
- /// If `T: Ord` does not implement a total order, the implementation may panic.
+ /// # Panics
+ ///
+ /// May panic if `compare` does not implement a [total order].
///
/// # Examples
///
/// ```
- /// let mut v = [5, 4, 1, 3, 2];
+ /// let mut v = [4, -5, 1, -3, 2];
/// v.sort_unstable_by(|a, b| a.cmp(b));
- /// assert!(v == [1, 2, 3, 4, 5]);
+ /// assert_eq!(v, [-5, -3, 1, 2, 4]);
///
/// // reverse sorting
/// v.sort_unstable_by(|a, b| b.cmp(a));
- /// assert!(v == [5, 4, 3, 2, 1]);
+ /// assert_eq!(v, [4, 2, 1, -3, -5]);
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[stable(feature = "sort_unstable", since = "1.20.0")]
#[inline]
pub fn sort_unstable_by<F>(&mut self, mut compare: F)
@@ -2985,9 +2987,10 @@ pub fn sort_unstable_by<F>(&mut self, mut compare: F)
/// This sort is unstable (i.e., may reorder equal elements), in-place (i.e., does not
/// allocate), and *O*(*n* \* log(*n*)) worst-case.
///
- /// If `K: Ord` does not implement a total order the resulting order is unspecified.
- /// All original elements will remain in the slice and any possible modifications via interior
- /// mutability are observed in the input. Same is true if `K: Ord` panics.
+ /// If the implementation of [`Ord`] for `K` does not implement a [total order] the resulting
+ /// order of elements in the slice is unspecified. All original elements will remain in the
+ /// slice and any possible modifications via interior mutability are observed in the input. Same
+ /// is true if the implementation of [`Ord`] for `K` panics.
///
/// # Current implementation
///
@@ -2999,18 +3002,21 @@ pub fn sort_unstable_by<F>(&mut self, mut compare: F)
/// It is typically faster than stable sorting, except in a few special cases, e.g., when the
/// slice is partially sorted.
///
- /// If `K: Ord` does not implement a total order, the implementation may panic.
+ /// # Panics
+ ///
+ /// May panic if the implementation of [`Ord`] for `K` does not implement a [total order].
///
/// # Examples
///
/// ```
- /// let mut v = [-5i32, 4, 1, -3, 2];
+ /// let mut v = [4i32, -5, 1, -3, 2];
///
/// v.sort_unstable_by_key(|k| k.abs());
- /// assert!(v == [1, 2, -3, 4, -5]);
+ /// assert_eq!(v, [1, 2, -3, 4, -5]);
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[stable(feature = "sort_unstable", since = "1.20.0")]
#[inline]
pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
@@ -3021,7 +3027,7 @@ pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
sort::unstable::sort(self, &mut |a, b| f(a).lt(&f(b)));
}
- /// Reorder the slice such that the element at `index` after the reordering is at its final
+ /// Reorders the slice such that the element at `index` after the reordering is at its final
/// sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
@@ -3042,15 +3048,14 @@ pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
/// Median of Medians using Tukey's Ninther for pivot selection, which guarantees linear runtime
/// for all inputs.
///
- /// It is typically faster than stable sorting, except in a few special cases, e.g., when the
- /// slice is nearly fully sorted, where `slice::sort` may be faster.
- ///
/// [`sort_unstable`]: slice::sort_unstable
///
/// # Panics
///
/// Panics when `index >= len()`, meaning it always panics on empty slices.
///
+ /// May panic if the implementation of [`Ord`] for `T` does not implement a [total order].
+ ///
/// # Examples
///
/// ```
@@ -3073,6 +3078,7 @@ pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[stable(feature = "slice_select_nth_unstable", since = "1.49.0")]
#[inline]
pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
@@ -3082,7 +3088,7 @@ pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [
sort::select::partition_at_index(self, index, T::lt)
}
- /// Reorder the slice with a comparator function such that the element at `index` after the
+ /// Reorders the slice with a comparator function such that the element at `index` after the
/// reordering is at its final sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
@@ -3103,15 +3109,14 @@ pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [
/// Median of Medians using Tukey's Ninther for pivot selection, which guarantees linear runtime
/// for all inputs.
///
- /// It is typically faster than stable sorting, except in a few special cases, e.g., when the
- /// slice is nearly fully sorted, where `slice::sort` may be faster.
- ///
/// [`sort_unstable`]: slice::sort_unstable
///
/// # Panics
///
/// Panics when `index >= len()`, meaning it always panics on empty slices.
///
+ /// May panic if `compare` does not implement a [total order].
+ ///
/// # Examples
///
/// ```
@@ -3134,6 +3139,7 @@ pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[stable(feature = "slice_select_nth_unstable", since = "1.49.0")]
#[inline]
pub fn select_nth_unstable_by<F>(
@@ -3147,7 +3153,7 @@ pub fn select_nth_unstable_by<F>(
sort::select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
}
- /// Reorder the slice with a key extraction function such that the element at `index` after the
+ /// Reorders the slice with a key extraction function such that the element at `index` after the
/// reordering is at its final sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
@@ -3168,15 +3174,14 @@ pub fn select_nth_unstable_by<F>(
/// Median of Medians using Tukey's Ninther for pivot selection, which guarantees linear runtime
/// for all inputs.
///
- /// It is typically faster than stable sorting, except in a few special cases, e.g., when the
- /// slice is nearly fully sorted, where `slice::sort` may be faster.
- ///
/// [`sort_unstable`]: slice::sort_unstable
///
/// # Panics
///
/// Panics when `index >= len()`, meaning it always panics on empty slices.
///
+ /// May panic if `K: Ord` does not implement a total order.
+ ///
/// # Examples
///
/// ```
@@ -3199,6 +3204,7 @@ pub fn select_nth_unstable_by<F>(
/// ```
///
/// [ipnsort]: https://github.com/Voultapher/sort-research-rs/tree/main/ipnsort
+ /// [total order]: https://en.wikipedia.org/wiki/Total_order
#[stable(feature = "slice_select_nth_unstable", since = "1.49.0")]
#[inline]
pub fn select_nth_unstable_by_key<K, F>(
@@ -3405,8 +3411,10 @@ pub fn partition_dedup_by_key<K, F>(&mut self, mut key: F) -> (&mut [T], &mut [T
/// Rotates the slice in-place such that the first `mid` elements of the
/// slice move to the end while the last `self.len() - mid` elements move to
- /// the front. After calling `rotate_left`, the element previously at index
- /// `mid` will become the first element in the slice.
+ /// the front.
+ ///
+ /// After calling `rotate_left`, the element previously at index `mid` will
+ /// become the first element in the slice.
///
/// # Panics
///
@@ -3448,8 +3456,10 @@ pub fn rotate_left(&mut self, mid: usize) {
/// Rotates the slice in-place such that the first `self.len() - k`
/// elements of the slice move to the end while the last `k` elements move
- /// to the front. After calling `rotate_right`, the element previously at
- /// index `self.len() - k` will become the first element in the slice.
+ /// to the front.
+ ///
+ /// After calling `rotate_right`, the element previously at index
+ /// `self.len() - k` will become the first element in the slice.
///
/// # Panics
///
@@ -3819,7 +3829,7 @@ const fn gcd(a: usize, b: usize) -> usize {
(us_len, ts_len)
}
- /// Transmute the slice to a slice of another type, ensuring alignment of the types is
+ /// Transmutes the slice to a slice of another type, ensuring alignment of the types is
/// maintained.
///
/// This method splits the slice into three distinct slices: prefix, correctly aligned middle
@@ -3884,7 +3894,7 @@ pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
}
}
- /// Transmute the mutable slice to a mutable slice of another type, ensuring alignment of the
+ /// Transmutes the mutable slice to a mutable slice of another type, ensuring alignment of the
/// types is maintained.
///
/// This method splits the slice into three distinct slices: prefix, correctly aligned middle
@@ -3957,7 +3967,7 @@ pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
}
}
- /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix.
+ /// Splits a slice into a prefix, a middle of aligned SIMD types, and a suffix.
///
/// This is a safe wrapper around [`slice::align_to`], so inherits the same
/// guarantees as that method.
@@ -4021,7 +4031,7 @@ pub fn as_simd<const LANES: usize>(&self) -> (&[T], &[Simd<T, LANES>], &[T])
unsafe { self.align_to() }
}
- /// Split a mutable slice into a mutable prefix, a middle of aligned SIMD types,
+ /// Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types,
/// and a mutable suffix.
///
/// This is a safe wrapper around [`slice::align_to_mut`], so inherits the same
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 280aead..85507eb 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -1,9 +1,7 @@
//! Free functions to create `&[T]` and `&mut [T]`.
-use crate::array;
use crate::ops::Range;
-use crate::ptr;
-use crate::ub_checks;
+use crate::{array, ptr, ub_checks};
/// Forms a slice from a pointer and a length.
///
diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs
index 1d7b863..1e4865a 100644
--- a/library/core/src/slice/rotate.rs
+++ b/library/core/src/slice/rotate.rs
@@ -1,6 +1,5 @@
-use crate::cmp;
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
-use crate::ptr;
+use crate::{cmp, ptr};
/// Rotates the range `[mid-left, mid+right)` such that the element at `mid` becomes the first
/// element. Equivalently, rotates the range `left` elements to the left or `right` elements to the
diff --git a/library/core/src/slice/sort/select.rs b/library/core/src/slice/sort/select.rs
index 6212def..f6529f2 100644
--- a/library/core/src/slice/sort/select.rs
+++ b/library/core/src/slice/sort/select.rs
@@ -7,12 +7,11 @@
//! better performance than one would get using heapsort as fallback.
use crate::mem::{self, SizedTypeProperties};
-
use crate::slice::sort::shared::pivot::choose_pivot;
use crate::slice::sort::shared::smallsort::insertion_sort_shift_left;
use crate::slice::sort::unstable::quicksort::partition;
-/// Reorder the slice such that the element at `index` is at its final sorted position.
+/// Reorders the slice such that the element at `index` is at its final sorted position.
pub(crate) fn partition_at_index<T, F>(
v: &mut [T],
index: usize,
diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs
index 5111ed8..db0c5c7 100644
--- a/library/core/src/slice/sort/shared/smallsort.rs
+++ b/library/core/src/slice/sort/shared/smallsort.rs
@@ -1,11 +1,8 @@
//! This module contains a variety of sort implementations that are optimized for small lengths.
-use crate::intrinsics;
use crate::mem::{self, ManuallyDrop, MaybeUninit};
-use crate::ptr;
-use crate::slice;
-
use crate::slice::sort::shared::FreezeMarker;
+use crate::{intrinsics, ptr, slice};
// It's important to differentiate between SMALL_SORT_THRESHOLD performance for
// small slices and small-sort performance sorting small sub-slices as part of
@@ -834,9 +831,9 @@ unsafe fn bidirectional_merge<T: FreezeMarker, F: FnMut(&T, &T) -> bool>(
right = right.add((!left_nonempty) as usize);
}
- // We now should have consumed the full input exactly once. This can
- // only fail if the comparison operator fails to be Ord, in which case
- // we will panic and never access the inconsistent state in dst.
+ // We now should have consumed the full input exactly once. This can only fail if the
+ // user-provided comparison function fails to implement a strict weak ordering. In that case
+ // we panic and never access the inconsistent state in dst.
if left != left_end || right != right_end {
panic_on_ord_violation();
}
@@ -845,7 +842,21 @@ unsafe fn bidirectional_merge<T: FreezeMarker, F: FnMut(&T, &T) -> bool>(
#[inline(never)]
fn panic_on_ord_violation() -> ! {
- panic!("Ord violation");
+ // This is indicative of a logic bug in the user-provided comparison function or Ord
+ // implementation. They are expected to implement a total order as explained in the Ord
+ // documentation.
+ //
+ // By panicking we inform the user, that they have a logic bug in their program. If a strict
+ // weak ordering is not given, the concept of comparison based sorting cannot yield a sorted
+ // result. E.g.: a < b < c < a
+ //
+ // The Ord documentation requires users to implement a total order. Arguably that's
+ // unnecessarily strict in the context of sorting. Issues only arise if the weaker requirement
+ // of a strict weak ordering is violated.
+ //
+ // The panic message talks about a total order because that's what the Ord documentation talks
+ // about and requires, so as to not confuse users.
+ panic!("user-provided comparison function does not correctly implement a total order");
}
#[must_use]
diff --git a/library/core/src/slice/sort/stable/drift.rs b/library/core/src/slice/sort/stable/drift.rs
index 2d9c4ac..644e75a 100644
--- a/library/core/src/slice/sort/stable/drift.rs
+++ b/library/core/src/slice/sort/stable/drift.rs
@@ -1,14 +1,12 @@
//! This module contains the hybrid top-level loop combining bottom-up Mergesort with top-down
//! Quicksort.
-use crate::cmp;
-use crate::intrinsics;
use crate::mem::MaybeUninit;
-
use crate::slice::sort::shared::find_existing_run;
use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl;
use crate::slice::sort::stable::merge::merge;
use crate::slice::sort::stable::quicksort::quicksort;
+use crate::{cmp, intrinsics};
/// Sorts `v` based on comparison function `is_less`. If `eager_sort` is true,
/// it will only do small-sorts and physical merges, ensuring O(N * log(N))
@@ -273,7 +271,7 @@ fn stable_quicksort<T, F: FnMut(&T, &T) -> bool>(
}
/// Compactly stores the length of a run, and whether or not it is sorted. This
-/// can always fit in a usize because the maximum slice length is isize::MAX.
+/// can always fit in a `usize` because the maximum slice length is [`isize::MAX`].
#[derive(Copy, Clone)]
struct DriftsortRun(usize);
diff --git a/library/core/src/slice/sort/stable/merge.rs b/library/core/src/slice/sort/stable/merge.rs
index 6739e11..0cb2174 100644
--- a/library/core/src/slice/sort/stable/merge.rs
+++ b/library/core/src/slice/sort/stable/merge.rs
@@ -1,8 +1,7 @@
//! This module contains logic for performing a merge of two sorted sub-slices.
-use crate::cmp;
use crate::mem::MaybeUninit;
-use crate::ptr;
+use crate::{cmp, ptr};
/// Merges non-decreasing runs `v[..mid]` and `v[mid..]` using `scratch` as
/// temporary storage, and stores the result into `v[..]`.
diff --git a/library/core/src/slice/sort/stable/mod.rs b/library/core/src/slice/sort/stable/mod.rs
index 18f7b2a..a383b0f 100644
--- a/library/core/src/slice/sort/stable/mod.rs
+++ b/library/core/src/slice/sort/stable/mod.rs
@@ -1,12 +1,10 @@
//! This module contains the entry points for `slice::sort`.
-use crate::cmp;
-use crate::intrinsics;
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
-
use crate::slice::sort::shared::smallsort::{
insertion_sort_shift_left, StableSmallSortTypeImpl, SMALL_SORT_GENERAL_SCRATCH_LEN,
};
+use crate::{cmp, intrinsics};
pub(crate) mod drift;
pub(crate) mod merge;
diff --git a/library/core/src/slice/sort/stable/quicksort.rs b/library/core/src/slice/sort/stable/quicksort.rs
index 181fe60..3319d67 100644
--- a/library/core/src/slice/sort/stable/quicksort.rs
+++ b/library/core/src/slice/sort/stable/quicksort.rs
@@ -1,12 +1,10 @@
//! This module contains a stable quicksort and partition implementation.
-use crate::intrinsics;
use crate::mem::{self, ManuallyDrop, MaybeUninit};
-use crate::ptr;
-
use crate::slice::sort::shared::pivot::choose_pivot;
use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl;
use crate::slice::sort::shared::FreezeMarker;
+use crate::{intrinsics, ptr};
/// Sorts `v` recursively using quicksort.
///
@@ -196,7 +194,8 @@ struct PartitionState<T> {
impl<T> PartitionState<T> {
/// # Safety
- /// scan and scratch must point to valid disjoint buffers of length len. The
+ ///
+ /// `scan` and `scratch` must point to valid disjoint buffers of length `len`. The
/// scan buffer must be initialized.
unsafe fn new(scan: *const T, scratch: *mut T, len: usize) -> Self {
// SAFETY: See function safety comment.
@@ -208,6 +207,7 @@ unsafe fn new(scan: *const T, scratch: *mut T, len: usize) -> Self {
/// branchless core of the partition.
///
/// # Safety
+ ///
/// This function may be called at most `len` times. If it is called exactly
/// `len` times the scratch buffer then contains a copy of each element from
/// the scan buffer exactly once - a permutation, and num_left <= len.
diff --git a/library/core/src/slice/sort/unstable/heapsort.rs b/library/core/src/slice/sort/unstable/heapsort.rs
index 559605e..27e2ad5 100644
--- a/library/core/src/slice/sort/unstable/heapsort.rs
+++ b/library/core/src/slice/sort/unstable/heapsort.rs
@@ -1,7 +1,6 @@
//! This module contains a branchless heapsort as fallback for unstable quicksort.
-use crate::intrinsics;
-use crate::ptr;
+use crate::{intrinsics, ptr};
/// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case.
///
diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs
index 692c2d8..932e01f 100644
--- a/library/core/src/slice/sort/unstable/mod.rs
+++ b/library/core/src/slice/sort/unstable/mod.rs
@@ -2,14 +2,13 @@
use crate::intrinsics;
use crate::mem::SizedTypeProperties;
-
use crate::slice::sort::shared::find_existing_run;
use crate::slice::sort::shared::smallsort::insertion_sort_shift_left;
pub(crate) mod heapsort;
pub(crate) mod quicksort;
-/// Unstable sort called ipnsort by Lukas Bergdoll.
+/// Unstable sort called ipnsort by Lukas Bergdoll and Orson Peters.
/// Design document:
/// <https://github.com/Voultapher/sort-research-rs/blob/main/writeup/ipnsort_introduction/text.md>
///
diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs
index 533b5b0..cd53656 100644
--- a/library/core/src/slice/sort/unstable/quicksort.rs
+++ b/library/core/src/slice/sort/unstable/quicksort.rs
@@ -1,11 +1,9 @@
//! This module contains an unstable quicksort and two partition implementations.
-use crate::intrinsics;
use crate::mem::{self, ManuallyDrop};
-use crate::ptr;
-
use crate::slice::sort::shared::pivot::choose_pivot;
use crate::slice::sort::shared::smallsort::UnstableSmallSortTypeImpl;
+use crate::{intrinsics, ptr};
/// Sorts `v` recursively.
///
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index 397759b..1956a04 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -1,9 +1,8 @@
//! Ways to create a `str` from bytes slice.
-use crate::{mem, ptr};
-
use super::validations::run_utf8_validation;
use super::Utf8Error;
+use crate::{mem, ptr};
/// Converts a slice of bytes to a string slice.
///
@@ -206,7 +205,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
unsafe { &mut *(v as *mut [u8] as *mut str) }
}
-/// Creates an `&str` from a pointer and a length.
+/// Creates a `&str` from a pointer and a length.
///
/// The pointed-to bytes must be valid UTF-8.
/// If this might not be the case, use `str::from_utf8(slice::from_raw_parts(ptr, len))`,
@@ -225,7 +224,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
unsafe { &*ptr::from_raw_parts(ptr, len) }
}
-/// Creates an `&mut str` from a pointer and a length.
+/// Creates a `&mut str` from a pointer and a length.
///
/// The pointed-to bytes must be valid UTF-8.
/// If this might not be the case, use `str::from_utf8_mut(slice::from_raw_parts_mut(ptr, len))`,
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 5845e3b..06f796f 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1,23 +1,20 @@
//! Iterators for `str` methods.
-use crate::char as char_mod;
+use super::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
+use super::validations::{next_code_point, next_code_point_reverse};
+use super::{
+ from_utf8_unchecked, BytesIsNotEmpty, CharEscapeDebugContinue, CharEscapeDefault,
+ CharEscapeUnicode, IsAsciiWhitespace, IsNotEmpty, IsWhitespace, LinesMap, UnsafeBytesToStr,
+};
use crate::fmt::{self, Write};
-use crate::iter::{Chain, FlatMap, Flatten};
-use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen};
-use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
+use crate::iter::{
+ Chain, Copied, Filter, FlatMap, Flatten, FusedIterator, Map, TrustedLen, TrustedRandomAccess,
+ TrustedRandomAccessNoCoerce,
+};
use crate::num::NonZero;
use crate::ops::Try;
-use crate::option;
use crate::slice::{self, Split as SliceSplit};
-
-use super::from_utf8_unchecked;
-use super::pattern::Pattern;
-use super::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
-use super::validations::{next_code_point, next_code_point_reverse};
-use super::LinesMap;
-use super::{BytesIsNotEmpty, UnsafeBytesToStr};
-use super::{CharEscapeDebugContinue, CharEscapeDefault, CharEscapeUnicode};
-use super::{IsAsciiWhitespace, IsNotEmpty, IsWhitespace};
+use crate::{char as char_mod, option};
/// An iterator over the [`char`]s of a string slice.
///
diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs
index 51a0777..3f31107 100644
--- a/library/core/src/str/lossy.rs
+++ b/library/core/src/str/lossy.rs
@@ -1,10 +1,8 @@
-use crate::fmt;
-use crate::fmt::Formatter;
-use crate::fmt::Write;
-use crate::iter::FusedIterator;
-
use super::from_utf8_unchecked;
use super::validations::utf8_char_width;
+use crate::fmt;
+use crate::fmt::{Formatter, Write};
+use crate::iter::FusedIterator;
impl [u8] {
/// Creates an iterator over the contiguous valid UTF-8 ranges of this
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 6cd029f..5651734 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -13,74 +13,52 @@
mod traits;
mod validations;
-use self::pattern::Pattern;
-use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
-
-use crate::ascii;
+use self::pattern::{DoubleEndedSearcher, Pattern, ReverseSearcher, Searcher};
use crate::char::{self, EscapeDebugExtArgs};
-use crate::mem;
use crate::ops::Range;
use crate::slice::{self, SliceIndex};
+use crate::{ascii, mem};
pub mod pattern;
mod lossy;
-#[stable(feature = "utf8_chunks", since = "1.79.0")]
-pub use lossy::{Utf8Chunk, Utf8Chunks};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use converts::{from_utf8, from_utf8_unchecked};
-
-#[stable(feature = "str_mut_extras", since = "1.20.0")]
-pub use converts::{from_utf8_mut, from_utf8_unchecked_mut};
-
#[unstable(feature = "str_from_raw_parts", issue = "119206")]
pub use converts::{from_raw_parts, from_raw_parts_mut};
-
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use converts::{from_utf8, from_utf8_unchecked};
+#[stable(feature = "str_mut_extras", since = "1.20.0")]
+pub use converts::{from_utf8_mut, from_utf8_unchecked_mut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use error::{ParseBoolError, Utf8Error};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use traits::FromStr;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use iter::{Bytes, CharIndices, Chars, Lines, SplitWhitespace};
-
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+pub use iter::EncodeUtf16;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use iter::LinesAny;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use iter::{RSplit, RSplitTerminator, Split, SplitTerminator};
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use iter::{RSplitN, SplitN};
-
-#[stable(feature = "str_matches", since = "1.2.0")]
-pub use iter::{Matches, RMatches};
-
-#[stable(feature = "str_match_indices", since = "1.5.0")]
-pub use iter::{MatchIndices, RMatchIndices};
-
-#[stable(feature = "encode_utf16", since = "1.8.0")]
-pub use iter::EncodeUtf16;
-
-#[stable(feature = "str_escape", since = "1.34.0")]
-pub use iter::{EscapeDebug, EscapeDefault, EscapeUnicode};
-
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
pub use iter::SplitAsciiWhitespace;
-
#[stable(feature = "split_inclusive", since = "1.51.0")]
pub use iter::SplitInclusive;
-
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use iter::{Bytes, CharIndices, Chars, Lines, SplitWhitespace};
+#[stable(feature = "str_escape", since = "1.34.0")]
+pub use iter::{EscapeDebug, EscapeDefault, EscapeUnicode};
+#[stable(feature = "str_match_indices", since = "1.5.0")]
+pub use iter::{MatchIndices, RMatchIndices};
+use iter::{MatchIndicesInternal, MatchesInternal, SplitInternal, SplitNInternal};
+#[stable(feature = "str_matches", since = "1.2.0")]
+pub use iter::{Matches, RMatches};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use iter::{RSplit, RSplitTerminator, Split, SplitTerminator};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use iter::{RSplitN, SplitN};
+#[stable(feature = "utf8_chunks", since = "1.79.0")]
+pub use lossy::{Utf8Chunk, Utf8Chunks};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use traits::FromStr;
#[unstable(feature = "str_internals", issue = "none")]
pub use validations::{next_code_point, utf8_char_width};
-use iter::MatchIndicesInternal;
-use iter::SplitInternal;
-use iter::{MatchesInternal, SplitNInternal};
-
#[inline(never)]
#[cold]
#[track_caller]
@@ -592,6 +570,7 @@ pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
/// Creates a string slice from another string slice, bypassing safety
/// checks.
+ ///
/// This is generally not recommended, use with caution! For a safe
/// alternative see [`str`] and [`IndexMut`].
///
@@ -623,7 +602,7 @@ pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut s
unsafe { &mut *(begin..end).get_unchecked_mut(self) }
}
- /// Divide one string slice into two at an index.
+ /// Divides one string slice into two at an index.
///
/// The argument, `mid`, should be a byte offset from the start of the
/// string. It must also be on the boundary of a UTF-8 code point.
@@ -662,7 +641,7 @@ pub fn split_at(&self, mid: usize) -> (&str, &str) {
}
}
- /// Divide one mutable string slice into two at an index.
+ /// Divides one mutable string slice into two at an index.
///
/// The argument, `mid`, should be a byte offset from the start of the
/// string. It must also be on the boundary of a UTF-8 code point.
@@ -705,7 +684,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
}
}
- /// Divide one string slice into two at an index.
+ /// Divides one string slice into two at an index.
///
/// The argument, `mid`, should be a valid byte offset from the start of the
/// string. It must also be on the boundary of a UTF-8 code point. The
@@ -744,7 +723,7 @@ pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
}
}
- /// Divide one mutable string slice into two at an index.
+ /// Divides one mutable string slice into two at an index.
///
/// The argument, `mid`, should be a valid byte offset from the start of the
/// string. It must also be on the boundary of a UTF-8 code point. The
@@ -784,7 +763,7 @@ pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str
}
}
- /// Divide one string slice into two at an index.
+ /// Divides one string slice into two at an index.
///
/// # Safety
///
@@ -912,7 +891,7 @@ pub fn char_indices(&self) -> CharIndices<'_> {
CharIndices { front_offset: 0, iter: self.chars() }
}
- /// An iterator over the bytes of a string slice.
+ /// Returns an iterator over the bytes of a string slice.
///
/// As a string slice consists of a sequence of bytes, we can iterate
/// through a string slice by byte. This method returns such an iterator.
@@ -1038,7 +1017,7 @@ pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
SplitAsciiWhitespace { inner }
}
- /// An iterator over the lines of a string, as string slices.
+ /// Returns an iterator over the lines of a string, as string slices.
///
/// Lines are split at line endings that are either newlines (`\n`) or
/// sequences of a carriage return followed by a line feed (`\r\n`).
@@ -1089,7 +1068,7 @@ pub fn lines(&self) -> Lines<'_> {
Lines(self.split_inclusive('\n').map(LinesMap))
}
- /// An iterator over the lines of a string.
+ /// Returns an iterator over the lines of a string.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.4.0", note = "use lines() instead now", suggestion = "lines")]
#[inline]
@@ -1303,7 +1282,7 @@ pub fn rfind<P: Pattern>(&self, pat: P) -> Option<usize>
pat.into_searcher(self).next_match_back().map(|(i, _)| i)
}
- /// An iterator over substrings of this string slice, separated by
+ /// Returns an iterator over substrings of this string slice, separated by
/// characters matched by a pattern.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
@@ -1428,10 +1407,11 @@ pub fn split<P: Pattern>(&self, pat: P) -> Split<'_, P> {
})
}
- /// An iterator over substrings of this string slice, separated by
- /// characters matched by a pattern. Differs from the iterator produced by
- /// `split` in that `split_inclusive` leaves the matched part as the
- /// terminator of the substring.
+ /// Returns an iterator over substrings of this string slice, separated by
+ /// characters matched by a pattern.
+ ///
+ /// Differs from the iterator produced by `split` in that `split_inclusive`
+ /// leaves the matched part as the terminator of the substring.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -1468,8 +1448,8 @@ pub fn split_inclusive<P: Pattern>(&self, pat: P) -> SplitInclusive<'_, P> {
})
}
- /// An iterator over substrings of the given string slice, separated by
- /// characters matched by a pattern and yielded in reverse order.
+ /// Returns an iterator over substrings of the given string slice, separated
+ /// by characters matched by a pattern and yielded in reverse order.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -1520,8 +1500,8 @@ pub fn rsplit<P: Pattern>(&self, pat: P) -> RSplit<'_, P>
RSplit(self.split(pat).0)
}
- /// An iterator over substrings of the given string slice, separated by
- /// characters matched by a pattern.
+ /// Returns an iterator over substrings of the given string slice, separated
+ /// by characters matched by a pattern.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -1566,7 +1546,7 @@ pub fn split_terminator<P: Pattern>(&self, pat: P) -> SplitTerminator<'_, P> {
SplitTerminator(SplitInternal { allow_trailing_empty: false, ..self.split(pat).0 })
}
- /// An iterator over substrings of `self`, separated by characters
+ /// Returns an iterator over substrings of `self`, separated by characters
/// matched by a pattern and yielded in reverse order.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
@@ -1615,8 +1595,8 @@ pub fn rsplit_terminator<P: Pattern>(&self, pat: P) -> RSplitTerminator<'_, P>
RSplitTerminator(self.split_terminator(pat).0)
}
- /// An iterator over substrings of the given string slice, separated by a
- /// pattern, restricted to returning at most `n` items.
+ /// Returns an iterator over substrings of the given string slice, separated
+ /// by a pattern, restricted to returning at most `n` items.
///
/// If `n` substrings are returned, the last substring (the `n`th substring)
/// will contain the remainder of the string.
@@ -1667,9 +1647,9 @@ pub fn splitn<P: Pattern>(&self, n: usize, pat: P) -> SplitN<'_, P> {
SplitN(SplitNInternal { iter: self.split(pat).0, count: n })
}
- /// An iterator over substrings of this string slice, separated by a
- /// pattern, starting from the end of the string, restricted to returning
- /// at most `n` items.
+ /// Returns an iterator over substrings of this string slice, separated by a
+ /// pattern, starting from the end of the string, restricted to returning at
+ /// most `n` items.
///
/// If `n` substrings are returned, the last substring (the `n`th substring)
/// will contain the remainder of the string.
@@ -1759,8 +1739,8 @@ pub fn rsplit_once<P: Pattern>(&self, delimiter: P) -> Option<(&'_ str, &'_ str)
unsafe { Some((self.get_unchecked(..start), self.get_unchecked(end..))) }
}
- /// An iterator over the disjoint matches of a pattern within the given string
- /// slice.
+ /// Returns an iterator over the disjoint matches of a pattern within the
+ /// given string slice.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -1794,8 +1774,8 @@ pub fn matches<P: Pattern>(&self, pat: P) -> Matches<'_, P> {
Matches(MatchesInternal(pat.into_searcher(self)))
}
- /// An iterator over the disjoint matches of a pattern within this string slice,
- /// yielded in reverse order.
+ /// Returns an iterator over the disjoint matches of a pattern within this
+ /// string slice, yielded in reverse order.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -1831,7 +1811,7 @@ pub fn rmatches<P: Pattern>(&self, pat: P) -> RMatches<'_, P>
RMatches(self.matches(pat).0)
}
- /// An iterator over the disjoint matches of a pattern within this string
+ /// Returns an iterator over the disjoint matches of a pattern within this string
/// slice as well as the index that the match starts at.
///
/// For matches of `pat` within `self` that overlap, only the indices
@@ -1872,7 +1852,7 @@ pub fn match_indices<P: Pattern>(&self, pat: P) -> MatchIndices<'_, P> {
MatchIndices(MatchIndicesInternal(pat.into_searcher(self)))
}
- /// An iterator over the disjoint matches of a pattern within `self`,
+ /// Returns an iterator over the disjoint matches of a pattern within `self`,
/// yielded in reverse order along with the index of the match.
///
/// For matches of `pat` within `self` that overlap, only the indices
@@ -2597,7 +2577,7 @@ pub const fn trim_ascii(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii()) }
}
- /// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
+ /// Returns an iterator that escapes each char in `self` with [`char::escape_debug`].
///
/// Note: only extended grapheme codepoints that begin the string will be
/// escaped.
@@ -2646,7 +2626,7 @@ pub fn escape_debug(&self) -> EscapeDebug<'_> {
}
}
- /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
+ /// Returns an iterator that escapes each char in `self` with [`char::escape_default`].
///
/// # Examples
///
@@ -2684,7 +2664,7 @@ pub fn escape_default(&self) -> EscapeDefault<'_> {
EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
}
- /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
+ /// Returns an iterator that escapes each char in `self` with [`char::escape_unicode`].
///
/// # Examples
///
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 33a5d45..2f1096d 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -38,11 +38,10 @@
issue = "27721"
)]
-use crate::cmp;
use crate::cmp::Ordering;
use crate::convert::TryInto as _;
-use crate::fmt;
use crate::slice::memchr;
+use crate::{cmp, fmt};
// Pattern
@@ -1759,8 +1758,7 @@ fn simd_contains(needle: &str, haystack: &str) -> Option<bool> {
use crate::ops::BitAnd;
use crate::simd::cmp::SimdPartialEq;
- use crate::simd::mask8x16 as Mask;
- use crate::simd::u8x16 as Block;
+ use crate::simd::{mask8x16 as Mask, u8x16 as Block};
let first_probe = needle[0];
let last_byte_offset = needle.len() - 1;
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 3de5546..b69c476 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -1,14 +1,11 @@
//! Trait implementations for `str`.
+use super::ParseBoolError;
use crate::cmp::Ordering;
use crate::intrinsics::unchecked_sub;
-use crate::ops;
-use crate::ptr;
-use crate::range;
use crate::slice::SliceIndex;
use crate::ub_checks::assert_unsafe_precondition;
-
-use super::ParseBoolError;
+use crate::{ops, ptr, range};
/// Implements ordering of strings.
///
diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs
index a11d7fe..cca8ff7 100644
--- a/library/core/src/str/validations.rs
+++ b/library/core/src/str/validations.rs
@@ -1,8 +1,7 @@
//! Operations related to UTF-8 validation.
-use crate::mem;
-
use super::Utf8Error;
+use crate::mem;
/// Returns the initial codepoint accumulator for the first byte.
/// The first byte is special, only want bottom 5 bits for width 2, 4 bits
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index efc07f3..495d919 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -223,12 +223,9 @@
#![allow(clippy::not_unsafe_ptr_arg_deref)]
use self::Ordering::*;
-
use crate::cell::UnsafeCell;
-use crate::fmt;
-use crate::intrinsics;
-
use crate::hint::spin_loop;
+use crate::{fmt, intrinsics};
// Some architectures don't have byte-sized atomics, which results in LLVM
// emulating them using a LL/SC loop. However for AtomicBool we can take
@@ -481,7 +478,7 @@ pub fn get_mut(&mut self) -> &mut bool {
unsafe { &mut *(self.v.get() as *mut bool) }
}
- /// Get atomic access to a `&mut bool`.
+ /// Gets atomic access to a `&mut bool`.
///
/// # Examples
///
@@ -503,7 +500,7 @@ pub fn from_mut(v: &mut bool) -> &mut Self {
unsafe { &mut *(v as *mut bool as *mut Self) }
}
- /// Get non-atomic access to a `&mut [AtomicBool]` slice.
+ /// Gets non-atomic access to a `&mut [AtomicBool]` slice.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
@@ -537,7 +534,7 @@ pub fn get_mut_slice(this: &mut [Self]) -> &mut [bool] {
unsafe { &mut *(this as *mut [Self] as *mut [bool]) }
}
- /// Get atomic access to a `&mut [bool]` slice.
+ /// Gets atomic access to a `&mut [bool]` slice.
///
/// # Examples
///
@@ -1080,7 +1077,7 @@ pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
/// assert_eq!(foo.load(Ordering::SeqCst), true);
/// ```
#[inline]
- #[stable(feature = "atomic_bool_fetch_not", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")]
#[cfg(target_has_atomic = "8")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn fetch_not(&self, order: Ordering) -> bool {
@@ -1276,7 +1273,7 @@ pub fn get_mut(&mut self) -> &mut *mut T {
self.p.get_mut()
}
- /// Get atomic access to a pointer.
+ /// Gets atomic access to a pointer.
///
/// # Examples
///
@@ -1303,7 +1300,7 @@ pub fn from_mut(v: &mut *mut T) -> &mut Self {
unsafe { &mut *(v as *mut *mut T as *mut Self) }
}
- /// Get non-atomic access to a `&mut [AtomicPtr]` slice.
+ /// Gets non-atomic access to a `&mut [AtomicPtr]` slice.
///
/// This is safe because the mutable reference guarantees that no other threads are
/// concurrently accessing the atomic data.
@@ -1343,7 +1340,7 @@ pub fn get_mut_slice(this: &mut [Self]) -> &mut [*mut T] {
unsafe { &mut *(this as *mut [Self] as *mut [*mut T]) }
}
- /// Get atomic access to a slice of pointers.
+ /// Gets atomic access to a slice of pointers.
///
/// # Examples
///
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index e8170c1..fbf8daf 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -114,7 +114,7 @@ pub const fn into_inner(self) -> T {
}
impl<T: ?Sized> Exclusive<T> {
- /// Get exclusive access to the underlying value.
+ /// Gets exclusive access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
#[inline]
@@ -122,7 +122,7 @@ pub const fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
- /// Get pinned exclusive access to the underlying value.
+ /// Gets pinned exclusive access to the underlying value.
///
/// `Exclusive` is considered to _structurally pin_ the underlying
/// value, which means _unpinned_ `Exclusive`s can produce _unpinned_
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index d2b1d74..29932c0 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -1,11 +1,10 @@
#![stable(feature = "futures_api", since = "1.36.0")]
use crate::any::Any;
-use crate::fmt;
use crate::marker::PhantomData;
use crate::mem::{transmute, ManuallyDrop};
use crate::panic::AssertUnwindSafe;
-use crate::ptr;
+use crate::{fmt, ptr};
/// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
/// or a [`LocalWaker`] which provides customized wakeup behavior.
@@ -61,7 +60,7 @@ pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
RawWaker { data, vtable }
}
- /// Get the `data` pointer used to create this `RawWaker`.
+ /// Gets the `data` pointer used to create this `RawWaker`.
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "96992")]
@@ -69,7 +68,7 @@ pub fn data(&self) -> *const () {
self.data
}
- /// Get the `vtable` pointer used to create this `RawWaker`.
+ /// Gets the `vtable` pointer used to create this `RawWaker`.
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "96992")]
@@ -150,7 +149,7 @@ pub struct RawWakerVTable {
/// pointer.
wake_by_ref: unsafe fn(*const ()),
- /// This function gets called when a [`Waker`] gets dropped.
+ /// This function will be called when a [`Waker`] gets dropped.
///
/// The implementation of this function must make sure to release any
/// resources that are associated with this instance of a [`RawWaker`] and
@@ -203,7 +202,8 @@ impl RawWakerVTable {
///
/// # `drop`
///
- /// This function gets called when a [`Waker`]/[`LocalWaker`] gets dropped.
+ /// This function will be called when a [`Waker`]/[`LocalWaker`] gets
+ /// dropped.
///
/// The implementation of this function must make sure to release any
/// resources that are associated with this instance of a [`RawWaker`] and
@@ -248,9 +248,9 @@ pub struct Context<'a> {
}
impl<'a> Context<'a> {
- /// Create a new `Context` from a [`&Waker`](Waker).
+ /// Creates a new `Context` from a [`&Waker`](Waker).
#[stable(feature = "futures_api", since = "1.36.0")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
#[must_use]
#[inline]
pub const fn from_waker(waker: &'a Waker) -> Self {
@@ -261,7 +261,7 @@ pub const fn from_waker(waker: &'a Waker) -> Self {
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
pub const fn waker(&self) -> &'a Waker {
&self.waker
}
@@ -269,7 +269,7 @@ pub const fn waker(&self) -> &'a Waker {
/// Returns a reference to the [`LocalWaker`] for the current task.
#[inline]
#[unstable(feature = "local_waker", issue = "118959")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_unstable(feature = "local_waker", issue = "118959")]
pub const fn local_waker(&self) -> &'a LocalWaker {
&self.local_waker
}
@@ -277,7 +277,7 @@ pub const fn local_waker(&self) -> &'a LocalWaker {
/// Returns a reference to the extension data for the current task.
#[inline]
#[unstable(feature = "context_ext", issue = "123392")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_unstable(feature = "context_ext", issue = "123392")]
pub const fn ext(&mut self) -> &mut dyn Any {
// FIXME: this field makes Context extra-weird about unwind safety
// can we justify AssertUnwindSafe if we stabilize this? do we care?
@@ -334,10 +334,10 @@ pub struct ContextBuilder<'a> {
}
impl<'a> ContextBuilder<'a> {
- /// Create a ContextBuilder from a Waker.
+ /// Creates a ContextBuilder from a Waker.
#[inline]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
#[unstable(feature = "local_waker", issue = "118959")]
+ #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
pub const fn from_waker(waker: &'a Waker) -> Self {
// SAFETY: LocalWaker is just Waker without thread safety
let local_waker = unsafe { transmute(waker) };
@@ -350,10 +350,10 @@ pub const fn from_waker(waker: &'a Waker) -> Self {
}
}
- /// Create a ContextBuilder from an existing Context.
+ /// Creates a ContextBuilder from an existing Context.
#[inline]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
#[unstable(feature = "context_ext", issue = "123392")]
+ #[rustc_const_unstable(feature = "context_ext", issue = "123392")]
pub const fn from(cx: &'a mut Context<'_>) -> Self {
let ext = match &mut cx.ext.0 {
ExtData::Some(ext) => ExtData::Some(*ext),
@@ -368,26 +368,26 @@ pub const fn from(cx: &'a mut Context<'_>) -> Self {
}
}
- /// This method is used to set the value for the waker on `Context`.
+ /// Sets the value for the waker on `Context`.
#[inline]
#[unstable(feature = "context_ext", issue = "123392")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_unstable(feature = "context_ext", issue = "123392")]
pub const fn waker(self, waker: &'a Waker) -> Self {
Self { waker, ..self }
}
- /// This method is used to set the value for the local waker on `Context`.
+ /// Sets the value for the local waker on `Context`.
#[inline]
#[unstable(feature = "local_waker", issue = "118959")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_unstable(feature = "local_waker", issue = "118959")]
pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self {
Self { local_waker, ..self }
}
- /// This method is used to set the value for the extension data on `Context`.
+ /// Sets the value for the extension data on `Context`.
#[inline]
#[unstable(feature = "context_ext", issue = "123392")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_unstable(feature = "context_ext", issue = "123392")]
pub const fn ext(self, data: &'a mut dyn Any) -> Self {
Self { ext: ExtData::Some(data), ..self }
}
@@ -395,7 +395,7 @@ pub const fn ext(self, data: &'a mut dyn Any) -> Self {
/// Builds the `Context`.
#[inline]
#[unstable(feature = "local_waker", issue = "118959")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
pub const fn build(self) -> Context<'a> {
let ContextBuilder { waker, local_waker, ext, _marker, _marker2 } = self;
Context { waker, local_waker, ext: AssertUnwindSafe(ext), _marker, _marker2 }
@@ -442,7 +442,7 @@ unsafe impl Send for Waker {}
unsafe impl Sync for Waker {}
impl Waker {
- /// Wake up the task associated with this `Waker`.
+ /// Wakes up the task associated with this `Waker`.
///
/// As long as the executor keeps running and the task is not finished, it is
/// guaranteed that each invocation of [`wake()`](Self::wake) (or
@@ -474,7 +474,7 @@ pub fn wake(self) {
unsafe { (this.waker.vtable.wake)(this.waker.data) };
}
- /// Wake up the task associated with this `Waker` without consuming the `Waker`.
+ /// Wakes up the task associated with this `Waker` without consuming the `Waker`.
///
/// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in
/// the case where an owned `Waker` is available. This method should be preferred to
@@ -502,6 +502,8 @@ pub fn wake_by_ref(&self) {
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn will_wake(&self, other: &Waker) -> bool {
+ // We optimize this by comparing vtable addresses instead of vtable contents.
+ // This is permitted since the function is documented as best-effort.
let RawWaker { data: a_data, vtable: a_vtable } = self.waker;
let RawWaker { data: b_data, vtable: b_vtable } = other.waker;
a_data == b_data && ptr::eq(a_vtable, b_vtable)
@@ -521,7 +523,7 @@ pub fn will_wake(&self, other: &Waker) -> bool {
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_stable(feature = "const_waker", since = "CURRENT_RUSTC_VERSION")]
pub const unsafe fn from_raw(waker: RawWaker) -> Waker {
Waker { waker }
}
@@ -555,7 +557,7 @@ pub const fn noop() -> &'static Waker {
WAKER
}
- /// Get a reference to the underlying [`RawWaker`].
+ /// Gets a reference to the underlying [`RawWaker`].
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "96992")]
@@ -701,7 +703,7 @@ pub struct LocalWaker {
impl Unpin for LocalWaker {}
impl LocalWaker {
- /// Wake up the task associated with this `LocalWaker`.
+ /// Wakes up the task associated with this `LocalWaker`.
///
/// As long as the executor keeps running and the task is not finished, it is
/// guaranteed that each invocation of [`wake()`](Self::wake) (or
@@ -733,7 +735,7 @@ pub fn wake(self) {
unsafe { (this.waker.vtable.wake)(this.waker.data) };
}
- /// Wake up the task associated with this `LocalWaker` without consuming the `LocalWaker`.
+ /// Wakes up the task associated with this `LocalWaker` without consuming the `LocalWaker`.
///
/// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in
/// the case where an owned `Waker` is available. This method should be preferred to
@@ -761,7 +763,11 @@ pub fn wake_by_ref(&self) {
#[must_use]
#[unstable(feature = "local_waker", issue = "118959")]
pub fn will_wake(&self, other: &LocalWaker) -> bool {
- self.waker == other.waker
+ // We optimize this by comparing vtable addresses instead of vtable contents.
+ // This is permitted since the function is documented as best-effort.
+ let RawWaker { data: a_data, vtable: a_vtable } = self.waker;
+ let RawWaker { data: b_data, vtable: b_vtable } = other.waker;
+ a_data == b_data && ptr::eq(a_vtable, b_vtable)
}
/// Creates a new `LocalWaker` from [`RawWaker`].
@@ -772,7 +778,7 @@ pub fn will_wake(&self, other: &LocalWaker) -> bool {
#[inline]
#[must_use]
#[unstable(feature = "local_waker", issue = "118959")]
- #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ #[rustc_const_unstable(feature = "local_waker", issue = "118959")]
pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker {
Self { waker }
}
@@ -807,7 +813,7 @@ pub const fn noop() -> &'static LocalWaker {
WAKER
}
- /// Get a reference to the underlying [`RawWaker`].
+ /// Gets a reference to the underlying [`RawWaker`].
#[inline]
#[must_use]
#[unstable(feature = "waker_getters", issue = "96992")]
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index d66f558..0390bb5 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -617,16 +617,14 @@ pub const fn as_nanos(&self) -> u128 {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0));
/// assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000));
/// ```
- #[stable(feature = "duration_abs_diff", since = "CURRENT_RUSTC_VERSION")]
- #[rustc_const_stable(feature = "duration_abs_diff", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "duration_abs_diff", since = "1.81.0")]
+ #[rustc_const_stable(feature = "duration_abs_diff", since = "1.81.0")]
#[rustc_allow_const_fn_unstable(const_option)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
@@ -640,8 +638,6 @@ pub const fn abs_diff(self, other: Duration) -> Duration {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// use std::time::Duration;
///
@@ -700,8 +696,6 @@ pub const fn saturating_add(self, rhs: Duration) -> Duration {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// use std::time::Duration;
///
@@ -758,8 +752,6 @@ pub const fn saturating_sub(self, rhs: Duration) -> Duration {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// use std::time::Duration;
///
@@ -814,8 +806,6 @@ pub const fn saturating_mul(self, rhs: u32) -> Duration {
///
/// # Examples
///
- /// Basic usage:
- ///
/// ```
/// use std::time::Duration;
///
@@ -1037,7 +1027,7 @@ pub fn mul_f32(self, rhs: f32) -> Duration {
Duration::from_secs_f32(rhs * self.as_secs_f32())
}
- /// Divide `Duration` by `f64`.
+ /// Divides `Duration` by `f64`.
///
/// # Panics
/// This method will panic if result is negative, overflows `Duration` or not finite.
@@ -1058,7 +1048,7 @@ pub fn div_f64(self, rhs: f64) -> Duration {
Duration::from_secs_f64(self.as_secs_f64() / rhs)
}
- /// Divide `Duration` by `f32`.
+ /// Divides `Duration` by `f32`.
///
/// # Panics
/// This method will panic if result is negative, overflows `Duration` or not finite.
@@ -1081,7 +1071,7 @@ pub fn div_f32(self, rhs: f32) -> Duration {
Duration::from_secs_f32(self.as_secs_f32() / rhs)
}
- /// Divide `Duration` by `Duration` and return `f64`.
+ /// Divides `Duration` by `Duration` and returns `f64`.
///
/// # Examples
/// ```
@@ -1102,7 +1092,7 @@ pub const fn div_duration_f64(self, rhs: Duration) -> f64 {
self_nanos / rhs_nanos
}
- /// Divide `Duration` by `Duration` and return `f32`.
+ /// Divides `Duration` by `Duration` and returns `f32`.
///
/// # Examples
/// ```
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index bc376b1..65d4d5c 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -1,9 +1,7 @@
// See core/src/primitive_docs.rs for documentation.
use crate::cmp::Ordering::{self, *};
-use crate::marker::ConstParamTy_;
-use crate::marker::StructuralPartialEq;
-use crate::marker::UnsizedConstParamTy;
+use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy};
// Recursive macro for implementing n-ary tuple functions and operations
//
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index 1aa6a28..b65b48c 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -3,9 +3,11 @@
use crate::intrinsics::{self, const_eval_select};
-/// Check that the preconditions of an unsafe function are followed. The check is enabled at
-/// runtime if debug assertions are enabled when the caller is monomorphized. In const-eval/Miri
-/// checks implemented with this macro for language UB are always ignored.
+/// Checks that the preconditions of an unsafe function are followed.
+///
+/// The check is enabled at runtime if debug assertions are enabled when the
+/// caller is monomorphized. In const-eval/Miri checks implemented with this
+/// macro for language UB are always ignored.
///
/// This macro should be called as
/// `assert_unsafe_precondition!(check_{library,lang}_ub, "message", (ident: type = expr, ident: type = expr) => check_expr)`
@@ -79,7 +81,6 @@ const fn precondition_check($($name:$ty),*) {
}
#[unstable(feature = "ub_checks", issue = "none")]
pub use assert_unsafe_precondition;
-
/// Checking library UB is always enabled when UB-checking is done
/// (and we use a reexport so that there is no unnecessary wrapper function).
#[unstable(feature = "ub_checks", issue = "none")]
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index e7773d1..b6d18f1 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -259,7 +259,8 @@ fn drop(&mut self) {
#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn array_default_impl_avoids_leaks_on_panic() {
- use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+ use core::sync::atomic::AtomicUsize;
+ use core::sync::atomic::Ordering::Relaxed;
static COUNTER: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
struct Bomb(#[allow(dead_code)] usize);
diff --git a/library/core/tests/ascii_char.rs b/library/core/tests/ascii_char.rs
new file mode 100644
index 0000000..75b5fd4
--- /dev/null
+++ b/library/core/tests/ascii_char.rs
@@ -0,0 +1,28 @@
+use core::ascii::Char;
+use core::fmt::Write;
+
+/// Tests Display implementation for ascii::Char.
+#[test]
+fn test_display() {
+ let want = (0..128u8).map(|b| b as char).collect::<String>();
+ let mut got = String::with_capacity(128);
+ for byte in 0..128 {
+ write!(&mut got, "{}", Char::from_u8(byte).unwrap()).unwrap();
+ }
+ assert_eq!(want, got);
+}
+
+/// Tests Debug implementation for ascii::Char.
+#[test]
+fn test_debug_control() {
+ for byte in 0..128u8 {
+ let mut want = format!("{:?}", byte as char);
+ // `char` uses `'\u{#}'` representation where ascii::char uses `'\x##'`.
+ // Transform former into the latter.
+ if let Some(rest) = want.strip_prefix("'\\u{") {
+ want = format!("'\\x{:0>2}'", rest.strip_suffix("}'").unwrap());
+ }
+ let chr = core::ascii::Char::from_u8(byte).unwrap();
+ assert_eq!(want, format!("{chr:?}"), "byte: {byte}");
+ }
+}
diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs
index 23efab2..b7130f1 100644
--- a/library/core/tests/clone.rs
+++ b/library/core/tests/clone.rs
@@ -36,7 +36,8 @@ fn test_clone_to_uninit_slice_success() {
#[test]
#[cfg(panic = "unwind")]
fn test_clone_to_uninit_slice_drops_on_panic() {
- use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+ use core::sync::atomic::AtomicUsize;
+ use core::sync::atomic::Ordering::Relaxed;
/// A static counter is OK to use as long as _this one test_ isn't run several times in
/// multiple threads.
diff --git a/library/core/tests/cmp.rs b/library/core/tests/cmp.rs
index 72fdd49..6c4e214 100644
--- a/library/core/tests/cmp.rs
+++ b/library/core/tests/cmp.rs
@@ -1,7 +1,5 @@
-use core::cmp::{
- self,
- Ordering::{self, *},
-};
+use core::cmp::Ordering::{self, *};
+use core::cmp::{self};
#[test]
fn test_int_totalord() {
diff --git a/library/core/tests/hash/sip.rs b/library/core/tests/hash/sip.rs
index 0a67c48..f79954f 100644
--- a/library/core/tests/hash/sip.rs
+++ b/library/core/tests/hash/sip.rs
@@ -1,7 +1,6 @@
#![allow(deprecated)]
-use core::hash::{Hash, Hasher};
-use core::hash::{SipHasher, SipHasher13};
+use core::hash::{Hash, Hasher, SipHasher, SipHasher13};
use core::{mem, slice};
// Hash just the bytes of the slice, without length prefix
diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs
index c93510d..1b2c026 100644
--- a/library/core/tests/iter/adapters/chain.rs
+++ b/library/core/tests/iter/adapters/chain.rs
@@ -1,7 +1,8 @@
-use super::*;
use core::iter::*;
use core::num::NonZero;
+use super::*;
+
#[test]
fn test_chain() {
let xs = [0, 1, 2, 3, 4, 5];
diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs
index 1f953f2..66b7b6c 100644
--- a/library/core/tests/iter/adapters/flatten.rs
+++ b/library/core/tests/iter/adapters/flatten.rs
@@ -1,8 +1,9 @@
-use super::*;
use core::assert_eq;
use core::iter::*;
use core::num::NonZero;
+use super::*;
+
#[test]
fn test_iterator_flatten() {
let xs = [0, 3, 6];
diff --git a/library/core/tests/iter/adapters/map_windows.rs b/library/core/tests/iter/adapters/map_windows.rs
index 6744eff..01cebc9 100644
--- a/library/core/tests/iter/adapters/map_windows.rs
+++ b/library/core/tests/iter/adapters/map_windows.rs
@@ -1,10 +1,12 @@
-use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering::SeqCst;
#[cfg(not(panic = "abort"))]
mod drop_checks {
//! These tests mainly make sure the elements are correctly dropped.
- use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst};
+ use std::sync::atomic::Ordering::SeqCst;
+ use std::sync::atomic::{AtomicBool, AtomicUsize};
#[derive(Debug)]
struct DropInfo {
diff --git a/library/core/tests/iter/adapters/peekable.rs b/library/core/tests/iter/adapters/peekable.rs
index c1a1c29..7f4341b 100644
--- a/library/core/tests/iter/adapters/peekable.rs
+++ b/library/core/tests/iter/adapters/peekable.rs
@@ -1,6 +1,7 @@
-use super::*;
use core::iter::*;
+use super::*;
+
#[test]
fn test_iterator_peekable() {
let xs = vec![0, 1, 2, 3, 4, 5];
diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs
index ba54de5..94b49ba 100644
--- a/library/core/tests/iter/adapters/zip.rs
+++ b/library/core/tests/iter/adapters/zip.rs
@@ -1,6 +1,7 @@
-use super::*;
use core::iter::*;
+use super::*;
+
#[test]
fn test_zip_nth() {
let xs = [0, 1, 2, 4, 5];
@@ -239,8 +240,7 @@ fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
#[test]
#[cfg(panic = "unwind")]
fn test_zip_trusted_random_access_next_back_drop() {
- use std::panic::catch_unwind;
- use std::panic::AssertUnwindSafe;
+ use std::panic::{catch_unwind, AssertUnwindSafe};
let mut counter = 0;
diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs
index e31db07..d5d2b8b 100644
--- a/library/core/tests/iter/range.rs
+++ b/library/core/tests/iter/range.rs
@@ -1,7 +1,8 @@
-use super::*;
use core::ascii::Char as AsciiChar;
use core::num::NonZero;
+use super::*;
+
#[test]
fn test_range() {
assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
diff --git a/library/core/tests/iter/sources.rs b/library/core/tests/iter/sources.rs
index a15f3a5..eb8c80d 100644
--- a/library/core/tests/iter/sources.rs
+++ b/library/core/tests/iter/sources.rs
@@ -1,6 +1,7 @@
-use super::*;
use core::iter::*;
+use super::*;
+
#[test]
fn test_repeat() {
let mut it = repeat(42);
diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs
index 7f7f1f0..a3b89f1 100644
--- a/library/core/tests/lazy.rs
+++ b/library/core/tests/lazy.rs
@@ -1,7 +1,6 @@
-use core::{
- cell::{Cell, LazyCell, OnceCell},
- sync::atomic::{AtomicUsize, Ordering::SeqCst},
-};
+use core::cell::{Cell, LazyCell, OnceCell};
+use core::sync::atomic::AtomicUsize;
+use core::sync::atomic::Ordering::SeqCst;
#[test]
fn once_cell() {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 51d57c9..8872b4c 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,6 +1,11 @@
+// tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(offset_of_nested))]
+#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
+#![cfg_attr(test, feature(cfg_match))]
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
#![feature(array_ptr_get)]
+#![feature(array_try_from_fn)]
#![feature(array_windows)]
#![feature(ascii_char)]
#![feature(ascii_char_variants)]
@@ -9,117 +14,115 @@
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
#![feature(clone_to_uninit)]
-#![feature(const_align_offset)]
#![feature(const_align_of_val_raw)]
+#![feature(const_align_offset)]
+#![feature(const_array_from_ref)]
#![feature(const_black_box)]
#![feature(const_cell_into_inner)]
#![feature(const_hash)]
#![feature(const_heap)]
#![feature(const_intrinsic_copy)]
+#![feature(const_ip)]
+#![feature(const_ipv4)]
+#![feature(const_ipv6)]
+#![feature(const_likely)]
#![feature(const_maybe_uninit_as_mut_ptr)]
+#![feature(const_mut_refs)]
#![feature(const_nonnull_new)]
+#![feature(const_option)]
+#![feature(const_option_ext)]
+#![feature(const_pin)]
#![feature(const_pointer_is_aligned)]
#![feature(const_ptr_as_ref)]
#![feature(const_ptr_write)]
+#![feature(const_result)]
+#![feature(const_slice_from_ref)]
#![feature(const_three_way_compare)]
#![feature(const_trait_impl)]
-#![feature(const_likely)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
#![feature(dec2flt)]
-#![feature(duration_consts_float)]
#![feature(duration_constants)]
#![feature(duration_constructors)]
+#![feature(duration_consts_float)]
+#![feature(error_generic_member_access)]
#![feature(exact_size_is_empty)]
#![feature(extern_types)]
-#![feature(freeze)]
+#![feature(float_minimum_maximum)]
#![feature(flt2dec)]
#![feature(fmt_internals)]
-#![feature(float_minimum_maximum)]
+#![feature(freeze)]
#![feature(future_join)]
#![feature(generic_assert_internals)]
-#![feature(array_try_from_fn)]
+#![feature(get_many_mut)]
#![feature(hasher_prefixfree_extras)]
#![feature(hashmap_internals)]
-#![feature(try_find)]
-#![feature(layout_for_ptr)]
-#![feature(pattern)]
-#![feature(slice_take)]
-#![feature(slice_from_ptr_range)]
-#![feature(slice_split_once)]
-#![feature(split_as_slice)]
-#![feature(maybe_uninit_fill)]
-#![feature(maybe_uninit_write_slice)]
-#![feature(maybe_uninit_uninit_array_transpose)]
-#![feature(min_specialization)]
-#![feature(noop_waker)]
-#![feature(numfmt)]
-#![feature(num_midpoint)]
-#![feature(offset_of_nested)]
-#![feature(isqrt)]
-#![feature(step_trait)]
-#![feature(str_internals)]
-#![feature(std_internals)]
-#![feature(test)]
-#![feature(trusted_len)]
-#![feature(try_blocks)]
-#![feature(try_trait_v2)]
-#![feature(slice_internals)]
-#![feature(slice_partition_dedup)]
+#![feature(int_roundings)]
#![feature(ip)]
+#![feature(is_ascii_octdigit)]
+#![feature(isqrt)]
#![feature(iter_advance_by)]
#![feature(iter_array_chunks)]
#![feature(iter_chain)]
#![feature(iter_collect_into)]
-#![feature(iter_partition_in_place)]
#![feature(iter_intersperse)]
#![feature(iter_is_partitioned)]
+#![feature(iter_map_windows)]
#![feature(iter_next_chunk)]
#![feature(iter_order_by)]
+#![feature(iter_partition_in_place)]
#![feature(iter_repeat_n)]
#![feature(iterator_try_collect)]
#![feature(iterator_try_reduce)]
-#![feature(const_ip)]
-#![feature(const_ipv4)]
-#![feature(const_ipv6)]
-#![feature(const_mut_refs)]
-#![feature(const_pin)]
-#![feature(const_waker)]
+#![feature(layout_for_ptr)]
+#![feature(maybe_uninit_fill)]
+#![feature(maybe_uninit_uninit_array_transpose)]
+#![feature(maybe_uninit_write_slice)]
+#![feature(min_specialization)]
#![feature(never_type)]
-#![feature(unwrap_infallible)]
+#![feature(noop_waker)]
+#![feature(num_midpoint)]
+#![feature(numfmt)]
+#![feature(pattern)]
#![feature(pointer_is_aligned_to)]
#![feature(portable_simd)]
#![feature(ptr_metadata)]
-#![feature(unsized_tuple_coercion)]
-#![feature(const_option)]
-#![feature(const_option_ext)]
-#![feature(const_result)]
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
-#![cfg_attr(test, feature(cfg_match))]
-#![feature(int_roundings)]
+#![feature(slice_from_ptr_range)]
+#![feature(slice_internals)]
+#![feature(slice_partition_dedup)]
+#![feature(slice_split_once)]
+#![feature(slice_take)]
#![feature(split_array)]
+#![feature(split_as_slice)]
+#![feature(std_internals)]
+#![feature(step_trait)]
+#![feature(str_internals)]
#![feature(strict_provenance)]
#![feature(strict_provenance_atomic_ptr)]
-#![feature(trusted_random_access)]
-#![feature(unsize)]
-#![feature(const_array_from_ref)]
-#![feature(const_slice_from_ref)]
-#![feature(waker_getters)]
-#![feature(error_generic_member_access)]
+#![feature(test)]
#![feature(trait_upcasting)]
-#![feature(is_ascii_octdigit)]
-#![feature(get_many_mut)]
-#![feature(iter_map_windows)]
+#![feature(trusted_len)]
+#![feature(trusted_random_access)]
+#![feature(try_blocks)]
+#![feature(try_find)]
+#![feature(try_trait_v2)]
+#![feature(unsigned_is_multiple_of)]
+#![feature(unsize)]
+#![feature(unsized_tuple_coercion)]
+#![feature(unwrap_infallible)]
+#![feature(waker_getters)]
+// tidy-alphabetical-end
#![allow(internal_features)]
-#![deny(unsafe_op_in_unsafe_fn)]
#![deny(fuzzy_provenance_casts)]
+#![deny(unsafe_op_in_unsafe_fn)]
mod alloc;
mod any;
mod array;
mod ascii;
+mod ascii_char;
mod asserting;
mod async_iter;
mod atomic;
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index cc73391..b7eee10 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -1,6 +1,5 @@
use core::mem::*;
use core::ptr;
-
#[cfg(panic = "unwind")]
use std::rc::Rc;
diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs
index f9b351e..a10b51c 100644
--- a/library/core/tests/net/ip_addr.rs
+++ b/library/core/tests/net/ip_addr.rs
@@ -1,9 +1,10 @@
-use super::{sa4, sa6};
use core::net::{
IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope, SocketAddr, SocketAddrV4, SocketAddrV6,
};
use core::str::FromStr;
+use super::{sa4, sa6};
+
#[test]
fn test_from_str_ipv4() {
assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
index 83e2707..070a53e 100644
--- a/library/core/tests/num/flt2dec/mod.rs
+++ b/library/core/tests/num/flt2dec/mod.rs
@@ -1,12 +1,10 @@
-use std::mem::MaybeUninit;
-use std::{fmt, str};
-
-use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
-use core::num::flt2dec::{round_up, Sign, MAX_SIG_DIGITS};
use core::num::flt2dec::{
- to_exact_exp_str, to_exact_fixed_str, to_shortest_exp_str, to_shortest_str,
+ decode, round_up, to_exact_exp_str, to_exact_fixed_str, to_shortest_exp_str, to_shortest_str,
+ DecodableFloat, Decoded, FullDecoded, Sign, MAX_SIG_DIGITS,
};
use core::num::fmt::{Formatted, Part};
+use std::mem::MaybeUninit;
+use std::{fmt, str};
mod estimator;
mod strategy {
diff --git a/library/core/tests/num/flt2dec/random.rs b/library/core/tests/num/flt2dec/random.rs
index 0084c1c..4817a66 100644
--- a/library/core/tests/num/flt2dec/random.rs
+++ b/library/core/tests/num/flt2dec/random.rs
@@ -1,13 +1,10 @@
#![cfg(not(target_arch = "wasm32"))]
+use core::num::flt2dec::strategy::grisu::{format_exact_opt, format_shortest_opt};
+use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded, MAX_SIG_DIGITS};
use std::mem::MaybeUninit;
use std::str;
-use core::num::flt2dec::strategy::grisu::format_exact_opt;
-use core::num::flt2dec::strategy::grisu::format_shortest_opt;
-use core::num::flt2dec::MAX_SIG_DIGITS;
-use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
-
use rand::distributions::{Distribution, Uniform};
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
diff --git a/library/core/tests/num/flt2dec/strategy/dragon.rs b/library/core/tests/num/flt2dec/strategy/dragon.rs
index fc2e724..be25fee 100644
--- a/library/core/tests/num/flt2dec/strategy/dragon.rs
+++ b/library/core/tests/num/flt2dec/strategy/dragon.rs
@@ -1,7 +1,8 @@
-use super::super::*;
use core::num::bignum::Big32x40 as Big;
use core::num::flt2dec::strategy::dragon::*;
+use super::super::*;
+
#[test]
fn test_mul_pow10() {
let mut prevpow10 = Big::from_small(1);
diff --git a/library/core/tests/num/flt2dec/strategy/grisu.rs b/library/core/tests/num/flt2dec/strategy/grisu.rs
index b59a3b9..9b2f045 100644
--- a/library/core/tests/num/flt2dec/strategy/grisu.rs
+++ b/library/core/tests/num/flt2dec/strategy/grisu.rs
@@ -1,6 +1,7 @@
-use super::super::*;
use core::num::flt2dec::strategy::grisu::*;
+use super::super::*;
+
#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_cached_power() {
diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs
index 9554406..d009ad8 100644
--- a/library/core/tests/num/uint_macros.rs
+++ b/library/core/tests/num/uint_macros.rs
@@ -261,6 +261,14 @@ fn test_checked_next_multiple_of() {
}
#[test]
+ fn test_is_next_multiple_of() {
+ assert!((12 as $T).is_multiple_of(4));
+ assert!(!(12 as $T).is_multiple_of(5));
+ assert!((0 as $T).is_multiple_of(0));
+ assert!(!(12 as $T).is_multiple_of(0));
+ }
+
+ #[test]
fn test_carrying_add() {
assert_eq!($T::MAX.carrying_add(1, false), (0, true));
assert_eq!($T::MAX.carrying_add(0, true), (0, true));
diff --git a/library/core/tests/ops.rs b/library/core/tests/ops.rs
index 0c81cba..2ee0abd 100644
--- a/library/core/tests/ops.rs
+++ b/library/core/tests/ops.rs
@@ -1,7 +1,8 @@
mod control_flow;
-use core::ops::{Bound, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
-use core::ops::{Deref, DerefMut};
+use core::ops::{
+ Bound, Deref, DerefMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
+};
// Test the Range structs and syntax.
diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs
index 6f617c8..7a6af46 100644
--- a/library/core/tests/pin.rs
+++ b/library/core/tests/pin.rs
@@ -29,3 +29,49 @@ const fn pin_mut_const() {
pin_mut_const();
}
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+ use core::cell::{Cell, RefCell, UnsafeCell};
+ use core::pin::Pin;
+ use core::ptr::NonNull;
+
+ pub trait MyTrait {}
+ impl MyTrait for String {}
+
+ // These Pins should continue to compile.
+ // Do note that these instances of Pin types cannot be used
+ // meaningfully because all methods require a Deref/DerefMut
+ // bounds on the pointer type and Cell, RefCell and UnsafeCell
+ // do not implement Deref/DerefMut.
+
+ pub fn cell(arg: Pin<Cell<Box<String>>>) -> Pin<Cell<Box<dyn MyTrait>>> {
+ arg
+ }
+ pub fn ref_cell(arg: Pin<RefCell<Box<String>>>) -> Pin<RefCell<Box<dyn MyTrait>>> {
+ arg
+ }
+ pub fn unsafe_cell(arg: Pin<UnsafeCell<Box<String>>>) -> Pin<UnsafeCell<Box<dyn MyTrait>>> {
+ arg
+ }
+
+ // These sensible Pin coercions are possible.
+ pub fn pin_mut_ref(arg: Pin<&mut String>) -> Pin<&mut dyn MyTrait> {
+ arg
+ }
+ pub fn pin_ref(arg: Pin<&String>) -> Pin<&dyn MyTrait> {
+ arg
+ }
+ pub fn pin_ptr(arg: Pin<*const String>) -> Pin<*const dyn MyTrait> {
+ arg
+ }
+ pub fn pin_ptr_mut(arg: Pin<*mut String>) -> Pin<*mut dyn MyTrait> {
+ arg
+ }
+ pub fn pin_non_null(arg: Pin<NonNull<String>>) -> Pin<NonNull<dyn MyTrait>> {
+ arg
+ }
+ pub fn nesting_pins(arg: Pin<Pin<&String>>) -> Pin<Pin<&dyn MyTrait>> {
+ arg
+ }
+}
diff --git a/library/core/tests/pin_macro.rs b/library/core/tests/pin_macro.rs
index 57485ef..36c6972 100644
--- a/library/core/tests/pin_macro.rs
+++ b/library/core/tests/pin_macro.rs
@@ -1,10 +1,8 @@
// edition:2021
-use core::{
- marker::PhantomPinned,
- mem::{drop as stuff, transmute},
- pin::{pin, Pin},
-};
+use core::marker::PhantomPinned;
+use core::mem::{drop as stuff, transmute};
+use core::pin::{pin, Pin};
#[test]
fn basic() {
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index e383016..78d1b13 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -810,9 +810,12 @@ fn ptr_metadata() {
assert_ne!(address_1, address_2);
// Different erased type => different vtable pointer
assert_ne!(address_2, address_3);
- // Same erased type and same trait => same vtable pointer
- assert_eq!(address_3, address_4);
- assert_eq!(address_3, address_5);
+ // Same erased type and same trait => same vtable pointer.
+ // This is *not guaranteed*, so we skip it in Miri.
+ if !cfg!(miri) {
+ assert_eq!(address_3, address_4);
+ assert_eq!(address_3, address_5);
+ }
}
}
@@ -1050,7 +1053,7 @@ impl<T> TaggedPointer<T> {
/// A mask for the non-data-carrying bits of the address.
pub const ADDRESS_MASK: usize = usize::MAX << Self::NUM_BITS;
- /// Create a new tagged pointer from a possibly null pointer.
+ /// Creates a new tagged pointer from a possibly null pointer.
pub fn new(pointer: *mut T) -> Option<TaggedPointer<T>> {
Some(TaggedPointer(NonNull::new(pointer)?))
}
diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs
index 00a6fd7..90ec844 100644
--- a/library/core/tests/result.rs
+++ b/library/core/tests/result.rs
@@ -410,7 +410,8 @@ fn try_num(x: i32) -> Result<i32, BadNumErr> {
#[test]
fn result_try_trait_v2_branch() {
use core::num::NonZero;
- use core::ops::{ControlFlow::*, Try};
+ use core::ops::ControlFlow::*;
+ use core::ops::Try;
assert_eq!(Ok::<i32, i32>(4).branch(), Continue(4));
assert_eq!(Err::<i32, i32>(4).branch(), Break(Err(4)));
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 4cbbabb..cdefb5d 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -69,13 +69,13 @@ fn test_binary_search() {
assert_eq!(b.binary_search(&8), Err(5));
let b = [(); usize::MAX];
- assert_eq!(b.binary_search(&()), Ok(usize::MAX / 2));
+ assert_eq!(b.binary_search(&()), Ok(usize::MAX - 1));
}
#[test]
fn test_binary_search_by_overflow() {
let b = [(); usize::MAX];
- assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX / 2));
+ assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX - 1));
assert_eq!(b.binary_search_by(|_| Ordering::Greater), Err(0));
assert_eq!(b.binary_search_by(|_| Ordering::Less), Err(usize::MAX));
}
@@ -87,13 +87,13 @@ fn test_binary_search_implementation_details() {
let b = [1, 1, 2, 2, 3, 3, 3];
assert_eq!(b.binary_search(&1), Ok(1));
assert_eq!(b.binary_search(&2), Ok(3));
- assert_eq!(b.binary_search(&3), Ok(5));
+ assert_eq!(b.binary_search(&3), Ok(6));
let b = [1, 1, 1, 1, 1, 3, 3, 3, 3];
assert_eq!(b.binary_search(&1), Ok(4));
- assert_eq!(b.binary_search(&3), Ok(7));
+ assert_eq!(b.binary_search(&3), Ok(8));
let b = [1, 1, 1, 1, 3, 3, 3, 3, 3];
- assert_eq!(b.binary_search(&1), Ok(2));
- assert_eq!(b.binary_search(&3), Ok(4));
+ assert_eq!(b.binary_search(&1), Ok(3));
+ assert_eq!(b.binary_search(&3), Ok(8));
}
#[test]
@@ -1856,6 +1856,7 @@ fn sort_unstable() {
#[cfg_attr(miri, ignore)] // Miri is too slow
fn select_nth_unstable() {
use core::cmp::Ordering::{Equal, Greater, Less};
+
use rand::seq::SliceRandom;
use rand::Rng;
diff --git a/library/core/tests/waker.rs b/library/core/tests/waker.rs
index 2c66e0d..361e900 100644
--- a/library/core/tests/waker.rs
+++ b/library/core/tests/waker.rs
@@ -20,3 +20,33 @@ fn test_waker_getters() {
|_| {},
|_| {},
);
+
+// https://github.com/rust-lang/rust/issues/102012#issuecomment-1915282956
+mod nop_waker {
+ use core::future::{ready, Future};
+ use core::pin::Pin;
+ use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
+
+ const NOP_RAWWAKER: RawWaker = {
+ fn nop(_: *const ()) {}
+ const VTAB: RawWakerVTable = RawWakerVTable::new(|_| NOP_RAWWAKER, nop, nop, nop);
+ RawWaker::new(&() as *const (), &VTAB)
+ };
+
+ const NOP_WAKER: &Waker = &unsafe { Waker::from_raw(NOP_RAWWAKER) };
+
+ const NOP_CONTEXT: Context<'static> = Context::from_waker(NOP_WAKER);
+
+ fn poll_once<T, F>(f: &mut F) -> Poll<T>
+ where
+ F: Future<Output = T> + ?Sized + Unpin,
+ {
+ let mut cx = NOP_CONTEXT;
+ Pin::new(f).as_mut().poll(&mut cx)
+ }
+
+ #[test]
+ fn test_const_waker() {
+ assert_eq!(poll_once(&mut ready(1)), Poll::Ready(1));
+ }
+}
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index 14ba4af..dc2b42b 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -14,7 +14,6 @@
#![feature(std_internals)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
-#![cfg_attr(bootstrap, feature(c_unwind))]
#![allow(internal_features)]
#[cfg(target_os = "android")]
diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs
index fed4c52..86a4318 100644
--- a/library/panic_unwind/src/emcc.rs
+++ b/library/panic_unwind/src/emcc.rs
@@ -8,10 +8,9 @@
use alloc::boxed::Box;
use core::any::Any;
-use core::intrinsics;
-use core::mem;
-use core::ptr;
use core::sync::atomic::{AtomicBool, Ordering};
+use core::{intrinsics, mem, ptr};
+
use unwind as uw;
// This matches the layout of std::type_info in C++
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 77abb91..2d174f4 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -24,7 +24,6 @@
#![feature(rustc_attrs)]
#![panic_runtime]
#![feature(panic_runtime)]
-#![cfg_attr(bootstrap, feature(c_unwind))]
// `real_imp` is unused with Miri, so silence warnings.
#![cfg_attr(miri, allow(dead_code))]
#![allow(internal_features)]
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
index e6e27c7..04de3a9 100644
--- a/library/portable-simd/crates/core_simd/src/masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks.rs
@@ -137,7 +137,7 @@ impl<T, const N: usize> Mask<T, N>
T: MaskElement,
LaneCount<N>: SupportedLaneCount,
{
- /// Construct a mask by setting all elements to the given value.
+ /// Constructs a mask by setting all elements to the given value.
#[inline]
pub fn splat(value: bool) -> Self {
Self(mask_impl::Mask::splat(value))
@@ -288,7 +288,7 @@ pub fn all(self) -> bool {
self.0.all()
}
- /// Create a bitmask from a mask.
+ /// Creates a bitmask from a mask.
///
/// Each bit is set if the corresponding element in the mask is `true`.
/// If the mask contains more than 64 elements, the bitmask is truncated to the first 64.
@@ -298,7 +298,7 @@ pub fn to_bitmask(self) -> u64 {
self.0.to_bitmask_integer()
}
- /// Create a mask from a bitmask.
+ /// Creates a mask from a bitmask.
///
/// For each bit, if it is set, the corresponding element in the mask is set to `true`.
/// If the mask contains more than 64 elements, the remainder are set to `false`.
@@ -308,7 +308,7 @@ pub fn from_bitmask(bitmask: u64) -> Self {
Self(mask_impl::Mask::from_bitmask_integer(bitmask))
}
- /// Create a bitmask vector from a mask.
+ /// Creates a bitmask vector from a mask.
///
/// Each bit is set if the corresponding element in the mask is `true`.
/// The remaining bits are unset.
@@ -328,7 +328,7 @@ pub fn to_bitmask_vector(self) -> Simd<u8, N> {
self.0.to_bitmask_vector()
}
- /// Create a mask from a bitmask vector.
+ /// Creates a mask from a bitmask vector.
///
/// For each bit, if it is set, the corresponding element in the mask is set to `true`.
///
@@ -350,7 +350,7 @@ pub fn from_bitmask_vector(bitmask: Simd<u8, N>) -> Self {
Self(mask_impl::Mask::from_bitmask_vector(bitmask))
}
- /// Find the index of the first set element.
+ /// Finds the index of the first set element.
///
/// ```
/// # #![feature(portable_simd)]
diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs
index cbffbc5..be635ea 100644
--- a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs
+++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs
@@ -54,7 +54,7 @@ pub trait SimdConstPtr: Copy + Sealed {
/// [`Self::with_exposed_provenance`] and returns the "address" portion.
fn expose_provenance(self) -> Self::Usize;
- /// Convert an address back to a pointer, picking up a previously "exposed" provenance.
+ /// Converts an address back to a pointer, picking up a previously "exposed" provenance.
///
/// Equivalent to calling [`core::ptr::with_exposed_provenance`] on each element.
fn with_exposed_provenance(addr: Self::Usize) -> Self;
diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs
index 6bc6ca3..f6823a9 100644
--- a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs
+++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs
@@ -51,7 +51,7 @@ pub trait SimdMutPtr: Copy + Sealed {
/// [`Self::with_exposed_provenance`] and returns the "address" portion.
fn expose_provenance(self) -> Self::Usize;
- /// Convert an address back to a pointer, picking up a previously "exposed" provenance.
+ /// Converts an address back to a pointer, picking up a previously "exposed" provenance.
///
/// Equivalent to calling [`core::ptr::with_exposed_provenance_mut`] on each element.
fn with_exposed_provenance(addr: Self::Usize) -> Self;
diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs
index 71110bb..2f4f777 100644
--- a/library/portable-simd/crates/core_simd/src/swizzle.rs
+++ b/library/portable-simd/crates/core_simd/src/swizzle.rs
@@ -69,12 +69,12 @@ impl Swizzle<{$index.len()}> for Impl {
}
}
-/// Create a vector from the elements of another vector.
+/// Creates a vector from the elements of another vector.
pub trait Swizzle<const N: usize> {
/// Map from the elements of the input vector to the output vector.
const INDEX: [usize; N];
- /// Create a new vector from the elements of `vector`.
+ /// Creates a new vector from the elements of `vector`.
///
/// Lane `i` of the output is `vector[Self::INDEX[i]]`.
#[inline]
@@ -109,7 +109,7 @@ fn swizzle<T, const M: usize>(vector: Simd<T, M>) -> Simd<T, N>
}
}
- /// Create a new vector from the elements of `first` and `second`.
+ /// Creates a new vector from the elements of `first` and `second`.
///
/// Lane `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of
/// `first` and `second`.
@@ -145,7 +145,7 @@ fn concat_swizzle<T, const M: usize>(first: Simd<T, M>, second: Simd<T, M>) -> S
}
}
- /// Create a new mask from the elements of `mask`.
+ /// Creates a new mask from the elements of `mask`.
///
/// Element `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of
/// `first` and `second`.
@@ -161,7 +161,7 @@ fn swizzle_mask<T, const M: usize>(mask: Mask<T, M>) -> Mask<T, N>
unsafe { Mask::from_int_unchecked(Self::swizzle(mask.to_int())) }
}
- /// Create a new mask from the elements of `first` and `second`.
+ /// Creates a new mask from the elements of `first` and `second`.
///
/// Element `i` of the output is `concat[Self::INDEX[i]]`, where `concat` is the concatenation of
/// `first` and `second`.
diff --git a/library/portable-simd/crates/core_simd/src/to_bytes.rs b/library/portable-simd/crates/core_simd/src/to_bytes.rs
index 222526c..4833ea9 100644
--- a/library/portable-simd/crates/core_simd/src/to_bytes.rs
+++ b/library/portable-simd/crates/core_simd/src/to_bytes.rs
@@ -10,7 +10,7 @@ impl<T: SimdElement, const N: usize> Sealed for Simd<T, N> where LaneCount<N>: S
}
use sealed::Sealed;
-/// Convert SIMD vectors to vectors of bytes
+/// Converts SIMD vectors to vectors of bytes
pub trait ToBytes: Sealed {
/// This type, reinterpreted as bytes.
type Bytes: Copy
@@ -22,26 +22,26 @@ pub trait ToBytes: Sealed {
+ SimdUint<Scalar = u8>
+ 'static;
- /// Return the memory representation of this integer as a byte array in native byte
+ /// Returns the memory representation of this integer as a byte array in native byte
/// order.
fn to_ne_bytes(self) -> Self::Bytes;
- /// Return the memory representation of this integer as a byte array in big-endian
+ /// Returns the memory representation of this integer as a byte array in big-endian
/// (network) byte order.
fn to_be_bytes(self) -> Self::Bytes;
- /// Return the memory representation of this integer as a byte array in little-endian
+ /// Returns the memory representation of this integer as a byte array in little-endian
/// byte order.
fn to_le_bytes(self) -> Self::Bytes;
- /// Create a native endian integer value from its memory representation as a byte array
+ /// Creates a native endian integer value from its memory representation as a byte array
/// in native endianness.
fn from_ne_bytes(bytes: Self::Bytes) -> Self;
- /// Create an integer value from its representation as a byte array in big endian.
+ /// Creates an integer value from its representation as a byte array in big endian.
fn from_be_bytes(bytes: Self::Bytes) -> Self;
- /// Create an integer value from its representation as a byte array in little endian.
+ /// Creates an integer value from its representation as a byte array in little endian.
fn from_le_bytes(bytes: Self::Bytes) -> Self;
}
diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs
index 8dbdfc0..3e23916 100644
--- a/library/portable-simd/crates/core_simd/src/vector.rs
+++ b/library/portable-simd/crates/core_simd/src/vector.rs
@@ -187,7 +187,7 @@ impl<const N: usize> Swizzle<N> for Splat {
unsafe { &mut *(self as *mut Self as *mut [T; N]) }
}
- /// Load a vector from an array of `T`.
+ /// Loads a vector from an array of `T`.
///
/// This function is necessary since `repr(simd)` has padding for non-power-of-2 vectors (at the time of writing).
/// With padding, `read_unaligned` will read past the end of an array of N elements.
@@ -567,7 +567,7 @@ pub unsafe fn gather_select_unchecked(
unsafe { Self::gather_select_ptr(ptrs, enable, or) }
}
- /// Read elementwise from pointers into a SIMD vector.
+ /// Reads elementwise from pointers into a SIMD vector.
///
/// # Safety
///
@@ -808,7 +808,7 @@ pub unsafe fn scatter_select_unchecked(
}
}
- /// Write pointers elementwise into a SIMD vector.
+ /// Writes pointers elementwise into a SIMD vector.
///
/// # Safety
///
diff --git a/library/proc_macro/src/bridge/arena.rs b/library/proc_macro/src/bridge/arena.rs
index f81f215..1d59860 100644
--- a/library/proc_macro/src/bridge/arena.rs
+++ b/library/proc_macro/src/bridge/arena.rs
@@ -5,12 +5,9 @@
//! being built at the same time as `std`.
use std::cell::{Cell, RefCell};
-use std::cmp;
use std::mem::MaybeUninit;
use std::ops::Range;
-use std::ptr;
-use std::slice;
-use std::str;
+use std::{cmp, ptr, slice, str};
// The arenas start with PAGE-sized chunks, and then each new chunk is twice as
// big as its predecessor, up until we reach HUGE_PAGE-sized chunks, whereupon
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index 9658fc4..5a10865 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -1,11 +1,11 @@
//! Client-side types.
-use super::*;
-
use std::cell::RefCell;
use std::marker::PhantomData;
use std::sync::atomic::AtomicU32;
+use super::*;
+
macro_rules! define_client_handles {
(
'owned: $($oty:ident,)*
@@ -190,10 +190,11 @@ impl<'a> !Sync for Bridge<'a> {}
#[allow(unsafe_code)]
mod state {
- use super::Bridge;
use std::cell::{Cell, RefCell};
use std::ptr;
+ use super::Bridge;
+
thread_local! {
static BRIDGE_STATE: Cell<*const ()> = const { Cell::new(ptr::null()) };
}
diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs
index 9fb79ea..74a4145 100644
--- a/library/proc_macro/src/bridge/fxhash.rs
+++ b/library/proc_macro/src/bridge/fxhash.rs
@@ -5,8 +5,7 @@
//! on the `rustc_hash` crate.
use std::collections::HashMap;
-use std::hash::BuildHasherDefault;
-use std::hash::Hasher;
+use std::hash::{BuildHasherDefault, Hasher};
use std::ops::BitXor;
/// Type alias for a hashmap using the `fx` hash algorithm.
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 8553e8d..03c3e69 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -8,16 +8,12 @@
#![deny(unsafe_code)]
-use crate::{Delimiter, Level, Spacing};
-use std::fmt;
use std::hash::Hash;
-use std::marker;
-use std::mem;
-use std::ops::Bound;
-use std::ops::Range;
-use std::panic;
+use std::ops::{Bound, Range};
use std::sync::Once;
-use std::thread;
+use std::{fmt, marker, mem, panic, thread};
+
+use crate::{Delimiter, Level, Spacing};
/// Higher-order macro describing the server RPC API, allowing automatic
/// generation of type-safe Rust APIs, both client-side and server-side.
diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs
index 0dbd4ba..692b603 100644
--- a/library/proc_macro/src/bridge/server.rs
+++ b/library/proc_macro/src/bridge/server.rs
@@ -1,10 +1,10 @@
//! Server-side traits.
-use super::*;
-
use std::cell::Cell;
use std::marker::PhantomData;
+use super::*;
+
macro_rules! define_server_handles {
(
'owned: $($oty:ident,)*
@@ -350,7 +350,7 @@ fn run_bridge_and_client(
/// A message pipe used for communicating between server and client threads.
pub trait MessagePipe<T>: Sized {
- /// Create a new pair of endpoints for the message pipe.
+ /// Creates a new pair of endpoints for the message pipe.
fn new() -> (Self, Self);
/// Send a message to the other endpoint of this pipe.
diff --git a/library/proc_macro/src/bridge/symbol.rs b/library/proc_macro/src/bridge/symbol.rs
index 86ce2cc..37aaee6 100644
--- a/library/proc_macro/src/bridge/symbol.rs
+++ b/library/proc_macro/src/bridge/symbol.rs
@@ -28,7 +28,7 @@ pub(crate) fn new(string: &str) -> Self {
INTERNER.with_borrow_mut(|i| i.intern(string))
}
- /// Create a new `Symbol` for an identifier.
+ /// Creates a new `Symbol` for an identifier.
///
/// Validates and normalizes before converting it to a symbol.
pub(crate) fn new_ident(string: &str, is_raw: bool) -> Self {
@@ -63,7 +63,7 @@ pub(crate) fn invalidate_all() {
INTERNER.with_borrow_mut(|i| i.clear());
}
- /// Check if the ident is a valid ASCII identifier.
+ /// Checks if the ident is a valid ASCII identifier.
///
/// This is a short-circuit which is cheap to implement within the
/// proc-macro client to avoid RPC when creating simple idents, but may
@@ -177,7 +177,7 @@ fn intern(&mut self, string: &str) -> Symbol {
name
}
- /// Read a symbol's value from the store while it is held.
+ /// Reads a symbol's value from the store while it is held.
fn get(&self, symbol: Symbol) -> &str {
// NOTE: Subtract out the offset which was added to make the symbol
// nonzero and prevent symbol name re-use.
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 5724735..c271ac1 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -37,6 +37,7 @@
#![recursion_limit = "256"]
#![allow(internal_features)]
#![deny(ffi_unwind_calls)]
+#![warn(rustdoc::unescaped_backticks)]
#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[doc(hidden)]
@@ -45,16 +46,17 @@
mod diagnostic;
mod escape;
-#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
-pub use diagnostic::{Diagnostic, Level, MultiSpan};
-
-use crate::escape::{escape_bytes, EscapeOptions};
use std::ffi::CStr;
use std::ops::{Range, RangeBounds};
use std::path::PathBuf;
use std::str::FromStr;
use std::{error, fmt};
+#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
+pub use diagnostic::{Diagnostic, Level, MultiSpan};
+
+use crate::escape::{escape_bytes, EscapeOptions};
+
/// Determines whether proc_macro has been made accessible to the currently
/// running program.
///
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 5929c94..2ce284c 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,7 +17,7 @@
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core", public = true }
-compiler_builtins = { version = "0.1.105" }
+compiler_builtins = { version = "0.1.118" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.14", default-features = false, features = [
@@ -95,8 +95,8 @@
compiler-builtins-c = ["alloc/compiler-builtins-c"]
compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"]
+compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"]
compiler-builtins-mangled-names = ["alloc/compiler-builtins-mangled-names"]
-compiler-builtins-weak-intrinsics = ["alloc/compiler-builtins-weak-intrinsics"]
llvm-libunwind = ["unwind/llvm-libunwind"]
system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
diff --git a/library/std/benches/hash/map.rs b/library/std/benches/hash/map.rs
index bf646cb..d6023c8 100644
--- a/library/std/benches/hash/map.rs
+++ b/library/std/benches/hash/map.rs
@@ -1,6 +1,7 @@
#![cfg(test)]
use std::collections::HashMap;
+
use test::Bencher;
#[bench]
diff --git a/library/std/benches/hash/set_ops.rs b/library/std/benches/hash/set_ops.rs
index 1a4c4a6..b97e3b4 100644
--- a/library/std/benches/hash/set_ops.rs
+++ b/library/std/benches/hash/set_ops.rs
@@ -1,4 +1,5 @@
use std::collections::HashSet;
+
use test::Bencher;
#[bench]
diff --git a/library/std/build.rs b/library/std/build.rs
index c542ba8..35a5977 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -11,6 +11,7 @@ fn main() {
.expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set")
.parse()
.unwrap();
+ let is_miri = env::var_os("CARGO_CFG_MIRI").is_some();
println!("cargo:rustc-check-cfg=cfg(netbsd10)");
if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
@@ -85,7 +86,14 @@ fn main() {
println!("cargo:rustc-check-cfg=cfg(reliable_f16)");
println!("cargo:rustc-check-cfg=cfg(reliable_f128)");
+ // This is a step beyond only having the types and basic functions available. Math functions
+ // aren't consistently available or correct.
+ println!("cargo:rustc-check-cfg=cfg(reliable_f16_math)");
+ println!("cargo:rustc-check-cfg=cfg(reliable_f128_math)");
+
let has_reliable_f16 = match (target_arch.as_str(), target_os.as_str()) {
+ // We can always enable these in Miri as that is not affected by codegen bugs.
+ _ if is_miri => true,
// Selection failure until recent LLVM <https://github.com/llvm/llvm-project/issues/93894>
// FIXME(llvm19): can probably be removed at the version bump
("loongarch64", _) => false,
@@ -94,7 +102,7 @@ fn main() {
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
- ("x86", "windows") => false,
+ ("x86_64", "windows") => false,
// x86 has ABI bugs that show up with optimizations. This should be partially fixed with
// the compiler-builtins update. <https://github.com/rust-lang/rust/issues/123885>
("x86" | "x86_64", _) => false,
@@ -113,6 +121,8 @@ fn main() {
};
let has_reliable_f128 = match (target_arch.as_str(), target_os.as_str()) {
+ // We can always enable these in Miri as that is not affected by codegen bugs.
+ _ if is_miri => true,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
("arm64ec", _) => false,
// ABI and precision bugs <https://github.com/rust-lang/rust/issues/125109>
@@ -122,16 +132,54 @@ fn main() {
("nvptx64", _) => false,
// ABI unsupported <https://github.com/llvm/llvm-project/issues/41838>
("sparc", _) => false,
+ // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
+ ("x86_64", "windows") => false,
// 64-bit Linux is about the only platform to have f128 symbols by default
(_, "linux") if target_pointer_width == 64 => true,
// Same as for f16, except MacOS is also missing f128 symbols.
_ => false,
};
+ // These are currently empty, but will fill up as some platforms move from completely
+ // unreliable to reliable basics but unreliable math.
+
+ // LLVM is currenlty adding missing routines, <https://github.com/llvm/llvm-project/issues/93566>
+ let has_reliable_f16_math = has_reliable_f16
+ && match (target_arch.as_str(), target_os.as_str()) {
+ // FIXME: Disabled on Miri as the intrinsics are not implemented yet.
+ _ if is_miri => false,
+ // Currently nothing special. Hooray!
+ // This will change as platforms gain better better support for standard ops but math
+ // lags behind.
+ _ => true,
+ };
+
+ let has_reliable_f128_math = has_reliable_f128
+ && match (target_arch.as_str(), target_os.as_str()) {
+ // FIXME: Disabled on Miri as the intrinsics are not implemented yet.
+ _ if is_miri => false,
+ // LLVM lowers `fp128` math to `long double` symbols even on platforms where
+ // `long double` is not IEEE binary128. See
+ // <https://github.com/llvm/llvm-project/issues/44744>.
+ //
+ // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits
+ // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86`
+ // (ld is 80-bit extended precision).
+ ("x86_64", _) => false,
+ (_, "linux") if target_pointer_width == 64 => true,
+ _ => false,
+ };
+
if has_reliable_f16 {
println!("cargo:rustc-cfg=reliable_f16");
}
if has_reliable_f128 {
println!("cargo:rustc-cfg=reliable_f128");
}
+ if has_reliable_f16_math {
+ println!("cargo:rustc-cfg=reliable_f16_math");
+ }
+ if has_reliable_f128_math {
+ println!("cargo:rustc-cfg=reliable_f128_math");
+ }
}
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index dc4924c..5d51d6a 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -56,10 +56,9 @@
#![deny(unsafe_op_in_unsafe_fn)]
#![stable(feature = "alloc_module", since = "1.28.0")]
-use core::hint;
use core::ptr::NonNull;
use core::sync::atomic::{AtomicPtr, Ordering};
-use core::{mem, ptr};
+use core::{hint, mem, ptr};
#[stable(feature = "alloc_module", since = "1.28.0")]
#[doc(inline)]
diff --git a/library/std/src/ascii.rs b/library/std/src/ascii.rs
index b18ab50..3a2880f 100644
--- a/library/std/src/ascii.rs
+++ b/library/std/src/ascii.rs
@@ -13,11 +13,10 @@
#![stable(feature = "rust1", since = "1.0.0")]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::ascii::{escape_default, EscapeDefault};
-
#[unstable(feature = "ascii_char", issue = "110998")]
pub use core::ascii::Char;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::ascii::{escape_default, EscapeDefault};
/// Extension methods for ASCII-subset only operations.
///
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 4d37675..7df9a8a 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -89,13 +89,13 @@
// a backtrace or actually symbolizing it.
use crate::backtrace_rs::{self, BytesOrWideString};
-use crate::env;
use crate::ffi::c_void;
-use crate::fmt;
use crate::panic::UnwindSafe;
-use crate::sync::atomic::{AtomicU8, Ordering::Relaxed};
+use crate::sync::atomic::AtomicU8;
+use crate::sync::atomic::Ordering::Relaxed;
use crate::sync::LazyLock;
use crate::sys::backtrace::{lock, output_filename, set_image_base};
+use crate::{env, fmt};
/// A captured OS thread stack backtrace.
///
@@ -271,7 +271,7 @@ fn enabled() -> bool {
enabled
}
- /// Capture a stack backtrace of the current thread.
+ /// Captures a stack backtrace of the current thread.
///
/// This function will capture a stack backtrace of the current OS thread of
/// execution, returning a `Backtrace` type which can be later used to print
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 1f6a3e9..822fa57 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1,13 +1,11 @@
#[cfg(test)]
mod tests;
-use self::Entry::*;
-
use hashbrown::hash_map as base;
+use self::Entry::*;
use crate::borrow::Borrow;
-use crate::collections::TryReserveError;
-use crate::collections::TryReserveErrorKind;
+use crate::collections::{TryReserveError, TryReserveErrorKind};
use crate::error::Error;
use crate::fmt::{self, Debug};
use crate::hash::{BuildHasher, Hash, RandomState};
diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs
index 8585376a..6641197 100644
--- a/library/std/src/collections/hash/map/tests.rs
+++ b/library/std/src/collections/hash/map/tests.rs
@@ -1,11 +1,12 @@
+use rand::Rng;
+use realstd::collections::TryReserveErrorKind::*;
+
use super::Entry::{Occupied, Vacant};
use super::HashMap;
use crate::assert_matches::assert_matches;
use crate::cell::RefCell;
use crate::hash::RandomState;
use crate::test_helpers::test_rng;
-use rand::Rng;
-use realstd::collections::TryReserveErrorKind::*;
// https://github.com/rust-lang/rust/issues/62301
fn _assert_hashmap_is_unwind_safe() {
@@ -946,7 +947,6 @@ fn test_raw_entry() {
mod test_extract_if {
use super::*;
-
use crate::panic::{catch_unwind, AssertUnwindSafe};
use crate::sync::atomic::{AtomicUsize, Ordering};
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index f0a498f..d611353 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -3,6 +3,7 @@
use hashbrown::hash_set as base;
+use super::map::map_try_reserve_error;
use crate::borrow::Borrow;
use crate::collections::TryReserveError;
use crate::fmt;
@@ -10,8 +11,6 @@
use crate::iter::{Chain, FusedIterator};
use crate::ops::{BitAnd, BitOr, BitXor, Sub};
-use super::map::map_try_reserve_error;
-
/// A [hash set] implemented as a `HashMap` where the value is `()`.
///
/// As with the [`HashMap`] type, a `HashSet` requires that the elements
diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs
index a188409..4e63516 100644
--- a/library/std/src/collections/hash/set/tests.rs
+++ b/library/std/src/collections/hash/set/tests.rs
@@ -1,5 +1,4 @@
use super::HashSet;
-
use crate::hash::RandomState;
use crate::panic::{catch_unwind, AssertUnwindSafe};
use crate::sync::atomic::{AtomicU32, Ordering};
diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs
index 1389d24..3b04412 100644
--- a/library/std/src/collections/mod.rs
+++ b/library/std/src/collections/mod.rs
@@ -401,12 +401,14 @@
#![stable(feature = "rust1", since = "1.0.0")]
-#[stable(feature = "rust1", since = "1.0.0")]
-// FIXME(#82080) The deprecation here is only theoretical, and does not actually produce a warning.
-#[deprecated(note = "moved to `std::ops::Bound`", since = "1.26.0")]
-#[doc(hidden)]
-pub use crate::ops::Bound;
-
+#[stable(feature = "try_reserve", since = "1.57.0")]
+pub use alloc_crate::collections::TryReserveError;
+#[unstable(
+ feature = "try_reserve_kind",
+ reason = "Uncertain how much info should be exposed",
+ issue = "48043"
+)]
+pub use alloc_crate::collections::TryReserveErrorKind;
#[stable(feature = "rust1", since = "1.0.0")]
pub use alloc_crate::collections::{binary_heap, btree_map, btree_set};
#[stable(feature = "rust1", since = "1.0.0")]
@@ -422,15 +424,11 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
pub use self::hash_set::HashSet;
-
-#[stable(feature = "try_reserve", since = "1.57.0")]
-pub use alloc_crate::collections::TryReserveError;
-#[unstable(
- feature = "try_reserve_kind",
- reason = "Uncertain how much info should be exposed",
- issue = "48043"
-)]
-pub use alloc_crate::collections::TryReserveErrorKind;
+#[stable(feature = "rust1", since = "1.0.0")]
+// FIXME(#82080) The deprecation here is only theoretical, and does not actually produce a warning.
+#[deprecated(note = "moved to `std::ops::Bound`", since = "1.26.0")]
+#[doc(hidden)]
+pub use crate::ops::Bound;
mod hash;
@@ -439,7 +437,6 @@ pub mod hash_map {
//! A hash map implemented with quadratic probing and SIMD lookup.
#[stable(feature = "rust1", since = "1.0.0")]
pub use super::hash::map::*;
-
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub use crate::hash::random::DefaultHasher;
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index fc9b8cf..50ae830 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -15,11 +15,9 @@
use crate::error::Error;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::path::{Path, PathBuf};
-use crate::sys;
use crate::sys::os as os_imp;
+use crate::{fmt, io, sys};
/// Returns the current working directory as a [`PathBuf`].
///
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 87aad8f..3e17431 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -4,14 +4,14 @@
#[cfg(test)]
mod tests;
-use crate::backtrace::Backtrace;
-use crate::fmt::{self, Write};
-
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::error::Error;
#[unstable(feature = "error_generic_member_access", issue = "99301")]
pub use core::error::{request_ref, request_value, Request};
+use crate::backtrace::Backtrace;
+use crate::fmt::{self, Write};
+
/// An error reporter that prints an error and its sources.
///
/// Report also exposes configuration options for formatting the error sources, either entirely on a
@@ -234,7 +234,7 @@ impl<E> Report<E>
where
Report<E>: From<E>,
{
- /// Create a new `Report` from an input error.
+ /// Creates a new `Report` from an input error.
#[unstable(feature = "error_reporter", issue = "90172")]
pub fn new(error: E) -> Report<E> {
Self::from(error)
@@ -500,13 +500,8 @@ fn fmt_multiline(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
if self.show_backtrace {
- let backtrace = self.backtrace();
-
- if let Some(backtrace) = backtrace {
- let backtrace = backtrace.to_string();
-
- f.write_str("\n\nStack backtrace:\n")?;
- f.write_str(backtrace.trim_end())?;
+ if let Some(backtrace) = self.backtrace() {
+ write!(f, "\n\nStack backtrace:\n{}", backtrace.to_string().trim_end())?;
}
}
diff --git a/library/std/src/error/tests.rs b/library/std/src/error/tests.rs
index ed070a2..88a9f33 100644
--- a/library/std/src/error/tests.rs
+++ b/library/std/src/error/tests.rs
@@ -1,6 +1,7 @@
+use core::error::Request;
+
use super::Error;
use crate::fmt;
-use core::error::Request;
#[derive(Debug, PartialEq)]
struct A;
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 0591c6f..f6df625 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -7,30 +7,185 @@
#[cfg(test)]
mod tests;
-#[cfg(not(test))]
-use crate::intrinsics;
-
#[unstable(feature = "f128", issue = "116909")]
pub use core::f128::consts;
#[cfg(not(test))]
+use crate::intrinsics;
+#[cfg(not(test))]
+use crate::sys::cmath;
+
+#[cfg(not(test))]
impl f128 {
- /// Raises a number to an integer power.
+ /// Returns the largest integer less than or equal to `self`.
///
- /// Using this function is generally faster than using `powf`.
- /// It might have a different sequence of rounding operations than `powf`,
- /// so the results are not guaranteed to agree.
+ /// This function always returns the precise result.
///
- /// # Unspecified precision
+ /// # Examples
///
- /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
- /// can even differ within the same execution from one invocation to the next.
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.7_f128;
+ /// let g = 3.0_f128;
+ /// let h = -3.7_f128;
+ ///
+ /// assert_eq!(f.floor(), 3.0);
+ /// assert_eq!(g.floor(), 3.0);
+ /// assert_eq!(h.floor(), -4.0);
+ /// # }
+ /// ```
#[inline]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
- pub fn powi(self, n: i32) -> f128 {
- unsafe { intrinsics::powif128(self, n) }
+ pub fn floor(self) -> f128 {
+ unsafe { intrinsics::floorf128(self) }
+ }
+
+ /// Returns the smallest integer greater than or equal to `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.01_f128;
+ /// let g = 4.0_f128;
+ ///
+ /// assert_eq!(f.ceil(), 4.0);
+ /// assert_eq!(g.ceil(), 4.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "ceiling")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ceil(self) -> f128 {
+ unsafe { intrinsics::ceilf128(self) }
+ }
+
+ /// Returns the nearest integer to `self`. If a value is half-way between two
+ /// integers, round away from `0.0`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.3_f128;
+ /// let g = -3.3_f128;
+ /// let h = -3.7_f128;
+ /// let i = 3.5_f128;
+ /// let j = 4.5_f128;
+ ///
+ /// assert_eq!(f.round(), 3.0);
+ /// assert_eq!(g.round(), -3.0);
+ /// assert_eq!(h.round(), -4.0);
+ /// assert_eq!(i.round(), 4.0);
+ /// assert_eq!(j.round(), 5.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn round(self) -> f128 {
+ unsafe { intrinsics::roundf128(self) }
+ }
+
+ /// Returns the nearest integer to a number. Rounds half-way cases to the number
+ /// with an even least significant digit.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.3_f128;
+ /// let g = -3.3_f128;
+ /// let h = 3.5_f128;
+ /// let i = 4.5_f128;
+ ///
+ /// assert_eq!(f.round_ties_even(), 3.0);
+ /// assert_eq!(g.round_ties_even(), -3.0);
+ /// assert_eq!(h.round_ties_even(), 4.0);
+ /// assert_eq!(i.round_ties_even(), 4.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn round_ties_even(self) -> f128 {
+ unsafe { intrinsics::rintf128(self) }
+ }
+
+ /// Returns the integer part of `self`.
+ /// This means that non-integer numbers are always truncated towards zero.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.7_f128;
+ /// let g = 3.0_f128;
+ /// let h = -3.7_f128;
+ ///
+ /// assert_eq!(f.trunc(), 3.0);
+ /// assert_eq!(g.trunc(), 3.0);
+ /// assert_eq!(h.trunc(), -3.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "truncate")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn trunc(self) -> f128 {
+ unsafe { intrinsics::truncf128(self) }
+ }
+
+ /// Returns the fractional part of `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 3.6_f128;
+ /// let y = -3.6_f128;
+ /// let abs_difference_x = (x.fract() - 0.6).abs();
+ /// let abs_difference_y = (y.fract() - (-0.6)).abs();
+ ///
+ /// assert!(abs_difference_x <= f128::EPSILON);
+ /// assert!(abs_difference_y <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn fract(self) -> f128 {
+ self - self.trunc()
}
/// Computes the absolute value of `self`.
@@ -41,7 +196,7 @@ pub fn powi(self, n: i32) -> f128 {
///
/// ```
/// #![feature(f128)]
- /// # #[cfg(reliable_f128)] { // FIXME(f16_f128): reliable_f128
+ /// # #[cfg(reliable_f128)] {
///
/// let x = 3.5_f128;
/// let y = -3.5_f128;
@@ -53,7 +208,6 @@ pub fn powi(self, n: i32) -> f128 {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -62,4 +216,1129 @@ pub fn abs(self) -> Self {
// We don't do this now because LLVM has lowering bugs for f128 math.
Self::from_bits(self.to_bits() & !(1 << 127))
}
+
+ /// Returns a number that represents the sign of `self`.
+ ///
+ /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
+ /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
+ /// - NaN if the number is NaN
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.5_f128;
+ ///
+ /// assert_eq!(f.signum(), 1.0);
+ /// assert_eq!(f128::NEG_INFINITY.signum(), -1.0);
+ ///
+ /// assert!(f128::NAN.signum().is_nan());
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn signum(self) -> f128 {
+ if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
+ }
+
+ /// Returns a number composed of the magnitude of `self` and the sign of
+ /// `sign`.
+ ///
+ /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
+ /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+ /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+ /// across arithmetical operations is not generally guaranteed.
+ /// See [explanation of NaN as a special value](primitive@f128) for more info.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 3.5_f128;
+ ///
+ /// assert_eq!(f.copysign(0.42), 3.5_f128);
+ /// assert_eq!(f.copysign(-0.42), -3.5_f128);
+ /// assert_eq!((-f).copysign(0.42), 3.5_f128);
+ /// assert_eq!((-f).copysign(-0.42), -3.5_f128);
+ ///
+ /// assert!(f128::NAN.copysign(1.0).is_nan());
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn copysign(self, sign: f128) -> f128 {
+ unsafe { intrinsics::copysignf128(self, sign) }
+ }
+
+ /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+ /// error, yielding a more accurate result than an unfused multiply-add.
+ ///
+ /// Using `mul_add` *may* be more performant than an unfused multiply-add if
+ /// the target architecture has a dedicated `fma` CPU instruction. However,
+ /// this is not always true, and will be heavily dependant on designing
+ /// algorithms with specific target hardware in mind.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result. It is specified by IEEE 754 as
+ /// `fusedMultiplyAdd` and guaranteed not to change.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let m = 10.0_f128;
+ /// let x = 4.0_f128;
+ /// let b = 60.0_f128;
+ ///
+ /// assert_eq!(m.mul_add(x, b), 100.0);
+ /// assert_eq!(m * x + b, 100.0);
+ ///
+ /// let one_plus_eps = 1.0_f128 + f128::EPSILON;
+ /// let one_minus_eps = 1.0_f128 - f128::EPSILON;
+ /// let minus_one = -1.0_f128;
+ ///
+ /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+ /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f128::EPSILON * f128::EPSILON);
+ /// // Different rounding with the non-fused multiply and add.
+ /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn mul_add(self, a: f128, b: f128) -> f128 {
+ unsafe { intrinsics::fmaf128(self, a, b) }
+ }
+
+ /// Calculates Euclidean division, the matching method for `rem_euclid`.
+ ///
+ /// This computes the integer `n` such that
+ /// `self = n * rhs + self.rem_euclid(rhs)`.
+ /// In other words, the result is `self / rhs` rounded to the integer `n`
+ /// such that `self >= n * rhs`.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let a: f128 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
+ /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
+ /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
+ /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn div_euclid(self, rhs: f128) -> f128 {
+ let q = (self / rhs).trunc();
+ if self % rhs < 0.0 {
+ return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+ }
+ q
+ }
+
+ /// Calculates the least nonnegative remainder of `self (mod rhs)`.
+ ///
+ /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
+ /// most cases. However, due to a floating point round-off error it can
+ /// result in `r == rhs.abs()`, violating the mathematical definition, if
+ /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
+ /// This result is not an element of the function's codomain, but it is the
+ /// closest floating point number in the real numbers and thus fulfills the
+ /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
+ /// approximately.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let a: f128 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.rem_euclid(b), 3.0);
+ /// assert_eq!((-a).rem_euclid(b), 1.0);
+ /// assert_eq!(a.rem_euclid(-b), 3.0);
+ /// assert_eq!((-a).rem_euclid(-b), 1.0);
+ /// // limitation due to round-off error
+ /// assert!((-f128::EPSILON).rem_euclid(3.0) != 0.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[doc(alias = "modulo", alias = "mod")]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn rem_euclid(self, rhs: f128) -> f128 {
+ let r = self % rhs;
+ if r < 0.0 { r + rhs.abs() } else { r }
+ }
+
+ /// Raises a number to an integer power.
+ ///
+ /// Using this function is generally faster than using `powf`.
+ /// It might have a different sequence of rounding operations than `powf`,
+ /// so the results are not guaranteed to agree.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn powi(self, n: i32) -> f128 {
+ unsafe { intrinsics::powif128(self, n) }
+ }
+
+ /// Raises a number to a floating point power.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 2.0_f128;
+ /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn powf(self, n: f128) -> f128 {
+ unsafe { intrinsics::powf128(self, n) }
+ }
+
+ /// Returns the square root of a number.
+ ///
+ /// Returns NaN if `self` is a negative number other than `-0.0`.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
+ /// and guaranteed not to change.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let positive = 4.0_f128;
+ /// let negative = -4.0_f128;
+ /// let negative_zero = -0.0_f128;
+ ///
+ /// assert_eq!(positive.sqrt(), 2.0);
+ /// assert!(negative.sqrt().is_nan());
+ /// assert!(negative_zero.sqrt() == negative_zero);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn sqrt(self) -> f128 {
+ unsafe { intrinsics::sqrtf128(self) }
+ }
+
+ /// Returns `e^(self)`, (the exponential function).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let one = 1.0f128;
+ /// // e^1
+ /// let e = one.exp();
+ ///
+ /// // ln(e) - 1 == 0
+ /// let abs_difference = (e.ln() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn exp(self) -> f128 {
+ unsafe { intrinsics::expf128(self) }
+ }
+
+ /// Returns `2^(self)`.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 2.0f128;
+ ///
+ /// // 2^2 - 4 == 0
+ /// let abs_difference = (f.exp2() - 4.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn exp2(self) -> f128 {
+ unsafe { intrinsics::exp2f128(self) }
+ }
+
+ /// Returns the natural logarithm of the number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let one = 1.0f128;
+ /// // e^1
+ /// let e = one.exp();
+ ///
+ /// // ln(e) - 1 == 0
+ /// let abs_difference = (e.ln() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ln(self) -> f128 {
+ unsafe { intrinsics::logf128(self) }
+ }
+
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// The result might not be correctly rounded owing to implementation details;
+ /// `self.log2()` can produce more accurate results for base 2, and
+ /// `self.log10()` can produce more accurate results for base 10.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let five = 5.0f128;
+ ///
+ /// // log5(5) - 1 == 0
+ /// let abs_difference = (five.log(5.0) - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn log(self, base: f128) -> f128 {
+ self.ln() / base.ln()
+ }
+
+ /// Returns the base 2 logarithm of the number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let two = 2.0f128;
+ ///
+ /// // log2(2) - 1 == 0
+ /// let abs_difference = (two.log2() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn log2(self) -> f128 {
+ unsafe { intrinsics::log2f128(self) }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let ten = 10.0f128;
+ ///
+ /// // log10(10) - 1 == 0
+ /// let abs_difference = (ten.log10() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn log10(self) -> f128 {
+ unsafe { intrinsics::log10f128(self) }
+ }
+
+ /// Returns the cube root of a number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ ///
+ /// This function currently corresponds to the `cbrtf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 8.0f128;
+ ///
+ /// // x^(1/3) - 2 == 0
+ /// let abs_difference = (x.cbrt() - 2.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn cbrt(self) -> f128 {
+ unsafe { cmath::cbrtf128(self) }
+ }
+
+ /// Compute the distance between the origin and a point (`x`, `y`) on the
+ /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
+ /// right-angle triangle with other sides having length `x.abs()` and
+ /// `y.abs()`.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ ///
+ /// This function currently corresponds to the `hypotf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 2.0f128;
+ /// let y = 3.0f128;
+ ///
+ /// // sqrt(x^2 + y^2)
+ /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn hypot(self, other: f128) -> f128 {
+ unsafe { cmath::hypotf128(self, other) }
+ }
+
+ /// Computes the sine of a number (in radians).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = std::f128::consts::FRAC_PI_2;
+ ///
+ /// let abs_difference = (x.sin() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn sin(self) -> f128 {
+ unsafe { intrinsics::sinf128(self) }
+ }
+
+ /// Computes the cosine of a number (in radians).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 2.0 * std::f128::consts::PI;
+ ///
+ /// let abs_difference = (x.cos() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn cos(self) -> f128 {
+ unsafe { intrinsics::cosf128(self) }
+ }
+
+ /// Computes the tangent of a number (in radians).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `tanf128` from libc on Unix and
+ /// Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = std::f128::consts::FRAC_PI_4;
+ /// let abs_difference = (x.tan() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn tan(self) -> f128 {
+ unsafe { cmath::tanf128(self) }
+ }
+
+ /// Computes the arcsine of a number. Return value is in radians in
+ /// the range [-pi/2, pi/2] or NaN if the number is outside the range
+ /// [-1, 1].
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `asinf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = std::f128::consts::FRAC_PI_2;
+ ///
+ /// // asin(sin(pi/2))
+ /// let abs_difference = (f.sin().asin() - std::f128::consts::FRAC_PI_2).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arcsin")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn asin(self) -> f128 {
+ unsafe { cmath::asinf128(self) }
+ }
+
+ /// Computes the arccosine of a number. Return value is in radians in
+ /// the range [0, pi] or NaN if the number is outside the range
+ /// [-1, 1].
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `acosf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = std::f128::consts::FRAC_PI_4;
+ ///
+ /// // acos(cos(pi/4))
+ /// let abs_difference = (f.cos().acos() - std::f128::consts::FRAC_PI_4).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arccos")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn acos(self) -> f128 {
+ unsafe { cmath::acosf128(self) }
+ }
+
+ /// Computes the arctangent of a number. Return value is in radians in the
+ /// range [-pi/2, pi/2];
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `atanf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let f = 1.0f128;
+ ///
+ /// // atan(tan(1))
+ /// let abs_difference = (f.tan().atan() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arctan")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn atan(self) -> f128 {
+ unsafe { cmath::atanf128(self) }
+ }
+
+ /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
+ ///
+ /// * `x = 0`, `y = 0`: `0`
+ /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
+ /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
+ /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `atan2f128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// // Positive angles measured counter-clockwise
+ /// // from positive x axis
+ /// // -pi/4 radians (45 deg clockwise)
+ /// let x1 = 3.0f128;
+ /// let y1 = -3.0f128;
+ ///
+ /// // 3pi/4 radians (135 deg counter-clockwise)
+ /// let x2 = -3.0f128;
+ /// let y2 = 3.0f128;
+ ///
+ /// let abs_difference_1 = (y1.atan2(x1) - (-std::f128::consts::FRAC_PI_4)).abs();
+ /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * std::f128::consts::FRAC_PI_4)).abs();
+ ///
+ /// assert!(abs_difference_1 <= f128::EPSILON);
+ /// assert!(abs_difference_2 <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn atan2(self, other: f128) -> f128 {
+ unsafe { cmath::atan2f128(self, other) }
+ }
+
+ /// Simultaneously computes the sine and cosine of the number, `x`. Returns
+ /// `(sin(x), cos(x))`.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `(f128::sin(x),
+ /// f128::cos(x))`. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = std::f128::consts::FRAC_PI_4;
+ /// let f = x.sin_cos();
+ ///
+ /// let abs_difference_0 = (f.0 - x.sin()).abs();
+ /// let abs_difference_1 = (f.1 - x.cos()).abs();
+ ///
+ /// assert!(abs_difference_0 <= f128::EPSILON);
+ /// assert!(abs_difference_1 <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "sincos")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ pub fn sin_cos(self) -> (f128, f128) {
+ (self.sin(), self.cos())
+ }
+
+ /// Returns `e^(self) - 1` in a way that is accurate even if the
+ /// number is close to zero.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `expm1f128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 1e-8_f128;
+ ///
+ /// // for very small x, e^x is approximately 1 + x + x^2 / 2
+ /// let approx = x + x * x / 2.0;
+ /// let abs_difference = (x.exp_m1() - approx).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn exp_m1(self) -> f128 {
+ unsafe { cmath::expm1f128(self) }
+ }
+
+ /// Returns `ln(1+n)` (natural logarithm) more accurately than if
+ /// the operations were performed separately.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `log1pf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 1e-8_f128;
+ ///
+ /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
+ /// let approx = x - x * x / 2.0;
+ /// let abs_difference = (x.ln_1p() - approx).abs();
+ ///
+ /// assert!(abs_difference < 1e-10);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "log1p")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ pub fn ln_1p(self) -> f128 {
+ unsafe { cmath::log1pf128(self) }
+ }
+
+ /// Hyperbolic sine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `sinhf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let e = std::f128::consts::E;
+ /// let x = 1.0f128;
+ ///
+ /// let f = x.sinh();
+ /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
+ /// let g = ((e * e) - 1.0) / (2.0 * e);
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn sinh(self) -> f128 {
+ unsafe { cmath::sinhf128(self) }
+ }
+
+ /// Hyperbolic cosine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `coshf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let e = std::f128::consts::E;
+ /// let x = 1.0f128;
+ /// let f = x.cosh();
+ /// // Solving cosh() at 1 gives this result
+ /// let g = ((e * e) + 1.0) / (2.0 * e);
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// // Same result
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn cosh(self) -> f128 {
+ unsafe { cmath::coshf128(self) }
+ }
+
+ /// Hyperbolic tangent function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `tanhf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let e = std::f128::consts::E;
+ /// let x = 1.0f128;
+ ///
+ /// let f = x.tanh();
+ /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
+ /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn tanh(self) -> f128 {
+ unsafe { cmath::tanhf128(self) }
+ }
+
+ /// Inverse hyperbolic sine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 1.0f128;
+ /// let f = x.sinh().asinh();
+ ///
+ /// let abs_difference = (f - x).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arcsinh")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn asinh(self) -> f128 {
+ let ax = self.abs();
+ let ix = 1.0 / ax;
+ (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
+ }
+
+ /// Inverse hyperbolic cosine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 1.0f128;
+ /// let f = x.cosh().acosh();
+ ///
+ /// let abs_difference = (f - x).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arccosh")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn acosh(self) -> f128 {
+ if self < 1.0 {
+ Self::NAN
+ } else {
+ (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
+ }
+ }
+
+ /// Inverse hyperbolic tangent function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let e = std::f128::consts::E;
+ /// let f = e.tanh().atanh();
+ ///
+ /// let abs_difference = (f - e).abs();
+ ///
+ /// assert!(abs_difference <= 1e-5);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arctanh")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn atanh(self) -> f128 {
+ 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
+ }
+
+ /// Gamma function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `tgammaf128` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// #![feature(float_gamma)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 5.0f128;
+ ///
+ /// let abs_difference = (x.gamma() - 24.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn gamma(self) -> f128 {
+ unsafe { cmath::tgammaf128(self) }
+ }
+
+ /// Natural logarithm of the absolute value of the gamma function
+ ///
+ /// The integer part of the tuple indicates the sign of the gamma function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `lgammaf128_r` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// #![feature(float_gamma)]
+ /// # #[cfg(reliable_f128_math)] {
+ ///
+ /// let x = 2.0f128;
+ ///
+ /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
+ ///
+ /// assert!(abs_difference <= f128::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ln_gamma(self) -> (f128, i32) {
+ let mut signgamp: i32 = 0;
+ let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) };
+ (x, signgamp)
+ }
}
diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs
index 0b3e485..7051c05 100644
--- a/library/std/src/f128/tests.rs
+++ b/library/std/src/f128/tests.rs
@@ -1,10 +1,23 @@
-#![cfg(not(bootstrap))]
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
#![cfg(reliable_f128)]
use crate::f128::consts;
-use crate::num::FpCategory as Fp;
-use crate::num::*;
+use crate::num::{FpCategory as Fp, *};
+
+// Note these tolerances make sense around zero, but not for more extreme exponents.
+
+/// For operations that are near exact, usually not involving math of different
+/// signs.
+const TOL_PRECISE: f128 = 1e-28;
+
+/// Default tolerances. Works for values that should be near precise but not exact. Roughly
+/// the precision carried by `100 * 100`.
+const TOL: f128 = 1e-12;
+
+/// Tolerances for math that is allowed to be imprecise, usually due to multiple chained
+/// operations.
+#[cfg(reliable_f128_math)]
+const TOL_IMPR: f128 = 1e-10;
/// Smallest number
const TINY_BITS: u128 = 0x1;
@@ -43,7 +56,33 @@ fn test_num_f128() {
test_num(10f128, 2f128);
}
-// FIXME(f16_f128): add min and max tests when available
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_min_nan() {
+ assert_eq!(f128::NAN.min(2.0), 2.0);
+ assert_eq!(2.0f128.min(f128::NAN), 2.0);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_max_nan() {
+ assert_eq!(f128::NAN.max(2.0), 2.0);
+ assert_eq!(2.0f128.max(f128::NAN), 2.0);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_minimum() {
+ assert!(f128::NAN.minimum(2.0).is_nan());
+ assert!(2.0f128.minimum(f128::NAN).is_nan());
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_maximum() {
+ assert!(f128::NAN.maximum(2.0).is_nan());
+ assert!(2.0f128.maximum(f128::NAN).is_nan());
+}
#[test]
fn test_nan() {
@@ -193,9 +232,100 @@ fn test_classify() {
assert_eq!(1e-4932f128.classify(), Fp::Subnormal);
}
-// FIXME(f16_f128): add missing math functions when available
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_floor() {
+ assert_approx_eq!(1.0f128.floor(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.3f128.floor(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.5f128.floor(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.7f128.floor(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.floor(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-0.0f128).floor(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.0f128).floor(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.3f128).floor(), -2.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.5f128).floor(), -2.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.7f128).floor(), -2.0f128, TOL_PRECISE);
+}
#[test]
+#[cfg(reliable_f128_math)]
+fn test_ceil() {
+ assert_approx_eq!(1.0f128.ceil(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.3f128.ceil(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.5f128.ceil(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.7f128.ceil(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.ceil(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-0.0f128).ceil(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.0f128).ceil(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.3f128).ceil(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.5f128).ceil(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.7f128).ceil(), -1.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_round() {
+ assert_approx_eq!(2.5f128.round(), 3.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.0f128.round(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.3f128.round(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.5f128.round(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.7f128.round(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.round(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-0.0f128).round(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.0f128).round(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.3f128).round(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.5f128).round(), -2.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.7f128).round(), -2.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_round_ties_even() {
+ assert_approx_eq!(2.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.0f128.round_ties_even(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.3f128.round_ties_even(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.5f128.round_ties_even(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.7f128.round_ties_even(), 2.0f128, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.round_ties_even(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-0.0f128).round_ties_even(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.0f128).round_ties_even(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.3f128).round_ties_even(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.5f128).round_ties_even(), -2.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.7f128).round_ties_even(), -2.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_trunc() {
+ assert_approx_eq!(1.0f128.trunc(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.3f128.trunc(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.5f128.trunc(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.7f128.trunc(), 1.0f128, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.trunc(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-0.0f128).trunc(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.0f128).trunc(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.3f128).trunc(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.5f128).trunc(), -1.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.7f128).trunc(), -1.0f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_fract() {
+ assert_approx_eq!(1.0f128.fract(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!(1.3f128.fract(), 0.3f128, TOL_PRECISE);
+ assert_approx_eq!(1.5f128.fract(), 0.5f128, TOL_PRECISE);
+ assert_approx_eq!(1.7f128.fract(), 0.7f128, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.fract(), 0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-0.0f128).fract(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.0f128).fract(), -0.0f128, TOL_PRECISE);
+ assert_approx_eq!((-1.3f128).fract(), -0.3f128, TOL_PRECISE);
+ assert_approx_eq!((-1.5f128).fract(), -0.5f128, TOL_PRECISE);
+ assert_approx_eq!((-1.7f128).fract(), -0.7f128, TOL_PRECISE);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
fn test_abs() {
assert_eq!(f128::INFINITY.abs(), f128::INFINITY);
assert_eq!(1f128.abs(), 1f128);
@@ -295,6 +425,24 @@ fn test_next_down() {
}
#[test]
+#[cfg(reliable_f128_math)]
+fn test_mul_add() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_approx_eq!(12.3f128.mul_add(4.5, 6.7), 62.05, TOL_PRECISE);
+ assert_approx_eq!((-12.3f128).mul_add(-4.5, -6.7), 48.65, TOL_PRECISE);
+ assert_approx_eq!(0.0f128.mul_add(8.9, 1.2), 1.2, TOL_PRECISE);
+ assert_approx_eq!(3.4f128.mul_add(-0.0, 5.6), 5.6, TOL_PRECISE);
+ assert!(nan.mul_add(7.8, 9.0).is_nan());
+ assert_eq!(inf.mul_add(7.8, 9.0), inf);
+ assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+ assert_eq!(8.9f128.mul_add(inf, 3.2), inf);
+ assert_eq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
fn test_recip() {
let nan: f128 = f128::NAN;
let inf: f128 = f128::INFINITY;
@@ -303,11 +451,161 @@ fn test_recip() {
assert_eq!(2.0f128.recip(), 0.5);
assert_eq!((-0.4f128).recip(), -2.5);
assert_eq!(0.0f128.recip(), inf);
+ assert_approx_eq!(
+ f128::MAX.recip(),
+ 8.40525785778023376565669454330438228902076605e-4933,
+ 1e-4900
+ );
assert!(nan.recip().is_nan());
assert_eq!(inf.recip(), 0.0);
assert_eq!(neg_inf.recip(), 0.0);
}
+// Many math functions allow for less accurate results, so the next tolerance up is used
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_powi() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_eq!(1.0f128.powi(1), 1.0);
+ assert_approx_eq!((-3.1f128).powi(2), 9.6100000000000005506706202140776519387, TOL);
+ assert_approx_eq!(5.9f128.powi(-2), 0.028727377190462507313100483690639638451, TOL);
+ assert_eq!(8.3f128.powi(0), 1.0);
+ assert!(nan.powi(2).is_nan());
+ assert_eq!(inf.powi(3), inf);
+ assert_eq!(neg_inf.powi(2), inf);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_powf() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_eq!(1.0f128.powf(1.0), 1.0);
+ assert_approx_eq!(3.4f128.powf(4.5), 246.40818323761892815995637964326426756, TOL_IMPR);
+ assert_approx_eq!(2.7f128.powf(-3.2), 0.041652009108526178281070304373500889273, TOL_IMPR);
+ assert_approx_eq!((-3.1f128).powf(2.0), 9.6100000000000005506706202140776519387, TOL_IMPR);
+ assert_approx_eq!(5.9f128.powf(-2.0), 0.028727377190462507313100483690639638451, TOL_IMPR);
+ assert_eq!(8.3f128.powf(0.0), 1.0);
+ assert!(nan.powf(2.0).is_nan());
+ assert_eq!(inf.powf(2.0), inf);
+ assert_eq!(neg_inf.powf(3.0), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_sqrt_domain() {
+ assert!(f128::NAN.sqrt().is_nan());
+ assert!(f128::NEG_INFINITY.sqrt().is_nan());
+ assert!((-1.0f128).sqrt().is_nan());
+ assert_eq!((-0.0f128).sqrt(), -0.0);
+ assert_eq!(0.0f128.sqrt(), 0.0);
+ assert_eq!(1.0f128.sqrt(), 1.0);
+ assert_eq!(f128::INFINITY.sqrt(), f128::INFINITY);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_exp() {
+ assert_eq!(1.0, 0.0f128.exp());
+ assert_approx_eq!(consts::E, 1.0f128.exp(), TOL);
+ assert_approx_eq!(148.41315910257660342111558004055227962348775, 5.0f128.exp(), TOL);
+
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ let nan: f128 = f128::NAN;
+ assert_eq!(inf, inf.exp());
+ assert_eq!(0.0, neg_inf.exp());
+ assert!(nan.exp().is_nan());
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_exp2() {
+ assert_eq!(32.0, 5.0f128.exp2());
+ assert_eq!(1.0, 0.0f128.exp2());
+
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ let nan: f128 = f128::NAN;
+ assert_eq!(inf, inf.exp2());
+ assert_eq!(0.0, neg_inf.exp2());
+ assert!(nan.exp2().is_nan());
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_ln() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_approx_eq!(1.0f128.exp().ln(), 1.0, TOL);
+ assert!(nan.ln().is_nan());
+ assert_eq!(inf.ln(), inf);
+ assert!(neg_inf.ln().is_nan());
+ assert!((-2.3f128).ln().is_nan());
+ assert_eq!((-0.0f128).ln(), neg_inf);
+ assert_eq!(0.0f128.ln(), neg_inf);
+ assert_approx_eq!(4.0f128.ln(), 1.3862943611198906188344642429163531366, TOL);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_log() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_eq!(10.0f128.log(10.0), 1.0);
+ assert_approx_eq!(2.3f128.log(3.5), 0.66485771361478710036766645911922010272, TOL);
+ assert_eq!(1.0f128.exp().log(1.0f128.exp()), 1.0);
+ assert!(1.0f128.log(1.0).is_nan());
+ assert!(1.0f128.log(-13.9).is_nan());
+ assert!(nan.log(2.3).is_nan());
+ assert_eq!(inf.log(10.0), inf);
+ assert!(neg_inf.log(8.8).is_nan());
+ assert!((-2.3f128).log(0.1).is_nan());
+ assert_eq!((-0.0f128).log(2.0), neg_inf);
+ assert_eq!(0.0f128.log(7.0), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_log2() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_approx_eq!(10.0f128.log2(), 3.32192809488736234787031942948939017, TOL);
+ assert_approx_eq!(2.3f128.log2(), 1.2016338611696504130002982471978765921, TOL);
+ assert_approx_eq!(1.0f128.exp().log2(), 1.4426950408889634073599246810018921381, TOL);
+ assert!(nan.log2().is_nan());
+ assert_eq!(inf.log2(), inf);
+ assert!(neg_inf.log2().is_nan());
+ assert!((-2.3f128).log2().is_nan());
+ assert_eq!((-0.0f128).log2(), neg_inf);
+ assert_eq!(0.0f128.log2(), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_log10() {
+ let nan: f128 = f128::NAN;
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ assert_eq!(10.0f128.log10(), 1.0);
+ assert_approx_eq!(2.3f128.log10(), 0.36172783601759284532595218865859309898, TOL);
+ assert_approx_eq!(1.0f128.exp().log10(), 0.43429448190325182765112891891660508222, TOL);
+ assert_eq!(1.0f128.log10(), 0.0);
+ assert!(nan.log10().is_nan());
+ assert_eq!(inf.log10(), inf);
+ assert!(neg_inf.log10().is_nan());
+ assert!((-2.3f128).log10().is_nan());
+ assert_eq!((-0.0f128).log10(), neg_inf);
+ assert_eq!(0.0f128.log10(), neg_inf);
+}
+
#[test]
fn test_to_degrees() {
let pi: f128 = consts::PI;
@@ -315,8 +613,8 @@ fn test_to_degrees() {
let inf: f128 = f128::INFINITY;
let neg_inf: f128 = f128::NEG_INFINITY;
assert_eq!(0.0f128.to_degrees(), 0.0);
- assert_approx_eq!((-5.8f128).to_degrees(), -332.315521);
- assert_eq!(pi.to_degrees(), 180.0);
+ assert_approx_eq!((-5.8f128).to_degrees(), -332.31552117587745090765431723855668471, TOL);
+ assert_approx_eq!(pi.to_degrees(), 180.0, TOL);
assert!(nan.to_degrees().is_nan());
assert_eq!(inf.to_degrees(), inf);
assert_eq!(neg_inf.to_degrees(), neg_inf);
@@ -330,19 +628,122 @@ fn test_to_radians() {
let inf: f128 = f128::INFINITY;
let neg_inf: f128 = f128::NEG_INFINITY;
assert_eq!(0.0f128.to_radians(), 0.0);
- assert_approx_eq!(154.6f128.to_radians(), 2.698279);
- assert_approx_eq!((-332.31f128).to_radians(), -5.799903);
+ assert_approx_eq!(154.6f128.to_radians(), 2.6982790235832334267135442069489767804, TOL);
+ assert_approx_eq!((-332.31f128).to_radians(), -5.7999036373023566567593094812182763013, TOL);
// check approx rather than exact because round trip for pi doesn't fall on an exactly
// representable value (unlike `f32` and `f64`).
- assert_approx_eq!(180.0f128.to_radians(), pi);
+ assert_approx_eq!(180.0f128.to_radians(), pi, TOL_PRECISE);
assert!(nan.to_radians().is_nan());
assert_eq!(inf.to_radians(), inf);
assert_eq!(neg_inf.to_radians(), neg_inf);
}
#[test]
+#[cfg(reliable_f128_math)]
+fn test_asinh() {
+ // Lower accuracy results are allowed, use increased tolerances
+ assert_eq!(0.0f128.asinh(), 0.0f128);
+ assert_eq!((-0.0f128).asinh(), -0.0f128);
+
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ let nan: f128 = f128::NAN;
+ assert_eq!(inf.asinh(), inf);
+ assert_eq!(neg_inf.asinh(), neg_inf);
+ assert!(nan.asinh().is_nan());
+ assert!((-0.0f128).asinh().is_sign_negative());
+
+ // issue 63271
+ assert_approx_eq!(2.0f128.asinh(), 1.443635475178810342493276740273105f128, TOL_IMPR);
+ assert_approx_eq!((-2.0f128).asinh(), -1.443635475178810342493276740273105f128, TOL_IMPR);
+ // regression test for the catastrophic cancellation fixed in 72486
+ assert_approx_eq!(
+ (-67452098.07139316f128).asinh(),
+ -18.720075426274544393985484294000831757220,
+ TOL_IMPR
+ );
+
+ // test for low accuracy from issue 104548
+ assert_approx_eq!(60.0f128, 60.0f128.sinh().asinh(), TOL_IMPR);
+ // mul needed for approximate comparison to be meaningful
+ assert_approx_eq!(1.0f128, 1e-15f128.sinh().asinh() * 1e15f128, TOL_IMPR);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_acosh() {
+ assert_eq!(1.0f128.acosh(), 0.0f128);
+ assert!(0.999f128.acosh().is_nan());
+
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ let nan: f128 = f128::NAN;
+ assert_eq!(inf.acosh(), inf);
+ assert!(neg_inf.acosh().is_nan());
+ assert!(nan.acosh().is_nan());
+ assert_approx_eq!(2.0f128.acosh(), 1.31695789692481670862504634730796844f128, TOL_IMPR);
+ assert_approx_eq!(3.0f128.acosh(), 1.76274717403908605046521864995958461f128, TOL_IMPR);
+
+ // test for low accuracy from issue 104548
+ assert_approx_eq!(60.0f128, 60.0f128.cosh().acosh(), TOL_IMPR);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_atanh() {
+ assert_eq!(0.0f128.atanh(), 0.0f128);
+ assert_eq!((-0.0f128).atanh(), -0.0f128);
+
+ let inf: f128 = f128::INFINITY;
+ let neg_inf: f128 = f128::NEG_INFINITY;
+ let nan: f128 = f128::NAN;
+ assert_eq!(1.0f128.atanh(), inf);
+ assert_eq!((-1.0f128).atanh(), neg_inf);
+ assert!(2f128.atanh().atanh().is_nan());
+ assert!((-2f128).atanh().atanh().is_nan());
+ assert!(inf.atanh().is_nan());
+ assert!(neg_inf.atanh().is_nan());
+ assert!(nan.atanh().is_nan());
+ assert_approx_eq!(0.5f128.atanh(), 0.54930614433405484569762261846126285f128, TOL_IMPR);
+ assert_approx_eq!((-0.5f128).atanh(), -0.54930614433405484569762261846126285f128, TOL_IMPR);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_gamma() {
+ // precision can differ among platforms
+ assert_approx_eq!(1.0f128.gamma(), 1.0f128, TOL_IMPR);
+ assert_approx_eq!(2.0f128.gamma(), 1.0f128, TOL_IMPR);
+ assert_approx_eq!(3.0f128.gamma(), 2.0f128, TOL_IMPR);
+ assert_approx_eq!(4.0f128.gamma(), 6.0f128, TOL_IMPR);
+ assert_approx_eq!(5.0f128.gamma(), 24.0f128, TOL_IMPR);
+ assert_approx_eq!(0.5f128.gamma(), consts::PI.sqrt(), TOL_IMPR);
+ assert_approx_eq!((-0.5f128).gamma(), -2.0 * consts::PI.sqrt(), TOL_IMPR);
+ assert_eq!(0.0f128.gamma(), f128::INFINITY);
+ assert_eq!((-0.0f128).gamma(), f128::NEG_INFINITY);
+ assert!((-1.0f128).gamma().is_nan());
+ assert!((-2.0f128).gamma().is_nan());
+ assert!(f128::NAN.gamma().is_nan());
+ assert!(f128::NEG_INFINITY.gamma().is_nan());
+ assert_eq!(f128::INFINITY.gamma(), f128::INFINITY);
+ assert_eq!(1760.9f128.gamma(), f128::INFINITY);
+}
+
+#[test]
+#[cfg(reliable_f128_math)]
+fn test_ln_gamma() {
+ assert_approx_eq!(1.0f128.ln_gamma().0, 0.0f128, TOL_IMPR);
+ assert_eq!(1.0f128.ln_gamma().1, 1);
+ assert_approx_eq!(2.0f128.ln_gamma().0, 0.0f128, TOL_IMPR);
+ assert_eq!(2.0f128.ln_gamma().1, 1);
+ assert_approx_eq!(3.0f128.ln_gamma().0, 2.0f128.ln(), TOL_IMPR);
+ assert_eq!(3.0f128.ln_gamma().1, 1);
+ assert_approx_eq!((-0.5f128).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln(), TOL_IMPR);
+ assert_eq!((-0.5f128).ln_gamma().1, -1);
+}
+
+#[test]
fn test_real_consts() {
- // FIXME(f16_f128): add math tests when available
use super::consts;
let pi: f128 = consts::PI;
@@ -353,29 +754,34 @@ fn test_real_consts() {
let frac_pi_8: f128 = consts::FRAC_PI_8;
let frac_1_pi: f128 = consts::FRAC_1_PI;
let frac_2_pi: f128 = consts::FRAC_2_PI;
- // let frac_2_sqrtpi: f128 = consts::FRAC_2_SQRT_PI;
- // let sqrt2: f128 = consts::SQRT_2;
- // let frac_1_sqrt2: f128 = consts::FRAC_1_SQRT_2;
- // let e: f128 = consts::E;
- // let log2_e: f128 = consts::LOG2_E;
- // let log10_e: f128 = consts::LOG10_E;
- // let ln_2: f128 = consts::LN_2;
- // let ln_10: f128 = consts::LN_10;
- assert_approx_eq!(frac_pi_2, pi / 2f128);
- assert_approx_eq!(frac_pi_3, pi / 3f128);
- assert_approx_eq!(frac_pi_4, pi / 4f128);
- assert_approx_eq!(frac_pi_6, pi / 6f128);
- assert_approx_eq!(frac_pi_8, pi / 8f128);
- assert_approx_eq!(frac_1_pi, 1f128 / pi);
- assert_approx_eq!(frac_2_pi, 2f128 / pi);
- // assert_approx_eq!(frac_2_sqrtpi, 2f128 / pi.sqrt());
- // assert_approx_eq!(sqrt2, 2f128.sqrt());
- // assert_approx_eq!(frac_1_sqrt2, 1f128 / 2f128.sqrt());
- // assert_approx_eq!(log2_e, e.log2());
- // assert_approx_eq!(log10_e, e.log10());
- // assert_approx_eq!(ln_2, 2f128.ln());
- // assert_approx_eq!(ln_10, 10f128.ln());
+ assert_approx_eq!(frac_pi_2, pi / 2f128, TOL_PRECISE);
+ assert_approx_eq!(frac_pi_3, pi / 3f128, TOL_PRECISE);
+ assert_approx_eq!(frac_pi_4, pi / 4f128, TOL_PRECISE);
+ assert_approx_eq!(frac_pi_6, pi / 6f128, TOL_PRECISE);
+ assert_approx_eq!(frac_pi_8, pi / 8f128, TOL_PRECISE);
+ assert_approx_eq!(frac_1_pi, 1f128 / pi, TOL_PRECISE);
+ assert_approx_eq!(frac_2_pi, 2f128 / pi, TOL_PRECISE);
+
+ #[cfg(reliable_f128_math)]
+ {
+ let frac_2_sqrtpi: f128 = consts::FRAC_2_SQRT_PI;
+ let sqrt2: f128 = consts::SQRT_2;
+ let frac_1_sqrt2: f128 = consts::FRAC_1_SQRT_2;
+ let e: f128 = consts::E;
+ let log2_e: f128 = consts::LOG2_E;
+ let log10_e: f128 = consts::LOG10_E;
+ let ln_2: f128 = consts::LN_2;
+ let ln_10: f128 = consts::LN_10;
+
+ assert_approx_eq!(frac_2_sqrtpi, 2f128 / pi.sqrt(), TOL_PRECISE);
+ assert_approx_eq!(sqrt2, 2f128.sqrt(), TOL_PRECISE);
+ assert_approx_eq!(frac_1_sqrt2, 1f128 / 2f128.sqrt(), TOL_PRECISE);
+ assert_approx_eq!(log2_e, e.log2(), TOL_PRECISE);
+ assert_approx_eq!(log10_e, e.log10(), TOL_PRECISE);
+ assert_approx_eq!(ln_2, 2f128.ln(), TOL_PRECISE);
+ assert_approx_eq!(ln_10, 10f128.ln(), TOL_PRECISE);
+ }
}
#[test]
@@ -384,10 +790,10 @@ fn test_float_bits_conv() {
assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
assert_eq!((1337f128).to_bits(), 0x40094e40000000000000000000000000);
assert_eq!((-14.25f128).to_bits(), 0xc002c800000000000000000000000000);
- assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0);
- assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5);
- assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0);
- assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25);
+ assert_approx_eq!(f128::from_bits(0x3fff0000000000000000000000000000), 1.0, TOL_PRECISE);
+ assert_approx_eq!(f128::from_bits(0x40029000000000000000000000000000), 12.5, TOL_PRECISE);
+ assert_approx_eq!(f128::from_bits(0x40094e40000000000000000000000000), 1337.0, TOL_PRECISE);
+ assert_approx_eq!(f128::from_bits(0xc002c800000000000000000000000000), -14.25, TOL_PRECISE);
// Check that NaNs roundtrip their bits regardless of signaling-ness
// 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index d485186..1090833 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -7,30 +7,185 @@
#[cfg(test)]
mod tests;
-#[cfg(not(test))]
-use crate::intrinsics;
-
#[unstable(feature = "f16", issue = "116909")]
pub use core::f16::consts;
#[cfg(not(test))]
+use crate::intrinsics;
+#[cfg(not(test))]
+use crate::sys::cmath;
+
+#[cfg(not(test))]
impl f16 {
- /// Raises a number to an integer power.
+ /// Returns the largest integer less than or equal to `self`.
///
- /// Using this function is generally faster than using `powf`.
- /// It might have a different sequence of rounding operations than `powf`,
- /// so the results are not guaranteed to agree.
+ /// This function always returns the precise result.
///
- /// # Unspecified precision
+ /// # Examples
///
- /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
- /// can even differ within the same execution from one invocation to the next.
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.7_f16;
+ /// let g = 3.0_f16;
+ /// let h = -3.7_f16;
+ ///
+ /// assert_eq!(f.floor(), 3.0);
+ /// assert_eq!(g.floor(), 3.0);
+ /// assert_eq!(h.floor(), -4.0);
+ /// # }
+ /// ```
#[inline]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
- pub fn powi(self, n: i32) -> f16 {
- unsafe { intrinsics::powif16(self, n) }
+ pub fn floor(self) -> f16 {
+ unsafe { intrinsics::floorf16(self) }
+ }
+
+ /// Returns the smallest integer greater than or equal to `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.01_f16;
+ /// let g = 4.0_f16;
+ ///
+ /// assert_eq!(f.ceil(), 4.0);
+ /// assert_eq!(g.ceil(), 4.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "ceiling")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ceil(self) -> f16 {
+ unsafe { intrinsics::ceilf16(self) }
+ }
+
+ /// Returns the nearest integer to `self`. If a value is half-way between two
+ /// integers, round away from `0.0`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.3_f16;
+ /// let g = -3.3_f16;
+ /// let h = -3.7_f16;
+ /// let i = 3.5_f16;
+ /// let j = 4.5_f16;
+ ///
+ /// assert_eq!(f.round(), 3.0);
+ /// assert_eq!(g.round(), -3.0);
+ /// assert_eq!(h.round(), -4.0);
+ /// assert_eq!(i.round(), 4.0);
+ /// assert_eq!(j.round(), 5.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn round(self) -> f16 {
+ unsafe { intrinsics::roundf16(self) }
+ }
+
+ /// Returns the nearest integer to a number. Rounds half-way cases to the number
+ /// with an even least significant digit.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.3_f16;
+ /// let g = -3.3_f16;
+ /// let h = 3.5_f16;
+ /// let i = 4.5_f16;
+ ///
+ /// assert_eq!(f.round_ties_even(), 3.0);
+ /// assert_eq!(g.round_ties_even(), -3.0);
+ /// assert_eq!(h.round_ties_even(), 4.0);
+ /// assert_eq!(i.round_ties_even(), 4.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn round_ties_even(self) -> f16 {
+ unsafe { intrinsics::rintf16(self) }
+ }
+
+ /// Returns the integer part of `self`.
+ /// This means that non-integer numbers are always truncated towards zero.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.7_f16;
+ /// let g = 3.0_f16;
+ /// let h = -3.7_f16;
+ ///
+ /// assert_eq!(f.trunc(), 3.0);
+ /// assert_eq!(g.trunc(), 3.0);
+ /// assert_eq!(h.trunc(), -3.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "truncate")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn trunc(self) -> f16 {
+ unsafe { intrinsics::truncf16(self) }
+ }
+
+ /// Returns the fractional part of `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 3.6_f16;
+ /// let y = -3.6_f16;
+ /// let abs_difference_x = (x.fract() - 0.6).abs();
+ /// let abs_difference_y = (y.fract() - (-0.6)).abs();
+ ///
+ /// assert!(abs_difference_x <= f16::EPSILON);
+ /// assert!(abs_difference_y <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn fract(self) -> f16 {
+ self - self.trunc()
}
/// Computes the absolute value of `self`.
@@ -53,7 +208,6 @@ pub fn powi(self, n: i32) -> f16 {
/// # }
/// ```
#[inline]
- #[cfg(not(bootstrap))]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
@@ -61,4 +215,1127 @@ pub fn abs(self) -> Self {
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
Self::from_bits(self.to_bits() & !(1 << 15))
}
+
+ /// Returns a number that represents the sign of `self`.
+ ///
+ /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
+ /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
+ /// - NaN if the number is NaN
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.5_f16;
+ ///
+ /// assert_eq!(f.signum(), 1.0);
+ /// assert_eq!(f16::NEG_INFINITY.signum(), -1.0);
+ ///
+ /// assert!(f16::NAN.signum().is_nan());
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn signum(self) -> f16 {
+ if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
+ }
+
+ /// Returns a number composed of the magnitude of `self` and the sign of
+ /// `sign`.
+ ///
+ /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
+ /// equal to `-self`. If `self` is a NaN, then a NaN with the sign bit of
+ /// `sign` is returned. Note, however, that conserving the sign bit on NaN
+ /// across arithmetical operations is not generally guaranteed.
+ /// See [explanation of NaN as a special value](primitive@f16) for more info.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 3.5_f16;
+ ///
+ /// assert_eq!(f.copysign(0.42), 3.5_f16);
+ /// assert_eq!(f.copysign(-0.42), -3.5_f16);
+ /// assert_eq!((-f).copysign(0.42), 3.5_f16);
+ /// assert_eq!((-f).copysign(-0.42), -3.5_f16);
+ ///
+ /// assert!(f16::NAN.copysign(1.0).is_nan());
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn copysign(self, sign: f16) -> f16 {
+ unsafe { intrinsics::copysignf16(self, sign) }
+ }
+
+ /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
+ /// error, yielding a more accurate result than an unfused multiply-add.
+ ///
+ /// Using `mul_add` *may* be more performant than an unfused multiply-add if
+ /// the target architecture has a dedicated `fma` CPU instruction. However,
+ /// this is not always true, and will be heavily dependant on designing
+ /// algorithms with specific target hardware in mind.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result. It is specified by IEEE 754 as
+ /// `fusedMultiplyAdd` and guaranteed not to change.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let m = 10.0_f16;
+ /// let x = 4.0_f16;
+ /// let b = 60.0_f16;
+ ///
+ /// assert_eq!(m.mul_add(x, b), 100.0);
+ /// assert_eq!(m * x + b, 100.0);
+ ///
+ /// let one_plus_eps = 1.0_f16 + f16::EPSILON;
+ /// let one_minus_eps = 1.0_f16 - f16::EPSILON;
+ /// let minus_one = -1.0_f16;
+ ///
+ /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+ /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f16::EPSILON * f16::EPSILON);
+ /// // Different rounding with the non-fused multiply and add.
+ /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn mul_add(self, a: f16, b: f16) -> f16 {
+ unsafe { intrinsics::fmaf16(self, a, b) }
+ }
+
+ /// Calculates Euclidean division, the matching method for `rem_euclid`.
+ ///
+ /// This computes the integer `n` such that
+ /// `self = n * rhs + self.rem_euclid(rhs)`.
+ /// In other words, the result is `self / rhs` rounded to the integer `n`
+ /// such that `self >= n * rhs`.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let a: f16 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
+ /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
+ /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
+ /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn div_euclid(self, rhs: f16) -> f16 {
+ let q = (self / rhs).trunc();
+ if self % rhs < 0.0 {
+ return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+ }
+ q
+ }
+
+ /// Calculates the least nonnegative remainder of `self (mod rhs)`.
+ ///
+ /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
+ /// most cases. However, due to a floating point round-off error it can
+ /// result in `r == rhs.abs()`, violating the mathematical definition, if
+ /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
+ /// This result is not an element of the function's codomain, but it is the
+ /// closest floating point number in the real numbers and thus fulfills the
+ /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
+ /// approximately.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let a: f16 = 7.0;
+ /// let b = 4.0;
+ /// assert_eq!(a.rem_euclid(b), 3.0);
+ /// assert_eq!((-a).rem_euclid(b), 1.0);
+ /// assert_eq!(a.rem_euclid(-b), 3.0);
+ /// assert_eq!((-a).rem_euclid(-b), 1.0);
+ /// // limitation due to round-off error
+ /// assert!((-f16::EPSILON).rem_euclid(3.0) != 0.0);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[doc(alias = "modulo", alias = "mod")]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn rem_euclid(self, rhs: f16) -> f16 {
+ let r = self % rhs;
+ if r < 0.0 { r + rhs.abs() } else { r }
+ }
+
+ /// Raises a number to an integer power.
+ ///
+ /// Using this function is generally faster than using `powf`.
+ /// It might have a different sequence of rounding operations than `powf`,
+ /// so the results are not guaranteed to agree.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn powi(self, n: i32) -> f16 {
+ unsafe { intrinsics::powif16(self, n) }
+ }
+
+ /// Raises a number to a floating point power.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 2.0_f16;
+ /// let abs_difference = (x.powf(2.0) - (x * x)).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn powf(self, n: f16) -> f16 {
+ unsafe { intrinsics::powf16(self, n) }
+ }
+
+ /// Returns the square root of a number.
+ ///
+ /// Returns NaN if `self` is a negative number other than `-0.0`.
+ ///
+ /// # Precision
+ ///
+ /// The result of this operation is guaranteed to be the rounded
+ /// infinite-precision result. It is specified by IEEE 754 as `squareRoot`
+ /// and guaranteed not to change.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let positive = 4.0_f16;
+ /// let negative = -4.0_f16;
+ /// let negative_zero = -0.0_f16;
+ ///
+ /// assert_eq!(positive.sqrt(), 2.0);
+ /// assert!(negative.sqrt().is_nan());
+ /// assert!(negative_zero.sqrt() == negative_zero);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn sqrt(self) -> f16 {
+ unsafe { intrinsics::sqrtf16(self) }
+ }
+
+ /// Returns `e^(self)`, (the exponential function).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let one = 1.0f16;
+ /// // e^1
+ /// let e = one.exp();
+ ///
+ /// // ln(e) - 1 == 0
+ /// let abs_difference = (e.ln() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn exp(self) -> f16 {
+ unsafe { intrinsics::expf16(self) }
+ }
+
+ /// Returns `2^(self)`.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 2.0f16;
+ ///
+ /// // 2^2 - 4 == 0
+ /// let abs_difference = (f.exp2() - 4.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn exp2(self) -> f16 {
+ unsafe { intrinsics::exp2f16(self) }
+ }
+
+ /// Returns the natural logarithm of the number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let one = 1.0f16;
+ /// // e^1
+ /// let e = one.exp();
+ ///
+ /// // ln(e) - 1 == 0
+ /// let abs_difference = (e.ln() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ln(self) -> f16 {
+ unsafe { intrinsics::logf16(self) }
+ }
+
+ /// Returns the logarithm of the number with respect to an arbitrary base.
+ ///
+ /// The result might not be correctly rounded owing to implementation details;
+ /// `self.log2()` can produce more accurate results for base 2, and
+ /// `self.log10()` can produce more accurate results for base 10.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let five = 5.0f16;
+ ///
+ /// // log5(5) - 1 == 0
+ /// let abs_difference = (five.log(5.0) - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn log(self, base: f16) -> f16 {
+ self.ln() / base.ln()
+ }
+
+ /// Returns the base 2 logarithm of the number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let two = 2.0f16;
+ ///
+ /// // log2(2) - 1 == 0
+ /// let abs_difference = (two.log2() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn log2(self) -> f16 {
+ unsafe { intrinsics::log2f16(self) }
+ }
+
+ /// Returns the base 10 logarithm of the number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let ten = 10.0f16;
+ ///
+ /// // log10(10) - 1 == 0
+ /// let abs_difference = (ten.log10() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn log10(self) -> f16 {
+ unsafe { intrinsics::log10f16(self) }
+ }
+
+ /// Returns the cube root of a number.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `cbrtf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 8.0f16;
+ ///
+ /// // x^(1/3) - 2 == 0
+ /// let abs_difference = (x.cbrt() - 2.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn cbrt(self) -> f16 {
+ (unsafe { cmath::cbrtf(self as f32) }) as f16
+ }
+
+ /// Compute the distance between the origin and a point (`x`, `y`) on the
+ /// Euclidean plane. Equivalently, compute the length of the hypotenuse of a
+ /// right-angle triangle with other sides having length `x.abs()` and
+ /// `y.abs()`.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `hypotf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 2.0f16;
+ /// let y = 3.0f16;
+ ///
+ /// // sqrt(x^2 + y^2)
+ /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn hypot(self, other: f16) -> f16 {
+ (unsafe { cmath::hypotf(self as f32, other as f32) }) as f16
+ }
+
+ /// Computes the sine of a number (in radians).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = std::f16::consts::FRAC_PI_2;
+ ///
+ /// let abs_difference = (x.sin() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn sin(self) -> f16 {
+ unsafe { intrinsics::sinf16(self) }
+ }
+
+ /// Computes the cosine of a number (in radians).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 2.0 * std::f16::consts::PI;
+ ///
+ /// let abs_difference = (x.cos() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn cos(self) -> f16 {
+ unsafe { intrinsics::cosf16(self) }
+ }
+
+ /// Computes the tangent of a number (in radians).
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `tanf` from libc on Unix and
+ /// Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = std::f16::consts::FRAC_PI_4;
+ /// let abs_difference = (x.tan() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn tan(self) -> f16 {
+ (unsafe { cmath::tanf(self as f32) }) as f16
+ }
+
+ /// Computes the arcsine of a number. Return value is in radians in
+ /// the range [-pi/2, pi/2] or NaN if the number is outside the range
+ /// [-1, 1].
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `asinf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = std::f16::consts::FRAC_PI_2;
+ ///
+ /// // asin(sin(pi/2))
+ /// let abs_difference = (f.sin().asin() - std::f16::consts::FRAC_PI_2).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arcsin")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn asin(self) -> f16 {
+ (unsafe { cmath::asinf(self as f32) }) as f16
+ }
+
+ /// Computes the arccosine of a number. Return value is in radians in
+ /// the range [0, pi] or NaN if the number is outside the range
+ /// [-1, 1].
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `acosf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = std::f16::consts::FRAC_PI_4;
+ ///
+ /// // acos(cos(pi/4))
+ /// let abs_difference = (f.cos().acos() - std::f16::consts::FRAC_PI_4).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arccos")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn acos(self) -> f16 {
+ (unsafe { cmath::acosf(self as f32) }) as f16
+ }
+
+ /// Computes the arctangent of a number. Return value is in radians in the
+ /// range [-pi/2, pi/2];
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `atanf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let f = 1.0f16;
+ ///
+ /// // atan(tan(1))
+ /// let abs_difference = (f.tan().atan() - 1.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arctan")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn atan(self) -> f16 {
+ (unsafe { cmath::atanf(self as f32) }) as f16
+ }
+
+ /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians.
+ ///
+ /// * `x = 0`, `y = 0`: `0`
+ /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
+ /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
+ /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `atan2f` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// // Positive angles measured counter-clockwise
+ /// // from positive x axis
+ /// // -pi/4 radians (45 deg clockwise)
+ /// let x1 = 3.0f16;
+ /// let y1 = -3.0f16;
+ ///
+ /// // 3pi/4 radians (135 deg counter-clockwise)
+ /// let x2 = -3.0f16;
+ /// let y2 = 3.0f16;
+ ///
+ /// let abs_difference_1 = (y1.atan2(x1) - (-std::f16::consts::FRAC_PI_4)).abs();
+ /// let abs_difference_2 = (y2.atan2(x2) - (3.0 * std::f16::consts::FRAC_PI_4)).abs();
+ ///
+ /// assert!(abs_difference_1 <= f16::EPSILON);
+ /// assert!(abs_difference_2 <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn atan2(self, other: f16) -> f16 {
+ (unsafe { cmath::atan2f(self as f32, other as f32) }) as f16
+ }
+
+ /// Simultaneously computes the sine and cosine of the number, `x`. Returns
+ /// `(sin(x), cos(x))`.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `(f16::sin(x),
+ /// f16::cos(x))`. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = std::f16::consts::FRAC_PI_4;
+ /// let f = x.sin_cos();
+ ///
+ /// let abs_difference_0 = (f.0 - x.sin()).abs();
+ /// let abs_difference_1 = (f.1 - x.cos()).abs();
+ ///
+ /// assert!(abs_difference_0 <= f16::EPSILON);
+ /// assert!(abs_difference_1 <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "sincos")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ pub fn sin_cos(self) -> (f16, f16) {
+ (self.sin(), self.cos())
+ }
+
+ /// Returns `e^(self) - 1` in a way that is accurate even if the
+ /// number is close to zero.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `expm1f` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 1e-4_f16;
+ ///
+ /// // for very small x, e^x is approximately 1 + x + x^2 / 2
+ /// let approx = x + x * x / 2.0;
+ /// let abs_difference = (x.exp_m1() - approx).abs();
+ ///
+ /// assert!(abs_difference < 1e-4);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn exp_m1(self) -> f16 {
+ (unsafe { cmath::expm1f(self as f32) }) as f16
+ }
+
+ /// Returns `ln(1+n)` (natural logarithm) more accurately than if
+ /// the operations were performed separately.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `log1pf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 1e-4_f16;
+ ///
+ /// // for very small x, ln(1 + x) is approximately x - x^2 / 2
+ /// let approx = x - x * x / 2.0;
+ /// let abs_difference = (x.ln_1p() - approx).abs();
+ ///
+ /// assert!(abs_difference < 1e-4);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "log1p")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ln_1p(self) -> f16 {
+ (unsafe { cmath::log1pf(self as f32) }) as f16
+ }
+
+ /// Hyperbolic sine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `sinhf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let e = std::f16::consts::E;
+ /// let x = 1.0f16;
+ ///
+ /// let f = x.sinh();
+ /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
+ /// let g = ((e * e) - 1.0) / (2.0 * e);
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn sinh(self) -> f16 {
+ (unsafe { cmath::sinhf(self as f32) }) as f16
+ }
+
+ /// Hyperbolic cosine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `coshf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let e = std::f16::consts::E;
+ /// let x = 1.0f16;
+ /// let f = x.cosh();
+ /// // Solving cosh() at 1 gives this result
+ /// let g = ((e * e) + 1.0) / (2.0 * e);
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// // Same result
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn cosh(self) -> f16 {
+ (unsafe { cmath::coshf(self as f32) }) as f16
+ }
+
+ /// Hyperbolic tangent function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `tanhf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let e = std::f16::consts::E;
+ /// let x = 1.0f16;
+ ///
+ /// let f = x.tanh();
+ /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
+ /// let g = (1.0 - e.powi(-2)) / (1.0 + e.powi(-2));
+ /// let abs_difference = (f - g).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn tanh(self) -> f16 {
+ (unsafe { cmath::tanhf(self as f32) }) as f16
+ }
+
+ /// Inverse hyperbolic sine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 1.0f16;
+ /// let f = x.sinh().asinh();
+ ///
+ /// let abs_difference = (f - x).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arcsinh")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn asinh(self) -> f16 {
+ let ax = self.abs();
+ let ix = 1.0 / ax;
+ (ax + (ax / (Self::hypot(1.0, ix) + ix))).ln_1p().copysign(self)
+ }
+
+ /// Inverse hyperbolic cosine function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 1.0f16;
+ /// let f = x.cosh().acosh();
+ ///
+ /// let abs_difference = (f - x).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arccosh")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn acosh(self) -> f16 {
+ if self < 1.0 {
+ Self::NAN
+ } else {
+ (self + ((self - 1.0).sqrt() * (self + 1.0).sqrt())).ln()
+ }
+ }
+
+ /// Inverse hyperbolic tangent function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let e = std::f16::consts::E;
+ /// let f = e.tanh().atanh();
+ ///
+ /// let abs_difference = (f - e).abs();
+ ///
+ /// assert!(abs_difference <= 0.01);
+ /// # }
+ /// ```
+ #[inline]
+ #[doc(alias = "arctanh")]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn atanh(self) -> f16 {
+ 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
+ }
+
+ /// Gamma function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `tgammaf` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// #![feature(float_gamma)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 5.0f16;
+ ///
+ /// let abs_difference = (x.gamma() - 24.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn gamma(self) -> f16 {
+ (unsafe { cmath::tgammaf(self as f32) }) as f16
+ }
+
+ /// Natural logarithm of the absolute value of the gamma function
+ ///
+ /// The integer part of the tuple indicates the sign of the gamma function.
+ ///
+ /// # Unspecified precision
+ ///
+ /// The precision of this function is non-deterministic. This means it varies by platform,
+ /// Rust version, and can even differ within the same execution from one invocation to the next.
+ ///
+ /// This function currently corresponds to the `lgamma_r` from libc on Unix
+ /// and Windows. Note that this might change in the future.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// #![feature(float_gamma)]
+ /// # #[cfg(reliable_f16_math)] {
+ ///
+ /// let x = 2.0f16;
+ ///
+ /// let abs_difference = (x.ln_gamma().0 - 0.0).abs();
+ ///
+ /// assert!(abs_difference <= f16::EPSILON);
+ /// # }
+ /// ```
+ #[inline]
+ #[rustc_allow_incoherent_impl]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub fn ln_gamma(self) -> (f16, i32) {
+ let mut signgamp: i32 = 0;
+ let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16;
+ (x, signgamp)
+ }
}
diff --git a/library/std/src/f16/tests.rs b/library/std/src/f16/tests.rs
index 26658a0..684ee3f 100644
--- a/library/std/src/f16/tests.rs
+++ b/library/std/src/f16/tests.rs
@@ -1,16 +1,24 @@
-#![cfg(not(bootstrap))]
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
#![cfg(reliable_f16)]
use crate::f16::consts;
-use crate::num::FpCategory as Fp;
-use crate::num::*;
+use crate::num::{FpCategory as Fp, *};
-// We run out of precision pretty quickly with f16
-// const F16_APPROX_L1: f16 = 0.001;
-const F16_APPROX_L2: f16 = 0.01;
-// const F16_APPROX_L3: f16 = 0.1;
-const F16_APPROX_L4: f16 = 0.5;
+/// Tolerance for results on the order of 10.0e-2
+#[allow(unused)]
+const TOL_N2: f16 = 0.0001;
+
+/// Tolerance for results on the order of 10.0e+0
+#[allow(unused)]
+const TOL_0: f16 = 0.01;
+
+/// Tolerance for results on the order of 10.0e+2
+#[allow(unused)]
+const TOL_P2: f16 = 0.5;
+
+/// Tolerance for results on the order of 10.0e+4
+#[allow(unused)]
+const TOL_P4: f16 = 10.0;
/// Smallest number
const TINY_BITS: u16 = 0x1;
@@ -49,7 +57,33 @@ fn test_num_f16() {
test_num(10f16, 2f16);
}
-// FIXME(f16_f128): add min and max tests when available
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_min_nan() {
+ assert_eq!(f16::NAN.min(2.0), 2.0);
+ assert_eq!(2.0f16.min(f16::NAN), 2.0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_max_nan() {
+ assert_eq!(f16::NAN.max(2.0), 2.0);
+ assert_eq!(2.0f16.max(f16::NAN), 2.0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_minimum() {
+ assert!(f16::NAN.minimum(2.0).is_nan());
+ assert!(2.0f16.minimum(f16::NAN).is_nan());
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_maximum() {
+ assert!(f16::NAN.maximum(2.0).is_nan());
+ assert!(2.0f16.maximum(f16::NAN).is_nan());
+}
#[test]
fn test_nan() {
@@ -199,9 +233,100 @@ fn test_classify() {
assert_eq!(1e-5f16.classify(), Fp::Subnormal);
}
-// FIXME(f16_f128): add missing math functions when available
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_floor() {
+ assert_approx_eq!(1.0f16.floor(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.3f16.floor(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.5f16.floor(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.7f16.floor(), 1.0f16, TOL_0);
+ assert_approx_eq!(0.0f16.floor(), 0.0f16, TOL_0);
+ assert_approx_eq!((-0.0f16).floor(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.0f16).floor(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.3f16).floor(), -2.0f16, TOL_0);
+ assert_approx_eq!((-1.5f16).floor(), -2.0f16, TOL_0);
+ assert_approx_eq!((-1.7f16).floor(), -2.0f16, TOL_0);
+}
#[test]
+#[cfg(reliable_f16_math)]
+fn test_ceil() {
+ assert_approx_eq!(1.0f16.ceil(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.3f16.ceil(), 2.0f16, TOL_0);
+ assert_approx_eq!(1.5f16.ceil(), 2.0f16, TOL_0);
+ assert_approx_eq!(1.7f16.ceil(), 2.0f16, TOL_0);
+ assert_approx_eq!(0.0f16.ceil(), 0.0f16, TOL_0);
+ assert_approx_eq!((-0.0f16).ceil(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.0f16).ceil(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.3f16).ceil(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.5f16).ceil(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.7f16).ceil(), -1.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_round() {
+ assert_approx_eq!(2.5f16.round(), 3.0f16, TOL_0);
+ assert_approx_eq!(1.0f16.round(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.3f16.round(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.5f16.round(), 2.0f16, TOL_0);
+ assert_approx_eq!(1.7f16.round(), 2.0f16, TOL_0);
+ assert_approx_eq!(0.0f16.round(), 0.0f16, TOL_0);
+ assert_approx_eq!((-0.0f16).round(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.0f16).round(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.3f16).round(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.5f16).round(), -2.0f16, TOL_0);
+ assert_approx_eq!((-1.7f16).round(), -2.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_round_ties_even() {
+ assert_approx_eq!(2.5f16.round_ties_even(), 2.0f16, TOL_0);
+ assert_approx_eq!(1.0f16.round_ties_even(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.3f16.round_ties_even(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.5f16.round_ties_even(), 2.0f16, TOL_0);
+ assert_approx_eq!(1.7f16.round_ties_even(), 2.0f16, TOL_0);
+ assert_approx_eq!(0.0f16.round_ties_even(), 0.0f16, TOL_0);
+ assert_approx_eq!((-0.0f16).round_ties_even(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.0f16).round_ties_even(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.3f16).round_ties_even(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.5f16).round_ties_even(), -2.0f16, TOL_0);
+ assert_approx_eq!((-1.7f16).round_ties_even(), -2.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_trunc() {
+ assert_approx_eq!(1.0f16.trunc(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.3f16.trunc(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.5f16.trunc(), 1.0f16, TOL_0);
+ assert_approx_eq!(1.7f16.trunc(), 1.0f16, TOL_0);
+ assert_approx_eq!(0.0f16.trunc(), 0.0f16, TOL_0);
+ assert_approx_eq!((-0.0f16).trunc(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.0f16).trunc(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.3f16).trunc(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.5f16).trunc(), -1.0f16, TOL_0);
+ assert_approx_eq!((-1.7f16).trunc(), -1.0f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_fract() {
+ assert_approx_eq!(1.0f16.fract(), 0.0f16, TOL_0);
+ assert_approx_eq!(1.3f16.fract(), 0.3f16, TOL_0);
+ assert_approx_eq!(1.5f16.fract(), 0.5f16, TOL_0);
+ assert_approx_eq!(1.7f16.fract(), 0.7f16, TOL_0);
+ assert_approx_eq!(0.0f16.fract(), 0.0f16, TOL_0);
+ assert_approx_eq!((-0.0f16).fract(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.0f16).fract(), -0.0f16, TOL_0);
+ assert_approx_eq!((-1.3f16).fract(), -0.3f16, TOL_0);
+ assert_approx_eq!((-1.5f16).fract(), -0.5f16, TOL_0);
+ assert_approx_eq!((-1.7f16).fract(), -0.7f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
fn test_abs() {
assert_eq!(f16::INFINITY.abs(), f16::INFINITY);
assert_eq!(1f16.abs(), 1f16);
@@ -301,6 +426,24 @@ fn test_next_down() {
}
#[test]
+#[cfg(reliable_f16_math)]
+fn test_mul_add() {
+ let nan: f16 = f16::NAN;
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ assert_approx_eq!(12.3f16.mul_add(4.5, 6.7), 62.05, TOL_P2);
+ assert_approx_eq!((-12.3f16).mul_add(-4.5, -6.7), 48.65, TOL_P2);
+ assert_approx_eq!(0.0f16.mul_add(8.9, 1.2), 1.2, TOL_0);
+ assert_approx_eq!(3.4f16.mul_add(-0.0, 5.6), 5.6, TOL_0);
+ assert!(nan.mul_add(7.8, 9.0).is_nan());
+ assert_eq!(inf.mul_add(7.8, 9.0), inf);
+ assert_eq!(neg_inf.mul_add(7.8, 9.0), neg_inf);
+ assert_eq!(8.9f16.mul_add(inf, 3.2), inf);
+ assert_eq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
fn test_recip() {
let nan: f16 = f16::NAN;
let inf: f16 = f16::INFINITY;
@@ -309,20 +452,166 @@ fn test_recip() {
assert_eq!(2.0f16.recip(), 0.5);
assert_eq!((-0.4f16).recip(), -2.5);
assert_eq!(0.0f16.recip(), inf);
+ assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4);
assert!(nan.recip().is_nan());
assert_eq!(inf.recip(), 0.0);
assert_eq!(neg_inf.recip(), 0.0);
}
#[test]
+#[cfg(reliable_f16_math)]
+fn test_powi() {
+ // FIXME(llvm19): LLVM misoptimizes `powi.f16`
+ // <https://github.com/llvm/llvm-project/issues/98665>
+ // let nan: f16 = f16::NAN;
+ // let inf: f16 = f16::INFINITY;
+ // let neg_inf: f16 = f16::NEG_INFINITY;
+ // assert_eq!(1.0f16.powi(1), 1.0);
+ // assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0);
+ // assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2);
+ // assert_eq!(8.3f16.powi(0), 1.0);
+ // assert!(nan.powi(2).is_nan());
+ // assert_eq!(inf.powi(3), inf);
+ // assert_eq!(neg_inf.powi(2), inf);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_powf() {
+ let nan: f16 = f16::NAN;
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ assert_eq!(1.0f16.powf(1.0), 1.0);
+ assert_approx_eq!(3.4f16.powf(4.5), 246.408183, TOL_P2);
+ assert_approx_eq!(2.7f16.powf(-3.2), 0.041652, TOL_N2);
+ assert_approx_eq!((-3.1f16).powf(2.0), 9.61, TOL_P2);
+ assert_approx_eq!(5.9f16.powf(-2.0), 0.028727, TOL_N2);
+ assert_eq!(8.3f16.powf(0.0), 1.0);
+ assert!(nan.powf(2.0).is_nan());
+ assert_eq!(inf.powf(2.0), inf);
+ assert_eq!(neg_inf.powf(3.0), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_sqrt_domain() {
+ assert!(f16::NAN.sqrt().is_nan());
+ assert!(f16::NEG_INFINITY.sqrt().is_nan());
+ assert!((-1.0f16).sqrt().is_nan());
+ assert_eq!((-0.0f16).sqrt(), -0.0);
+ assert_eq!(0.0f16.sqrt(), 0.0);
+ assert_eq!(1.0f16.sqrt(), 1.0);
+ assert_eq!(f16::INFINITY.sqrt(), f16::INFINITY);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_exp() {
+ assert_eq!(1.0, 0.0f16.exp());
+ assert_approx_eq!(2.718282, 1.0f16.exp(), TOL_0);
+ assert_approx_eq!(148.413159, 5.0f16.exp(), TOL_0);
+
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ let nan: f16 = f16::NAN;
+ assert_eq!(inf, inf.exp());
+ assert_eq!(0.0, neg_inf.exp());
+ assert!(nan.exp().is_nan());
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_exp2() {
+ assert_eq!(32.0, 5.0f16.exp2());
+ assert_eq!(1.0, 0.0f16.exp2());
+
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ let nan: f16 = f16::NAN;
+ assert_eq!(inf, inf.exp2());
+ assert_eq!(0.0, neg_inf.exp2());
+ assert!(nan.exp2().is_nan());
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_ln() {
+ let nan: f16 = f16::NAN;
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ assert_approx_eq!(1.0f16.exp().ln(), 1.0, TOL_0);
+ assert!(nan.ln().is_nan());
+ assert_eq!(inf.ln(), inf);
+ assert!(neg_inf.ln().is_nan());
+ assert!((-2.3f16).ln().is_nan());
+ assert_eq!((-0.0f16).ln(), neg_inf);
+ assert_eq!(0.0f16.ln(), neg_inf);
+ assert_approx_eq!(4.0f16.ln(), 1.386294, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_log() {
+ let nan: f16 = f16::NAN;
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ assert_eq!(10.0f16.log(10.0), 1.0);
+ assert_approx_eq!(2.3f16.log(3.5), 0.664858, TOL_0);
+ assert_eq!(1.0f16.exp().log(1.0f16.exp()), 1.0);
+ assert!(1.0f16.log(1.0).is_nan());
+ assert!(1.0f16.log(-13.9).is_nan());
+ assert!(nan.log(2.3).is_nan());
+ assert_eq!(inf.log(10.0), inf);
+ assert!(neg_inf.log(8.8).is_nan());
+ assert!((-2.3f16).log(0.1).is_nan());
+ assert_eq!((-0.0f16).log(2.0), neg_inf);
+ assert_eq!(0.0f16.log(7.0), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_log2() {
+ let nan: f16 = f16::NAN;
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ assert_approx_eq!(10.0f16.log2(), 3.321928, TOL_0);
+ assert_approx_eq!(2.3f16.log2(), 1.201634, TOL_0);
+ assert_approx_eq!(1.0f16.exp().log2(), 1.442695, TOL_0);
+ assert!(nan.log2().is_nan());
+ assert_eq!(inf.log2(), inf);
+ assert!(neg_inf.log2().is_nan());
+ assert!((-2.3f16).log2().is_nan());
+ assert_eq!((-0.0f16).log2(), neg_inf);
+ assert_eq!(0.0f16.log2(), neg_inf);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_log10() {
+ let nan: f16 = f16::NAN;
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ assert_eq!(10.0f16.log10(), 1.0);
+ assert_approx_eq!(2.3f16.log10(), 0.361728, TOL_0);
+ assert_approx_eq!(1.0f16.exp().log10(), 0.434294, TOL_0);
+ assert_eq!(1.0f16.log10(), 0.0);
+ assert!(nan.log10().is_nan());
+ assert_eq!(inf.log10(), inf);
+ assert!(neg_inf.log10().is_nan());
+ assert!((-2.3f16).log10().is_nan());
+ assert_eq!((-0.0f16).log10(), neg_inf);
+ assert_eq!(0.0f16.log10(), neg_inf);
+}
+
+#[test]
fn test_to_degrees() {
let pi: f16 = consts::PI;
let nan: f16 = f16::NAN;
let inf: f16 = f16::INFINITY;
let neg_inf: f16 = f16::NEG_INFINITY;
assert_eq!(0.0f16.to_degrees(), 0.0);
- assert_approx_eq!((-5.8f16).to_degrees(), -332.315521);
- assert_approx_eq!(pi.to_degrees(), 180.0, F16_APPROX_L4);
+ assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2);
+ assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2);
assert!(nan.to_degrees().is_nan());
assert_eq!(inf.to_degrees(), inf);
assert_eq!(neg_inf.to_degrees(), neg_inf);
@@ -336,15 +625,113 @@ fn test_to_radians() {
let inf: f16 = f16::INFINITY;
let neg_inf: f16 = f16::NEG_INFINITY;
assert_eq!(0.0f16.to_radians(), 0.0);
- assert_approx_eq!(154.6f16.to_radians(), 2.698279);
- assert_approx_eq!((-332.31f16).to_radians(), -5.799903);
- assert_approx_eq!(180.0f16.to_radians(), pi, F16_APPROX_L2);
+ assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0);
+ assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0);
+ assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0);
assert!(nan.to_radians().is_nan());
assert_eq!(inf.to_radians(), inf);
assert_eq!(neg_inf.to_radians(), neg_inf);
}
#[test]
+#[cfg(reliable_f16_math)]
+fn test_asinh() {
+ assert_eq!(0.0f16.asinh(), 0.0f16);
+ assert_eq!((-0.0f16).asinh(), -0.0f16);
+
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ let nan: f16 = f16::NAN;
+ assert_eq!(inf.asinh(), inf);
+ assert_eq!(neg_inf.asinh(), neg_inf);
+ assert!(nan.asinh().is_nan());
+ assert!((-0.0f16).asinh().is_sign_negative());
+ // issue 63271
+ assert_approx_eq!(2.0f16.asinh(), 1.443635475178810342493276740273105f16, TOL_0);
+ assert_approx_eq!((-2.0f16).asinh(), -1.443635475178810342493276740273105f16, TOL_0);
+ // regression test for the catastrophic cancellation fixed in 72486
+ assert_approx_eq!((-200.0f16).asinh(), -5.991470797049389, TOL_0);
+
+ // test for low accuracy from issue 104548
+ assert_approx_eq!(10.0f16, 10.0f16.sinh().asinh(), TOL_0);
+ // mul needed for approximate comparison to be meaningful
+ assert_approx_eq!(1.0f16, 1e-3f16.sinh().asinh() * 1e3f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_acosh() {
+ assert_eq!(1.0f16.acosh(), 0.0f16);
+ assert!(0.999f16.acosh().is_nan());
+
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ let nan: f16 = f16::NAN;
+ assert_eq!(inf.acosh(), inf);
+ assert!(neg_inf.acosh().is_nan());
+ assert!(nan.acosh().is_nan());
+ assert_approx_eq!(2.0f16.acosh(), 1.31695789692481670862504634730796844f16, TOL_0);
+ assert_approx_eq!(3.0f16.acosh(), 1.76274717403908605046521864995958461f16, TOL_0);
+
+ // test for low accuracy from issue 104548
+ assert_approx_eq!(10.0f16, 10.0f16.cosh().acosh(), TOL_P2);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_atanh() {
+ assert_eq!(0.0f16.atanh(), 0.0f16);
+ assert_eq!((-0.0f16).atanh(), -0.0f16);
+
+ let inf: f16 = f16::INFINITY;
+ let neg_inf: f16 = f16::NEG_INFINITY;
+ let nan: f16 = f16::NAN;
+ assert_eq!(1.0f16.atanh(), inf);
+ assert_eq!((-1.0f16).atanh(), neg_inf);
+ assert!(2f16.atanh().atanh().is_nan());
+ assert!((-2f16).atanh().atanh().is_nan());
+ assert!(inf.atanh().is_nan());
+ assert!(neg_inf.atanh().is_nan());
+ assert!(nan.atanh().is_nan());
+ assert_approx_eq!(0.5f16.atanh(), 0.54930614433405484569762261846126285f16, TOL_0);
+ assert_approx_eq!((-0.5f16).atanh(), -0.54930614433405484569762261846126285f16, TOL_0);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_gamma() {
+ // precision can differ among platforms
+ assert_approx_eq!(1.0f16.gamma(), 1.0f16, TOL_0);
+ assert_approx_eq!(2.0f16.gamma(), 1.0f16, TOL_0);
+ assert_approx_eq!(3.0f16.gamma(), 2.0f16, TOL_0);
+ assert_approx_eq!(4.0f16.gamma(), 6.0f16, TOL_0);
+ assert_approx_eq!(5.0f16.gamma(), 24.0f16, TOL_0);
+ assert_approx_eq!(0.5f16.gamma(), consts::PI.sqrt(), TOL_0);
+ assert_approx_eq!((-0.5f16).gamma(), -2.0 * consts::PI.sqrt(), TOL_0);
+ assert_eq!(0.0f16.gamma(), f16::INFINITY);
+ assert_eq!((-0.0f16).gamma(), f16::NEG_INFINITY);
+ assert!((-1.0f16).gamma().is_nan());
+ assert!((-2.0f16).gamma().is_nan());
+ assert!(f16::NAN.gamma().is_nan());
+ assert!(f16::NEG_INFINITY.gamma().is_nan());
+ assert_eq!(f16::INFINITY.gamma(), f16::INFINITY);
+ assert_eq!(171.71f16.gamma(), f16::INFINITY);
+}
+
+#[test]
+#[cfg(reliable_f16_math)]
+fn test_ln_gamma() {
+ assert_approx_eq!(1.0f16.ln_gamma().0, 0.0f16, TOL_0);
+ assert_eq!(1.0f16.ln_gamma().1, 1);
+ assert_approx_eq!(2.0f16.ln_gamma().0, 0.0f16, TOL_0);
+ assert_eq!(2.0f16.ln_gamma().1, 1);
+ assert_approx_eq!(3.0f16.ln_gamma().0, 2.0f16.ln(), TOL_0);
+ assert_eq!(3.0f16.ln_gamma().1, 1);
+ assert_approx_eq!((-0.5f16).ln_gamma().0, (2.0 * consts::PI.sqrt()).ln(), TOL_0);
+ assert_eq!((-0.5f16).ln_gamma().1, -1);
+}
+
+#[test]
fn test_real_consts() {
// FIXME(f16_f128): add math tests when available
use super::consts;
@@ -357,29 +744,34 @@ fn test_real_consts() {
let frac_pi_8: f16 = consts::FRAC_PI_8;
let frac_1_pi: f16 = consts::FRAC_1_PI;
let frac_2_pi: f16 = consts::FRAC_2_PI;
- // let frac_2_sqrtpi: f16 = consts::FRAC_2_SQRT_PI;
- // let sqrt2: f16 = consts::SQRT_2;
- // let frac_1_sqrt2: f16 = consts::FRAC_1_SQRT_2;
- // let e: f16 = consts::E;
- // let log2_e: f16 = consts::LOG2_E;
- // let log10_e: f16 = consts::LOG10_E;
- // let ln_2: f16 = consts::LN_2;
- // let ln_10: f16 = consts::LN_10;
- assert_approx_eq!(frac_pi_2, pi / 2f16);
- assert_approx_eq!(frac_pi_3, pi / 3f16);
- assert_approx_eq!(frac_pi_4, pi / 4f16);
- assert_approx_eq!(frac_pi_6, pi / 6f16);
- assert_approx_eq!(frac_pi_8, pi / 8f16);
- assert_approx_eq!(frac_1_pi, 1f16 / pi);
- assert_approx_eq!(frac_2_pi, 2f16 / pi);
- // assert_approx_eq!(frac_2_sqrtpi, 2f16 / pi.sqrt());
- // assert_approx_eq!(sqrt2, 2f16.sqrt());
- // assert_approx_eq!(frac_1_sqrt2, 1f16 / 2f16.sqrt());
- // assert_approx_eq!(log2_e, e.log2());
- // assert_approx_eq!(log10_e, e.log10());
- // assert_approx_eq!(ln_2, 2f16.ln());
- // assert_approx_eq!(ln_10, 10f16.ln());
+ assert_approx_eq!(frac_pi_2, pi / 2f16, TOL_0);
+ assert_approx_eq!(frac_pi_3, pi / 3f16, TOL_0);
+ assert_approx_eq!(frac_pi_4, pi / 4f16, TOL_0);
+ assert_approx_eq!(frac_pi_6, pi / 6f16, TOL_0);
+ assert_approx_eq!(frac_pi_8, pi / 8f16, TOL_0);
+ assert_approx_eq!(frac_1_pi, 1f16 / pi, TOL_0);
+ assert_approx_eq!(frac_2_pi, 2f16 / pi, TOL_0);
+
+ #[cfg(reliable_f16_math)]
+ {
+ let frac_2_sqrtpi: f16 = consts::FRAC_2_SQRT_PI;
+ let sqrt2: f16 = consts::SQRT_2;
+ let frac_1_sqrt2: f16 = consts::FRAC_1_SQRT_2;
+ let e: f16 = consts::E;
+ let log2_e: f16 = consts::LOG2_E;
+ let log10_e: f16 = consts::LOG10_E;
+ let ln_2: f16 = consts::LN_2;
+ let ln_10: f16 = consts::LN_10;
+
+ assert_approx_eq!(frac_2_sqrtpi, 2f16 / pi.sqrt(), TOL_0);
+ assert_approx_eq!(sqrt2, 2f16.sqrt(), TOL_0);
+ assert_approx_eq!(frac_1_sqrt2, 1f16 / 2f16.sqrt(), TOL_0);
+ assert_approx_eq!(log2_e, e.log2(), TOL_0);
+ assert_approx_eq!(log10_e, e.log10(), TOL_0);
+ assert_approx_eq!(ln_2, 2f16.ln(), TOL_0);
+ assert_approx_eq!(ln_10, 10f16.ln(), TOL_0);
+ }
}
#[test]
@@ -388,10 +780,10 @@ fn test_float_bits_conv() {
assert_eq!((12.5f16).to_bits(), 0x4a40);
assert_eq!((1337f16).to_bits(), 0x6539);
assert_eq!((-14.25f16).to_bits(), 0xcb20);
- assert_approx_eq!(f16::from_bits(0x3c00), 1.0);
- assert_approx_eq!(f16::from_bits(0x4a40), 12.5);
- assert_approx_eq!(f16::from_bits(0x6539), 1337.0);
- assert_approx_eq!(f16::from_bits(0xcb20), -14.25);
+ assert_approx_eq!(f16::from_bits(0x3c00), 1.0, TOL_0);
+ assert_approx_eq!(f16::from_bits(0x4a40), 12.5, TOL_0);
+ assert_approx_eq!(f16::from_bits(0x6539), 1337.0, TOL_P4);
+ assert_approx_eq!(f16::from_bits(0xcb20), -14.25, TOL_0);
// Check that NaNs roundtrip their bits regardless of signaling-ness
let masked_nan1 = f16::NAN.to_bits() ^ NAN_MASK1;
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 4fc82fe..12433d2 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -15,11 +15,6 @@
#[cfg(test)]
mod tests;
-#[cfg(not(test))]
-use crate::intrinsics;
-#[cfg(not(test))]
-use crate::sys::cmath;
-
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated, deprecated_in_future)]
pub use core::f32::{
@@ -28,6 +23,11 @@
};
#[cfg(not(test))]
+use crate::intrinsics;
+#[cfg(not(test))]
+use crate::sys::cmath;
+
+#[cfg(not(test))]
impl f32 {
/// Returns the largest integer less than or equal to `self`.
///
@@ -574,7 +574,7 @@ pub fn log(self, base: f32) -> f32 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log2(self) -> f32 {
- crate::sys::log2f32(self)
+ unsafe { intrinsics::log2f32(self) }
}
/// Returns the base 10 logarithm of the number.
diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs
index 63e6569..3a4c1c1 100644
--- a/library/std/src/f32/tests.rs
+++ b/library/std/src/f32/tests.rs
@@ -1,6 +1,5 @@
use crate::f32::consts;
-use crate::num::FpCategory as Fp;
-use crate::num::*;
+use crate::num::{FpCategory as Fp, *};
/// Smallest number
#[allow(dead_code)] // unused on x86
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 1ca2b32..a343e19 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -15,11 +15,6 @@
#[cfg(test)]
mod tests;
-#[cfg(not(test))]
-use crate::intrinsics;
-#[cfg(not(test))]
-use crate::sys::cmath;
-
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated, deprecated_in_future)]
pub use core::f64::{
@@ -28,6 +23,11 @@
};
#[cfg(not(test))]
+use crate::intrinsics;
+#[cfg(not(test))]
+use crate::sys::cmath;
+
+#[cfg(not(test))]
impl f64 {
/// Returns the largest integer less than or equal to `self`.
///
@@ -574,7 +574,7 @@ pub fn log(self, base: f64) -> f64 {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn log2(self) -> f64 {
- crate::sys::log2f64(self)
+ unsafe { intrinsics::log2f64(self) }
}
/// Returns the base 10 logarithm of the number.
diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs
index d9e17fd..bac8405 100644
--- a/library/std/src/f64/tests.rs
+++ b/library/std/src/f64/tests.rs
@@ -1,6 +1,5 @@
use crate::f64::consts;
-use crate::num::FpCategory as Fp;
-use crate::num::*;
+use crate::num::{FpCategory as Fp, *};
/// Smallest number
#[allow(dead_code)] // unused on x86
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index b59b0c5..cb0ca5d 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -1,19 +1,14 @@
//! [`CStr`], [`CString`], and related types.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::ffi::c_str::CStr;
-
-#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-pub use core::ffi::c_str::FromBytesWithNulError;
-
-#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
-pub use core::ffi::c_str::FromBytesUntilNulError;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc::ffi::c_str::{CString, NulError};
-
#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
pub use alloc::ffi::c_str::FromVecWithNulError;
-
#[stable(feature = "cstring_into", since = "1.7.0")]
pub use alloc::ffi::c_str::IntoStringError;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc::ffi::c_str::{CString, NulError};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::ffi::c_str::CStr;
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+pub use core::ffi::c_str::FromBytesUntilNulError;
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
+pub use core::ffi::c_str::FromBytesWithNulError;
diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs
index f45fd77..2b67750 100644
--- a/library/std/src/ffi/mod.rs
+++ b/library/std/src/ffi/mod.rs
@@ -164,43 +164,13 @@
#[unstable(feature = "c_str_module", issue = "112134")]
pub mod c_str;
-#[doc(inline)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::c_str::{CStr, CString};
-
-#[doc(no_inline)]
-#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-pub use self::c_str::FromBytesWithNulError;
-
-#[doc(no_inline)]
-#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
-pub use self::c_str::FromBytesUntilNulError;
-
-#[doc(no_inline)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::c_str::NulError;
-
-#[doc(no_inline)]
-#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
-pub use self::c_str::FromVecWithNulError;
-
-#[doc(no_inline)]
-#[stable(feature = "cstring_into", since = "1.7.0")]
-pub use self::c_str::IntoStringError;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(inline)]
-pub use self::os_str::{OsStr, OsString};
-
+#[stable(feature = "core_c_void", since = "1.30.0")]
+pub use core::ffi::c_void;
#[stable(feature = "core_ffi_c", since = "1.64.0")]
pub use core::ffi::{
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
c_ulong, c_ulonglong, c_ushort,
};
-
-#[stable(feature = "core_c_void", since = "1.30.0")]
-pub use core::ffi::c_void;
-
#[unstable(
feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
@@ -209,5 +179,27 @@
)]
pub use core::ffi::{VaList, VaListImpl};
+#[doc(no_inline)]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+pub use self::c_str::FromBytesUntilNulError;
+#[doc(no_inline)]
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
+pub use self::c_str::FromBytesWithNulError;
+#[doc(no_inline)]
+#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
+pub use self::c_str::FromVecWithNulError;
+#[doc(no_inline)]
+#[stable(feature = "cstring_into", since = "1.7.0")]
+pub use self::c_str::IntoStringError;
+#[doc(no_inline)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::c_str::NulError;
+#[doc(inline)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::c_str::{CStr, CString};
+#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(inline)]
+pub use self::os_str::{OsStr, OsString};
+
#[unstable(feature = "os_str_display", issue = "120048")]
pub mod os_str;
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 0fb3964..a501bcc 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -4,18 +4,15 @@
mod tests;
use crate::borrow::{Borrow, Cow};
-use crate::cmp;
use crate::collections::TryReserveError;
-use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::ops::{self, Range};
use crate::rc::Rc;
-use crate::slice;
use crate::str::FromStr;
use crate::sync::Arc;
-
use crate::sys::os_str::{Buf, Slice};
use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::{cmp, fmt, slice};
/// A type that can represent owned, mutable platform-native strings, but is
/// cheaply inter-convertible with Rust strings.
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 536d0d1..c5edb03 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -50,7 +50,7 @@
/// }
/// ```
///
-/// Read the contents of a file into a [`String`] (you can also use [`read`]):
+/// Reads the contents of a file into a [`String`] (you can also use [`read`]):
///
/// ```no_run
/// use std::fs::File;
@@ -229,7 +229,7 @@ pub struct DirBuilder {
recursive: bool,
}
-/// Read the entire contents of a file into a bytes vector.
+/// Reads the entire contents of a file into a bytes vector.
///
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
/// with fewer imports and without an intermediate variable.
@@ -268,7 +268,7 @@ fn inner(path: &Path) -> io::Result<Vec<u8>> {
inner(path.as_ref())
}
-/// Read the entire contents of a file into a string.
+/// Reads the entire contents of a file into a string.
///
/// This is a convenience function for using [`File::open`] and [`read_to_string`]
/// with fewer imports and without an intermediate variable.
@@ -311,7 +311,7 @@ fn inner(path: &Path) -> io::Result<String> {
inner(path.as_ref())
}
-/// Write a slice as the entire contents of a file.
+/// Writes a slice as the entire contents of a file.
///
/// This function will create a file if it does not exist,
/// and will entirely replace its contents if it does.
@@ -767,7 +767,7 @@ fn buffer_capacity_required(mut file: &File) -> Option<usize> {
#[stable(feature = "rust1", since = "1.0.0")]
impl Read for &File {
- /// Read some bytes from the file.
+ /// Reads some bytes from the file.
///
/// See [`Read::read`] docs for more info.
///
@@ -835,7 +835,7 @@ fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for &File {
- /// Write some bytes from the file.
+ /// Writes some bytes from the file.
///
/// See [`Write::write`] docs for more info.
///
@@ -1526,7 +1526,7 @@ fn from_inner(attr: fs_imp::FileAttr) -> Metadata {
}
impl FileTimes {
- /// Create a new `FileTimes` with no times set.
+ /// Creates a new `FileTimes` with no times set.
///
/// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps.
#[stable(feature = "file_set_times", since = "1.75.0")]
@@ -2005,7 +2005,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
fs_imp::unlink(path.as_ref())
}
-/// Given a path, query the file system to get information about a file,
+/// Given a path, queries the file system to get information about a file,
/// directory, etc.
///
/// This function will traverse symbolic links to query information about the
@@ -2044,7 +2044,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
fs_imp::stat(path.as_ref()).map(Metadata)
}
-/// Query the metadata about a file without following symlinks.
+/// Queries the metadata about a file without following symlinks.
///
/// # Platform-specific behavior
///
@@ -2079,7 +2079,7 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
fs_imp::lstat(path.as_ref()).map(Metadata)
}
-/// Rename a file or directory to a new name, replacing the original file if
+/// Renames a file or directory to a new name, replacing the original file if
/// `to` already exists.
///
/// This will not work if the new name is on a different mount point.
@@ -2744,7 +2744,7 @@ fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
/// ```
///
/// [`Path::exists`]: crate::path::Path::exists
-#[stable(feature = "fs_try_exists", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "fs_try_exists", since = "1.81.0")]
#[inline]
pub fn exists<P: AsRef<Path>>(path: P) -> io::Result<bool> {
fs_imp::exists(path.as_ref())
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index c1fc2e5..13028c4 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,20 +1,11 @@
-use crate::io::prelude::*;
-
-use crate::env;
-use crate::fs::{self, File, FileTimes, OpenOptions};
-use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
-use crate::mem::MaybeUninit;
-use crate::path::Path;
-use crate::str;
-use crate::sync::Arc;
-use crate::sys_common::io::test::{tmpdir, TempDir};
-use crate::thread;
-use crate::time::{Duration, Instant, SystemTime};
-
use rand::RngCore;
#[cfg(target_os = "macos")]
use crate::ffi::{c_char, c_int};
+use crate::fs::{self, File, FileTimes, OpenOptions};
+use crate::io::prelude::*;
+use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
+use crate::mem::MaybeUninit;
#[cfg(unix)]
use crate::os::unix::fs::symlink as symlink_dir;
#[cfg(unix)]
@@ -23,8 +14,13 @@
use crate::os::unix::fs::symlink as junction_point;
#[cfg(windows)]
use crate::os::windows::fs::{junction_point, symlink_dir, symlink_file, OpenOptionsExt};
+use crate::path::Path;
+use crate::sync::Arc;
#[cfg(target_os = "macos")]
use crate::sys::weak::weak;
+use crate::sys_common::io::test::{tmpdir, TempDir};
+use crate::time::{Duration, Instant, SystemTime};
+use crate::{env, str, thread};
macro_rules! check {
($e:expr) => {
@@ -1514,7 +1510,9 @@ fn symlink_hard_link() {
#[test]
#[cfg(windows)]
fn create_dir_long_paths() {
- use crate::{ffi::OsStr, iter, os::windows::ffi::OsStrExt};
+ use crate::ffi::OsStr;
+ use crate::iter;
+ use crate::os::windows::ffi::OsStrExt;
const PATH_LEN: usize = 247;
let tmpdir = tmpdir();
diff --git a/library/std/src/hash/random.rs b/library/std/src/hash/random.rs
index 0adf91e..8ef4517 100644
--- a/library/std/src/hash/random.rs
+++ b/library/std/src/hash/random.rs
@@ -10,8 +10,7 @@
#[allow(deprecated)]
use super::{BuildHasher, Hasher, SipHasher13};
use crate::cell::Cell;
-use crate::fmt;
-use crate::sys;
+use crate::{fmt, sys};
/// `RandomState` is the default state for [`HashMap`] types.
///
diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs
index 0cdc49c..0b12e57 100644
--- a/library/std/src/io/buffered/bufreader.rs
+++ b/library/std/src/io/buffered/bufreader.rs
@@ -1,11 +1,12 @@
mod buffer;
+use buffer::Buffer;
+
use crate::fmt;
use crate::io::{
self, uninlined_slow_read_byte, BorrowedCursor, BufRead, IoSliceMut, Read, Seek, SeekFrom,
SizeHint, SpecReadByte, DEFAULT_BUF_SIZE,
};
-use buffer::Buffer;
/// The `BufReader<R>` struct adds buffering to any reader.
///
@@ -93,6 +94,40 @@ pub fn new(inner: R) -> BufReader<R> {
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
BufReader { inner, buf: Buffer::with_capacity(capacity) }
}
+
+ /// Attempt to look ahead `n` bytes.
+ ///
+ /// `n` must be less than `capacity`.
+ ///
+ /// ## Examples
+ ///
+ /// ```rust
+ /// #![feature(bufreader_peek)]
+ /// use std::io::{Read, BufReader};
+ ///
+ /// let mut bytes = &b"oh, hello"[..];
+ /// let mut rdr = BufReader::with_capacity(6, &mut bytes);
+ /// assert_eq!(rdr.peek(2).unwrap(), b"oh");
+ /// let mut buf = [0; 4];
+ /// rdr.read(&mut buf[..]).unwrap();
+ /// assert_eq!(&buf, b"oh, ");
+ /// assert_eq!(rdr.peek(2).unwrap(), b"he");
+ /// let mut s = String::new();
+ /// rdr.read_to_string(&mut s).unwrap();
+ /// assert_eq!(&s, "hello");
+ /// ```
+ #[unstable(feature = "bufreader_peek", issue = "128405")]
+ pub fn peek(&mut self, n: usize) -> io::Result<&[u8]> {
+ assert!(n <= self.capacity());
+ while n > self.buf.buffer().len() {
+ if self.buf.pos() > 0 {
+ self.buf.backshift();
+ }
+ self.buf.read_more(&mut self.inner)?;
+ debug_assert_eq!(self.buf.pos(), 0);
+ }
+ Ok(&self.buf.buffer()[..n])
+ }
}
impl<R: ?Sized> BufReader<R> {
diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs
index 796137c..ccd67fa 100644
--- a/library/std/src/io/buffered/bufreader/buffer.rs
+++ b/library/std/src/io/buffered/bufreader/buffer.rs
@@ -97,6 +97,27 @@ pub fn unconsume(&mut self, amt: usize) {
self.pos = self.pos.saturating_sub(amt);
}
+ /// Read more bytes into the buffer without discarding any of its contents
+ pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<()> {
+ let mut buf = BorrowedBuf::from(&mut self.buf[self.pos..]);
+ let old_init = self.initialized - self.pos;
+ unsafe {
+ buf.set_init(old_init);
+ }
+ reader.read_buf(buf.unfilled())?;
+ self.filled += buf.len();
+ self.initialized += buf.init_len() - old_init;
+ Ok(())
+ }
+
+ /// Remove bytes that have already been read from the buffer.
+ pub fn backshift(&mut self) {
+ self.buf.copy_within(self.pos.., 0);
+ self.initialized -= self.pos;
+ self.filled -= self.pos;
+ self.pos = 0;
+ }
+
#[inline]
pub fn fill_buf(&mut self, mut reader: impl Read) -> io::Result<&[u8]> {
// If we've reached the end of our internal buffer then we need to fetch
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index a8680e9..21650d4 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -1,10 +1,8 @@
-use crate::error;
-use crate::fmt;
use crate::io::{
self, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
};
use crate::mem::{self, ManuallyDrop};
-use crate::ptr;
+use crate::{error, fmt, ptr};
/// Wraps a writer and buffers its output.
///
diff --git a/library/std/src/io/buffered/linewriter.rs b/library/std/src/io/buffered/linewriter.rs
index 3d4ae70..cc6921b 100644
--- a/library/std/src/io/buffered/linewriter.rs
+++ b/library/std/src/io/buffered/linewriter.rs
@@ -1,5 +1,6 @@
use crate::fmt;
-use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSlice, Write};
+use crate::io::buffered::LineWriterShim;
+use crate::io::{self, BufWriter, IntoInnerError, IoSlice, Write};
/// Wraps a writer and buffers output to it, flushing whenever a newline
/// (`0x0a`, `'\n'`) is detected.
diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs
index c3ac785..3d04ccd 100644
--- a/library/std/src/io/buffered/linewritershim.rs
+++ b/library/std/src/io/buffered/linewritershim.rs
@@ -1,7 +1,9 @@
-use crate::io::{self, BufWriter, IoSlice, Write};
use core::slice::memchr;
+use crate::io::{self, BufWriter, IoSlice, Write};
+
/// Private helper struct for implementing the line-buffered writing logic.
+///
/// This shim temporarily wraps a BufWriter, and uses its internals to
/// implement a line-buffered writer (specifically by using the internal
/// methods like write_to_buf and flush_buf). In this way, a more
@@ -20,27 +22,27 @@ pub fn new(buffer: &'a mut BufWriter<W>) -> Self {
Self { buffer }
}
- /// Get a reference to the inner writer (that is, the writer
+ /// Gets a reference to the inner writer (that is, the writer
/// wrapped by the BufWriter).
fn inner(&self) -> &W {
self.buffer.get_ref()
}
- /// Get a mutable reference to the inner writer (that is, the writer
+ /// Gets a mutable reference to the inner writer (that is, the writer
/// wrapped by the BufWriter). Be careful with this writer, as writes to
/// it will bypass the buffer.
fn inner_mut(&mut self) -> &mut W {
self.buffer.get_mut()
}
- /// Get the content currently buffered in self.buffer
+ /// Gets the content currently buffered in self.buffer
fn buffered(&self) -> &[u8] {
self.buffer.buffer()
}
- /// Flush the buffer iff the last byte is a newline (indicating that an
+ /// Flushes the buffer iff the last byte is a newline (indicating that an
/// earlier write only succeeded partially, and we want to retry flushing
- /// the buffered line before continuing with a subsequent write)
+ /// the buffered line before continuing with a subsequent write).
fn flush_if_completed_line(&mut self) -> io::Result<()> {
match self.buffered().last().copied() {
Some(b'\n') => self.buffer.flush_buf(),
@@ -50,10 +52,11 @@ fn flush_if_completed_line(&mut self) -> io::Result<()> {
}
impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> {
- /// Write some data into this BufReader with line buffering. This means
- /// that, if any newlines are present in the data, the data up to the last
- /// newline is sent directly to the underlying writer, and data after it
- /// is buffered. Returns the number of bytes written.
+ /// Writes some data into this BufReader with line buffering.
+ ///
+ /// This means that, if any newlines are present in the data, the data up to
+ /// the last newline is sent directly to the underlying writer, and data
+ /// after it is buffered. Returns the number of bytes written.
///
/// This function operates on a "best effort basis"; in keeping with the
/// convention of `Write::write`, it makes at most one attempt to write
@@ -136,11 +139,12 @@ fn flush(&mut self) -> io::Result<()> {
self.buffer.flush()
}
- /// Write some vectored data into this BufReader with line buffering. This
- /// means that, if any newlines are present in the data, the data up to
- /// and including the buffer containing the last newline is sent directly
- /// to the inner writer, and the data after it is buffered. Returns the
- /// number of bytes written.
+ /// Writes some vectored data into this BufReader with line buffering.
+ ///
+ /// This means that, if any newlines are present in the data, the data up to
+ /// and including the buffer containing the last newline is sent directly to
+ /// the inner writer, and the data after it is buffered. Returns the number
+ /// of bytes written.
///
/// This function operates on a "best effort basis"; in keeping with the
/// convention of `Write::write`, it makes at most one attempt to write
@@ -245,10 +249,11 @@ fn is_write_vectored(&self) -> bool {
self.inner().is_write_vectored()
}
- /// Write some data into this BufReader with line buffering. This means
- /// that, if any newlines are present in the data, the data up to the last
- /// newline is sent directly to the underlying writer, and data after it
- /// is buffered.
+ /// Writes some data into this BufReader with line buffering.
+ ///
+ /// This means that, if any newlines are present in the data, the data up to
+ /// the last newline is sent directly to the underlying writer, and data
+ /// after it is buffered.
///
/// Because this function attempts to send completed lines to the underlying
/// writer, it will also flush the existing buffer if it contains any
diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs
index 100dab1..475d877 100644
--- a/library/std/src/io/buffered/mod.rs
+++ b/library/std/src/io/buffered/mod.rs
@@ -8,16 +8,14 @@
#[cfg(test)]
mod tests;
-use crate::error;
-use crate::fmt;
-use crate::io::Error;
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
+pub use bufwriter::WriterPanicked;
+use linewritershim::LineWriterShim;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::{bufreader::BufReader, bufwriter::BufWriter, linewriter::LineWriter};
-use linewritershim::LineWriterShim;
-
-#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
-pub use bufwriter::WriterPanicked;
+use crate::io::Error;
+use crate::{error, fmt};
/// An error returned by [`BufWriter::into_inner`] which combines an error that
/// happened while writing out the buffer, and the buffered writer object
@@ -48,7 +46,7 @@
pub struct IntoInnerError<W>(W, Error);
impl<W> IntoInnerError<W> {
- /// Construct a new IntoInnerError
+ /// Constructs a new IntoInnerError
fn new(writer: W, error: Error) -> Self {
Self(writer, error)
}
diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs
index ab66dea..d89ecd3 100644
--- a/library/std/src/io/buffered/tests.rs
+++ b/library/std/src/io/buffered/tests.rs
@@ -3,9 +3,8 @@
self, BorrowedBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom,
};
use crate::mem::MaybeUninit;
-use crate::panic;
use crate::sync::atomic::{AtomicUsize, Ordering};
-use crate::thread;
+use crate::{panic, thread};
/// A dummy reader intended at testing short-reads propagation.
pub struct ShortReader {
diff --git a/library/std/src/io/copy/tests.rs b/library/std/src/io/copy/tests.rs
index a1f909a..7e08826 100644
--- a/library/std/src/io/copy/tests.rs
+++ b/library/std/src/io/copy/tests.rs
@@ -119,13 +119,12 @@ fn copy_specializes_from_slice() {
#[cfg(unix)]
mod io_benches {
- use crate::fs::File;
- use crate::fs::OpenOptions;
+ use test::Bencher;
+
+ use crate::fs::{File, OpenOptions};
use crate::io::prelude::*;
use crate::io::BufReader;
- use test::Bencher;
-
#[bench]
fn bench_copy_buf_reader(b: &mut Bencher) {
let mut file_in = File::open("/dev/zero").expect("opening /dev/zero failed");
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index 2ed64a4..9f913ea 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -1,10 +1,9 @@
#[cfg(test)]
mod tests;
-use crate::io::prelude::*;
-
use crate::alloc::Allocator;
use crate::cmp;
+use crate::io::prelude::*;
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
/// A `Cursor` wraps an in-memory buffer and provides it with a
@@ -210,55 +209,60 @@ impl<T> Cursor<T>
where
T: AsRef<[u8]>,
{
- /// Returns the remaining slice.
+ /// Splits the underlying slice at the cursor position and returns them.
///
/// # Examples
///
/// ```
- /// #![feature(cursor_remaining)]
+ /// #![feature(cursor_split)]
/// use std::io::Cursor;
///
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
///
- /// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]);
+ /// assert_eq!(buff.split(), ([].as_slice(), [1, 2, 3, 4, 5].as_slice()));
///
/// buff.set_position(2);
- /// assert_eq!(buff.remaining_slice(), &[3, 4, 5]);
- ///
- /// buff.set_position(4);
- /// assert_eq!(buff.remaining_slice(), &[5]);
+ /// assert_eq!(buff.split(), ([1, 2].as_slice(), [3, 4, 5].as_slice()));
///
/// buff.set_position(6);
- /// assert_eq!(buff.remaining_slice(), &[]);
+ /// assert_eq!(buff.split(), ([1, 2, 3, 4, 5].as_slice(), [].as_slice()));
/// ```
- #[unstable(feature = "cursor_remaining", issue = "86369")]
- pub fn remaining_slice(&self) -> &[u8] {
- let len = self.pos.min(self.inner.as_ref().len() as u64);
- &self.inner.as_ref()[(len as usize)..]
+ #[unstable(feature = "cursor_split", issue = "86369")]
+ pub fn split(&self) -> (&[u8], &[u8]) {
+ let slice = self.inner.as_ref();
+ let pos = self.pos.min(slice.len() as u64);
+ slice.split_at(pos as usize)
}
+}
- /// Returns `true` if the remaining slice is empty.
+impl<T> Cursor<T>
+where
+ T: AsMut<[u8]>,
+{
+ /// Splits the underlying slice at the cursor position and returns them
+ /// mutably.
///
/// # Examples
///
/// ```
- /// #![feature(cursor_remaining)]
+ /// #![feature(cursor_split)]
/// use std::io::Cursor;
///
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
///
+ /// assert_eq!(buff.split_mut(), ([].as_mut_slice(), [1, 2, 3, 4, 5].as_mut_slice()));
+ ///
/// buff.set_position(2);
- /// assert!(!buff.is_empty());
+ /// assert_eq!(buff.split_mut(), ([1, 2].as_mut_slice(), [3, 4, 5].as_mut_slice()));
///
- /// buff.set_position(5);
- /// assert!(buff.is_empty());
- ///
- /// buff.set_position(10);
- /// assert!(buff.is_empty());
+ /// buff.set_position(6);
+ /// assert_eq!(buff.split_mut(), ([1, 2, 3, 4, 5].as_mut_slice(), [].as_mut_slice()));
/// ```
- #[unstable(feature = "cursor_remaining", issue = "86369")]
- pub fn is_empty(&self) -> bool {
- self.pos >= self.inner.as_ref().len() as u64
+ #[unstable(feature = "cursor_split", issue = "86369")]
+ pub fn split_mut(&mut self) -> (&mut [u8], &mut [u8]) {
+ let slice = self.inner.as_mut();
+ let pos = self.pos.min(slice.len() as u64);
+ slice.split_at_mut(pos as usize)
}
}
@@ -320,7 +324,7 @@ impl<T> Read for Cursor<T>
T: AsRef<[u8]>,
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- let n = Read::read(&mut self.remaining_slice(), buf)?;
+ let n = Read::read(&mut Cursor::split(self).1, buf)?;
self.pos += n as u64;
Ok(n)
}
@@ -328,7 +332,7 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
fn read_buf(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
let prev_written = cursor.written();
- Read::read_buf(&mut self.remaining_slice(), cursor.reborrow())?;
+ Read::read_buf(&mut Cursor::split(self).1, cursor.reborrow())?;
self.pos += (cursor.written() - prev_written) as u64;
@@ -352,7 +356,7 @@ fn is_read_vectored(&self) -> bool {
}
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
- let result = Read::read_exact(&mut self.remaining_slice(), buf);
+ let result = Read::read_exact(&mut Cursor::split(self).1, buf);
match result {
Ok(_) => self.pos += buf.len() as u64,
@@ -366,14 +370,14 @@ fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> {
let prev_written = cursor.written();
- let result = Read::read_buf_exact(&mut self.remaining_slice(), cursor.reborrow());
+ let result = Read::read_buf_exact(&mut Cursor::split(self).1, cursor.reborrow());
self.pos += (cursor.written() - prev_written) as u64;
result
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
- let content = self.remaining_slice();
+ let content = Cursor::split(self).1;
let len = content.len();
buf.try_reserve(len)?;
buf.extend_from_slice(content);
@@ -384,7 +388,7 @@ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
let content =
- crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?;
+ crate::str::from_utf8(Cursor::split(self).1).map_err(|_| io::Error::INVALID_UTF8)?;
let len = content.len();
buf.try_reserve(len)?;
buf.push_str(content);
@@ -400,7 +404,7 @@ impl<T> BufRead for Cursor<T>
T: AsRef<[u8]>,
{
fn fill_buf(&mut self) -> io::Result<&[u8]> {
- Ok(self.remaining_slice())
+ Ok(Cursor::split(self).1)
}
fn consume(&mut self, amt: usize) {
self.pos += amt as u64;
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 8de2736..e8ae1d9 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -11,10 +11,7 @@
#[cfg(any(not(target_pointer_width = "64"), target_os = "uefi"))]
use repr_unpacked::Repr;
-use crate::error;
-use crate::fmt;
-use crate::result;
-use crate::sys;
+use crate::{error, fmt, result, sys};
/// A specialized [`Result`] type for I/O operations.
///
@@ -167,7 +164,7 @@ pub(crate) const fn new(kind: ErrorKind, message: &'static str) -> Self {
}
}
-/// Create and return an `io::Error` for a given `ErrorKind` and constant
+/// Creates and returns an `io::Error` for a given `ErrorKind` and constant
/// message. This doesn't allocate.
pub(crate) macro const_io_error($kind:expr, $message:expr $(,)?) {
$crate::io::error::Error::from_static_message({
@@ -852,7 +849,7 @@ pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
}
}
- /// Attempt to downcast the custom boxed error to `E`.
+ /// Attempts to downcast the custom boxed error to `E`.
///
/// If this [`Error`] contains a custom boxed error,
/// then it would attempt downcasting on the boxed error,
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index fbb7496..9d3ade4 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -102,10 +102,11 @@
//! to use a pointer type to store something that may hold an integer, some of
//! the time.
-use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
use core::marker::PhantomData;
use core::ptr::{self, NonNull};
+use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
+
// The 2 least-significant bits are used as tag.
const TAG_MASK: usize = 0b11;
const TAG_SIMPLE_MESSAGE: usize = 0b00;
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
index fc6db28..064e2e3 100644
--- a/library/std/src/io/error/tests.rs
+++ b/library/std/src/io/error/tests.rs
@@ -1,10 +1,9 @@
use super::{const_io_error, Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage};
use crate::assert_matches::assert_matches;
-use crate::error;
-use crate::fmt;
use crate::mem::size_of;
use crate::sys::decode_error_kind;
use crate::sys::os::error_string;
+use crate::{error, fmt};
#[test]
fn test_size() {
@@ -95,7 +94,8 @@ fn test_errorkind_packing() {
#[test]
fn test_simple_message_packing() {
- use super::{ErrorKind::*, SimpleMessage};
+ use super::ErrorKind::*;
+ use super::SimpleMessage;
macro_rules! check_simple_msg {
($err:expr, $kind:ident, $msg:literal) => {{
let e = &$err;
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index a8a2e94..8502354 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -2,12 +2,9 @@
mod tests;
use crate::alloc::Allocator;
-use crate::cmp;
use crate::collections::VecDeque;
-use crate::fmt;
use crate::io::{self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
-use crate::mem;
-use crate::str;
+use crate::{cmp, fmt, mem, str};
// =============================================================================
// Forwarding implementations
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 1345a30..644b294 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -297,15 +297,12 @@
#[cfg(test)]
mod tests;
-use crate::cmp;
-use crate::fmt;
-use crate::mem::take;
-use crate::ops::{Deref, DerefMut};
-use crate::slice;
-use crate::str;
-use crate::sys;
+#[unstable(feature = "read_buf", issue = "78485")]
+pub use core::io::{BorrowedBuf, BorrowedCursor};
use core::slice::memchr;
+pub(crate) use error::const_io_error;
+
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
pub use self::buffered::WriterPanicked;
#[unstable(feature = "raw_os_error_ty", issue = "107792")]
@@ -328,10 +325,9 @@
stdio::{stderr, stdin, stdout, Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock},
util::{empty, repeat, sink, Empty, Repeat, Sink},
};
-
-#[unstable(feature = "read_buf", issue = "78485")]
-pub use core::io::{BorrowedBuf, BorrowedCursor};
-pub(crate) use error::const_io_error;
+use crate::mem::take;
+use crate::ops::{Deref, DerefMut};
+use crate::{cmp, fmt, slice, str, sys};
mod buffered;
pub(crate) mod copy;
@@ -782,7 +778,7 @@ fn is_read_vectored(&self) -> bool {
false
}
- /// Read all bytes until EOF in this source, placing them into `buf`.
+ /// Reads all bytes until EOF in this source, placing them into `buf`.
///
/// All bytes read from this source will be appended to the specified buffer
/// `buf`. This function will continuously call [`read()`] to append more data to
@@ -866,7 +862,7 @@ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
default_read_to_end(self, buf, None)
}
- /// Read all bytes until EOF in this source, appending them to `buf`.
+ /// Reads all bytes until EOF in this source, appending them to `buf`.
///
/// If successful, this function returns the number of bytes which were read
/// and appended to `buf`.
@@ -909,7 +905,7 @@ fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
default_read_to_string(self, buf, None)
}
- /// Read the exact number of bytes required to fill `buf`.
+ /// Reads the exact number of bytes required to fill `buf`.
///
/// This function reads as many bytes as necessary to completely fill the
/// specified buffer `buf`.
@@ -973,7 +969,7 @@ fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
default_read_buf(|b| self.read(b), buf)
}
- /// Read the exact number of bytes required to fill `cursor`.
+ /// Reads the exact number of bytes required to fill `cursor`.
///
/// This is similar to the [`read_exact`](Read::read_exact) method, except
/// that it is passed a [`BorrowedCursor`] rather than `[u8]` to allow use
@@ -1159,7 +1155,7 @@ fn take(self, limit: u64) -> Take<Self>
}
}
-/// Read all bytes from a [reader][Read] into a new [`String`].
+/// Reads all bytes from a [reader][Read] into a new [`String`].
///
/// This is a convenience function for [`Read::read_to_string`]. Using this
/// function avoids having to create a variable first and provides more type
@@ -1212,7 +1208,7 @@ pub fn read_to_string<R: Read>(mut reader: R) -> Result<String> {
/// A buffer type used with `Read::read_vectored`.
///
-/// It is semantically a wrapper around an `&mut [u8]`, but is guaranteed to be
+/// It is semantically a wrapper around a `&mut [u8]`, but is guaranteed to be
/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
/// Windows.
#[stable(feature = "iovec", since = "1.36.0")]
@@ -1266,7 +1262,7 @@ pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
/// buf.advance(3);
/// assert_eq!(buf.deref(), [1; 5].as_ref());
/// ```
- #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "io_slice_advance", since = "1.81.0")]
#[inline]
pub fn advance(&mut self, n: usize) {
self.0.advance(n)
@@ -1305,7 +1301,7 @@ pub fn advance(&mut self, n: usize) {
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
/// ```
- #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "io_slice_advance", since = "1.81.0")]
#[inline]
pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
// Number of buffers to remove.
@@ -1406,7 +1402,7 @@ pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
/// buf.advance(3);
/// assert_eq!(buf.deref(), [1; 5].as_ref());
/// ```
- #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "io_slice_advance", since = "1.81.0")]
#[inline]
pub fn advance(&mut self, n: usize) {
self.0.advance(n)
@@ -1444,7 +1440,7 @@ pub fn advance(&mut self, n: usize) {
/// IoSlice::advance_slices(&mut bufs, 10);
/// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
/// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
- #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+ #[stable(feature = "io_slice_advance", since = "1.81.0")]
#[inline]
pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
// Number of buffers to remove.
@@ -1531,7 +1527,7 @@ fn deref(&self) -> &[u8] {
#[doc(notable_trait)]
#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")]
pub trait Write {
- /// Write a buffer into this writer, returning how many bytes were written.
+ /// Writes a buffer into this writer, returning how many bytes were written.
///
/// This function will attempt to write the entire contents of `buf`, but
/// the entire write might not succeed, or the write may also generate an
@@ -1630,7 +1626,7 @@ fn is_write_vectored(&self) -> bool {
false
}
- /// Flush this output stream, ensuring that all intermediately buffered
+ /// Flushes this output stream, ensuring that all intermediately buffered
/// contents reach their destination.
///
/// # Errors
@@ -2247,7 +2243,7 @@ pub trait BufRead: Read {
#[stable(feature = "rust1", since = "1.0.0")]
fn consume(&mut self, amt: usize);
- /// Check if the underlying `Read` has any data left to be read.
+ /// Checks if the underlying `Read` has any data left to be read.
///
/// This function may fill the buffer to check for data,
/// so this functions returns `Result<bool>`, not `bool`.
@@ -2278,7 +2274,7 @@ fn has_data_left(&mut self) -> Result<bool> {
self.fill_buf().map(|b| !b.is_empty())
}
- /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
+ /// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
///
/// This function will read bytes from the underlying stream until the
/// delimiter or EOF is found. Once found, all bytes up to, and including,
@@ -2337,7 +2333,7 @@ fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
read_until(self, byte, buf)
}
- /// Skip all bytes until the delimiter `byte` or EOF is reached.
+ /// Skips all bytes until the delimiter `byte` or EOF is reached.
///
/// This function will read (and discard) bytes from the underlying stream until the
/// delimiter or EOF is found.
@@ -2399,7 +2395,7 @@ fn skip_until(&mut self, byte: u8) -> Result<usize> {
skip_until(self, byte)
}
- /// Read all bytes until a newline (the `0xA` byte) is reached, and append
+ /// Reads all bytes until a newline (the `0xA` byte) is reached, and append
/// them to the provided `String` buffer.
///
/// Previous content of the buffer will be preserved. To avoid appending to
@@ -3038,7 +3034,7 @@ impl<R> SpecReadByte for R
}
}
-/// Read a single byte in a slow, generic way. This is used by the default
+/// Reads a single byte in a slow, generic way. This is used by the default
/// `spec_read_byte`.
#[inline]
fn inlined_slow_read_byte<R: Read>(reader: &mut R) -> Option<Result<u8>> {
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 9aee2bb..6de069a 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -3,11 +3,10 @@
#[cfg(test)]
mod tests;
-use crate::io::prelude::*;
-
use crate::cell::{Cell, RefCell};
use crate::fmt;
use crate::fs::File;
+use crate::io::prelude::*;
use crate::io::{
self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
};
@@ -1092,7 +1091,7 @@ pub fn try_set_output_capture(
OUTPUT_CAPTURE.try_with(move |slot| slot.replace(sink))
}
-/// Write `args` to the capture buffer if enabled and possible, or `global_s`
+/// Writes `args` to the capture buffer if enabled and possible, or `global_s`
/// otherwise. `label` identifies the stream in a panic message.
///
/// This function is used to print error messages, so it takes extra
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index a2c1c43..bb6a53b 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -1,7 +1,8 @@
use super::{repeat, BorrowedBuf, Cursor, SeekFrom};
use crate::cmp::{self, min};
-use crate::io::{self, IoSlice, IoSliceMut, DEFAULT_BUF_SIZE};
-use crate::io::{BufRead, BufReader, Read, Seek, Write};
+use crate::io::{
+ self, BufRead, BufReader, IoSlice, IoSliceMut, Read, Seek, Write, DEFAULT_BUF_SIZE,
+};
use crate::mem::MaybeUninit;
use crate::ops::Deref;
@@ -530,7 +531,7 @@ fn io_slice_advance_slices_beyond_total_length() {
assert!(bufs.is_empty());
}
-/// Create a new writer that reads from at most `n_bufs` and reads
+/// Creates a new writer that reads from at most `n_bufs` and reads
/// `per_call` bytes (in total) per call to write.
fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
TestWriter { n_bufs, per_call, written: Vec::new() }
@@ -675,13 +676,13 @@ fn cursor_read_exact_eof() {
let mut r = slice.clone();
assert!(r.read_exact(&mut [0; 10]).is_err());
- assert!(r.is_empty());
+ assert!(Cursor::split(&r).1.is_empty());
let mut r = slice;
let buf = &mut [0; 10];
let mut buf = BorrowedBuf::from(buf.as_mut_slice());
assert!(r.read_buf_exact(buf.unfilled()).is_err());
- assert!(r.is_empty());
+ assert!(Cursor::split(&r).1.is_empty());
assert_eq!(buf.filled(), b"123456");
}
diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs
index 6de91e2..1dff3f3 100644
--- a/library/std/src/io/util/tests.rs
+++ b/library/std/src/io/util/tests.rs
@@ -1,6 +1,5 @@
use crate::io::prelude::*;
use crate::io::{empty, repeat, sink, BorrowedBuf, Empty, Repeat, SeekFrom, Sink};
-
use crate::mem::MaybeUninit;
#[test]
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 8415f36..9f4d244 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -155,7 +155,7 @@ mod break_keyword {}
/// const WORDS: &str = "hello convenience!";
/// ```
///
-/// `const` items looks remarkably similar to `static` items, which introduces some confusion as
+/// `const` items look remarkably similar to `static` items, which introduces some confusion as
/// to which one should be used at which times. To put it simply, constants are inlined wherever
/// they're used, making using them identical to simply replacing the name of the `const` with its
/// value. Static variables, on the other hand, point to a single location in memory, which all
@@ -1175,7 +1175,7 @@ mod ref_keyword {}
#[doc(keyword = "return")]
//
-/// Return a value from a function.
+/// Returns a value from a function.
///
/// A `return` marks the end of an execution path in a function:
///
@@ -2310,7 +2310,7 @@ mod where_keyword {}
#[doc(alias = "promise")]
#[doc(keyword = "async")]
//
-/// Return a [`Future`] instead of blocking the current thread.
+/// Returns a [`Future`] instead of blocking the current thread.
///
/// Use `async` in front of `fn`, `closure`, or a `block` to turn the marked code into a `Future`.
/// As such the code will not be run immediately, but will only be evaluated when the returned
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 9fba657..93a74ef 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -254,6 +254,7 @@
#![deny(fuzzy_provenance_casts)]
#![deny(unsafe_op_in_unsafe_fn)]
#![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
// Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
#![deny(ffi_unwind_calls)]
// std may use features in a platform-specific way
@@ -268,14 +269,10 @@
#![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))]
#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))]
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
-#![cfg_attr(
- all(any(target_arch = "x86_64", target_arch = "x86"), target_os = "uefi"),
- feature(stdarch_x86_has_cpuid)
-)]
//
// Language features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(c_unwind))]
+#![cfg_attr(bootstrap, feature(min_exhaustive_patterns))]
#![feature(alloc_error_handler)]
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
@@ -302,7 +299,7 @@
#![feature(let_chains)]
#![feature(link_cfg)]
#![feature(linkage)]
-#![feature(min_exhaustive_patterns)]
+#![feature(macro_metavar_expr_concat)]
#![feature(min_specialization)]
#![feature(must_not_suspend)]
#![feature(needs_panic_runtime)]
@@ -342,6 +339,7 @@
#![feature(maybe_uninit_write_slice)]
#![feature(panic_can_unwind)]
#![feature(panic_internals)]
+#![feature(pin_coerce_unsized_trait)]
#![feature(pointer_is_aligned_to)]
#![feature(portable_simd)]
#![feature(prelude_2024)]
@@ -407,7 +405,6 @@
#![feature(const_ip)]
#![feature(const_ipv4)]
#![feature(const_ipv6)]
-#![feature(const_waker)]
#![feature(thread_local_internals)]
// tidy-alphabetical-end
//
@@ -472,24 +469,6 @@
pub mod prelude;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::borrow;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::boxed;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::fmt;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::format;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::rc;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::slice;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::str;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::string;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::vec;
-#[stable(feature = "rust1", since = "1.0.0")]
pub use core::any;
#[stable(feature = "core_array", since = "1.36.0")]
pub use core::array;
@@ -566,6 +545,25 @@
#[allow(deprecated, deprecated_in_future)]
pub use core::usize;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::borrow;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::boxed;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::fmt;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::format;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::rc;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::slice;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::str;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::string;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::vec;
+
#[unstable(feature = "f128", issue = "116909")]
pub mod f128;
#[unstable(feature = "f16", issue = "116909")]
@@ -588,7 +586,7 @@
pub mod num;
pub mod os;
pub mod panic;
-#[unstable(feature = "core_pattern_types", issue = "none")]
+#[unstable(feature = "core_pattern_types", issue = "123646")]
pub mod pat;
pub mod path;
#[unstable(feature = "anonymous_pipe", issue = "127154")]
@@ -610,9 +608,10 @@ pub mod simd {
#![doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")]
#[doc(inline)]
- pub use crate::std_float::StdFloat;
- #[doc(inline)]
pub use core::simd::*;
+
+ #[doc(inline)]
+ pub use crate::std_float::StdFloat;
}
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -620,12 +619,11 @@ pub mod task {
//! Types and Traits for working with asynchronous tasks.
#[doc(inline)]
- #[stable(feature = "futures_api", since = "1.36.0")]
- pub use core::task::*;
-
- #[doc(inline)]
#[stable(feature = "wake_trait", since = "1.51.0")]
pub use alloc::task::*;
+ #[doc(inline)]
+ #[stable(feature = "futures_api", since = "1.36.0")]
+ pub use core::task::*;
}
#[doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")]
@@ -670,14 +668,16 @@ pub mod arch {
#[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)]
mod backtrace_rs;
-// Re-export macros defined in core.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated, deprecated_in_future)]
-pub use core::{
- assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, todo, r#try,
- unimplemented, unreachable, write, writeln,
-};
-
+#[unstable(feature = "cfg_match", issue = "115585")]
+pub use core::cfg_match;
+#[unstable(
+ feature = "concat_bytes",
+ issue = "87555",
+ reason = "`concat_bytes` is not stable enough for use and is subject to change"
+)]
+pub use core::concat_bytes;
+#[stable(feature = "core_primitive", since = "1.43.0")]
+pub use core::primitive;
// Re-export built-in macros defined through core.
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow(deprecated)]
@@ -686,19 +686,13 @@ pub mod arch {
env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax,
module_path, option_env, stringify, trace_macros,
};
-
-#[unstable(
- feature = "concat_bytes",
- issue = "87555",
- reason = "`concat_bytes` is not stable enough for use and is subject to change"
-)]
-pub use core::concat_bytes;
-
-#[unstable(feature = "cfg_match", issue = "115585")]
-pub use core::cfg_match;
-
-#[stable(feature = "core_primitive", since = "1.43.0")]
-pub use core::primitive;
+// Re-export macros defined in core.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated, deprecated_in_future)]
+pub use core::{
+ assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, matches, todo, r#try,
+ unimplemented, unreachable, write, writeln,
+};
// Include a number of private modules that exist solely to provide
// the rustdoc documentation for primitive types. Using `include!`
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index ba519af..1b0d7f3 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -382,7 +382,7 @@ macro_rules! assert_approx_eq {
let diff = (*a - *b).abs();
assert!(
diff < $lim,
- "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, actual {diff:?})",
+ "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})",
lim = $lim
);
}};
diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs
index e167fbd..8a9426b6 100644
--- a/library/std/src/net/ip_addr.rs
+++ b/library/std/src/net/ip_addr.rs
@@ -2,17 +2,15 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use crate::sys::net::netc as c;
-use crate::sys_common::{FromInner, IntoInner};
-
#[stable(feature = "ip_addr", since = "1.7.0")]
pub use core::net::IpAddr;
-
+#[unstable(feature = "ip", issue = "27709")]
+pub use core::net::Ipv6MulticastScope;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::net::{Ipv4Addr, Ipv6Addr};
-#[unstable(feature = "ip", issue = "27709")]
-pub use core::net::Ipv6MulticastScope;
+use crate::sys::net::netc as c;
+use crate::sys_common::{FromInner, IntoInner};
impl IntoInner<c::in_addr> for Ipv4Addr {
#[inline]
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index 858776f..3b19c74 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -21,7 +21,8 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::io::{self, ErrorKind};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::net::AddrParseError;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
@@ -33,8 +34,7 @@
pub use self::tcp::{Incoming, TcpListener, TcpStream};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::udp::UdpSocket;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::net::AddrParseError;
+use crate::io::{self, ErrorKind};
mod ip_addr;
mod socket_addr;
diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs
index 421fed9..84922aa 100644
--- a/library/std/src/net/socket_addr.rs
+++ b/library/std/src/net/socket_addr.rs
@@ -2,19 +2,14 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use crate::io;
-use crate::iter;
-use crate::mem;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
+
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-use crate::option;
-use crate::slice;
use crate::sys::net::netc as c;
use crate::sys_common::net::LookupHost;
use crate::sys_common::{FromInner, IntoInner};
-use crate::vec;
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::{io, iter, mem, option, slice, vec};
impl FromInner<c::sockaddr_in> for SocketAddrV4 {
fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 {
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 6336354..22d2dfe 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -3,14 +3,12 @@
#[cfg(all(test, not(any(target_os = "emscripten", target_os = "xous"))))]
mod tests;
-use crate::io::prelude::*;
-
use crate::fmt;
+use crate::io::prelude::*;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::iter::FusedIterator;
use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
-use crate::sys_common::net as net_imp;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{net as net_imp, AsInner, FromInner, IntoInner};
use crate::time::Duration;
/// A TCP stream between a local and a remote socket.
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index 3ad0467..d26517d 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -1,12 +1,11 @@
-use crate::fmt;
use crate::io::prelude::*;
use crate::io::{BorrowedBuf, IoSlice, IoSliceMut};
use crate::mem::MaybeUninit;
use crate::net::test::{next_test_ip4, next_test_ip6};
use crate::net::*;
use crate::sync::mpsc::channel;
-use crate::thread;
use crate::time::{Duration, Instant};
+use crate::{fmt, thread};
fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
f(next_test_ip4());
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 60347a1..32e9086 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -4,8 +4,7 @@
use crate::fmt;
use crate::io::{self, ErrorKind};
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
-use crate::sys_common::net as net_imp;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{net as net_imp, AsInner, FromInner, IntoInner};
use crate::time::Duration;
/// A UDP socket.
diff --git a/library/std/src/num.rs b/library/std/src/num.rs
index 8910cde..c1e6e7e 100644
--- a/library/std/src/num.rs
+++ b/library/std/src/num.rs
@@ -9,32 +9,27 @@
#[cfg(test)]
mod tests;
+#[stable(feature = "int_error_matching", since = "1.55.0")]
+pub use core::num::IntErrorKind;
+#[stable(feature = "generic_nonzero", since = "1.79.0")]
+pub use core::num::NonZero;
#[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub use core::num::Saturating;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::Wrapping;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};
-
#[unstable(
feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time",
issue = "none"
)]
pub use core::num::ZeroablePrimitive;
-
-#[stable(feature = "generic_nonzero", since = "1.79.0")]
-pub use core::num::NonZero;
-
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};
#[stable(feature = "signed_nonzero", since = "1.34.0")]
pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
-
#[stable(feature = "nonzero", since = "1.28.0")]
pub use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
-#[stable(feature = "int_error_matching", since = "1.55.0")]
-pub use core::num::IntErrorKind;
-
#[cfg(test)]
use crate::fmt;
#[cfg(test)]
diff --git a/library/std/src/os/aix/raw.rs b/library/std/src/os/aix/raw.rs
index b4c8dc7..13f61fc 100644
--- a/library/std/src/os/aix/raw.rs
+++ b/library/std/src/os/aix/raw.rs
@@ -4,6 +4,5 @@
#[stable(feature = "pthread_t", since = "1.8.0")]
pub use libc::pthread_t;
-
#[stable(feature = "raw_ext", since = "1.1.0")]
pub use libc::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t, stat, time_t};
diff --git a/library/std/src/os/android/fs.rs b/library/std/src/os/android/fs.rs
index 1beb3cf..6b931e38 100644
--- a/library/std/src/os/android/fs.rs
+++ b/library/std/src/os/android/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::android::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs
index 349e73e..960a304 100644
--- a/library/std/src/os/android/net.rs
+++ b/library/std/src/os/android/net.rs
@@ -4,9 +4,7 @@
#[stable(feature = "unix_socket_abstract", since = "1.70.0")]
pub use crate::os::net::linux_ext::addr::SocketAddrExt;
-
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub use crate::os::net::linux_ext::socket::UnixSocketExt;
-
#[unstable(feature = "tcp_quickack", issue = "96256")]
pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/darwin/fs.rs b/library/std/src/os/darwin/fs.rs
index 2032cca..2d154b2 100644
--- a/library/std/src/os/darwin/fs.rs
+++ b/library/std/src/os/darwin/fs.rs
@@ -1,13 +1,12 @@
#![allow(dead_code)]
+#[allow(deprecated)]
+use super::raw;
use crate::fs::{self, Metadata};
use crate::sealed::Sealed;
use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
use crate::time::SystemTime;
-#[allow(deprecated)]
-use super::raw;
-
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: crate::fs::Metadata
diff --git a/library/std/src/os/dragonfly/fs.rs b/library/std/src/os/dragonfly/fs.rs
index 1424fc4..0cd543b 100644
--- a/library/std/src/os/dragonfly/fs.rs
+++ b/library/std/src/os/dragonfly/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::dragonfly::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/emscripten/fs.rs b/library/std/src/os/emscripten/fs.rs
index d5ec8e0..3282b79 100644
--- a/library/std/src/os/emscripten/fs.rs
+++ b/library/std/src/os/emscripten/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::emscripten::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/espidf/fs.rs b/library/std/src/os/espidf/fs.rs
index 88701da..ffff584 100644
--- a/library/std/src/os/espidf/fs.rs
+++ b/library/std/src/os/espidf/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::espidf::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index bbd5093..2d087c0 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -4,14 +4,12 @@
#![deny(unsafe_op_in_unsafe_fn)]
use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
-use crate::fmt;
-use crate::fs;
-use crate::io;
use crate::marker::PhantomData;
use crate::mem::ManuallyDrop;
#[cfg(not(any(target_arch = "wasm32", target_env = "sgx", target_os = "hermit")))]
use crate::sys::cvt;
use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::{fmt, fs, io};
/// A borrowed file descriptor.
///
@@ -70,7 +68,7 @@ pub struct OwnedFd {
}
impl BorrowedFd<'_> {
- /// Return a `BorrowedFd` holding the given raw file descriptor.
+ /// Returns a `BorrowedFd` holding the given raw file descriptor.
///
/// # Safety
///
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index ef896ea..0d99d54 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -2,8 +2,9 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::fs;
-use crate::io;
+#[cfg(target_os = "hermit")]
+use hermit_abi as libc;
+
#[cfg(target_os = "hermit")]
use crate::os::hermit::io::OwnedFd;
#[cfg(not(target_os = "hermit"))]
@@ -15,8 +16,7 @@
#[cfg(target_os = "wasi")]
use crate::os::wasi::io::OwnedFd;
use crate::sys_common::{AsInner, IntoInner};
-#[cfg(target_os = "hermit")]
-use hermit_abi as libc;
+use crate::{fs, io};
/// Raw file descriptors.
#[rustc_allowed_through_unstable_modules]
@@ -138,6 +138,7 @@ pub trait IntoRawFd {
/// let raw_fd: RawFd = f.into_raw_fd();
/// # Ok::<(), io::Error>(())
/// ```
+ #[must_use = "losing the raw file descriptor may leak resources"]
#[stable(feature = "into_raw_os", since = "1.4.0")]
fn into_raw_fd(self) -> RawFd;
}
diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs
index 8358cb9..4c8048e 100644
--- a/library/std/src/os/fortanix_sgx/arch.rs
+++ b/library/std/src/os/fortanix_sgx/arch.rs
@@ -4,9 +4,10 @@
//! Software Developer's Manual, Volume 3, Chapter 40.
#![unstable(feature = "sgx_platform", issue = "56975")]
-use crate::mem::MaybeUninit;
use core::arch::asm;
+use crate::mem::MaybeUninit;
+
/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]
#[unstable(feature = "sgx_platform", issue = "56975")]
diff --git a/library/std/src/os/fortanix_sgx/mod.rs b/library/std/src/os/fortanix_sgx/mod.rs
index b31dc06..64f4d97 100644
--- a/library/std/src/os/fortanix_sgx/mod.rs
+++ b/library/std/src/os/fortanix_sgx/mod.rs
@@ -22,20 +22,12 @@ pub mod alloc {
/// Lowest-level interfaces to usercalls and usercall ABI type definitions.
pub mod raw {
pub use crate::sys::abi::usercalls::raw::{
- accept_stream, alloc, async_queues, bind_stream, close, connect_stream, exit, flush,
- free, insecure_time, launch_thread, read, read_alloc, send, wait, write,
- };
- pub use crate::sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs};
- pub use crate::sys::abi::usercalls::raw::{Register, RegisterArgument, ReturnValue};
-
- pub use crate::sys::abi::usercalls::raw::Error;
- pub use crate::sys::abi::usercalls::raw::{
- ByteBuffer, Cancel, FifoDescriptor, Return, Usercall,
- };
- pub use crate::sys::abi::usercalls::raw::{Fd, Result, Tcs};
- pub use crate::sys::abi::usercalls::raw::{
- EV_RETURNQ_NOT_EMPTY, EV_UNPARK, EV_USERCALLQ_NOT_FULL, FD_STDERR, FD_STDIN, FD_STDOUT,
- RESULT_SUCCESS, USERCALL_USER_DEFINED, WAIT_INDEFINITE, WAIT_NO,
+ accept_stream, alloc, async_queues, bind_stream, close, connect_stream, do_usercall,
+ exit, flush, free, insecure_time, launch_thread, read, read_alloc, send, wait, write,
+ ByteBuffer, Cancel, Error, Fd, FifoDescriptor, Register, RegisterArgument, Result,
+ Return, ReturnValue, Tcs, Usercall, Usercalls as UsercallNrs, EV_RETURNQ_NOT_EMPTY,
+ EV_UNPARK, EV_USERCALLQ_NOT_FULL, FD_STDERR, FD_STDIN, FD_STDOUT, RESULT_SUCCESS,
+ USERCALL_USER_DEFINED, WAIT_INDEFINITE, WAIT_NO,
};
}
}
diff --git a/library/std/src/os/freebsd/fs.rs b/library/std/src/os/freebsd/fs.rs
index 5689a82..34384a4 100644
--- a/library/std/src/os/freebsd/fs.rs
+++ b/library/std/src/os/freebsd/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::freebsd::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs
index b7e0fdc..fcfc5c1 100644
--- a/library/std/src/os/freebsd/net.rs
+++ b/library/std/src/os/freebsd/net.rs
@@ -42,7 +42,7 @@ pub trait UnixSocketExt: Sealed {
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>;
- /// Get a filter name if one had been set previously on the socket.
+ /// Gets a filter name if one had been set previously on the socket.
#[unstable(feature = "acceptfilter", issue = "121891")]
fn acceptfilter(&self) -> io::Result<&CStr>;
diff --git a/library/std/src/os/haiku/fs.rs b/library/std/src/os/haiku/fs.rs
index a23a2af..23f6493 100644
--- a/library/std/src/os/haiku/fs.rs
+++ b/library/std/src/os/haiku/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::haiku::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/hermit/io/net.rs b/library/std/src/os/hermit/io/net.rs
index 8f3802d..7a77434 100644
--- a/library/std/src/os/hermit/io/net.rs
+++ b/library/std/src/os/hermit/io/net.rs
@@ -1,5 +1,4 @@
-use crate::os::hermit::io::OwnedFd;
-use crate::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
use crate::{net, sys};
diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs
index 02a4b2c..5812206 100644
--- a/library/std/src/os/hermit/mod.rs
+++ b/library/std/src/os/hermit/mod.rs
@@ -1,4 +1,5 @@
#![stable(feature = "rust1", since = "1.0.0")]
+#![deny(unsafe_op_in_unsafe_fn)]
#[allow(unused_extern_crates)]
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/os/illumos/fs.rs b/library/std/src/os/illumos/fs.rs
index 63be48b..75dbe16 100644
--- a/library/std/src/os/illumos/fs.rs
+++ b/library/std/src/os/illumos/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::illumos::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/ios/mod.rs b/library/std/src/os/ios/mod.rs
index 5e130d7..52d592e 100644
--- a/library/std/src/os/ios/mod.rs
+++ b/library/std/src/os/ios/mod.rs
@@ -7,7 +7,6 @@ pub mod fs {
#[doc(inline)]
#[stable(feature = "file_set_times", since = "1.75.0")]
pub use crate::os::darwin::fs::FileTimesExt;
-
#[doc(inline)]
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub use crate::os::darwin::fs::MetadataExt;
diff --git a/library/std/src/os/l4re/fs.rs b/library/std/src/os/l4re/fs.rs
index 6d6a535..0511ddc 100644
--- a/library/std/src/os/l4re/fs.rs
+++ b/library/std/src/os/l4re/fs.rs
@@ -5,10 +5,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::l4re::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/linux/fs.rs b/library/std/src/os/linux/fs.rs
index ab0b2a3..20a7a16 100644
--- a/library/std/src/os/linux/fs.rs
+++ b/library/std/src/os/linux/fs.rs
@@ -5,10 +5,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::linux::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs
index f898e70..1de120c 100644
--- a/library/std/src/os/linux/net.rs
+++ b/library/std/src/os/linux/net.rs
@@ -4,9 +4,7 @@
#[stable(feature = "unix_socket_abstract", since = "1.70.0")]
pub use crate::os::net::linux_ext::addr::SocketAddrExt;
-
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub use crate::os::net::linux_ext::socket::UnixSocketExt;
-
#[unstable(feature = "tcp_quickack", issue = "96256")]
pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/macos/mod.rs b/library/std/src/os/macos/mod.rs
index 3638406..59fe908 100644
--- a/library/std/src/os/macos/mod.rs
+++ b/library/std/src/os/macos/mod.rs
@@ -7,7 +7,6 @@ pub mod fs {
#[doc(inline)]
#[stable(feature = "file_set_times", since = "1.75.0")]
pub use crate::os::darwin::fs::FileTimesExt;
-
#[doc(inline)]
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub use crate::os::darwin::fs::MetadataExt;
diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs
index ff29afe..c8d0129 100644
--- a/library/std/src/os/net/linux_ext/tcp.rs
+++ b/library/std/src/os/net/linux_ext/tcp.rs
@@ -2,10 +2,9 @@
//!
//! [`std::net`]: crate::net
-use crate::io;
-use crate::net;
use crate::sealed::Sealed;
use crate::sys_common::AsInner;
+use crate::{io, net};
/// Os-specific extensions for [`TcpStream`]
///
diff --git a/library/std/src/os/net/linux_ext/tests.rs b/library/std/src/os/net/linux_ext/tests.rs
index f8dbbfc..12f3569 100644
--- a/library/std/src/os/net/linux_ext/tests.rs
+++ b/library/std/src/os/net/linux_ext/tests.rs
@@ -1,9 +1,8 @@
#[test]
fn quickack() {
- use crate::{
- net::{test::next_test_ip4, TcpListener, TcpStream},
- os::net::linux_ext::tcp::TcpStreamExt,
- };
+ use crate::net::test::next_test_ip4;
+ use crate::net::{TcpListener, TcpStream};
+ use crate::os::net::linux_ext::tcp::TcpStreamExt;
macro_rules! t {
($e:expr) => {
@@ -30,10 +29,9 @@ macro_rules! t {
#[test]
#[cfg(target_os = "linux")]
fn deferaccept() {
- use crate::{
- net::{test::next_test_ip4, TcpListener, TcpStream},
- os::net::linux_ext::tcp::TcpStreamExt,
- };
+ use crate::net::test::next_test_ip4;
+ use crate::net::{TcpListener, TcpStream};
+ use crate::os::net::linux_ext::tcp::TcpStreamExt;
macro_rules! t {
($e:expr) => {
diff --git a/library/std/src/os/netbsd/fs.rs b/library/std/src/os/netbsd/fs.rs
index fe0be06..74fbbab 100644
--- a/library/std/src/os/netbsd/fs.rs
+++ b/library/std/src/os/netbsd/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::netbsd::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs
index b9679c7..e1950d3 100644
--- a/library/std/src/os/netbsd/net.rs
+++ b/library/std/src/os/netbsd/net.rs
@@ -42,7 +42,7 @@ pub trait UnixSocketExt: Sealed {
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
fn set_local_creds(&self, local_creds: bool) -> io::Result<()>;
- /// Get a filter name if one had been set previously on the socket.
+ /// Gets a filter name if one had been set previously on the socket.
#[unstable(feature = "acceptfilter", issue = "121891")]
fn acceptfilter(&self) -> io::Result<&CStr>;
diff --git a/library/std/src/os/openbsd/fs.rs b/library/std/src/os/openbsd/fs.rs
index b8d8d31..e584098 100644
--- a/library/std/src/os/openbsd/fs.rs
+++ b/library/std/src/os/openbsd/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::openbsd::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/redox/fs.rs b/library/std/src/os/redox/fs.rs
index 682ca6a..c6b813f 100644
--- a/library/std/src/os/redox/fs.rs
+++ b/library/std/src/os/redox/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::redox::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/solaris/fs.rs b/library/std/src/os/solaris/fs.rs
index 0931437..9b0527d 100644
--- a/library/std/src/os/solaris/fs.rs
+++ b/library/std/src/os/solaris/fs.rs
@@ -1,10 +1,9 @@
#![stable(feature = "metadata_ext", since = "1.1.0")]
use crate::fs::Metadata;
-use crate::sys_common::AsInner;
-
#[allow(deprecated)]
use crate::os::solaris::raw;
+use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs
index bbf7e96..2d18f33 100644
--- a/library/std/src/os/solid/io.rs
+++ b/library/std/src/os/solid/io.rs
@@ -46,12 +46,10 @@
#![unstable(feature = "solid_ext", issue = "none")]
-use crate::fmt;
use crate::marker::PhantomData;
use crate::mem::ManuallyDrop;
-use crate::net;
-use crate::sys;
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::{fmt, net, sys};
/// Raw file descriptors.
pub type RawFd = i32;
@@ -98,7 +96,7 @@ pub struct OwnedFd {
}
impl BorrowedFd<'_> {
- /// Return a `BorrowedFd` holding the given raw file descriptor.
+ /// Returns a `BorrowedFd` holding the given raw file descriptor.
///
/// # Safety
///
@@ -344,6 +342,7 @@ pub trait IntoRawFd {
/// This function **transfers ownership** of the underlying file descriptor
/// to the caller. Callers are then the unique owners of the file descriptor
/// and must close the descriptor once it's no longer needed.
+ #[must_use = "losing the raw file descriptor may leak resources"]
fn into_raw_fd(self) -> RawFd;
}
diff --git a/library/std/src/os/uefi/env.rs b/library/std/src/os/uefi/env.rs
index 5d082e7..cf8ae69 100644
--- a/library/std/src/os/uefi/env.rs
+++ b/library/std/src/os/uefi/env.rs
@@ -2,8 +2,9 @@
#![unstable(feature = "uefi_std", issue = "100499")]
+use crate::ffi::c_void;
+use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
-use crate::{ffi::c_void, ptr::NonNull};
static SYSTEM_TABLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
static IMAGE_HANDLE: AtomicPtr<c_void> = AtomicPtr::new(crate::ptr::null_mut());
@@ -26,7 +27,7 @@
/// standard library is loaded.
///
/// # SAFETY
-/// Calling this function more than once will panic
+/// Calling this function more than once will panic.
pub(crate) unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull<c_void>) {
IMAGE_HANDLE
.compare_exchange(
@@ -47,23 +48,25 @@ pub(crate) unsafe fn init_globals(handle: NonNull<c_void>, system_table: NonNull
BOOT_SERVICES_FLAG.store(true, Ordering::Release)
}
-/// Get the SystemTable Pointer.
+/// Gets the SystemTable Pointer.
+///
/// If you want to use `BootServices` then please use [`boot_services`] as it performs some
/// additional checks.
///
-/// Note: This function panics if the System Table or Image Handle is not initialized
+/// Note: This function panics if the System Table or Image Handle is not initialized.
pub fn system_table() -> NonNull<c_void> {
try_system_table().unwrap()
}
-/// Get the ImageHandle Pointer.
+/// Gets the ImageHandle Pointer.
///
-/// Note: This function panics if the System Table or Image Handle is not initialized
+/// Note: This function panics if the System Table or Image Handle is not initialized.
pub fn image_handle() -> NonNull<c_void> {
try_image_handle().unwrap()
}
-/// Get the BootServices Pointer.
+/// Gets the BootServices Pointer.
+///
/// This function also checks if `ExitBootServices` has already been called.
pub fn boot_services() -> Option<NonNull<c_void>> {
if BOOT_SERVICES_FLAG.load(Ordering::Acquire) {
@@ -75,14 +78,16 @@ pub fn boot_services() -> Option<NonNull<c_void>> {
}
}
-/// Get the SystemTable Pointer.
-/// This function is mostly intended for places where panic is not an option
+/// Gets the SystemTable Pointer.
+///
+/// This function is mostly intended for places where panic is not an option.
pub(crate) fn try_system_table() -> Option<NonNull<c_void>> {
NonNull::new(SYSTEM_TABLE.load(Ordering::Acquire))
}
-/// Get the SystemHandle Pointer.
-/// This function is mostly intended for places where panicking is not an option
+/// Gets the SystemHandle Pointer.
+///
+/// This function is mostly intended for places where panicking is not an option.
pub(crate) fn try_image_handle() -> Option<NonNull<c_void>> {
NonNull::new(IMAGE_HANDLE.load(Ordering::Acquire))
}
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 20c4720..caf6980 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -4,19 +4,19 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use super::platform::fs::MetadataExt as _;
-use crate::fs::{self, OpenOptions, Permissions};
-use crate::io;
-use crate::os::unix::io::{AsFd, AsRawFd};
-use crate::path::Path;
-use crate::sys;
-use crate::sys_common::{AsInner, AsInnerMut, FromInner};
-// Used for `File::read` on intra-doc links
-use crate::ffi::OsStr;
-use crate::sealed::Sealed;
#[allow(unused_imports)]
use io::{Read, Write};
+use super::platform::fs::MetadataExt as _;
+// Used for `File::read` on intra-doc links
+use crate::ffi::OsStr;
+use crate::fs::{self, OpenOptions, Permissions};
+use crate::os::unix::io::{AsFd, AsRawFd};
+use crate::path::Path;
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, FromInner};
+use crate::{io, sys};
+
// Tests for this module
#[cfg(test)]
mod tests;
diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs
index fe8e2be..9b487a6 100644
--- a/library/std/src/os/unix/net/ancillary.rs
+++ b/library/std/src/os/unix/net/ancillary.rs
@@ -164,7 +164,7 @@ struct AncillaryDataIter<'a, T> {
}
impl<'a, T> AncillaryDataIter<'a, T> {
- /// Create `AncillaryDataIter` struct to iterate through the data unit in the control message.
+ /// Creates `AncillaryDataIter` struct to iterate through the data unit in the control message.
///
/// # Safety
///
@@ -220,7 +220,7 @@ fn next(&mut self) -> Option<T> {
#[doc(cfg(any(target_os = "android", target_os = "linux")))]
#[cfg(any(target_os = "android", target_os = "linux"))]
impl SocketCred {
- /// Create a Unix credential struct.
+ /// Creates a Unix credential struct.
///
/// PID, UID and GID is set to 0.
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -235,7 +235,7 @@ pub fn set_pid(&mut self, pid: libc::pid_t) {
self.0.pid = pid;
}
- /// Get the current PID.
+ /// Gets the current PID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_pid(&self) -> libc::pid_t {
@@ -248,7 +248,7 @@ pub fn set_uid(&mut self, uid: libc::uid_t) {
self.0.uid = uid;
}
- /// Get the current UID.
+ /// Gets the current UID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_uid(&self) -> libc::uid_t {
@@ -261,7 +261,7 @@ pub fn set_gid(&mut self, gid: libc::gid_t) {
self.0.gid = gid;
}
- /// Get the current GID.
+ /// Gets the current GID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_gid(&self) -> libc::gid_t {
@@ -271,7 +271,7 @@ pub fn get_gid(&self) -> libc::gid_t {
#[cfg(target_os = "freebsd")]
impl SocketCred {
- /// Create a Unix credential struct.
+ /// Creates a Unix credential struct.
///
/// PID, UID and GID is set to 0.
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -295,7 +295,7 @@ pub fn set_pid(&mut self, pid: libc::pid_t) {
self.0.sc_pid = pid;
}
- /// Get the current PID.
+ /// Gets the current PID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_pid(&self) -> libc::pid_t {
@@ -308,7 +308,7 @@ pub fn set_uid(&mut self, uid: libc::uid_t) {
self.0.sc_euid = uid;
}
- /// Get the current UID.
+ /// Gets the current UID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_uid(&self) -> libc::uid_t {
@@ -321,7 +321,7 @@ pub fn set_gid(&mut self, gid: libc::gid_t) {
self.0.sc_egid = gid;
}
- /// Get the current GID.
+ /// Gets the current GID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_gid(&self) -> libc::gid_t {
@@ -331,7 +331,7 @@ pub fn get_gid(&self) -> libc::gid_t {
#[cfg(target_os = "netbsd")]
impl SocketCred {
- /// Create a Unix credential struct.
+ /// Creates a Unix credential struct.
///
/// PID, UID and GID is set to 0.
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -353,7 +353,7 @@ pub fn set_pid(&mut self, pid: libc::pid_t) {
self.0.sc_pid = pid;
}
- /// Get the current PID.
+ /// Gets the current PID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_pid(&self) -> libc::pid_t {
@@ -366,7 +366,7 @@ pub fn set_uid(&mut self, uid: libc::uid_t) {
self.0.sc_uid = uid;
}
- /// Get the current UID.
+ /// Gets the current UID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_uid(&self) -> libc::uid_t {
@@ -379,7 +379,7 @@ pub fn set_gid(&mut self, gid: libc::gid_t) {
self.0.sc_gid = gid;
}
- /// Get the current GID.
+ /// Gets the current GID.
#[must_use]
#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
pub fn get_gid(&self) -> libc::gid_t {
@@ -466,7 +466,7 @@ pub enum AncillaryData<'a> {
}
impl<'a> AncillaryData<'a> {
- /// Create an `AncillaryData::ScmRights` variant.
+ /// Creates an `AncillaryData::ScmRights` variant.
///
/// # Safety
///
@@ -478,7 +478,7 @@ unsafe fn as_rights(data: &'a [u8]) -> Self {
AncillaryData::ScmRights(scm_rights)
}
- /// Create an `AncillaryData::ScmCredentials` variant.
+ /// Creates an `AncillaryData::ScmCredentials` variant.
///
/// # Safety
///
@@ -605,7 +605,7 @@ pub struct SocketAncillary<'a> {
}
impl<'a> SocketAncillary<'a> {
- /// Create an ancillary data with the given buffer.
+ /// Creates an ancillary data with the given buffer.
///
/// # Example
///
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index f58f9b4..a605c3d 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -1,3 +1,17 @@
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "netbsd",
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "haiku",
+ target_os = "nto",
+))]
+use libc::MSG_NOSIGNAL;
+
#[cfg(any(doc, target_os = "android", target_os = "linux"))]
use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
use super::{sockaddr_un, SocketAddr};
@@ -12,20 +26,6 @@
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
use crate::{fmt, io};
-
-#[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "openbsd",
- target_os = "netbsd",
- target_os = "solaris",
- target_os = "illumos",
- target_os = "haiku",
- target_os = "nto",
-))]
-use libc::MSG_NOSIGNAL;
#[cfg(not(any(
target_os = "linux",
target_os = "android",
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index e456e41..21e2176 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -1,18 +1,16 @@
use super::*;
use crate::io::prelude::*;
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
+#[cfg(target_os = "android")]
+use crate::os::android::net::{SocketAddrExt, UnixSocketExt};
+#[cfg(target_os = "linux")]
+use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
#[cfg(any(target_os = "android", target_os = "linux"))]
use crate::os::unix::io::AsRawFd;
use crate::sys_common::io::test::tmpdir;
use crate::thread;
use crate::time::Duration;
-#[cfg(target_os = "android")]
-use crate::os::android::net::{SocketAddrExt, UnixSocketExt};
-
-#[cfg(target_os = "linux")]
-use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
-
macro_rules! or_panic {
($e:expr) => {
match $e {
diff --git a/library/std/src/os/unix/net/ucred.rs b/library/std/src/os/unix/net/ucred.rs
index 1497e73..b96e373 100644
--- a/library/std/src/os/unix/net/ucred.rs
+++ b/library/std/src/os/unix/net/ucred.rs
@@ -23,9 +23,8 @@ pub struct UCred {
pub pid: Option<pid_t>,
}
-#[cfg(any(target_os = "android", target_os = "linux"))]
-pub(super) use self::impl_linux::peer_cred;
-
+#[cfg(target_vendor = "apple")]
+pub(super) use self::impl_apple::peer_cred;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
@@ -34,17 +33,17 @@ pub struct UCred {
target_os = "nto"
))]
pub(super) use self::impl_bsd::peer_cred;
-
-#[cfg(target_vendor = "apple")]
-pub(super) use self::impl_apple::peer_cred;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub(super) use self::impl_linux::peer_cred;
#[cfg(any(target_os = "linux", target_os = "android"))]
mod impl_linux {
+ use libc::{c_void, getsockopt, socklen_t, ucred, SOL_SOCKET, SO_PEERCRED};
+
use super::UCred;
use crate::os::unix::io::AsRawFd;
use crate::os::unix::net::UnixStream;
use crate::{io, mem};
- use libc::{c_void, getsockopt, socklen_t, ucred, SOL_SOCKET, SO_PEERCRED};
pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
let ucred_size = mem::size_of::<ucred>();
@@ -99,11 +98,12 @@ pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
#[cfg(target_vendor = "apple")]
mod impl_apple {
+ use libc::{c_void, getpeereid, getsockopt, pid_t, socklen_t, LOCAL_PEERPID, SOL_LOCAL};
+
use super::UCred;
use crate::os::unix::io::AsRawFd;
use crate::os::unix::net::UnixStream;
use crate::{io, mem};
- use libc::{c_void, getpeereid, getsockopt, pid_t, socklen_t, LOCAL_PEERPID, SOL_LOCAL};
pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
let mut cred = UCred { uid: 1, gid: 1, pid: None };
diff --git a/library/std/src/os/unix/net/ucred/tests.rs b/library/std/src/os/unix/net/ucred/tests.rs
index a6cc813..59414f4 100644
--- a/library/std/src/os/unix/net/ucred/tests.rs
+++ b/library/std/src/os/unix/net/ucred/tests.rs
@@ -1,6 +1,7 @@
-use crate::os::unix::net::UnixStream;
use libc::{getegid, geteuid, getpid};
+use crate::os::unix::net::UnixStream;
+
#[test]
#[cfg(any(
target_os = "android",
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 72ea54b..c534236 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -4,16 +4,14 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::ffi::OsStr;
-use crate::io;
-use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
-use crate::process;
-use crate::sealed::Sealed;
-use crate::sys;
-use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
-
use cfg_if::cfg_if;
+use crate::ffi::OsStr;
+use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
+use crate::{io, process, sys};
+
cfg_if! {
if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon", target_os = "vita"))] {
type UserId = u16;
@@ -444,7 +442,7 @@ fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
}
}
-/// Create a `ChildStdin` from the provided `OwnedFd`.
+/// Creates a `ChildStdin` from the provided `OwnedFd`.
///
/// The provided file descriptor must point to a pipe
/// with the `CLOEXEC` flag set.
@@ -475,7 +473,7 @@ fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
}
}
-/// Create a `ChildStdout` from the provided `OwnedFd`.
+/// Creates a `ChildStdout` from the provided `OwnedFd`.
///
/// The provided file descriptor must point to a pipe
/// with the `CLOEXEC` flag set.
@@ -506,7 +504,7 @@ fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
}
}
-/// Create a `ChildStderr` from the provided `OwnedFd`.
+/// Creates a `ChildStderr` from the provided `OwnedFd`.
///
/// The provided file descriptor must point to a pipe
/// with the `CLOEXEC` flag set.
diff --git a/library/std/src/os/vita/mod.rs b/library/std/src/os/vita/mod.rs
index da9edd1..92a2bf0 100644
--- a/library/std/src/os/vita/mod.rs
+++ b/library/std/src/os/vita/mod.rs
@@ -1,5 +1,6 @@
//! Definitions for vita
+#![forbid(unsafe_op_in_unsafe_fn)]
#![stable(feature = "raw_ext", since = "1.1.0")]
pub mod fs;
diff --git a/library/std/src/os/vita/raw.rs b/library/std/src/os/vita/raw.rs
index 74cae4d..e4b65ef 100644
--- a/library/std/src/os/vita/raw.rs
+++ b/library/std/src/os/vita/raw.rs
@@ -10,9 +10,6 @@
)]
#![allow(deprecated)]
-use crate::os::raw::c_long;
-use crate::os::unix::raw::{gid_t, uid_t};
-
#[stable(feature = "pthread_t", since = "1.8.0")]
pub type pthread_t = libc::pthread_t;
@@ -34,37 +31,3 @@
#[stable(feature = "raw_ext", since = "1.1.0")]
pub type time_t = libc::time_t;
-
-#[repr(C)]
-#[derive(Clone)]
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub struct stat {
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_dev: dev_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_ino: ino_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_mode: mode_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_nlink: nlink_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_uid: uid_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_gid: gid_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_rdev: dev_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_size: off_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_atime: time_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_mtime: time_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_ctime: time_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_blksize: blksize_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_blocks: blkcnt_t,
- #[stable(feature = "raw_ext", since = "1.1.0")]
- pub st_spare4: [c_long; 2usize],
-}
diff --git a/library/std/src/os/vxworks/mod.rs b/library/std/src/os/vxworks/mod.rs
index 0a7ac64..b09aa72 100644
--- a/library/std/src/os/vxworks/mod.rs
+++ b/library/std/src/os/vxworks/mod.rs
@@ -1,6 +1,7 @@
//! VxWorks-specific definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
+#![forbid(unsafe_op_in_unsafe_fn)]
pub mod fs;
pub mod raw;
diff --git a/library/std/src/os/wasi/fs.rs b/library/std/src/os/wasi/fs.rs
index 46fc2a5..a58ca54 100644
--- a/library/std/src/os/wasi/fs.rs
+++ b/library/std/src/os/wasi/fs.rs
@@ -5,14 +5,15 @@
#![deny(unsafe_op_in_unsafe_fn)]
#![unstable(feature = "wasi_ext", issue = "71213")]
+// Used for `File::read` on intra-doc links
+#[allow(unused_imports)]
+use io::{Read, Write};
+
use crate::ffi::OsStr;
use crate::fs::{self, File, Metadata, OpenOptions};
use crate::io::{self, IoSlice, IoSliceMut};
use crate::path::{Path, PathBuf};
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
-// Used for `File::read` on intra-doc links
-#[allow(unused_imports)]
-use io::{Read, Write};
/// WASI-specific extensions to [`File`].
pub trait FileExt {
@@ -169,55 +170,55 @@ fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
#[doc(alias = "fd_tell")]
fn tell(&self) -> io::Result<u64>;
- /// Adjust the flags associated with this file.
+ /// Adjusts the flags associated with this file.
///
/// This corresponds to the `fd_fdstat_set_flags` syscall.
#[doc(alias = "fd_fdstat_set_flags")]
fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
- /// Adjust the rights associated with this file.
+ /// Adjusts the rights associated with this file.
///
/// This corresponds to the `fd_fdstat_set_rights` syscall.
#[doc(alias = "fd_fdstat_set_rights")]
fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
- /// Provide file advisory information on a file descriptor.
+ /// Provides file advisory information on a file descriptor.
///
/// This corresponds to the `fd_advise` syscall.
#[doc(alias = "fd_advise")]
fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
- /// Force the allocation of space in a file.
+ /// Forces the allocation of space in a file.
///
/// This corresponds to the `fd_allocate` syscall.
#[doc(alias = "fd_allocate")]
fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
- /// Create a directory.
+ /// Creates a directory.
///
/// This corresponds to the `path_create_directory` syscall.
#[doc(alias = "path_create_directory")]
fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()>;
- /// Read the contents of a symbolic link.
+ /// Reads the contents of a symbolic link.
///
/// This corresponds to the `path_readlink` syscall.
#[doc(alias = "path_readlink")]
fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>;
- /// Return the attributes of a file or directory.
+ /// Returns the attributes of a file or directory.
///
/// This corresponds to the `path_filestat_get` syscall.
#[doc(alias = "path_filestat_get")]
fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata>;
- /// Unlink a file.
+ /// Unlinks a file.
///
/// This corresponds to the `path_unlink_file` syscall.
#[doc(alias = "path_unlink_file")]
fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
- /// Remove a directory.
+ /// Removes a directory.
///
/// This corresponds to the `path_remove_directory` syscall.
#[doc(alias = "path_remove_directory")]
@@ -501,7 +502,7 @@ fn ino(&self) -> u64 {
}
}
-/// Create a hard link.
+/// Creates a hard link.
///
/// This corresponds to the `path_link` syscall.
#[doc(alias = "path_link")]
@@ -520,7 +521,7 @@ pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
)
}
-/// Rename a file or directory.
+/// Renames a file or directory.
///
/// This corresponds to the `path_rename` syscall.
#[doc(alias = "path_rename")]
@@ -537,7 +538,7 @@ pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
)
}
-/// Create a symbolic link.
+/// Creates a symbolic link.
///
/// This corresponds to the `path_symlink` syscall.
#[doc(alias = "path_symlink")]
@@ -551,7 +552,7 @@ pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
.symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?)
}
-/// Create a symbolic link.
+/// Creates a symbolic link.
///
/// This is a convenience API similar to `std::os::unix::fs::symlink` and
/// `std::os::windows::fs::symlink_file` and `std::os::windows::fs::symlink_dir`.
diff --git a/library/std/src/os/wasi/net/mod.rs b/library/std/src/os/wasi/net/mod.rs
index 73c097d..4704dd5 100644
--- a/library/std/src/os/wasi/net/mod.rs
+++ b/library/std/src/os/wasi/net/mod.rs
@@ -2,9 +2,8 @@
#![unstable(feature = "wasi_ext", issue = "71213")]
-use crate::io;
-use crate::net;
use crate::sys_common::AsInner;
+use crate::{io, net};
/// WASI-specific extensions to [`std::net::TcpListener`].
///
diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs
index 96bab59..496443d 100644
--- a/library/std/src/os/windows/ffi.rs
+++ b/library/std/src/os/windows/ffi.rs
@@ -56,11 +56,10 @@
use crate::ffi::{OsStr, OsString};
use crate::sealed::Sealed;
use crate::sys::os_str::Buf;
-use crate::sys_common::wtf8::Wtf8Buf;
-use crate::sys_common::{AsInner, FromInner};
-
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::sys_common::wtf8::EncodeWide;
+use crate::sys_common::wtf8::Wtf8Buf;
+use crate::sys_common::{AsInner, FromInner};
/// Windows-specific extensions to [`OsString`].
///
diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs
index 7cac8c3..3dcde43 100644
--- a/library/std/src/os/windows/fs.rs
+++ b/library/std/src/os/windows/fs.rs
@@ -5,12 +5,11 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::fs::{self, Metadata, OpenOptions};
-use crate::io;
use crate::path::Path;
use crate::sealed::Sealed;
-use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
use crate::time::SystemTime;
+use crate::{io, sys};
/// Windows-specific extensions to [`fs::File`].
#[stable(feature = "file_offset", since = "1.15.0")]
@@ -631,7 +630,7 @@ pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::
sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
}
-/// Create a junction point.
+/// Creates a junction point.
///
/// The `link` path will be a directory junction pointing to the original path.
/// If `link` is a relative path then it will be made absolute prior to creating the junction point.
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 9865386..a4fa94e 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -3,15 +3,11 @@
#![stable(feature = "io_safety", since = "1.63.0")]
use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
-use crate::fmt;
-use crate::fs;
-use crate::io;
use crate::marker::PhantomData;
use crate::mem::ManuallyDrop;
-use crate::ptr;
-use crate::sys;
use crate::sys::cvt;
use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::{fmt, fs, io, ptr, sys};
/// A borrowed handle.
///
@@ -135,7 +131,7 @@ unsafe impl Sync for HandleOrInvalid {}
unsafe impl Sync for BorrowedHandle<'_> {}
impl BorrowedHandle<'_> {
- /// Return a `BorrowedHandle` holding the given raw handle.
+ /// Returns a `BorrowedHandle` holding the given raw handle.
///
/// # Safety
///
diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs
index 343cc6e..6658248 100644
--- a/library/std/src/os/windows/io/raw.rs
+++ b/library/std/src/os/windows/io/raw.rs
@@ -2,16 +2,12 @@
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::fs;
-use crate::io;
-use crate::net;
#[cfg(doc)]
use crate::os::windows::io::{AsHandle, AsSocket};
use crate::os::windows::io::{OwnedHandle, OwnedSocket};
use crate::os::windows::raw;
-use crate::ptr;
-use crate::sys;
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::{fs, io, net, ptr, sys};
/// Raw HANDLEs.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -44,7 +40,7 @@ pub trait AsRawHandle {
fn as_raw_handle(&self) -> RawHandle;
}
-/// Construct I/O objects from raw handles.
+/// Constructs I/O objects from raw handles.
#[stable(feature = "from_raw_os", since = "1.1.0")]
pub trait FromRawHandle {
/// Constructs a new I/O object from the specified raw handle.
@@ -89,6 +85,7 @@ pub trait IntoRawHandle {
/// However, transferring ownership is not strictly required. Use a
/// `Into<OwnedHandle>::into` implementation for an API which strictly
/// transfers ownership.
+ #[must_use = "losing the raw handle may leak resources"]
#[stable(feature = "into_raw_os", since = "1.4.0")]
fn into_raw_handle(self) -> RawHandle;
}
@@ -232,6 +229,7 @@ pub trait IntoRawSocket {
/// However, transferring ownership is not strictly required. Use a
/// `Into<OwnedSocket>::into` implementation for an API which strictly
/// transfers ownership.
+ #[must_use = "losing the raw socket may leak resources"]
#[stable(feature = "into_raw_os", since = "1.4.0")]
fn into_raw_socket(self) -> RawSocket;
}
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index df5b56d..1fcfb6e 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -3,13 +3,11 @@
#![stable(feature = "io_safety", since = "1.63.0")]
use super::raw::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::mem::{self, ManuallyDrop};
-use crate::sys;
#[cfg(not(target_vendor = "uwp"))]
use crate::sys::cvt;
+use crate::{fmt, io, sys};
/// A borrowed socket.
///
@@ -63,7 +61,7 @@ pub struct OwnedSocket {
}
impl BorrowedSocket<'_> {
- /// Return a `BorrowedSocket` holding the given raw socket.
+ /// Returns a `BorrowedSocket` holding the given raw socket.
///
/// # Safety
///
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 3927b2e..c2830d2 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -8,10 +8,9 @@
use crate::os::windows::io::{
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
};
-use crate::process;
use crate::sealed::Sealed;
-use crate::sys;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
+use crate::{process, sys};
#[stable(feature = "process_extensions", since = "1.2.0")]
impl FromRawHandle for process::Stdio {
@@ -109,7 +108,7 @@ fn into_raw_handle(self) -> RawHandle {
}
}
-/// Create a `ChildStdin` from the provided `OwnedHandle`.
+/// Creates a `ChildStdin` from the provided `OwnedHandle`.
///
/// The provided handle must be asynchronous, as reading and
/// writing from and to it is implemented using asynchronous APIs.
@@ -122,7 +121,7 @@ fn from(handle: OwnedHandle) -> process::ChildStdin {
}
}
-/// Create a `ChildStdout` from the provided `OwnedHandle`.
+/// Creates a `ChildStdout` from the provided `OwnedHandle`.
///
/// The provided handle must be asynchronous, as reading and
/// writing from and to it is implemented using asynchronous APIs.
@@ -135,7 +134,7 @@ fn from(handle: OwnedHandle) -> process::ChildStdout {
}
}
-/// Create a `ChildStderr` from the provided `OwnedHandle`.
+/// Creates a `ChildStderr` from the provided `OwnedHandle`.
///
/// The provided handle must be asynchronous, as reading and
/// writing from and to it is implemented using asynchronous APIs.
diff --git a/library/std/src/os/xous/ffi.rs b/library/std/src/os/xous/ffi.rs
index e9a9f53..1a4a940 100644
--- a/library/std/src/os/xous/ffi.rs
+++ b/library/std/src/os/xous/ffi.rs
@@ -274,7 +274,7 @@ fn connect_impl(address: ServerAddress, blocking: bool) -> Result<Connection, Er
}
}
-/// Connect to a Xous server represented by the specified `address`.
+/// Connects to a Xous server represented by the specified `address`.
///
/// The current thread will block until the server is available. Returns
/// an error if the server cannot accept any more connections.
@@ -282,7 +282,7 @@ pub(crate) fn connect(address: ServerAddress) -> Result<Connection, Error> {
connect_impl(address, true)
}
-/// Attempt to connect to a Xous server represented by the specified `address`.
+/// Attempts to connect to a Xous server represented by the specified `address`.
///
/// If the server does not exist then None is returned.
pub(crate) fn try_connect(address: ServerAddress) -> Result<Option<Connection>, Error> {
@@ -293,7 +293,7 @@ pub(crate) fn try_connect(address: ServerAddress) -> Result<Option<Connection>,
}
}
-/// Terminate the current process and return the specified code to the parent process.
+/// Terminates the current process and returns the specified code to the parent process.
pub(crate) fn exit(return_code: u32) -> ! {
let a0 = Syscall::TerminateProcess as usize;
let a1 = return_code as usize;
@@ -320,7 +320,7 @@ pub(crate) fn exit(return_code: u32) -> ! {
unreachable!();
}
-/// Suspend the current thread and allow another thread to run. This thread may
+/// Suspends the current thread and allow another thread to run. This thread may
/// continue executing again immediately if there are no other threads available
/// to run on the system.
pub(crate) fn do_yield() {
@@ -348,9 +348,11 @@ pub(crate) fn do_yield() {
};
}
-/// Allocate memory from the system. An optional physical and/or virtual address
-/// may be specified in order to ensure memory is allocated at specific offsets,
-/// otherwise the kernel will select an address.
+/// Allocates memory from the system.
+///
+/// An optional physical and/or virtual address may be specified in order to
+/// ensure memory is allocated at specific offsets, otherwise the kernel will
+/// select an address.
///
/// # Safety
///
@@ -400,7 +402,7 @@ pub(crate) unsafe fn map_memory<T>(
}
}
-/// Destroy the given memory, returning it to the compiler.
+/// Destroys the given memory, returning it to the compiler.
///
/// Safety: The memory pointed to by `range` should not be used after this
/// function returns, even if this function returns Err().
@@ -439,9 +441,10 @@ pub(crate) unsafe fn unmap_memory<T>(range: *mut [T]) -> Result<(), Error> {
}
}
-/// Adjust the memory flags for the given range. This can be used to remove flags
-/// from a given region in order to harden memory access. Note that flags may
-/// only be removed and may never be added.
+/// Adjusts the memory flags for the given range.
+///
+/// This can be used to remove flags from a given region in order to harden
+/// memory access. Note that flags may only be removed and may never be added.
///
/// Safety: The memory pointed to by `range` may become inaccessible or have its
/// mutability removed. It is up to the caller to ensure that the flags specified
@@ -484,7 +487,7 @@ pub(crate) unsafe fn update_memory_flags<T>(
}
}
-/// Create a thread with a given stack and up to four arguments
+/// Creates a thread with a given stack and up to four arguments.
pub(crate) fn create_thread(
start: *mut usize,
stack: *mut [u8],
@@ -527,7 +530,7 @@ pub(crate) fn create_thread(
}
}
-/// Wait for the given thread to terminate and return the exit code from that thread.
+/// Waits for the given thread to terminate and returns the exit code from that thread.
pub(crate) fn join_thread(thread_id: ThreadId) -> Result<usize, Error> {
let mut a0 = Syscall::JoinThread as usize;
let mut a1 = thread_id.into();
@@ -567,7 +570,7 @@ pub(crate) fn join_thread(thread_id: ThreadId) -> Result<usize, Error> {
}
}
-/// Get the current thread's ID
+/// Gets the current thread's ID.
pub(crate) fn thread_id() -> Result<ThreadId, Error> {
let mut a0 = Syscall::GetThreadId as usize;
let mut a1 = 0;
@@ -603,7 +606,7 @@ pub(crate) fn thread_id() -> Result<ThreadId, Error> {
}
}
-/// Adjust the given `knob` limit to match the new value `new`. The current value must
+/// Adjusts the given `knob` limit to match the new value `new`. The current value must
/// match the `current` in order for this to take effect.
///
/// The new value is returned as a result of this call. If the call fails, then the old
diff --git a/library/std/src/os/xous/services.rs b/library/std/src/os/xous/services.rs
index a75be1b..ddf0236 100644
--- a/library/std/src/os/xous/services.rs
+++ b/library/std/src/os/xous/services.rs
@@ -1,6 +1,7 @@
-use crate::os::xous::ffi::Connection;
use core::sync::atomic::{AtomicU32, Ordering};
+use crate::os::xous::ffi::Connection;
+
mod dns;
pub(crate) use dns::*;
@@ -83,7 +84,7 @@ pub fn try_connect_with_name(name: &str) -> Option<Connection> {
}
}
-/// Attempt to connect to a server by name. If the server does not exist, this will
+/// Attempts to connect to a server by name. If the server does not exist, this will
/// block until the server is created.
///
/// Note that this is different from connecting to a server by address. Server
@@ -94,7 +95,7 @@ pub fn connect(name: &str) -> Option<Connection> {
ns::connect_with_name(name)
}
-/// Attempt to connect to a server by name. If the server does not exist, this will
+/// Attempts to connect to a server by name. If the server does not exist, this will
/// immediately return `None`.
///
/// Note that this is different from connecting to a server by address. Server
@@ -107,7 +108,7 @@ pub fn try_connect(name: &str) -> Option<Connection> {
static NAME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
-/// Return a `Connection` to the name server. If the name server has not been started,
+/// Returns a `Connection` to the name server. If the name server has not been started,
/// then this call will block until the name server has been started. The `Connection`
/// will be shared among all connections in a process, so it is safe to call this
/// multiple times.
diff --git a/library/std/src/os/xous/services/dns.rs b/library/std/src/os/xous/services/dns.rs
index a7d88f4..0288164 100644
--- a/library/std/src/os/xous/services/dns.rs
+++ b/library/std/src/os/xous/services/dns.rs
@@ -1,6 +1,7 @@
+use core::sync::atomic::{AtomicU32, Ordering};
+
use crate::os::xous::ffi::Connection;
use crate::os::xous::services::connect;
-use core::sync::atomic::{AtomicU32, Ordering};
#[repr(usize)]
pub(crate) enum DnsLendMut {
@@ -13,7 +14,7 @@ fn into(self) -> usize {
}
}
-/// Return a `Connection` to the DNS lookup server. This server is used for
+/// Returns a `Connection` to the DNS lookup server. This server is used for
/// querying domain name values.
pub(crate) fn dns_server() -> Connection {
static DNS_CONNECTION: AtomicU32 = AtomicU32::new(0);
diff --git a/library/std/src/os/xous/services/log.rs b/library/std/src/os/xous/services/log.rs
index 55a501d..1661011 100644
--- a/library/std/src/os/xous/services/log.rs
+++ b/library/std/src/os/xous/services/log.rs
@@ -1,10 +1,11 @@
-use crate::os::xous::ffi::Connection;
use core::sync::atomic::{AtomicU32, Ordering};
-/// Group `usize` bytes into a `usize` and return it, beginning
-/// from `offset` * sizeof(usize) bytes from the start. For example,
-/// `group_or_null([1,2,3,4,5,6,7,8], 1)` on a 32-bit system will
-/// return a usize with 5678 packed into it.
+use crate::os::xous::ffi::Connection;
+
+/// Group a `usize` worth of bytes into a `usize` and return it, beginning from
+/// `offset` * sizeof(usize) bytes from the start. For example,
+/// `group_or_null([1,2,3,4,5,6,7,8], 1)` on a 32-bit system will return a
+/// `usize` with 5678 packed into it.
fn group_or_null(data: &[u8], offset: usize) -> usize {
let start = offset * core::mem::size_of::<usize>();
let mut out_array = [0u8; core::mem::size_of::<usize>()];
@@ -56,10 +57,12 @@ fn into(self) -> usize {
}
}
-/// Return a `Connection` to the log server, which is used for printing messages to
-/// the console and reporting panics. If the log server has not yet started, this
-/// will block until the server is running. It is safe to call this multiple times,
-/// because the address is shared among all threads in a process.
+/// Returns a `Connection` to the log server, which is used for printing messages to
+/// the console and reporting panics.
+///
+/// If the log server has not yet started, this will block until the server is
+/// running. It is safe to call this multiple times, because the address is
+/// shared among all threads in a process.
pub(crate) fn log_server() -> Connection {
static LOG_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
diff --git a/library/std/src/os/xous/services/net.rs b/library/std/src/os/xous/services/net.rs
index 26d337d..83acc79 100644
--- a/library/std/src/os/xous/services/net.rs
+++ b/library/std/src/os/xous/services/net.rs
@@ -1,6 +1,7 @@
+use core::sync::atomic::{AtomicU32, Ordering};
+
use crate::os::xous::ffi::Connection;
use crate::os::xous::services::connect;
-use core::sync::atomic::{AtomicU32, Ordering};
pub(crate) enum NetBlockingScalar {
StdGetTtlUdp(u16 /* fd */), /* 36 */
@@ -80,7 +81,7 @@ fn into(self) -> usize {
}
}
-/// Return a `Connection` to the Network server. This server provides all
+/// Returns a `Connection` to the Network server. This server provides all
/// OS-level networking functions.
pub(crate) fn net_server() -> Connection {
static NET_CONNECTION: AtomicU32 = AtomicU32::new(0);
diff --git a/library/std/src/os/xous/services/systime.rs b/library/std/src/os/xous/services/systime.rs
index bbb875c..079ede7 100644
--- a/library/std/src/os/xous/services/systime.rs
+++ b/library/std/src/os/xous/services/systime.rs
@@ -1,6 +1,7 @@
-use crate::os::xous::ffi::{connect, Connection};
use core::sync::atomic::{AtomicU32, Ordering};
+use crate::os::xous::ffi::{connect, Connection};
+
pub(crate) enum SystimeScalar {
GetUtcTimeMs,
}
@@ -13,7 +14,7 @@ pub(crate) enum SystimeScalar {
}
}
-/// Return a `Connection` to the systime server. This server is used for reporting the
+/// Returns a `Connection` to the systime server. This server is used for reporting the
/// realtime clock.
pub(crate) fn systime_server() -> Connection {
static SYSTIME_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
diff --git a/library/std/src/os/xous/services/ticktimer.rs b/library/std/src/os/xous/services/ticktimer.rs
index 7759303..66ade6d 100644
--- a/library/std/src/os/xous/services/ticktimer.rs
+++ b/library/std/src/os/xous/services/ticktimer.rs
@@ -1,6 +1,7 @@
-use crate::os::xous::ffi::Connection;
use core::sync::atomic::{AtomicU32, Ordering};
+use crate::os::xous::ffi::Connection;
+
pub(crate) enum TicktimerScalar {
ElapsedMs,
SleepMs(usize),
@@ -27,7 +28,7 @@ pub(crate) enum TicktimerScalar {
}
}
-/// Return a `Connection` to the ticktimer server. This server is used for synchronization
+/// Returns a `Connection` to the ticktimer server. This server is used for synchronization
/// primitives such as sleep, Mutex, and Condvar.
pub(crate) fn ticktimer_server() -> Connection {
static TICKTIMER_SERVER_CONNECTION: AtomicU32 = AtomicU32::new(0);
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index c5d1a89..6f0952c 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -3,12 +3,10 @@
#![stable(feature = "std_panic", since = "1.9.0")]
use crate::any::Any;
-use crate::collections;
-use crate::fmt;
-use crate::panicking;
use crate::sync::atomic::{AtomicU8, Ordering};
use crate::sync::{Condvar, Mutex, RwLock};
use crate::thread::Result;
+use crate::{collections, fmt, panicking};
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[deprecated(
@@ -39,7 +37,7 @@
/// ```
///
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
-#[stable(feature = "panic_hook_info", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_hook_info", since = "1.81.0")]
#[derive(Debug)]
pub struct PanicHookInfo<'a> {
payload: &'a (dyn Any + Send),
@@ -236,20 +234,17 @@ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
pub use core::panic::panic_2021;
-
-#[stable(feature = "panic_hooks", since = "1.10.0")]
-pub use crate::panicking::{set_hook, take_hook};
-
-#[unstable(feature = "panic_update_hook", issue = "92649")]
-pub use crate::panicking::update_hook;
-
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use core::panic::Location;
-
#[stable(feature = "catch_unwind", since = "1.9.0")]
pub use core::panic::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
-/// Panic the current thread with the given message as the panic payload.
+#[unstable(feature = "panic_update_hook", issue = "92649")]
+pub use crate::panicking::update_hook;
+#[stable(feature = "panic_hooks", since = "1.10.0")]
+pub use crate::panicking::{set_hook, take_hook};
+
+/// Panics the current thread with the given message as the panic payload.
///
/// The message can be of any (`Any + Send`) type, not just strings.
///
@@ -380,7 +375,7 @@ pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
panicking::rust_panic_without_hook(payload)
}
-/// Make all future panics abort directly without running the panic hook or unwinding.
+/// Makes all future panics abort directly without running the panic hook or unwinding.
///
/// There is no way to undo this; the effect lasts until the process exits or
/// execs (or the equivalent).
@@ -445,13 +440,12 @@ fn as_u8(self) -> u8 {
}
fn from_u8(s: u8) -> Option<Self> {
- Some(match s {
- 0 => return None,
- 1 => BacktraceStyle::Short,
- 2 => BacktraceStyle::Full,
- 3 => BacktraceStyle::Off,
- _ => unreachable!(),
- })
+ match s {
+ 1 => Some(BacktraceStyle::Short),
+ 2 => Some(BacktraceStyle::Full),
+ 3 => Some(BacktraceStyle::Off),
+ _ => None,
+ }
}
}
@@ -461,18 +455,17 @@ fn from_u8(s: u8) -> Option<Self> {
// Internally stores equivalent of an Option<BacktraceStyle>.
static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0);
-/// Configure whether the default panic hook will capture and display a
+/// Configures whether the default panic hook will capture and display a
/// backtrace.
///
/// The default value for this setting may be set by the `RUST_BACKTRACE`
/// environment variable; see the details in [`get_backtrace_style`].
#[unstable(feature = "panic_backtrace_config", issue = "93346")]
pub fn set_backtrace_style(style: BacktraceStyle) {
- if !cfg!(feature = "backtrace") {
- // If the `backtrace` feature of this crate isn't enabled, skip setting.
- return;
+ if cfg!(feature = "backtrace") {
+ // If the `backtrace` feature of this crate is enabled, set the backtrace style.
+ SHOULD_CAPTURE.store(style.as_u8(), Ordering::Relaxed);
}
- SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release);
}
/// Checks whether the standard library's panic hook will capture and print a
@@ -504,27 +497,24 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> {
// to optimize away callers.
return None;
}
- if let Some(style) = BacktraceStyle::from_u8(SHOULD_CAPTURE.load(Ordering::Acquire)) {
+
+ let current = SHOULD_CAPTURE.load(Ordering::Relaxed);
+ if let Some(style) = BacktraceStyle::from_u8(current) {
return Some(style);
}
- let format = crate::env::var_os("RUST_BACKTRACE")
- .map(|x| {
- if &x == "0" {
- BacktraceStyle::Off
- } else if &x == "full" {
- BacktraceStyle::Full
- } else {
- BacktraceStyle::Short
- }
- })
- .unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT {
- BacktraceStyle::Full
- } else {
- BacktraceStyle::Off
- });
- set_backtrace_style(format);
- Some(format)
+ let format = match crate::env::var_os("RUST_BACKTRACE") {
+ Some(x) if &x == "0" => BacktraceStyle::Off,
+ Some(x) if &x == "full" => BacktraceStyle::Full,
+ Some(_) => BacktraceStyle::Short,
+ None if crate::sys::FULL_BACKTRACE_DEFAULT => BacktraceStyle::Full,
+ None => BacktraceStyle::Off,
+ };
+
+ match SHOULD_CAPTURE.compare_exchange(0, format.as_u8(), Ordering::Relaxed, Ordering::Relaxed) {
+ Ok(_) => Some(format),
+ Err(new) => BacktraceStyle::from_u8(new),
+ }
}
#[cfg(test)]
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 418a855..e818b44 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -9,27 +9,24 @@
#![deny(unsafe_op_in_unsafe_fn)]
-use crate::panic::{BacktraceStyle, PanicHookInfo};
use core::panic::{Location, PanicPayload};
-use crate::any::Any;
-use crate::fmt;
-use crate::intrinsics;
-use crate::mem::{self, ManuallyDrop};
-use crate::process;
-use crate::sync::atomic::{AtomicBool, Ordering};
-use crate::sync::{PoisonError, RwLock};
-use crate::sys::backtrace;
-use crate::sys::stdio::panic_output;
-use crate::thread;
-
-#[cfg(not(test))]
-use crate::io::try_set_output_capture;
// make sure to use the stderr output configured
// by libtest in the real copy of std
#[cfg(test)]
use realstd::io::try_set_output_capture;
+use crate::any::Any;
+#[cfg(not(test))]
+use crate::io::try_set_output_capture;
+use crate::mem::{self, ManuallyDrop};
+use crate::panic::{BacktraceStyle, PanicHookInfo};
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::{PoisonError, RwLock};
+use crate::sys::backtrace;
+use crate::sys::stdio::panic_output;
+use crate::{fmt, intrinsics, process, thread};
+
// Binary interface to the panic runtime that the standard library depends on.
//
// The standard library is tagged with `#![needs_panic_runtime]` (introduced in
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 0cef862..8016366 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -71,22 +71,17 @@
mod tests;
use crate::borrow::{Borrow, Cow};
-use crate::cmp;
use crate::collections::TryReserveError;
use crate::error::Error;
-use crate::fmt;
-use crate::fs;
+use crate::ffi::{os_str, OsStr, OsString};
use crate::hash::{Hash, Hasher};
-use crate::io;
use crate::iter::FusedIterator;
use crate::ops::{self, Deref};
use crate::rc::Rc;
use crate::str::FromStr;
use crate::sync::Arc;
-
-use crate::ffi::{os_str, OsStr, OsString};
-use crate::sys;
use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR};
+use crate::{cmp, fmt, fs, io, sys};
////////////////////////////////////////////////////////////////////////////////
// GENERAL NOTES
@@ -1797,7 +1792,7 @@ fn from(s: &T) -> PathBuf {
#[stable(feature = "rust1", since = "1.0.0")]
impl From<OsString> for PathBuf {
- /// Converts an [`OsString`] into a [`PathBuf`]
+ /// Converts an [`OsString`] into a [`PathBuf`].
///
/// This conversion does not allocate or copy memory.
#[inline]
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index 3ade4fb..a12e42c 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -1,8 +1,8 @@
-use super::*;
+use core::hint::black_box;
+use super::*;
use crate::collections::{BTreeSet, HashSet};
use crate::hash::DefaultHasher;
-use core::hint::black_box;
#[allow(unknown_lints, unused_macro_rules)]
macro_rules! t (
diff --git a/library/std/src/pipe.rs b/library/std/src/pipe.rs
index f251b57..aa4c701 100644
--- a/library/std/src/pipe.rs
+++ b/library/std/src/pipe.rs
@@ -11,10 +11,8 @@
//! # }
//! ```
-use crate::{
- io,
- sys::anonymous_pipe::{pipe as pipe_inner, AnonPipe},
-};
+use crate::io;
+use crate::sys::anonymous_pipe::{pipe as pipe_inner, AnonPipe};
/// Create anonymous pipe that is close-on-exec and blocking.
#[unstable(feature = "anonymous_pipe", issue = "127154")]
diff --git a/library/std/src/sys/anonymous_pipe/tests.rs b/library/std/src/pipe/tests.rs
similarity index 78%
rename from library/std/src/sys/anonymous_pipe/tests.rs
rename to library/std/src/pipe/tests.rs
index f5ea583..9c38e10 100644
--- a/library/std/src/sys/anonymous_pipe/tests.rs
+++ b/library/std/src/pipe/tests.rs
@@ -1,9 +1,8 @@
-use crate::{
- io::{Read, Write},
- pipe::pipe,
-};
+use crate::io::{Read, Write};
+use crate::pipe::pipe;
#[test]
+#[cfg(all(windows, unix, not(miri)))]
fn pipe_creation_clone_and_rw() {
let (rx, tx) = pipe().unwrap();
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index fc86578..9ffdebe 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -151,21 +151,18 @@
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
mod tests;
-use crate::io::prelude::*;
-
use crate::convert::Infallible;
use crate::ffi::OsStr;
-use crate::fmt;
-use crate::fs;
+use crate::io::prelude::*;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::num::NonZero;
use crate::path::Path;
-use crate::str;
use crate::sys::pipe::{read2, AnonPipe};
use crate::sys::process as imp;
#[stable(feature = "command_access", since = "1.57.0")]
pub use crate::sys_common::process::CommandEnvs;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
+use crate::{fmt, fs, str};
/// Representation of a running or exited child process.
///
@@ -2056,7 +2053,7 @@ impl ExitCode {
// representation of an ExitCode
//
// More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426
- /// Convert an `ExitCode` into an i32
+ /// Converts an `ExitCode` into an i32
#[unstable(
feature = "process_exitcode_internals",
reason = "exposed only for libstd",
@@ -2079,7 +2076,7 @@ fn default() -> Self {
#[stable(feature = "process_exitcode", since = "1.61.0")]
impl From<u8> for ExitCode {
- /// Construct an `ExitCode` from an arbitrary u8 value.
+ /// Constructs an `ExitCode` from an arbitrary u8 value.
fn from(code: u8) -> Self {
ExitCode(imp::ExitCode::from(code))
}
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 055601d..f8e8e0d 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -1,6 +1,5 @@
-use crate::io::prelude::*;
-
use super::{Command, Output, Stdio};
+use crate::io::prelude::*;
use crate::io::{BorrowedBuf, ErrorKind};
use crate::mem::MaybeUninit;
use crate::str;
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 18906ac..953aef4 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -1,3 +1,4 @@
+use super::once::ExclusiveState;
use crate::cell::UnsafeCell;
use crate::mem::ManuallyDrop;
use crate::ops::Deref;
@@ -5,8 +6,6 @@
use crate::sync::Once;
use crate::{fmt, ptr};
-use super::once::ExclusiveState;
-
// We use the state of a Once as discriminant value. Upon creation, the state is
// "incomplete" and `f` contains the initialization closure. In the first call to
// `call_once`, `f` is taken and run. If it succeeds, `value` is set and the state
@@ -175,7 +174,7 @@ pub fn force(this: &LazyLock<T, F>) -> &T {
}
impl<T, F> LazyLock<T, F> {
- /// Get the inner value if it has already been initialized.
+ /// Gets the inner value if it has already been initialized.
fn get(&self) -> Option<&T> {
if self.once.is_completed() {
// SAFETY:
diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs
index a5d4e25..8a6ab4a 100644
--- a/library/std/src/sync/lazy_lock/tests.rs
+++ b/library/std/src/sync/lazy_lock/tests.rs
@@ -1,13 +1,8 @@
-use crate::{
- cell::LazyCell,
- panic,
- sync::{
- atomic::{AtomicUsize, Ordering::SeqCst},
- Mutex,
- },
- sync::{LazyLock, OnceLock},
- thread,
-};
+use crate::cell::LazyCell;
+use crate::sync::atomic::AtomicUsize;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::{LazyLock, Mutex, OnceLock};
+use crate::{panic, thread};
fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
thread::spawn(f).join().unwrap()
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 9a38c42..d0ba8cc 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -159,16 +159,19 @@
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
-pub use alloc_crate::sync::{Arc, Weak};
-#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
pub use core::sync::Exclusive;
#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc_crate::sync::{Arc, Weak};
+
+#[stable(feature = "rust1", since = "1.0.0")]
pub use self::barrier::{Barrier, BarrierWaitResult};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::condvar::{Condvar, WaitTimeoutResult};
+#[stable(feature = "lazy_cell", since = "1.80.0")]
+pub use self::lazy_lock::LazyLock;
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
pub use self::mutex::MappedMutexGuard;
#[stable(feature = "rust1", since = "1.0.0")]
@@ -176,21 +179,17 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::once::{Once, OnceState, ONCE_INIT};
+#[stable(feature = "once_cell", since = "1.70.0")]
+pub use self::once_lock::OnceLock;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult};
+#[unstable(feature = "reentrant_lock", issue = "121440")]
+pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
#[unstable(feature = "mapped_lock_guards", issue = "117108")]
pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
-#[stable(feature = "lazy_cell", since = "1.80.0")]
-pub use self::lazy_lock::LazyLock;
-#[stable(feature = "once_cell", since = "1.70.0")]
-pub use self::once_lock::OnceLock;
-
-#[unstable(feature = "reentrant_lock", issue = "121440")]
-pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};
-
pub mod mpsc;
mod barrier;
diff --git a/library/std/src/sync/mpmc/array.rs b/library/std/src/sync/mpmc/array.rs
index 185319a..34acd9c 100644
--- a/library/std/src/sync/mpmc/array.rs
+++ b/library/std/src/sync/mpmc/array.rs
@@ -13,7 +13,6 @@
use super::select::{Operation, Selected, Token};
use super::utils::{Backoff, CachePadded};
use super::waker::SyncWaker;
-
use crate::cell::UnsafeCell;
use crate::mem::MaybeUninit;
use crate::ptr;
diff --git a/library/std/src/sync/mpmc/context.rs b/library/std/src/sync/mpmc/context.rs
index bbfc6ce..8db3c98 100644
--- a/library/std/src/sync/mpmc/context.rs
+++ b/library/std/src/sync/mpmc/context.rs
@@ -2,7 +2,6 @@
use super::select::Selected;
use super::waker::current_thread_id;
-
use crate::cell::Cell;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
diff --git a/library/std/src/sync/mpmc/counter.rs b/library/std/src/sync/mpmc/counter.rs
index 3478cf4..d1bfe61 100644
--- a/library/std/src/sync/mpmc/counter.rs
+++ b/library/std/src/sync/mpmc/counter.rs
@@ -1,6 +1,5 @@
-use crate::ops;
-use crate::process;
use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
+use crate::{ops, process};
/// Reference counter internals.
struct Counter<C> {
diff --git a/library/std/src/sync/mpmc/error.rs b/library/std/src/sync/mpmc/error.rs
index 33b2bff..e3aec7e 100644
--- a/library/std/src/sync/mpmc/error.rs
+++ b/library/std/src/sync/mpmc/error.rs
@@ -1,7 +1,5 @@
-use crate::error;
-use crate::fmt;
-
pub use crate::sync::mpsc::{RecvError, RecvTimeoutError, SendError, TryRecvError, TrySendError};
+use crate::{error, fmt};
/// An error returned from the [`send_timeout`] method.
///
diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs
index edac7a0..bbe205c 100644
--- a/library/std/src/sync/mpmc/list.rs
+++ b/library/std/src/sync/mpmc/list.rs
@@ -5,7 +5,6 @@
use super::select::{Operation, Selected, Token};
use super::utils::{Backoff, CachePadded};
use super::waker::SyncWaker;
-
use crate::cell::UnsafeCell;
use crate::marker::PhantomData;
use crate::mem::MaybeUninit;
diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs
index 2068dda..c640e07 100644
--- a/library/std/src/sync/mpmc/mod.rs
+++ b/library/std/src/sync/mpmc/mod.rs
@@ -40,10 +40,11 @@
mod waker;
mod zero;
+pub use error::*;
+
use crate::fmt;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::time::{Duration, Instant};
-pub use error::*;
/// Creates a channel of unbounded capacity.
///
diff --git a/library/std/src/sync/mpmc/waker.rs b/library/std/src/sync/mpmc/waker.rs
index 9aab1b9..fb87788 100644
--- a/library/std/src/sync/mpmc/waker.rs
+++ b/library/std/src/sync/mpmc/waker.rs
@@ -2,7 +2,6 @@
use super::context::Context;
use super::select::{Operation, Selected};
-
use crate::ptr;
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::Mutex;
diff --git a/library/std/src/sync/mpmc/zero.rs b/library/std/src/sync/mpmc/zero.rs
index 6d1c9d6..2b82eed 100644
--- a/library/std/src/sync/mpmc/zero.rs
+++ b/library/std/src/sync/mpmc/zero.rs
@@ -7,7 +7,6 @@
use super::select::{Operation, Selected, Token};
use super::utils::Backoff;
use super::waker::Waker;
-
use crate::cell::UnsafeCell;
use crate::marker::PhantomData;
use crate::sync::atomic::{AtomicBool, Ordering};
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index feee694..26d5b95 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -148,10 +148,9 @@
// not exposed publicly, but if you are curious about the implementation,
// that's where everything is.
-use crate::error;
-use crate::fmt;
use crate::sync::mpmc;
use crate::time::{Duration, Instant};
+use crate::{error, fmt};
/// The receiving half of Rust's [`channel`] (or [`sync_channel`]) type.
/// This half can only be owned by one thread.
diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs
index 945de28..49b65c8 100644
--- a/library/std/src/sync/mpsc/sync_tests.rs
+++ b/library/std/src/sync/mpsc/sync_tests.rs
@@ -1,8 +1,7 @@
use super::*;
-use crate::env;
use crate::rc::Rc;
use crate::sync::mpmc::SendTimeoutError;
-use crate::thread;
+use crate::{env, thread};
pub fn stress_factor() -> usize {
match env::var("RUST_TEST_STRESS") {
diff --git a/library/std/src/sync/mpsc/tests.rs b/library/std/src/sync/mpsc/tests.rs
index ac1a804..13892fa 100644
--- a/library/std/src/sync/mpsc/tests.rs
+++ b/library/std/src/sync/mpsc/tests.rs
@@ -1,6 +1,5 @@
use super::*;
-use crate::env;
-use crate::thread;
+use crate::{env, thread};
pub fn stress_factor() -> usize {
match env::var("RUST_TEST_STRESS") {
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index 9d969af..bf595fd 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -70,7 +70,7 @@ pub(crate) enum ExclusiveState {
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(
since = "1.38.0",
- note = "the `new` function is now preferred",
+ note = "the `Once::new()` function is now preferred",
suggestion = "Once::new()"
)]
pub const ONCE_INIT: Once = Once::new();
@@ -264,6 +264,47 @@ pub fn is_completed(&self) -> bool {
self.inner.is_completed()
}
+ /// Blocks the current thread until initialization has completed.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// #![feature(once_wait)]
+ ///
+ /// use std::sync::Once;
+ /// use std::thread;
+ ///
+ /// static READY: Once = Once::new();
+ ///
+ /// let thread = thread::spawn(|| {
+ /// READY.wait();
+ /// println!("everything is ready");
+ /// });
+ ///
+ /// READY.call_once(|| println!("performing setup"));
+ /// ```
+ ///
+ /// # Panics
+ ///
+ /// If this [`Once`] has been poisoned because an initialization closure has
+ /// panicked, this method will also panic. Use [`wait_force`](Self::wait_force)
+ /// if this behaviour is not desired.
+ #[unstable(feature = "once_wait", issue = "127527")]
+ pub fn wait(&self) {
+ if !self.inner.is_completed() {
+ self.inner.wait(false);
+ }
+ }
+
+ /// Blocks the current thread until initialization has completed, ignoring
+ /// poisoning.
+ #[unstable(feature = "once_wait", issue = "127527")]
+ pub fn wait_force(&self) {
+ if !self.inner.is_completed() {
+ self.inner.wait(true);
+ }
+ }
+
/// Returns the current state of the `Once` instance.
///
/// Since this takes a mutable reference, no initialization can currently
diff --git a/library/std/src/sync/once/tests.rs b/library/std/src/sync/once/tests.rs
index 0c35597e..ce96468 100644
--- a/library/std/src/sync/once/tests.rs
+++ b/library/std/src/sync/once/tests.rs
@@ -1,7 +1,9 @@
use super::Once;
-use crate::panic;
+use crate::sync::atomic::AtomicBool;
+use crate::sync::atomic::Ordering::Relaxed;
use crate::sync::mpsc::channel;
-use crate::thread;
+use crate::time::Duration;
+use crate::{panic, thread};
#[test]
fn smoke_once() {
@@ -114,3 +116,47 @@ fn wait_for_force_to_finish() {
assert!(t1.join().is_ok());
assert!(t2.join().is_ok());
}
+
+#[test]
+fn wait() {
+ for _ in 0..50 {
+ let val = AtomicBool::new(false);
+ let once = Once::new();
+
+ thread::scope(|s| {
+ for _ in 0..4 {
+ s.spawn(|| {
+ once.wait();
+ assert!(val.load(Relaxed));
+ });
+ }
+
+ once.call_once(|| val.store(true, Relaxed));
+ });
+ }
+}
+
+#[test]
+fn wait_on_poisoned() {
+ let once = Once::new();
+
+ panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
+ panic::catch_unwind(|| once.wait()).unwrap_err();
+}
+
+#[test]
+fn wait_force_on_poisoned() {
+ let once = Once::new();
+
+ thread::scope(|s| {
+ panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err();
+
+ s.spawn(|| {
+ thread::sleep(Duration::from_millis(100));
+
+ once.call_once_force(|_| {});
+ });
+
+ once.wait_force();
+ })
+}
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index 94955be..56cf877 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -167,6 +167,34 @@ pub fn get_mut(&mut self) -> Option<&mut T> {
}
}
+ /// Blocks the current thread until the cell is initialized.
+ ///
+ /// # Example
+ ///
+ /// Waiting for a computation on another thread to finish:
+ /// ```rust
+ /// #![feature(once_wait)]
+ ///
+ /// use std::thread;
+ /// use std::sync::OnceLock;
+ ///
+ /// let value = OnceLock::new();
+ ///
+ /// thread::scope(|s| {
+ /// s.spawn(|| value.set(1 + 1));
+ ///
+ /// let result = value.wait();
+ /// assert_eq!(result, &2);
+ /// })
+ /// ```
+ #[inline]
+ #[unstable(feature = "once_wait", issue = "127527")]
+ pub fn wait(&self) -> &T {
+ self.once.wait_force();
+
+ unsafe { self.get_unchecked() }
+ }
+
/// Sets the contents of this cell to `value`.
///
/// May block if another thread is currently attempting to initialize the cell. The cell is
@@ -281,9 +309,7 @@ pub fn get_or_init<F>(&self, f: F) -> &T
/// Gets the mutable reference of the contents of the cell, initializing
/// it with `f` if the cell was empty.
///
- /// Many threads may call `get_mut_or_init` concurrently with different
- /// initializing functions, but it is guaranteed that only one function
- /// will be executed.
+ /// This method never blocks.
///
/// # Panics
///
@@ -373,6 +399,8 @@ pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
/// it with `f` if the cell was empty. If the cell was empty and `f` failed,
/// an error is returned.
///
+ /// This method never blocks.
+ ///
/// # Panics
///
/// If `f` panics, the panic is propagated to the caller, and
@@ -578,7 +606,7 @@ fn clone(&self) -> OnceLock<T> {
#[stable(feature = "once_cell", since = "1.70.0")]
impl<T> From<T> for OnceLock<T> {
- /// Create a new cell with its contents set to `value`.
+ /// Creates a new cell with its contents set to `value`.
///
/// # Example
///
diff --git a/library/std/src/sync/once_lock/tests.rs b/library/std/src/sync/once_lock/tests.rs
index d5d32e7..176830c 100644
--- a/library/std/src/sync/once_lock/tests.rs
+++ b/library/std/src/sync/once_lock/tests.rs
@@ -1,12 +1,8 @@
-use crate::{
- panic,
- sync::OnceLock,
- sync::{
- atomic::{AtomicUsize, Ordering::SeqCst},
- mpsc::channel,
- },
- thread,
-};
+use crate::sync::atomic::AtomicUsize;
+use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::mpsc::channel;
+use crate::sync::OnceLock;
+use crate::{panic, thread};
fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
thread::spawn(f).join().unwrap()
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index f497508..da66a08 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -1,6 +1,5 @@
use crate::error::Error;
use crate::fmt;
-
#[cfg(panic = "unwind")]
use crate::sync::atomic::{AtomicBool, Ordering};
#[cfg(panic = "unwind")]
@@ -31,13 +30,13 @@ pub const fn new() -> Flag {
}
}
- /// Check the flag for an unguarded borrow, where we only care about existing poison.
+ /// Checks the flag for an unguarded borrow, where we only care about existing poison.
#[inline]
pub fn borrow(&self) -> LockResult<()> {
if self.get() { Err(PoisonError::new(())) } else { Ok(()) }
}
- /// Check the flag for a guarded borrow, where we may also set poison when `done`.
+ /// Checks the flag for a guarded borrow, where we may also set poison when `done`.
#[inline]
pub fn guard(&self) -> LockResult<Guard> {
let ret = Guard {
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index a4ec52a..d995a16 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -573,7 +573,7 @@ fn from(t: T) -> Self {
}
impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
- /// Create a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
+ /// Creates a new instance of `RwLockReadGuard<T>` from a `RwLock<T>`.
// SAFETY: if and only if `lock.inner.read()` (or `lock.inner.try_read()`) has been
// successfully called from the same thread before instantiating this object.
unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> {
@@ -585,7 +585,7 @@ unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockReadGuard<'rwlock, T
}
impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
- /// Create a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
+ /// Creates a new instance of `RwLockWriteGuard<T>` from a `RwLock<T>`.
// SAFETY: if and only if `lock.inner.write()` (or `lock.inner.try_write()`) has been
// successfully called from the same thread before instantiating this object.
unsafe fn new(lock: &'rwlock RwLock<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> {
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs
index 9cc5e7a..37a2e41 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/rwlock/tests.rs
@@ -1,3 +1,5 @@
+use rand::Rng;
+
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sync::mpsc::channel;
use crate::sync::{
@@ -5,7 +7,6 @@
TryLockError,
};
use crate::thread;
-use rand::Rng;
#[derive(Eq, PartialEq, Debug)]
struct NonCopy(i32);
@@ -20,6 +21,10 @@ fn smoke() {
}
#[test]
+// FIXME: On macOS we use a provenance-incorrect implementation and Miri
+// catches that issue with a chance of around 1/1000.
+// See <https://github.com/rust-lang/rust/issues/121950> for details.
+#[cfg_attr(all(miri, target_os = "macos"), ignore)]
fn frob() {
const N: u32 = 10;
const M: usize = if cfg!(miri) { 100 } else { 1000 };
diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs
index 7487567..aa14c8b 100644
--- a/library/std/src/sys/anonymous_pipe/mod.rs
+++ b/library/std/src/sys/anonymous_pipe/mod.rs
@@ -1,18 +1,14 @@
+#![forbid(unsafe_op_in_unsafe_fn)]
+
cfg_if::cfg_if! {
if #[cfg(unix)] {
mod unix;
- pub(crate) use unix::{AnonPipe, pipe};
-
- #[cfg(all(test, not(miri)))]
- mod tests;
+ pub use unix::{AnonPipe, pipe};
} else if #[cfg(windows)] {
mod windows;
- pub(crate) use windows::{AnonPipe, pipe};
-
- #[cfg(all(test, not(miri)))]
- mod tests;
+ pub use windows::{AnonPipe, pipe};
} else {
mod unsupported;
- pub(crate) use unsupported::{AnonPipe, pipe};
+ pub use unsupported::{AnonPipe, pipe};
}
}
diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs
index ddbf1d7..9168024 100644
--- a/library/std/src/sys/anonymous_pipe/unix.rs
+++ b/library/std/src/sys/anonymous_pipe/unix.rs
@@ -1,16 +1,15 @@
-use crate::{
- io,
- os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
- pipe::{PipeReader, PipeWriter},
- process::Stdio,
- sys::{fd::FileDesc, pipe::anon_pipe},
- sys_common::{FromInner, IntoInner},
-};
+use crate::io;
+use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+use crate::pipe::{PipeReader, PipeWriter};
+use crate::process::Stdio;
+use crate::sys::fd::FileDesc;
+use crate::sys::pipe::anon_pipe;
+use crate::sys_common::{FromInner, IntoInner};
-pub(crate) type AnonPipe = FileDesc;
+pub type AnonPipe = FileDesc;
#[inline]
-pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
+pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
}
@@ -35,7 +34,7 @@ fn from(pipe: PipeReader) -> Self {
#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl FromRawFd for PipeReader {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
- Self(FileDesc::from_raw_fd(raw_fd))
+ unsafe { Self(FileDesc::from_raw_fd(raw_fd)) }
}
}
#[unstable(feature = "anonymous_pipe", issue = "127154")]
@@ -72,7 +71,7 @@ fn from(pipe: PipeWriter) -> Self {
#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl FromRawFd for PipeWriter {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
- Self(FileDesc::from_raw_fd(raw_fd))
+ unsafe { Self(FileDesc::from_raw_fd(raw_fd)) }
}
}
#[unstable(feature = "anonymous_pipe", issue = "127154")]
diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs
index 5962b69..dd51e70 100644
--- a/library/std/src/sys/anonymous_pipe/unsupported.rs
+++ b/library/std/src/sys/anonymous_pipe/unsupported.rs
@@ -1,13 +1,10 @@
-use crate::{
- io,
- pipe::{PipeReader, PipeWriter},
- process::Stdio,
-};
-
-pub(crate) use crate::sys::pipe::AnonPipe;
+use crate::io;
+use crate::pipe::{PipeReader, PipeWriter};
+use crate::process::Stdio;
+pub use crate::sys::pipe::AnonPipe;
#[inline]
-pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
+pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
Err(io::Error::UNSUPPORTED_PLATFORM)
}
diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs
index 81f95aa..a48198f 100644
--- a/library/std/src/sys/anonymous_pipe/windows.rs
+++ b/library/std/src/sys/anonymous_pipe/windows.rs
@@ -1,19 +1,26 @@
-use crate::{
- io,
- os::windows::io::{
- AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
- },
- pipe::{PipeReader, PipeWriter},
- process::Stdio,
- sys::{handle::Handle, pipe::unnamed_anon_pipe},
- sys_common::{FromInner, IntoInner},
+use crate::os::windows::io::{
+ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
};
+use crate::pipe::{PipeReader, PipeWriter};
+use crate::process::Stdio;
+use crate::sys::c;
+use crate::sys::handle::Handle;
+use crate::sys_common::{FromInner, IntoInner};
+use crate::{io, ptr};
-pub(crate) type AnonPipe = Handle;
+pub type AnonPipe = Handle;
-#[inline]
-pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
- unnamed_anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
+pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
+ let mut read_pipe = c::INVALID_HANDLE_VALUE;
+ let mut write_pipe = c::INVALID_HANDLE_VALUE;
+
+ let ret = unsafe { c::CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) };
+
+ if ret == 0 {
+ Err(io::Error::last_os_error())
+ } else {
+ unsafe { Ok((Handle::from_raw_handle(read_pipe), Handle::from_raw_handle(write_pipe))) }
+ }
}
#[unstable(feature = "anonymous_pipe", issue = "127154")]
@@ -32,7 +39,7 @@ fn as_raw_handle(&self) -> RawHandle {
#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl FromRawHandle for PipeReader {
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
- Self(Handle::from_raw_handle(raw_handle))
+ unsafe { Self(Handle::from_raw_handle(raw_handle)) }
}
}
#[unstable(feature = "anonymous_pipe", issue = "127154")]
@@ -71,7 +78,7 @@ fn as_raw_handle(&self) -> RawHandle {
#[unstable(feature = "anonymous_pipe", issue = "127154")]
impl FromRawHandle for PipeWriter {
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
- Self(Handle::from_raw_handle(raw_handle))
+ unsafe { Self(Handle::from_raw_handle(raw_handle)) }
}
}
#[unstable(feature = "anonymous_pipe", issue = "127154")]
diff --git a/library/std/src/sys/backtrace.rs b/library/std/src/sys/backtrace.rs
index 133ea52..4d939e1 100644
--- a/library/std/src/sys/backtrace.rs
+++ b/library/std/src/sys/backtrace.rs
@@ -3,12 +3,10 @@
use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt};
use crate::borrow::Cow;
-use crate::env;
-use crate::fmt;
-use crate::io;
use crate::io::prelude::*;
use crate::path::{self, Path, PathBuf};
use crate::sync::{Mutex, MutexGuard, PoisonError};
+use crate::{env, fmt, io};
/// Max number of frames to print.
const MAX_NB_FRAMES: usize = 100;
diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs
index 99df503..2997e90 100644
--- a/library/std/src/sys/cmath.rs
+++ b/library/std/src/sys/cmath.rs
@@ -28,6 +28,21 @@
pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
+ pub fn acosf128(n: f128) -> f128;
+ pub fn asinf128(n: f128) -> f128;
+ pub fn atanf128(n: f128) -> f128;
+ pub fn atan2f128(a: f128, b: f128) -> f128;
+ pub fn cbrtf128(n: f128) -> f128;
+ pub fn coshf128(n: f128) -> f128;
+ pub fn expm1f128(n: f128) -> f128;
+ pub fn hypotf128(x: f128, y: f128) -> f128;
+ pub fn log1pf128(n: f128) -> f128;
+ pub fn sinhf128(n: f128) -> f128;
+ pub fn tanf128(n: f128) -> f128;
+ pub fn tanhf128(n: f128) -> f128;
+ pub fn tgammaf128(n: f128) -> f128;
+ pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
+
cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] {
pub fn acosf(n: f32) -> f32;
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 202997b..a86b362 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -7,7 +7,6 @@
mod personality;
-#[unstable(feature = "anonymous_pipe", issue = "127154")]
pub mod anonymous_pipe;
pub mod backtrace;
pub mod cmath;
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 2a7477e..0f8bd64 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -3,13 +3,11 @@
use crate::borrow::Cow;
use crate::collections::TryReserveError;
-use crate::fmt;
use crate::fmt::Write;
-use crate::mem;
use crate::rc::Rc;
-use crate::str;
use crate::sync::Arc;
use crate::sys_common::{AsInner, IntoInner};
+use crate::{fmt, mem, str};
#[cfg(test)]
mod tests;
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index 806bf03..ed975ba 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -2,12 +2,11 @@
//! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
use crate::borrow::Cow;
use crate::collections::TryReserveError;
-use crate::fmt;
-use crate::mem;
use crate::rc::Rc;
use crate::sync::Arc;
use crate::sys_common::wtf8::{check_utf8_boundary, Wtf8, Wtf8Buf};
use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::{fmt, mem};
#[derive(Clone, Hash)]
pub struct Buf {
diff --git a/library/std/src/sys/pal/common/alloc.rs b/library/std/src/sys/pal/common/alloc.rs
index 54506c3..1b465f9 100644
--- a/library/std/src/sys/pal/common/alloc.rs
+++ b/library/std/src/sys/pal/common/alloc.rs
@@ -1,7 +1,6 @@
#![forbid(unsafe_op_in_unsafe_fn)]
use crate::alloc::{GlobalAlloc, Layout, System};
-use crate::cmp;
-use crate::ptr;
+use crate::{cmp, ptr};
// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values.
diff --git a/library/std/src/sys/pal/common/small_c_string.rs b/library/std/src/sys/pal/common/small_c_string.rs
index 37812fc..3c96714 100644
--- a/library/std/src/sys/pal/common/small_c_string.rs
+++ b/library/std/src/sys/pal/common/small_c_string.rs
@@ -1,8 +1,7 @@
use crate::ffi::{CStr, CString};
use crate::mem::MaybeUninit;
use crate::path::Path;
-use crate::slice;
-use crate::{io, ptr};
+use crate::{io, ptr, slice};
// Make sure to stay under 4096 so the compiler doesn't insert a probe frame:
// https://docs.rs/compiler_builtins/latest/compiler_builtins/probestack/index.html
diff --git a/library/std/src/sys/pal/common/tests.rs b/library/std/src/sys/pal/common/tests.rs
index e72d022..b769890 100644
--- a/library/std/src/sys/pal/common/tests.rs
+++ b/library/std/src/sys/pal/common/tests.rs
@@ -1,8 +1,9 @@
+use core::iter::repeat;
+
use crate::ffi::CString;
use crate::hint::black_box;
use crate::path::Path;
use crate::sys::common::small_c_string::run_path_with_cstr;
-use core::iter::repeat;
#[test]
fn stack_allocation_works() {
diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/pal/hermit/alloc.rs
index 2cd0db9..f10d5f9 100644
--- a/library/std/src/sys/pal/hermit/alloc.rs
+++ b/library/std/src/sys/pal/hermit/alloc.rs
@@ -1,31 +1,28 @@
use super::hermit_abi;
use crate::alloc::{GlobalAlloc, Layout, System};
-use crate::ptr;
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
- hermit_abi::malloc(layout.size(), layout.align())
- }
-
- unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
- let addr = hermit_abi::malloc(layout.size(), layout.align());
-
- if !addr.is_null() {
- ptr::write_bytes(addr, 0x00, layout.size());
- }
-
- addr
+ let size = layout.size();
+ let align = layout.align();
+ unsafe { hermit_abi::malloc(size, align) }
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- hermit_abi::free(ptr, layout.size(), layout.align())
+ let size = layout.size();
+ let align = layout.align();
+ unsafe {
+ hermit_abi::free(ptr, size, align);
+ }
}
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
- hermit_abi::realloc(ptr, layout.size(), layout.align(), new_size)
+ let size = layout.size();
+ let align = layout.align();
+ unsafe { hermit_abi::realloc(ptr, size, align, new_size) }
}
}
diff --git a/library/std/src/sys/pal/hermit/args.rs b/library/std/src/sys/pal/hermit/args.rs
index 220a76e..51afe34 100644
--- a/library/std/src/sys/pal/hermit/args.rs
+++ b/library/std/src/sys/pal/hermit/args.rs
@@ -1,12 +1,8 @@
use crate::ffi::{c_char, CStr, OsString};
-use crate::fmt;
use crate::os::hermit::ffi::OsStringExt;
-use crate::ptr;
-use crate::sync::atomic::{
- AtomicIsize, AtomicPtr,
- Ordering::{Acquire, Relaxed, Release},
-};
-use crate::vec;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{AtomicIsize, AtomicPtr};
+use crate::{fmt, ptr, vec};
static ARGC: AtomicIsize = AtomicIsize::new(0);
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs
index 3c52b85..79fc13b 100644
--- a/library/std/src/sys/pal/hermit/fd.rs
+++ b/library/std/src/sys/pal/hermit/fd.rs
@@ -3,13 +3,10 @@
use super::hermit_abi;
use crate::cmp;
use crate::io::{self, IoSlice, IoSliceMut, Read};
-use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd};
-use crate::sys::cvt;
-use crate::sys::unsupported;
+use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd, *};
+use crate::sys::{cvt, unsupported};
use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::os::hermit::io::*;
-
const fn max_iov() -> usize {
hermit_abi::IOV_MAX
}
@@ -114,7 +111,8 @@ fn from_inner(owned_fd: OwnedFd) -> Self {
impl FromRawFd for FileDesc {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
- Self { fd: FromRawFd::from_raw_fd(raw_fd) }
+ let fd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
+ Self { fd }
}
}
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index e4e9eee..aaf1a04 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -4,21 +4,17 @@
O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
};
use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt;
-use crate::io::{self, Error, ErrorKind};
-use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
-use crate::mem;
+use crate::io::{self, BorrowedCursor, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom};
use crate::os::hermit::ffi::OsStringExt;
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::path::{Path, PathBuf};
use crate::sync::Arc;
use crate::sys::common::small_c_string::run_path_with_cstr;
-use crate::sys::cvt;
use crate::sys::time::SystemTime;
-use crate::sys::unsupported;
-use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
-
+use crate::sys::{cvt, unsupported};
pub use crate::sys_common::fs::{copy, exists};
+use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
+use crate::{fmt, mem};
#[derive(Debug)]
pub struct File(FileDesc);
@@ -488,7 +484,8 @@ fn into_raw_fd(self) -> RawFd {
impl FromRawFd for File {
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
- Self(FromRawFd::from_raw_fd(raw_fd))
+ let file_desc = unsafe { FileDesc::from_raw_fd(raw_fd) };
+ Self(file_desc)
}
}
diff --git a/library/std/src/sys/pal/hermit/io.rs b/library/std/src/sys/pal/hermit/io.rs
index 9de7b53..aad1eef 100644
--- a/library/std/src/sys/pal/hermit/io.rs
+++ b/library/std/src/sys/pal/hermit/io.rs
@@ -1,9 +1,9 @@
+use hermit_abi::{c_void, iovec};
+
use crate::marker::PhantomData;
use crate::os::hermit::io::{AsFd, AsRawFd};
use crate::slice;
-use hermit_abi::{c_void, iovec};
-
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IoSlice<'a> {
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 55583b8..ef406b9 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -13,7 +13,8 @@
//! compiling for wasm. That way it's a compile time error for something that's
//! guaranteed to be a runtime error!
-#![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![allow(missing_docs, nonstandard_style)]
use crate::os::raw::c_char;
@@ -49,9 +50,7 @@ pub fn unsupported_err() -> crate::io::Error {
}
pub fn abort_internal() -> ! {
- unsafe {
- hermit_abi::abort();
- }
+ unsafe { hermit_abi::abort() }
}
pub fn hashmap_random_keys() -> (u64, u64) {
@@ -80,7 +79,9 @@ pub extern "C" fn __rust_abort() {
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
- args::init(argc, argv);
+ unsafe {
+ args::init(argc, argv);
+ }
}
// SAFETY: must be called only once during runtime cleanup.
@@ -101,10 +102,12 @@ pub unsafe fn cleanup() {}
// initialize environment
os::init_environment(env as *const *const i8);
- let result = main(argc as isize, argv);
+ let result = unsafe { main(argc as isize, argv) };
- crate::sys::thread_local::destructors::run();
- hermit_abi::exit(result);
+ unsafe {
+ crate::sys::thread_local::destructors::run();
+ }
+ unsafe { hermit_abi::exit(result) }
}
#[inline]
diff --git a/library/std/src/sys/pal/hermit/net.rs b/library/std/src/sys/pal/hermit/net.rs
index 6016d50..416469c 100644
--- a/library/std/src/sys/pal/hermit/net.rs
+++ b/library/std/src/sys/pal/hermit/net.rs
@@ -1,17 +1,16 @@
#![allow(dead_code)]
+use core::ffi::c_int;
+
use super::fd::FileDesc;
-use crate::cmp;
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::mem;
use crate::net::{Shutdown, SocketAddr};
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
use crate::sys::time::Instant;
use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
-
-use core::ffi::c_int;
+use crate::{cmp, mem};
#[allow(unused_extern_crates)]
pub extern crate hermit_abi as netc;
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index a7a73c7..f8ea80a 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -1,17 +1,15 @@
+use core::slice::memchr;
+
use super::hermit_abi;
use crate::collections::HashMap;
use crate::error::Error as StdError;
use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::os::hermit::ffi::OsStringExt;
use crate::path::{self, PathBuf};
-use crate::str;
use crate::sync::Mutex;
use crate::sys::unsupported;
-use crate::vec;
-use core::slice::memchr;
+use crate::{fmt, io, str, vec};
pub fn errno() -> i32 {
unsafe { hermit_abi::get_errno() }
@@ -70,21 +68,21 @@ pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
}
-static mut ENV: Option<Mutex<HashMap<OsString, OsString>>> = None;
+static ENV: Mutex<Option<HashMap<OsString, OsString>>> = Mutex::new(None);
pub fn init_environment(env: *const *const i8) {
+ let mut guard = ENV.lock().unwrap();
+ let map = guard.insert(HashMap::new());
+
+ if env.is_null() {
+ return;
+ }
+
unsafe {
- ENV = Some(Mutex::new(HashMap::new()));
-
- if env.is_null() {
- return;
- }
-
- let mut guard = ENV.as_ref().unwrap().lock().unwrap();
let mut environ = env;
while !(*environ).is_null() {
if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
- guard.insert(key, value);
+ map.insert(key, value);
}
environ = environ.add(1);
}
@@ -156,30 +154,26 @@ fn size_hint(&self) -> (usize, Option<usize>) {
/// Returns a vector of (variable, value) byte-vector pairs for all the
/// environment variables of the current process.
pub fn env() -> Env {
- unsafe {
- let guard = ENV.as_ref().unwrap().lock().unwrap();
- let mut result = Vec::new();
+ let guard = ENV.lock().unwrap();
+ let env = guard.as_ref().unwrap();
- for (key, value) in guard.iter() {
- result.push((key.clone(), value.clone()));
- }
+ let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect::<Vec<_>>();
- return Env { iter: result.into_iter() };
- }
+ Env { iter: result.into_iter() }
}
pub fn getenv(k: &OsStr) -> Option<OsString> {
- unsafe { ENV.as_ref().unwrap().lock().unwrap().get_mut(k).cloned() }
+ ENV.lock().unwrap().as_ref().unwrap().get(k).cloned()
}
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
let (k, v) = (k.to_owned(), v.to_owned());
- ENV.as_ref().unwrap().lock().unwrap().insert(k, v);
+ ENV.lock().unwrap().as_mut().unwrap().insert(k, v);
Ok(())
}
pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> {
- ENV.as_ref().unwrap().lock().unwrap().remove(k);
+ ENV.lock().unwrap().as_mut().unwrap().remove(k);
Ok(())
}
@@ -192,9 +186,7 @@ pub fn home_dir() -> Option<PathBuf> {
}
pub fn exit(code: i32) -> ! {
- unsafe {
- hermit_abi::exit(code);
- }
+ unsafe { hermit_abi::exit(code) }
}
pub fn getpid() -> u32 {
diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs
index 3723f03..6321f92 100644
--- a/library/std/src/sys/pal/hermit/thread.rs
+++ b/library/std/src/sys/pal/hermit/thread.rs
@@ -2,11 +2,10 @@
use super::hermit_abi;
use crate::ffi::CStr;
-use crate::io;
use crate::mem::ManuallyDrop;
use crate::num::NonZero;
-use crate::ptr;
use crate::time::Duration;
+use crate::{io, ptr};
pub type Tid = hermit_abi::Tid;
@@ -26,18 +25,22 @@ pub unsafe fn new_with_coreid(
core_id: isize,
) -> io::Result<Thread> {
let p = Box::into_raw(Box::new(p));
- let tid = hermit_abi::spawn2(
- thread_start,
- p.expose_provenance(),
- hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO),
- stack,
- core_id,
- );
+ let tid = unsafe {
+ hermit_abi::spawn2(
+ thread_start,
+ p.expose_provenance(),
+ hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO),
+ stack,
+ core_id,
+ )
+ };
return if tid == 0 {
// The thread failed to start and as a result p was not consumed. Therefore, it is
// safe to reconstruct the box so that it gets deallocated.
- drop(Box::from_raw(p));
+ unsafe {
+ drop(Box::from_raw(p));
+ }
Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Unable to create thread!"))
} else {
Ok(Thread { tid: tid })
@@ -55,7 +58,9 @@ extern "C" fn thread_start(main: usize) {
}
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- Thread::new_with_coreid(stack, p, -1 /* = no specific core */)
+ unsafe {
+ Thread::new_with_coreid(stack, p, -1 /* = no specific core */)
+ }
}
#[inline]
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index e0cb7c2..2c87c48 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -1,10 +1,11 @@
#![allow(dead_code)]
+use core::hash::{Hash, Hasher};
+
use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME};
use crate::cmp::Ordering;
use crate::ops::{Add, AddAssign, Sub, SubAssign};
use crate::time::Duration;
-use core::hash::{Hash, Hasher};
const NSEC_PER_SEC: i32 = 1_000_000_000;
diff --git a/library/std/src/sys/pal/itron/error.rs b/library/std/src/sys/pal/itron/error.rs
index fbc822d..8ff3017 100644
--- a/library/std/src/sys/pal/itron/error.rs
+++ b/library/std/src/sys/pal/itron/error.rs
@@ -1,6 +1,6 @@
-use crate::{fmt, io::ErrorKind};
-
use super::abi;
+use crate::fmt;
+use crate::io::ErrorKind;
/// Wraps a μITRON error code.
#[derive(Debug, Copy, Clone)]
@@ -9,7 +9,7 @@ pub struct ItronError {
}
impl ItronError {
- /// Construct `ItronError` from the specified error code. Returns `None` if the
+ /// Constructs `ItronError` from the specified error code. Returns `None` if the
/// error code does not represent a failure or warning.
#[inline]
pub fn new(er: abi::ER) -> Option<Self> {
@@ -22,7 +22,7 @@ pub fn err_if_negative(er: abi::ER) -> Result<abi::ER, Self> {
if let Some(error) = Self::new(er) { Err(error) } else { Ok(er) }
}
- /// Get the raw error code.
+ /// Gets the raw error code.
#[inline]
pub fn as_raw(&self) -> abi::ER {
self.er
diff --git a/library/std/src/sys/pal/itron/spin.rs b/library/std/src/sys/pal/itron/spin.rs
index 44d4094..6a9a7c7 100644
--- a/library/std/src/sys/pal/itron/spin.rs
+++ b/library/std/src/sys/pal/itron/spin.rs
@@ -1,9 +1,7 @@
use super::abi;
-use crate::{
- cell::UnsafeCell,
- mem::MaybeUninit,
- sync::atomic::{AtomicBool, AtomicUsize, Ordering},
-};
+use crate::cell::UnsafeCell;
+use crate::mem::MaybeUninit;
+use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
/// A mutex implemented by `dis_dsp` (for intra-core synchronization) and a
/// spinlock (for inter-core synchronization).
diff --git a/library/std/src/sys/pal/itron/task.rs b/library/std/src/sys/pal/itron/task.rs
index 94beb50..5da0c59 100644
--- a/library/std/src/sys/pal/itron/task.rs
+++ b/library/std/src/sys/pal/itron/task.rs
@@ -1,23 +1,20 @@
-use super::{
- abi,
- error::{fail, fail_aborting, ItronError},
-};
-
+use super::abi;
+use super::error::{fail, fail_aborting, ItronError};
use crate::mem::MaybeUninit;
-/// Get the ID of the task in Running state. Panics on failure.
+/// Gets the ID of the task in Running state. Panics on failure.
#[inline]
pub fn current_task_id() -> abi::ID {
try_current_task_id().unwrap_or_else(|e| fail(e, &"get_tid"))
}
-/// Get the ID of the task in Running state. Aborts on failure.
+/// Gets the ID of the task in Running state. Aborts on failure.
#[inline]
pub fn current_task_id_aborting() -> abi::ID {
try_current_task_id().unwrap_or_else(|e| fail_aborting(e, &"get_tid"))
}
-/// Get the ID of the task in Running state.
+/// Gets the ID of the task in Running state.
#[inline]
pub fn try_current_task_id() -> Result<abi::ID, ItronError> {
unsafe {
@@ -27,13 +24,13 @@ pub fn try_current_task_id() -> Result<abi::ID, ItronError> {
}
}
-/// Get the specified task's priority. Panics on failure.
+/// Gets the specified task's priority. Panics on failure.
#[inline]
pub fn task_priority(task: abi::ID) -> abi::PRI {
try_task_priority(task).unwrap_or_else(|e| fail(e, &"get_pri"))
}
-/// Get the specified task's priority.
+/// Gets the specified task's priority.
#[inline]
pub fn try_task_priority(task: abi::ID) -> Result<abi::PRI, ItronError> {
unsafe {
diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs
index fd7b555..01e69af 100644
--- a/library/std/src/sys/pal/itron/thread.rs
+++ b/library/std/src/sys/pal/itron/thread.rs
@@ -1,22 +1,17 @@
//! Thread implementation backed by μITRON tasks. Assumes `acre_tsk` and
//! `exd_tsk` are available.
-use super::{
- abi,
- error::{expect_success, expect_success_aborting, ItronError},
- task,
- time::dur2reltims,
-};
-use crate::{
- cell::UnsafeCell,
- ffi::CStr,
- hint, io,
- mem::ManuallyDrop,
- num::NonZero,
- ptr::NonNull,
- sync::atomic::{AtomicUsize, Ordering},
- time::Duration,
-};
+use super::error::{expect_success, expect_success_aborting, ItronError};
+use super::time::dur2reltims;
+use super::{abi, task};
+use crate::cell::UnsafeCell;
+use crate::ffi::CStr;
+use crate::mem::ManuallyDrop;
+use crate::num::NonZero;
+use crate::ptr::NonNull;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::time::Duration;
+use crate::{hint, io};
pub struct Thread {
p_inner: NonNull<ThreadInner>,
@@ -308,7 +303,7 @@ fn drop(&mut self) {
}
}
-/// Terminate and delete the specified task.
+/// Terminates and deletes the specified task.
///
/// This function will abort if `deleted_task` refers to the calling task.
///
@@ -337,7 +332,7 @@ unsafe fn terminate_and_delete_task(deleted_task: abi::ID) {
expect_success_aborting(unsafe { abi::del_tsk(deleted_task) }, &"del_tsk");
}
-/// Terminate and delete the calling task.
+/// Terminates and deletes the calling task.
///
/// Atomicity is not required - i.e., it can be assumed that other threads won't
/// `ter_tsk` the calling task while this function is still in progress. (This
diff --git a/library/std/src/sys/pal/itron/time.rs b/library/std/src/sys/pal/itron/time.rs
index 427ea0d..7976c27 100644
--- a/library/std/src/sys/pal/itron/time.rs
+++ b/library/std/src/sys/pal/itron/time.rs
@@ -1,5 +1,7 @@
-use super::{abi, error::expect_success};
-use crate::{mem::MaybeUninit, time::Duration};
+use super::abi;
+use super::error::expect_success;
+use crate::mem::MaybeUninit;
+use crate::time::Duration;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Instant(abi::SYSTIM);
diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs
index df01762..9be018c 100644
--- a/library/std/src/sys/pal/mod.rs
+++ b/library/std/src/sys/pal/mod.rs
@@ -76,23 +76,5 @@
}
}
-#[cfg(not(test))]
-cfg_if::cfg_if! {
- if #[cfg(target_os = "android")] {
- pub use self::android::log2f32;
- pub use self::android::log2f64;
- } else {
- #[inline]
- pub fn log2f32(n: f32) -> f32 {
- unsafe { crate::intrinsics::log2f32(n) }
- }
-
- #[inline]
- pub fn log2f64(n: f64) -> f64 {
- unsafe { crate::intrinsics::log2f64(n) }
- }
- }
-}
-
#[cfg(not(target_os = "uefi"))]
pub type RawOsError = i32;
diff --git a/library/std/src/sys/pal/sgx/abi/mod.rs b/library/std/src/sys/pal/sgx/abi/mod.rs
index 9508c38..d883645 100644
--- a/library/std/src/sys/pal/sgx/abi/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/mod.rs
@@ -1,9 +1,10 @@
#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
-use crate::io::Write;
use core::arch::global_asm;
use core::sync::atomic::{AtomicUsize, Ordering};
+use crate::io::Write;
+
// runtime features
pub(super) mod panic;
mod reloc;
diff --git a/library/std/src/sys/pal/sgx/abi/panic.rs b/library/std/src/sys/pal/sgx/abi/panic.rs
index 229b3b3..c06b97e 100644
--- a/library/std/src/sys/pal/sgx/abi/panic.rs
+++ b/library/std/src/sys/pal/sgx/abi/panic.rs
@@ -1,7 +1,6 @@
use super::usercalls::alloc::UserRef;
-use crate::cmp;
use crate::io::{self, Write};
-use crate::mem;
+use crate::{cmp, mem};
extern "C" {
fn take_debug_panic_buf_ptr() -> *mut u8;
diff --git a/library/std/src/sys/pal/sgx/abi/tls/mod.rs b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
index bab59a3..34fc2f2 100644
--- a/library/std/src/sys/pal/sgx/abi/tls/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/tls/mod.rs
@@ -2,10 +2,9 @@
use self::sync_bitset::*;
use crate::cell::Cell;
-use crate::mem;
use crate::num::NonZero;
-use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::{mem, ptr};
#[cfg(target_pointer_width = "64")]
const USIZE_BITS: usize = 64;
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
index b625636..5069ab8 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
@@ -1,18 +1,17 @@
#![allow(unused)]
-use crate::arch::asm;
-use crate::cell::UnsafeCell;
-use crate::cmp;
-use crate::convert::TryInto;
-use crate::intrinsics;
-use crate::mem::{self, ManuallyDrop};
-use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
-use crate::ptr::{self, NonNull};
-use crate::slice;
-use crate::slice::SliceIndex;
+use fortanix_sgx_abi::*;
use super::super::mem::{is_enclave_range, is_user_range};
-use fortanix_sgx_abi::*;
+use crate::arch::asm;
+use crate::cell::UnsafeCell;
+use crate::convert::TryInto;
+use crate::mem::{self, ManuallyDrop};
+use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
+use crate::pin::PinCoerceUnsized;
+use crate::ptr::{self, NonNull};
+use crate::slice::SliceIndex;
+use crate::{cmp, intrinsics, slice};
/// A type that can be safely read from or written to userspace.
///
@@ -67,7 +66,7 @@ pub unsafe trait UserSafe {
/// Equivalent to `mem::align_of::<Self>`.
fn align_of() -> usize;
- /// Construct a pointer to `Self` given a memory range in user space.
+ /// Constructs a pointer to `Self` given a memory range in user space.
///
/// N.B., this takes a size, not a length!
///
@@ -77,7 +76,7 @@ pub unsafe trait UserSafe {
/// correct size and is correctly aligned and points to the right type.
unsafe fn from_raw_sized_unchecked(ptr: *mut u8, size: usize) -> *mut Self;
- /// Construct a pointer to `Self` given a memory range.
+ /// Constructs a pointer to `Self` given a memory range.
///
/// N.B., this takes a size, not a length!
///
@@ -276,7 +275,7 @@ impl<T> User<T>
where
T: UserSafe,
{
- /// Allocate space for `T` in user memory.
+ /// Allocates space for `T` in user memory.
pub fn uninitialized() -> Self {
Self::new_uninit_bytes(mem::size_of::<T>())
}
@@ -287,7 +286,7 @@ impl<T> User<[T]>
where
[T]: UserSafe,
{
- /// Allocate space for a `[T]` of `n` elements in user memory.
+ /// Allocates space for a `[T]` of `n` elements in user memory.
pub fn uninitialized(n: usize) -> Self {
Self::new_uninit_bytes(n * mem::size_of::<T>())
}
@@ -753,6 +752,9 @@ fn drop(&mut self) {
#[unstable(feature = "sgx_platform", issue = "56975")]
impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UserRef<T> {}
+
#[unstable(feature = "sgx_platform", issue = "56975")]
impl<T, I> Index<I> for UserRef<[T]>
where
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs b/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs
index e19e843..def1ccd 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs
@@ -171,10 +171,12 @@ pub fn wait(event_mask: u64, mut timeout: u64) -> IoResult<u64> {
unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
}
-/// This function makes an effort to wait for a non-spurious event at least as
-/// long as `duration`. Note that in general there is no guarantee about accuracy
-/// of time and timeouts in SGX model. The enclave runner serving usercalls may
-/// lie about current time and/or ignore timeout values.
+/// Makes an effort to wait for a non-spurious event at least as long as
+/// `duration`.
+///
+/// Note that in general there is no guarantee about accuracy of time and
+/// timeouts in SGX model. The enclave runner serving usercalls may lie about
+/// current time and/or ignore timeout values.
///
/// Once the event is observed, `should_wake_up` will be used to determine
/// whether or not the event was spurious.
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/tests.rs b/library/std/src/sys/pal/sgx/abi/usercalls/tests.rs
index 58b8eb2..ef824d3 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/tests.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/tests.rs
@@ -1,5 +1,4 @@
-use super::alloc::User;
-use super::alloc::{copy_from_userspace, copy_to_userspace};
+use super::alloc::{copy_from_userspace, copy_to_userspace, User};
#[test]
fn test_copy_to_userspace_function() {
diff --git a/library/std/src/sys/pal/sgx/alloc.rs b/library/std/src/sys/pal/sgx/alloc.rs
index 0c7bf9a..f68ede9 100644
--- a/library/std/src/sys/pal/sgx/alloc.rs
+++ b/library/std/src/sys/pal/sgx/alloc.rs
@@ -1,9 +1,9 @@
-use crate::alloc::{GlobalAlloc, Layout, System};
-use crate::ptr;
use core::sync::atomic::{AtomicBool, Ordering};
use super::abi::mem as sgx_mem;
use super::waitqueue::SpinMutex;
+use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::ptr;
// Using a SpinMutex because we never want to exit the enclave waiting for the
// allocator.
diff --git a/library/std/src/sys/pal/sgx/args.rs b/library/std/src/sys/pal/sgx/args.rs
index ef4176c..a72a041 100644
--- a/library/std/src/sys/pal/sgx/args.rs
+++ b/library/std/src/sys/pal/sgx/args.rs
@@ -1,10 +1,10 @@
-use super::abi::usercalls::{alloc, raw::ByteBuffer};
+use super::abi::usercalls::alloc;
+use super::abi::usercalls::raw::ByteBuffer;
use crate::ffi::OsString;
-use crate::fmt;
-use crate::slice;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
use crate::sys_common::FromInner;
+use crate::{fmt, slice};
#[cfg_attr(test, linkage = "available_externally")]
#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"]
diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs
index 68a2d5e..f2e751c 100644
--- a/library/std/src/sys/pal/sgx/net.rs
+++ b/library/std/src/sys/pal/sgx/net.rs
@@ -1,13 +1,11 @@
-use crate::error;
-use crate::fmt;
+use super::abi::usercalls;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
use crate::sync::Arc;
use crate::sys::fd::FileDesc;
use crate::sys::{sgx_ineffective, unsupported, AsInner, FromInner, IntoInner, TryIntoInner};
use crate::time::Duration;
-
-use super::abi::usercalls;
+use crate::{error, fmt};
const DEFAULT_FAKE_TTL: u32 = 64;
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index c021300..46af710 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -3,16 +3,12 @@
use crate::collections::HashMap;
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
-use crate::str;
use crate::sync::atomic::{AtomicUsize, Ordering};
-use crate::sync::Mutex;
-use crate::sync::Once;
+use crate::sync::{Mutex, Once};
use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
-use crate::vec;
+use crate::{fmt, io, str, vec};
pub fn errno() -> i32 {
RESULT_SUCCESS
diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs
index 446cdd1..cecd53c 100644
--- a/library/std/src/sys/pal/sgx/thread.rs
+++ b/library/std/src/sys/pal/sgx/thread.rs
@@ -1,12 +1,12 @@
#![cfg_attr(test, allow(dead_code))] // why is this necessary?
+
+use super::abi::usercalls;
use super::unsupported;
use crate::ffi::CStr;
use crate::io;
use crate::num::NonZero;
use crate::time::Duration;
-use super::abi::usercalls;
-
pub struct Thread(task_queue::JoinHandle);
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
diff --git a/library/std/src/sys/pal/sgx/thread_parking.rs b/library/std/src/sys/pal/sgx/thread_parking.rs
index 0006cd4..660624e 100644
--- a/library/std/src/sys/pal/sgx/thread_parking.rs
+++ b/library/std/src/sys/pal/sgx/thread_parking.rs
@@ -1,7 +1,8 @@
+use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE};
+
use super::abi::usercalls;
use crate::io::ErrorKind;
use crate::time::Duration;
-use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE};
pub type ThreadId = fortanix_sgx_abi::Tcs;
diff --git a/library/std/src/sys/pal/sgx/waitqueue/mod.rs b/library/std/src/sys/pal/sgx/waitqueue/mod.rs
index f5668a9..bd11452 100644
--- a/library/std/src/sys/pal/sgx/waitqueue/mod.rs
+++ b/library/std/src/sys/pal/sgx/waitqueue/mod.rs
@@ -16,17 +16,15 @@
mod spin_mutex;
mod unsafe_list;
-use crate::num::NonZero;
-use crate::ops::{Deref, DerefMut};
-use crate::panic::{self, AssertUnwindSafe};
-use crate::time::Duration;
-
-use super::abi::thread;
-use super::abi::usercalls;
use fortanix_sgx_abi::{Tcs, EV_UNPARK, WAIT_INDEFINITE};
pub use self::spin_mutex::{try_lock_or_false, SpinMutex, SpinMutexGuard};
use self::unsafe_list::{UnsafeList, UnsafeListEntry};
+use super::abi::{thread, usercalls};
+use crate::num::NonZero;
+use crate::ops::{Deref, DerefMut};
+use crate::panic::{self, AssertUnwindSafe};
+use crate::time::Duration;
/// An queue entry in a `WaitQueue`.
struct WaitEntry {
diff --git a/library/std/src/sys/pal/solid/abi/fs.rs b/library/std/src/sys/pal/solid/abi/fs.rs
index 75efaaa..394be15 100644
--- a/library/std/src/sys/pal/solid/abi/fs.rs
+++ b/library/std/src/sys/pal/solid/abi/fs.rs
@@ -1,11 +1,12 @@
//! `solid_fs.h`
-use crate::os::raw::{c_char, c_int, c_uchar};
pub use libc::{
ino_t, off_t, stat, time_t, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY,
SEEK_CUR, SEEK_END, SEEK_SET, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFMT, S_IFREG, S_IWRITE,
};
+use crate::os::raw::{c_char, c_int, c_uchar};
+
pub const O_ACCMODE: c_int = 0x3;
pub const SOLID_MAX_PATH: usize = 256;
diff --git a/library/std/src/sys/pal/solid/abi/mod.rs b/library/std/src/sys/pal/solid/abi/mod.rs
index 8440d57..62cd862 100644
--- a/library/std/src/sys/pal/solid/abi/mod.rs
+++ b/library/std/src/sys/pal/solid/abi/mod.rs
@@ -3,7 +3,6 @@
mod fs;
pub mod sockets;
pub use self::fs::*;
-
// `solid_types.h`
pub use super::itron::abi::{ER, ER_ID, E_TMOUT, ID};
diff --git a/library/std/src/sys/pal/solid/abi/sockets.rs b/library/std/src/sys/pal/solid/abi/sockets.rs
index 11c4303..3c9e3f9 100644
--- a/library/std/src/sys/pal/solid/abi/sockets.rs
+++ b/library/std/src/sys/pal/solid/abi/sockets.rs
@@ -1,6 +1,7 @@
-use crate::os::raw::{c_char, c_uint, c_void};
pub use libc::{c_int, c_long, size_t, ssize_t, timeval};
+use crate::os::raw::{c_char, c_uint, c_void};
+
pub const SOLID_NET_ERR_BASE: c_int = -2000;
pub const EINPROGRESS: c_int = SOLID_NET_ERR_BASE - libc::EINPROGRESS;
diff --git a/library/std/src/sys/pal/solid/alloc.rs b/library/std/src/sys/pal/solid/alloc.rs
index d013bd8..4cf60ac 100644
--- a/library/std/src/sys/pal/solid/alloc.rs
+++ b/library/std/src/sys/pal/solid/alloc.rs
@@ -1,7 +1,5 @@
-use crate::{
- alloc::{GlobalAlloc, Layout, System},
- sys::common::alloc::{realloc_fallback, MIN_ALIGN},
-};
+use crate::alloc::{GlobalAlloc, Layout, System};
+use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
diff --git a/library/std/src/sys/pal/solid/error.rs b/library/std/src/sys/pal/solid/error.rs
index 547b4f3..66c4d8a 100644
--- a/library/std/src/sys/pal/solid/error.rs
+++ b/library/std/src/sys/pal/solid/error.rs
@@ -1,8 +1,7 @@
+pub use self::itron::error::{expect_success, ItronError as SolidError};
use super::{abi, itron, net};
use crate::io::ErrorKind;
-pub use self::itron::error::{expect_success, ItronError as SolidError};
-
/// Describe the specified SOLID error code. Returns `None` if it's an
/// undefined error code.
///
diff --git a/library/std/src/sys/pal/solid/fs.rs b/library/std/src/sys/pal/solid/fs.rs
index dc83e4f..8179ec8 100644
--- a/library/std/src/sys/pal/solid/fs.rs
+++ b/library/std/src/sys/pal/solid/fs.rs
@@ -1,17 +1,14 @@
use super::{abi, error};
-use crate::{
- ffi::{CStr, CString, OsStr, OsString},
- fmt,
- io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom},
- mem::MaybeUninit,
- os::raw::{c_int, c_short},
- os::solid::ffi::OsStrExt,
- path::{Path, PathBuf},
- sync::Arc,
- sys::time::SystemTime,
- sys::unsupported,
-};
-
+use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::fmt;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
+use crate::mem::MaybeUninit;
+use crate::os::raw::{c_int, c_short};
+use crate::os::solid::ffi::OsStrExt;
+use crate::path::{Path, PathBuf};
+use crate::sync::Arc;
+use crate::sys::time::SystemTime;
+use crate::sys::unsupported;
pub use crate::sys_common::fs::exists;
/// A file descriptor.
diff --git a/library/std/src/sys/pal/solid/io.rs b/library/std/src/sys/pal/solid/io.rs
index a862bb7..4b1f788 100644
--- a/library/std/src/sys/pal/solid/io.rs
+++ b/library/std/src/sys/pal/solid/io.rs
@@ -1,8 +1,8 @@
-use crate::marker::PhantomData;
-use crate::slice;
+use libc::c_void;
use super::abi::sockets::iovec;
-use libc::c_void;
+use crate::marker::PhantomData;
+use crate::slice;
#[derive(Copy, Clone)]
#[repr(transparent)]
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 0b158fb..cbf3428 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -32,8 +32,7 @@ pub mod itron {
#[path = "../unsupported/process.rs"]
pub mod process;
pub mod stdio;
-pub use self::itron::thread;
-pub use self::itron::thread_parking;
+pub use self::itron::{thread, thread_parking};
pub mod time;
// SAFETY: must be called only once during runtime initialization.
diff --git a/library/std/src/sys/pal/solid/net.rs b/library/std/src/sys/pal/solid/net.rs
index 5bd3398..b6a3139 100644
--- a/library/std/src/sys/pal/solid/net.rs
+++ b/library/std/src/sys/pal/solid/net.rs
@@ -1,19 +1,15 @@
-use super::abi;
-use crate::{
- cmp,
- ffi::CStr,
- io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut},
- mem,
- net::{Shutdown, SocketAddr},
- os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd},
- ptr, str,
- sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr},
- sys_common::{FromInner, IntoInner},
- time::Duration,
-};
+use libc::{c_int, c_void, size_t};
use self::netc::{sockaddr, socklen_t, MSG_PEEK};
-use libc::{c_int, c_void, size_t};
+use super::abi;
+use crate::ffi::CStr;
+use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
+use crate::net::{Shutdown, SocketAddr};
+use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd};
+use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
+use crate::sys_common::{FromInner, IntoInner};
+use crate::time::Duration;
+use crate::{cmp, mem, ptr, str};
pub mod netc {
pub use super::super::abi::sockets::*;
diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs
index ac90aae..d8afcb9 100644
--- a/library/std/src/sys/pal/solid/os.rs
+++ b/library/std/src/sys/pal/solid/os.rs
@@ -1,20 +1,14 @@
-use super::unsupported;
+use core::slice::memchr;
+
+use super::{error, itron, unsupported};
use crate::error::Error as StdError;
use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt;
-use crate::io;
-use crate::os::{
- raw::{c_char, c_int},
- solid::ffi::{OsStrExt, OsStringExt},
-};
+use crate::os::raw::{c_char, c_int};
+use crate::os::solid::ffi::{OsStrExt, OsStringExt};
use crate::path::{self, PathBuf};
use crate::sync::{PoisonError, RwLock};
use crate::sys::common::small_c_string::run_with_cstr;
-use crate::vec;
-
-use super::{error, itron};
-
-use core::slice::memchr;
+use crate::{fmt, io, vec};
// `solid` directly maps `errno`s to μITRON error codes.
impl itron::error::ItronError {
diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/pal/solid/time.rs
index f83f164..3f9bbb0 100644
--- a/library/std/src/sys/pal/solid/time.rs
+++ b/library/std/src/sys/pal/solid/time.rs
@@ -1,7 +1,8 @@
-use super::{abi, error::expect_success};
-use crate::{mem::MaybeUninit, time::Duration};
-
+use super::abi;
+use super::error::expect_success;
pub use super::itron::time::Instant;
+use crate::mem::MaybeUninit;
+use crate::time::Duration;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct SystemTime(abi::time_t);
diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs
index 3be0846..82cade7 100644
--- a/library/std/src/sys/pal/teeos/os.rs
+++ b/library/std/src/sys/pal/teeos/os.rs
@@ -2,14 +2,11 @@
use core::marker::PhantomData;
+use super::unsupported;
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
-use crate::path;
use crate::path::PathBuf;
-
-use super::unsupported;
+use crate::{fmt, io, path};
pub fn errno() -> i32 {
unsafe { (*libc::__errno_location()) as i32 }
diff --git a/library/std/src/sys/pal/teeos/stdio.rs b/library/std/src/sys/pal/teeos/stdio.rs
index 9ca04f2..67e2518 100644
--- a/library/std/src/sys/pal/teeos/stdio.rs
+++ b/library/std/src/sys/pal/teeos/stdio.rs
@@ -1,8 +1,9 @@
#![deny(unsafe_op_in_unsafe_fn)]
-use crate::io;
use core::arch::asm;
+use crate::io;
+
pub struct Stdin;
pub struct Stdout;
pub struct Stderr;
diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs
index b821e98..15c6524 100644
--- a/library/std/src/sys/pal/teeos/thread.rs
+++ b/library/std/src/sys/pal/teeos/thread.rs
@@ -1,11 +1,9 @@
-use crate::cmp;
use crate::ffi::CStr;
-use crate::io;
use crate::mem::{self, ManuallyDrop};
use crate::num::NonZero;
-use crate::ptr;
use crate::sys::os;
use crate::time::Duration;
+use crate::{cmp, io, ptr};
pub const DEFAULT_MIN_STACK_SIZE: usize = 8 * 1024;
diff --git a/library/std/src/sys/pal/uefi/args.rs b/library/std/src/sys/pal/uefi/args.rs
index 18a69af..bdf6f5a 100644
--- a/library/std/src/sys/pal/uefi/args.rs
+++ b/library/std/src/sys/pal/uefi/args.rs
@@ -3,10 +3,9 @@
use super::helpers;
use crate::env::current_exe;
use crate::ffi::OsString;
-use crate::fmt;
use crate::iter::Iterator;
use crate::mem::size_of;
-use crate::vec;
+use crate::{fmt, vec};
pub struct Args {
parsed_args_list: vec::IntoIter<OsString>,
@@ -76,7 +75,7 @@ fn next_back(&mut self) -> Option<OsString> {
/// This implementation is based on what is defined in Section 3.4 of
/// [UEFI Shell Specification](https://uefi.org/sites/default/files/resources/UEFI_Shell_Spec_2_0.pdf)
///
-/// Return None in the following cases:
+/// Returns None in the following cases:
/// - Invalid UTF-16 (unpaired surrogate)
/// - Empty/improper arguments
fn parse_lp_cmd_line(code_units: &[u16]) -> Option<Vec<OsString>> {
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 29984a9..4031d33 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -15,7 +15,9 @@
use crate::ffi::{OsStr, OsString};
use crate::io::{self, const_io_error};
use crate::mem::{size_of, MaybeUninit};
-use crate::os::uefi::{self, env::boot_services, ffi::OsStrExt, ffi::OsStringExt};
+use crate::os::uefi::env::boot_services;
+use crate::os::uefi::ffi::{OsStrExt, OsStringExt};
+use crate::os::uefi::{self};
use crate::ptr::NonNull;
use crate::slice;
use crate::sync::atomic::{AtomicPtr, Ordering};
@@ -30,8 +32,9 @@
const BOOT_SERVICES_UNAVAILABLE: io::Error =
const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
-/// Locate Handles with a particular Protocol GUID
-/// Implemented using `EFI_BOOT_SERVICES.LocateHandles()`
+/// Locates Handles with a particular Protocol GUID.
+///
+/// Implemented using `EFI_BOOT_SERVICES.LocateHandles()`.
///
/// Returns an array of [Handles](r_efi::efi::Handle) that support a specified protocol.
pub(crate) fn locate_handles(mut guid: Guid) -> io::Result<Vec<NonNull<crate::ffi::c_void>>> {
@@ -148,8 +151,9 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
-/// Get the Protocol for current system handle.
-/// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
+/// Gets the Protocol for current system handle.
+///
+/// Note: Some protocols need to be manually freed. It is the caller's responsibility to do so.
pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNull<T>> {
let system_handle = uefi::env::try_image_handle().ok_or(io::const_io_error!(
io::ErrorKind::NotFound,
@@ -220,7 +224,7 @@ fn path_to_text(
Err(io::const_io_error!(io::ErrorKind::NotFound, "No device path to text protocol found"))
}
-/// Get RuntimeServices
+/// Gets RuntimeServices.
pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> {
let system_table: NonNull<r_efi::efi::SystemTable> =
crate::os::uefi::env::try_system_table()?.cast();
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index c54e947..851bcea 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -101,9 +101,10 @@ pub const fn unsupported_err() -> std_io::Error {
}
pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind {
- use crate::io::ErrorKind;
use r_efi::efi::Status;
+ use crate::io::ErrorKind;
+
match r_efi::efi::Status::from_usize(code) {
Status::ALREADY_STARTED
| Status::COMPROMISED_DATA
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index 0b27977..4d2d726 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -1,14 +1,14 @@
+use r_efi::efi::protocols::{device_path, loaded_image_device_path};
+use r_efi::efi::Status;
+
use super::{helpers, unsupported, RawOsError};
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::os::uefi;
use crate::path::{self, PathBuf};
use crate::ptr::NonNull;
-use r_efi::efi::protocols::{device_path, loaded_image_device_path};
-use r_efi::efi::Status;
+use crate::{fmt, io};
pub fn errno() -> RawOsError {
0
diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs
index 5c7c841..fdc5f5d 100644
--- a/library/std/src/sys/pal/uefi/process.rs
+++ b/library/std/src/sys/pal/uefi/process.rs
@@ -1,20 +1,15 @@
use r_efi::protocols::simple_text_output;
-use crate::ffi::OsStr;
-use crate::ffi::OsString;
-use crate::fmt;
-use crate::io;
-use crate::num::NonZero;
-use crate::num::NonZeroI32;
+use super::helpers;
+pub use crate::ffi::OsString as EnvKey;
+use crate::ffi::{OsStr, OsString};
+use crate::num::{NonZero, NonZeroI32};
use crate::path::Path;
use crate::sys::fs::File;
use crate::sys::pipe::AnonPipe;
use crate::sys::unsupported;
use crate::sys_common::process::{CommandEnv, CommandEnvs};
-
-pub use crate::ffi::OsString as EnvKey;
-
-use super::helpers;
+use crate::{fmt, io};
////////////////////////////////////////////////////////////////////////////////
// Command
diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs
index 76562cf..495ff2d 100644
--- a/library/std/src/sys/pal/uefi/time.rs
+++ b/library/std/src/sys/pal/uefi/time.rs
@@ -59,11 +59,12 @@ pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
}
pub(crate) mod system_time_internal {
+ use r_efi::efi::{RuntimeServices, Time};
+
use super::super::helpers;
use super::*;
use crate::mem::MaybeUninit;
use crate::ptr::NonNull;
- use r_efi::efi::{RuntimeServices, Time};
pub fn now() -> Option<SystemTime> {
let runtime_services: NonNull<RuntimeServices> = helpers::runtime_services()?;
@@ -114,13 +115,14 @@ pub const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration {
}
pub(crate) mod instant_internal {
+ use r_efi::protocols::timestamp;
+
use super::super::helpers;
use super::*;
use crate::mem::MaybeUninit;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys_common::mul_div_u64;
- use r_efi::protocols::timestamp;
const NS_PER_SEC: u64 = 1_000_000_000;
@@ -173,10 +175,6 @@ pub fn platform_specific() -> Option<Instant> {
#[cfg(target_arch = "x86_64")]
fn timestamp_rdtsc() -> Option<Duration> {
- if !crate::arch::x86_64::has_cpuid() {
- return None;
- }
-
static FREQUENCY: crate::sync::OnceLock<u64> = crate::sync::OnceLock::new();
// Get Frequency in Mhz
@@ -198,10 +196,6 @@ fn timestamp_rdtsc() -> Option<Duration> {
#[cfg(target_arch = "x86")]
fn timestamp_rdtsc() -> Option<Duration> {
- if !crate::arch::x86::has_cpuid() {
- return None;
- }
-
static FREQUENCY: crate::sync::OnceLock<u64> = crate::sync::OnceLock::new();
let freq = FREQUENCY
diff --git a/library/std/src/sys/pal/unix/android.rs b/library/std/src/sys/pal/unix/android.rs
deleted file mode 100644
index 0f70499..0000000
--- a/library/std/src/sys/pal/unix/android.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-//! Android ABI-compatibility module
-//!
-//! The ABI of Android has changed quite a bit over time, and std attempts to be
-//! both forwards and backwards compatible as much as possible. We want to
-//! always work with the most recent version of Android, but we also want to
-//! work with older versions of Android for whenever projects need to.
-//!
-//! Our current minimum supported Android version is `android-9`, e.g., Android
-//! with API level 9. We then in theory want to work on that and all future
-//! versions of Android!
-//!
-//! Some of the detection here is done at runtime via `dlopen` and
-//! introspection. Other times no detection is performed at all and we just
-//! provide a fallback implementation as some versions of Android we support
-//! don't have the function.
-//!
-//! You'll find more details below about why each compatibility shim is needed.
-
-#![cfg(target_os = "android")]
-
-use libc::{c_int, sighandler_t};
-
-use super::weak::weak;
-
-// The `log2` and `log2f` functions apparently appeared in android-18, or at
-// least you can see they're not present in the android-17 header [1] and they
-// are present in android-18 [2].
-//
-// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
-// /android-17/arch-arm/usr/include/math.h
-// [2]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
-// /android-18/arch-arm/usr/include/math.h
-//
-// Note that these shims are likely less precise than directly calling `log2`,
-// but hopefully that should be enough for now...
-//
-// Note that mathematically, for any arbitrary `y`:
-//
-// log_2(x) = log_y(x) / log_y(2)
-// = log_y(x) / (1 / log_2(y))
-// = log_y(x) * log_2(y)
-//
-// Hence because `ln` (log_e) is available on all Android we just choose `y = e`
-// and get:
-//
-// log_2(x) = ln(x) * log_2(e)
-
-#[cfg(not(test))]
-pub fn log2f32(f: f32) -> f32 {
- f.ln() * crate::f32::consts::LOG2_E
-}
-
-#[cfg(not(test))]
-pub fn log2f64(f: f64) -> f64 {
- f.ln() * crate::f64::consts::LOG2_E
-}
-
-// Back in the day [1] the `signal` function was just an inline wrapper
-// around `bsd_signal`, but starting in API level android-20 the `signal`
-// symbols was introduced [2]. Finally, in android-21 the API `bsd_signal` was
-// removed [3].
-//
-// Basically this means that if we want to be binary compatible with multiple
-// Android releases (oldest being 9 and newest being 21) then we need to check
-// for both symbols and not actually link against either.
-//
-// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
-// /android-18/arch-arm/usr/include/signal.h
-// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental
-// /platforms/android-20/arch-arm
-// /usr/include/signal.h
-// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms
-// /android-21/arch-arm/usr/include/signal.h
-pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t {
- weak!(fn signal(c_int, sighandler_t) -> sighandler_t);
- weak!(fn bsd_signal(c_int, sighandler_t) -> sighandler_t);
-
- let f = signal.get().or_else(|| bsd_signal.get());
- let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
- f(signum, handler)
-}
diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs
index e2ec838..9a37e1a 100644
--- a/library/std/src/sys/pal/unix/args.rs
+++ b/library/std/src/sys/pal/unix/args.rs
@@ -6,9 +6,8 @@
#![allow(dead_code)] // runtime init functions not used during testing
use crate::ffi::{CStr, OsString};
-use crate::fmt;
use crate::os::unix::ffi::OsStringExt;
-use crate::vec;
+use crate::{fmt, vec};
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index f705bd6..d8e239e 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -3,12 +3,6 @@
#[cfg(test)]
mod tests;
-use crate::cmp;
-use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
-use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
-use crate::sys::cvt;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
-
#[cfg(any(
target_os = "android",
target_os = "linux",
@@ -26,6 +20,12 @@
)))]
use libc::off_t as off64_t;
+use crate::cmp;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
+use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
+use crate::sys::cvt;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
#[derive(Debug)]
pub struct FileDesc(OwnedFd);
diff --git a/library/std/src/sys/pal/unix/fd/tests.rs b/library/std/src/sys/pal/unix/fd/tests.rs
index 5d17e46..c5301ce 100644
--- a/library/std/src/sys/pal/unix/fd/tests.rs
+++ b/library/std/src/sys/pal/unix/fd/tests.rs
@@ -1,6 +1,7 @@
+use core::mem::ManuallyDrop;
+
use super::{FileDesc, IoSlice};
use crate::os::unix::io::FromRawFd;
-use core::mem::ManuallyDrop;
#[test]
fn limit_vector_count() {
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index c7915e2..be13e1a 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -4,29 +4,6 @@
#[cfg(test)]
mod tests;
-use crate::os::unix::prelude::*;
-
-use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt::{self, Write as _};
-use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
-use crate::mem;
-use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
-use crate::path::{Path, PathBuf};
-use crate::ptr;
-use crate::sync::Arc;
-use crate::sys::common::small_c_string::run_path_with_cstr;
-use crate::sys::fd::FileDesc;
-use crate::sys::time::SystemTime;
-use crate::sys::{cvt, cvt_r};
-use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
-
-#[cfg(all(target_os = "linux", target_env = "gnu"))]
-use crate::sys::weak::syscall;
-#[cfg(target_os = "android")]
-use crate::sys::weak::weak;
-
-use libc::{c_int, mode_t};
-
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::c_char;
#[cfg(any(
@@ -73,6 +50,7 @@
target_os = "hurd",
)))]
use libc::readdir_r as readdir64_r;
+use libc::{c_int, mode_t};
#[cfg(target_os = "android")]
use libc::{
dirent as dirent64, fstat as fstat64, fstatat as fstatat64, ftruncate64, lseek64,
@@ -97,7 +75,24 @@
))]
use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, stat64};
+use crate::ffi::{CStr, OsStr, OsString};
+use crate::fmt::{self, Write as _};
+use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
+use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
+use crate::os::unix::prelude::*;
+use crate::path::{Path, PathBuf};
+use crate::sync::Arc;
+use crate::sys::common::small_c_string::run_path_with_cstr;
+use crate::sys::fd::FileDesc;
+use crate::sys::time::SystemTime;
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
+use crate::sys::weak::syscall;
+#[cfg(target_os = "android")]
+use crate::sys::weak::weak;
+use crate::sys::{cvt, cvt_r};
pub use crate::sys_common::fs::exists;
+use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
+use crate::{mem, ptr};
pub struct File(FileDesc);
@@ -1557,17 +1552,6 @@ fn get_path(_fd: c_int) -> Option<PathBuf> {
None
}
- #[cfg(any(
- target_os = "linux",
- target_os = "freebsd",
- target_os = "hurd",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "vxworks",
- target_os = "solaris",
- target_os = "illumos",
- target_vendor = "apple",
- ))]
fn get_mode(fd: c_int) -> Option<(bool, bool)> {
let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if mode == -1 {
@@ -1581,22 +1565,6 @@ fn get_mode(fd: c_int) -> Option<(bool, bool)> {
}
}
- #[cfg(not(any(
- target_os = "linux",
- target_os = "freebsd",
- target_os = "hurd",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "vxworks",
- target_os = "solaris",
- target_os = "illumos",
- target_vendor = "apple",
- )))]
- fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
- // FIXME(#24570): implement this for other Unix platforms
- None
- }
-
let fd = self.as_raw_fd();
let mut b = f.debug_struct("File");
b.field("fd", &fd);
@@ -2021,6 +1989,11 @@ mod remove_dir_impl {
miri
)))]
mod remove_dir_impl {
+ #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
+ use libc::{fdopendir, openat, unlinkat};
+ #[cfg(all(target_os = "linux", target_env = "gnu"))]
+ use libc::{fdopendir, openat64 as openat, unlinkat};
+
use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir};
use crate::ffi::CStr;
use crate::io;
@@ -2030,11 +2003,6 @@ mod remove_dir_impl {
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::{cvt, cvt_r};
- #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
- use libc::{fdopendir, openat, unlinkat};
- #[cfg(all(target_os = "linux", target_env = "gnu"))]
- use libc::{fdopendir, openat64 as openat, unlinkat};
-
pub fn openat_nofollow_dironly(parent_fd: Option<RawFd>, p: &CStr) -> io::Result<OwnedFd> {
let fd = cvt_r(|| unsafe {
openat(
diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs
index b8900da..cc72504 100644
--- a/library/std/src/sys/pal/unix/futex.rs
+++ b/library/std/src/sys/pal/unix/futex.rs
@@ -16,7 +16,7 @@
/// Must be the underlying type of SmallAtomic
pub type SmallPrimitive = u32;
-/// Wait for a futex_wake operation to wake us.
+/// Waits for a `futex_wake` operation to wake us.
///
/// Returns directly if the futex doesn't hold the expected value.
///
@@ -87,7 +87,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
}
}
-/// Wake up one thread that's blocked on futex_wait on this futex.
+/// Wakes up one thread that's blocked on `futex_wait` on this futex.
///
/// Returns true if this actually woke up such a thread,
/// or false if no thread was waiting on this futex.
@@ -100,7 +100,7 @@ pub fn futex_wake(futex: &AtomicU32) -> bool {
unsafe { libc::syscall(libc::SYS_futex, ptr, op, 1) > 0 }
}
-/// Wake up all threads that are waiting on futex_wait on this futex.
+/// Wakes up all threads that are waiting on `futex_wait` on this futex.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wake_all(futex: &AtomicU32) {
let ptr = futex as *const AtomicU32;
diff --git a/library/std/src/sys/pal/unix/io.rs b/library/std/src/sys/pal/unix/io.rs
index 29c340d..181c35a 100644
--- a/library/std/src/sys/pal/unix/io.rs
+++ b/library/std/src/sys/pal/unix/io.rs
@@ -1,9 +1,9 @@
+use libc::{c_void, iovec};
+
use crate::marker::PhantomData;
use crate::os::fd::{AsFd, AsRawFd};
use crate::slice;
-use libc::{c_void, iovec};
-
#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IoSlice<'a> {
diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs
index cd38b7c..a671383 100644
--- a/library/std/src/sys/pal/unix/kernel_copy.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy.rs
@@ -42,6 +42,12 @@
//! progress, they can hit a performance cliff.
//! * complexity
+#[cfg(not(any(all(target_os = "linux", target_env = "gnu"), target_os = "hurd")))]
+use libc::sendfile as sendfile64;
+#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "hurd"))]
+use libc::sendfile64;
+use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
+
use crate::cmp::min;
use crate::fs::{File, Metadata};
use crate::io::copy::generic_copy;
@@ -54,16 +60,12 @@
use crate::os::unix::fs::FileTypeExt;
use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use crate::os::unix::net::UnixStream;
+use crate::pipe::{PipeReader, PipeWriter};
use crate::process::{ChildStderr, ChildStdin, ChildStdout};
use crate::ptr;
use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use crate::sys::cvt;
use crate::sys::weak::syscall;
-#[cfg(not(any(all(target_os = "linux", target_env = "gnu"), target_os = "hurd")))]
-use libc::sendfile as sendfile64;
-#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "hurd"))]
-use libc::sendfile64;
-use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV};
#[cfg(test)]
mod tests;
@@ -404,6 +406,30 @@ fn properties(&self) -> CopyParams {
}
}
+impl CopyRead for PipeReader {
+ fn properties(&self) -> CopyParams {
+ CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+ }
+}
+
+impl CopyRead for &PipeReader {
+ fn properties(&self) -> CopyParams {
+ CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+ }
+}
+
+impl CopyWrite for PipeWriter {
+ fn properties(&self) -> CopyParams {
+ CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+ }
+}
+
+impl CopyWrite for &PipeWriter {
+ fn properties(&self) -> CopyParams {
+ CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+ }
+}
+
impl CopyWrite for ChildStdin {
fn properties(&self) -> CopyParams {
CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
diff --git a/library/std/src/sys/pal/unix/kernel_copy/tests.rs b/library/std/src/sys/pal/unix/kernel_copy/tests.rs
index a524270e..1350d74 100644
--- a/library/std/src/sys/pal/unix/kernel_copy/tests.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy/tests.rs
@@ -1,8 +1,6 @@
use crate::fs::OpenOptions;
use crate::io;
-use crate::io::Result;
-use crate::io::SeekFrom;
-use crate::io::{BufRead, Read, Seek, Write};
+use crate::io::{BufRead, Read, Result, Seek, SeekFrom, Write};
use crate::os::unix::io::AsRawFd;
use crate::sys_common::io::test::tmpdir;
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index bdb9958..b62129f 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -1,15 +1,13 @@
#![allow(missing_docs, nonstandard_style)]
-use crate::io::ErrorKind;
-
pub use self::rand::hashmap_random_keys;
+use crate::io::ErrorKind;
#[cfg(not(target_os = "espidf"))]
#[macro_use]
pub mod weak;
pub mod alloc;
-pub mod android;
pub mod args;
pub mod env;
pub mod fd;
@@ -86,11 +84,12 @@ unsafe fn sanitize_standard_fds() {
target_vendor = "apple",
)))]
'poll: {
- use crate::sys::os::errno;
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::open as open64;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::open64;
+
+ use crate::sys::os::errno;
let pfds: &mut [_] = &mut [
libc::pollfd { fd: 0, events: 0, revents: 0 },
libc::pollfd { fd: 1, events: 0, revents: 0 },
@@ -140,11 +139,12 @@ unsafe fn sanitize_standard_fds() {
target_os = "vita",
)))]
{
- use crate::sys::os::errno;
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::open as open64;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::open64;
+
+ use crate::sys::os::errno;
for fd in 0..3 {
if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
@@ -165,6 +165,7 @@ unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
target_os = "fuchsia",
target_os = "horizon",
target_os = "vxworks",
+ target_os = "vita",
// Unikraft's `signal` implementation is currently broken:
// https://github.com/unikraft/lib-musl/issues/57
target_vendor = "unikraft",
@@ -211,6 +212,7 @@ mod sigpipe {
target_os = "fuchsia",
target_os = "horizon",
target_os = "vxworks",
+ target_os = "vita",
)))]
static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool =
crate::sync::atomic::AtomicBool::new(false);
@@ -221,6 +223,7 @@ mod sigpipe {
target_os = "fuchsia",
target_os = "horizon",
target_os = "vxworks",
+ target_os = "vita",
)))]
pub(crate) fn on_broken_pipe_flag_used() -> bool {
ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed)
@@ -232,10 +235,7 @@ pub unsafe fn cleanup() {
stack_overflow::cleanup();
}
-#[cfg(target_os = "android")]
-pub use crate::sys::android::signal;
#[allow(unused_imports)]
-#[cfg(not(target_os = "android"))]
pub use libc::signal;
#[inline]
@@ -308,7 +308,7 @@ fn is_minus_one(&self) -> bool {
impl_is_minus_one! { i8 i16 i32 i64 isize }
-/// Convert native return values to Result using the *-1 means error is in `errno`* convention.
+/// Converts native return values to Result using the *-1 means error is in `errno`* convention.
/// Non-error values are `Ok`-wrapped.
pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index eafde51..bc0e3f4 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -1,7 +1,7 @@
-use crate::cmp;
+use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
+
use crate::ffi::CStr;
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::mem;
use crate::net::{Shutdown, SocketAddr};
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc;
@@ -9,8 +9,7 @@
use crate::sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr};
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::{Duration, Instant};
-
-use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
+use crate::{cmp, mem};
cfg_if::cfg_if! {
if #[cfg(target_vendor = "apple")] {
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 9adc2b9..a785b97 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -5,29 +5,20 @@
#[cfg(test)]
mod tests;
-use crate::os::unix::prelude::*;
+use core::slice::memchr;
+
+use libc::{c_char, c_int, c_void};
use crate::error::Error as StdError;
use crate::ffi::{CStr, CString, OsStr, OsString};
-use crate::fmt;
-use crate::io;
-use crate::iter;
-use crate::mem;
+use crate::os::unix::prelude::*;
use crate::path::{self, PathBuf};
-use crate::ptr;
-use crate::slice;
-use crate::str;
use crate::sync::{PoisonError, RwLock};
use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
-use crate::sys::cvt;
-use crate::sys::fd;
-use crate::vec;
-use core::slice::memchr;
-
#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
use crate::sys::weak::weak;
-
-use libc::{c_char, c_int, c_void};
+use crate::sys::{cvt, fd};
+use crate::{fmt, io, iter, mem, ptr, slice, str, vec};
const TMPBUF_SZ: usize = 128;
@@ -248,13 +239,12 @@ fn description(&self) -> &str {
#[cfg(target_os = "aix")]
pub fn current_exe() -> io::Result<PathBuf> {
- use crate::io::ErrorKind;
-
#[cfg(test)]
use realstd::env;
#[cfg(not(test))]
use crate::env;
+ use crate::io::ErrorKind;
let exe_path = env::args().next().ok_or(io::const_io_error!(
ErrorKind::NotFound,
@@ -513,13 +503,12 @@ pub fn current_exe() -> io::Result<PathBuf> {
#[cfg(target_os = "fuchsia")]
pub fn current_exe() -> io::Result<PathBuf> {
- use crate::io::ErrorKind;
-
#[cfg(test)]
use realstd::env;
#[cfg(not(test))]
use crate::env;
+ use crate::io::ErrorKind;
let exe_path = env::args().next().ok_or(io::const_io_error!(
ErrorKind::Uncategorized,
diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs
index 8762af6..f0ebc76 100644
--- a/library/std/src/sys/pal/unix/pipe.rs
+++ b/library/std/src/sys/pal/unix/pipe.rs
@@ -47,6 +47,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
}
impl AnonPipe {
+ #[allow(dead_code)]
+ // FIXME: This function seems legitimately unused.
pub fn try_clone(&self) -> io::Result<Self> {
self.0.duplicate().map(Self)
}
@@ -85,6 +87,8 @@ pub fn is_write_vectored(&self) -> bool {
self.0.is_write_vectored()
}
+ #[allow(dead_code)]
+ // FIXME: This function seems legitimately unused.
pub fn as_file_desc(&self) -> &FileDesc {
&self.0
}
diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs
index f615e80..fec8250 100644
--- a/library/std/src/sys/pal/unix/process/process_common.rs
+++ b/library/std/src/sys/pal/unix/process/process_common.rs
@@ -1,24 +1,20 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use crate::os::unix::prelude::*;
+use libc::{c_char, c_int, gid_t, pid_t, uid_t, EXIT_FAILURE, EXIT_SUCCESS};
use crate::collections::BTreeMap;
use crate::ffi::{CStr, CString, OsStr, OsString};
-use crate::fmt;
-use crate::io;
+use crate::os::unix::prelude::*;
use crate::path::Path;
-use crate::ptr;
use crate::sys::fd::FileDesc;
use crate::sys::fs::File;
+#[cfg(not(target_os = "fuchsia"))]
+use crate::sys::fs::OpenOptions;
use crate::sys::pipe::{self, AnonPipe};
use crate::sys_common::process::{CommandEnv, CommandEnvs};
use crate::sys_common::{FromInner, IntoInner};
-
-#[cfg(not(target_os = "fuchsia"))]
-use crate::sys::fs::OpenOptions;
-
-use libc::{c_char, c_int, gid_t, pid_t, uid_t, EXIT_FAILURE, EXIT_SUCCESS};
+use crate::{fmt, io, ptr};
cfg_if::cfg_if! {
if #[cfg(target_os = "fuchsia")] {
@@ -128,6 +124,7 @@ pub struct StdioPipes {
// passed to do_exec() with configuration of what the child stdio should look
// like
+#[cfg_attr(target_os = "vita", allow(dead_code))]
pub struct ChildPipes {
pub stdin: ChildStdio,
pub stdout: ChildStdio,
diff --git a/library/std/src/sys/pal/unix/process/process_common/tests.rs b/library/std/src/sys/pal/unix/process/process_common/tests.rs
index 823b4a5..e5c8dd6 100644
--- a/library/std/src/sys/pal/unix/process/process_common/tests.rs
+++ b/library/std/src/sys/pal/unix/process/process_common/tests.rs
@@ -1,9 +1,7 @@
use super::*;
-
use crate::ffi::OsStr;
-use crate::mem;
-use crate::ptr;
use crate::sys::{cvt, cvt_nz};
+use crate::{mem, ptr};
macro_rules! t {
($e:expr) => {
diff --git a/library/std/src/sys/pal/unix/process/process_fuchsia.rs b/library/std/src/sys/pal/unix/process/process_fuchsia.rs
index 23c2be6..f3d5fdec 100644
--- a/library/std/src/sys/pal/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/pal/unix/process/process_fuchsia.rs
@@ -1,13 +1,9 @@
-use crate::fmt;
-use crate::io;
-use crate::mem;
-use crate::num::NonZero;
-use crate::ptr;
+use libc::{c_int, size_t};
+use crate::num::NonZero;
use crate::sys::process::process_common::*;
use crate::sys::process::zircon::{zx_handle_t, Handle};
-
-use libc::{c_int, size_t};
+use crate::{fmt, io, mem, ptr};
////////////////////////////////////////////////////////////////////////////////
// Command
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index abd4a33..5552e9a 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -1,20 +1,7 @@
-use crate::fmt;
-use crate::io::{self, Error, ErrorKind};
-use crate::mem;
-use crate::num::NonZero;
-use crate::sys;
-use crate::sys::cvt;
-use crate::sys::process::process_common::*;
-
-#[cfg(target_os = "linux")]
-use crate::sys::pal::unix::linux::pidfd::PidFd;
-
#[cfg(target_os = "vxworks")]
use libc::RTP_ID as pid_t;
-
#[cfg(not(target_os = "vxworks"))]
use libc::{c_int, pid_t};
-
#[cfg(not(any(
target_os = "vxworks",
target_os = "l4re",
@@ -23,6 +10,14 @@
)))]
use libc::{gid_t, uid_t};
+use crate::io::{self, Error, ErrorKind};
+use crate::num::NonZero;
+use crate::sys::cvt;
+#[cfg(target_os = "linux")]
+use crate::sys::pal::unix::linux::pidfd::PidFd;
+use crate::sys::process::process_common::*;
+use crate::{fmt, mem, sys};
+
cfg_if::cfg_if! {
if #[cfg(all(target_os = "nto", target_env = "nto71"))] {
use crate::thread;
@@ -446,11 +441,12 @@ fn posix_spawn(
stdio: &ChildPipes,
envp: Option<&CStringArray>,
) -> io::Result<Option<Process>> {
+ #[cfg(target_os = "linux")]
+ use core::sync::atomic::{AtomicU8, Ordering};
+
use crate::mem::MaybeUninit;
use crate::sys::weak::weak;
use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used};
- #[cfg(target_os = "linux")]
- use core::sync::atomic::{AtomicU8, Ordering};
if self.get_gid().is_some()
|| self.get_uid().is_some()
@@ -762,10 +758,11 @@ fn drop(&mut self) {
#[cfg(target_os = "linux")]
fn send_pidfd(&self, sock: &crate::sys::net::Socket) {
+ use libc::{CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_SPACE, SCM_RIGHTS, SOL_SOCKET};
+
use crate::io::IoSlice;
use crate::os::fd::RawFd;
use crate::sys::cvt_r;
- use libc::{CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_SPACE, SCM_RIGHTS, SOL_SOCKET};
unsafe {
let child_pid = libc::getpid();
@@ -819,11 +816,11 @@ union Cmsg {
#[cfg(target_os = "linux")]
fn recv_pidfd(&self, sock: &crate::sys::net::Socket) -> pid_t {
+ use libc::{CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_SPACE, SCM_RIGHTS, SOL_SOCKET};
+
use crate::io::IoSliceMut;
use crate::sys::cvt_r;
- use libc::{CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_SPACE, SCM_RIGHTS, SOL_SOCKET};
-
unsafe {
const SCM_MSG_LEN: usize = mem::size_of::<[c_int; 1]>();
@@ -1047,7 +1044,7 @@ fn from(a: c_int) -> ExitStatus {
}
}
-/// Convert a signal number to a readable, searchable name.
+/// Converts a signal number to a readable, searchable name.
///
/// This string should be displayed right after the signal number.
/// If a signal is unrecognized, it returns the empty string, so that
@@ -1189,12 +1186,11 @@ pub fn code(self) -> Option<NonZero<i32>> {
#[cfg(target_os = "linux")]
mod linux_child_ext {
- use crate::io;
- use crate::mem;
use crate::os::linux::process as os;
use crate::sys::pal::unix::linux::pidfd as imp;
use crate::sys::pal::unix::ErrorKind;
use crate::sys_common::FromInner;
+ use crate::{io, mem};
#[unstable(feature = "linux_pidfd", issue = "82971")]
impl crate::os::linux::process::ChildExt for crate::process::Child {
diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/pal/unix/process/process_unix/tests.rs
index e5e1f95..f4d6ac6 100644
--- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix/tests.rs
@@ -24,7 +24,20 @@ fn exitstatus_display_tests() {
// The purpose of this test is to test our string formatting, not our understanding of the wait
// status magic numbers. So restrict these to Linux.
if cfg!(target_os = "linux") {
+ #[cfg(any(target_arch = "mips", target_arch = "mips64"))]
+ t(0x0137f, "stopped (not terminated) by signal: 19 (SIGPWR)");
+
+ #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
+ t(0x0137f, "stopped (not terminated) by signal: 19 (SIGCONT)");
+
+ #[cfg(not(any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "sparc",
+ target_arch = "sparc64"
+ )))]
t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)");
+
t(0x0ffff, "continued (WIFCONTINUED)");
}
diff --git a/library/std/src/sys/pal/unix/process/process_unsupported.rs b/library/std/src/sys/pal/unix/process/process_unsupported.rs
index 90d5346..c585488 100644
--- a/library/std/src/sys/pal/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/pal/unix/process/process_unsupported.rs
@@ -1,10 +1,10 @@
+use libc::{c_int, pid_t};
+
use crate::io;
use crate::num::NonZero;
use crate::sys::pal::unix::unsupported::*;
use crate::sys::process::process_common::*;
-use libc::{c_int, pid_t};
-
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs b/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs
index 973188b..f04036b 100644
--- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs
+++ b/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs
@@ -2,12 +2,11 @@
//!
//! Separate module to facilitate testing against a real Unix implementation.
+use super::ExitStatusError;
use crate::ffi::c_int;
use crate::fmt;
use crate::num::NonZero;
-use super::ExitStatusError;
-
/// Emulated wait status for use by `process_unsupported.rs`
///
/// Uses the "traditional unix" encoding. For use on platfors which are `#[cfg(unix)]`
diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/pal/unix/process/process_vxworks.rs
index 26b8a0a..0477b3d 100644
--- a/library/std/src/sys/pal/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/pal/unix/process/process_vxworks.rs
@@ -1,12 +1,12 @@
-use crate::fmt;
+#![forbid(unsafe_op_in_unsafe_fn)]
+use libc::{self, c_char, c_int, RTP_ID};
+
use crate::io::{self, ErrorKind};
use crate::num::NonZero;
-use crate::sys;
use crate::sys::cvt;
use crate::sys::pal::unix::thread;
use crate::sys::process::process_common::*;
-use libc::RTP_ID;
-use libc::{self, c_char, c_int};
+use crate::{fmt, sys};
////////////////////////////////////////////////////////////////////////////////
// Command
diff --git a/library/std/src/sys/pal/unix/process/zircon.rs b/library/std/src/sys/pal/unix/process/zircon.rs
index 2e59648..4035e23 100644
--- a/library/std/src/sys/pal/unix/process/zircon.rs
+++ b/library/std/src/sys/pal/unix/process/zircon.rs
@@ -1,11 +1,11 @@
#![allow(non_camel_case_types, unused)]
+use libc::{c_int, c_void, size_t};
+
use crate::io;
use crate::mem::MaybeUninit;
use crate::os::raw::c_char;
-use libc::{c_int, c_void, size_t};
-
pub type zx_handle_t = u32;
pub type zx_vaddr_t = usize;
pub type zx_rights_t = u32;
diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs
index e6df109..cc0852a 100644
--- a/library/std/src/sys/pal/unix/rand.rs
+++ b/library/std/src/sys/pal/unix/rand.rs
@@ -2,7 +2,9 @@
const KEY_LEN: usize = core::mem::size_of::<u64>();
let mut v = [0u8; KEY_LEN * 2];
- imp::fill_bytes(&mut v);
+ if let Err(err) = read(&mut v) {
+ panic!("failed to retrieve random hash map seed: {err}");
+ }
let key1 = v[0..KEY_LEN].try_into().unwrap();
let key2 = v[KEY_LEN..].try_into().unwrap();
@@ -10,28 +12,78 @@
(u64::from_ne_bytes(key1), u64::from_ne_bytes(key2))
}
-#[cfg(all(
- unix,
- not(target_os = "openbsd"),
- not(target_os = "netbsd"),
- not(target_os = "fuchsia"),
- not(target_os = "redox"),
- not(target_os = "vxworks"),
- not(target_os = "emscripten"),
- not(target_os = "vita"),
- not(target_vendor = "apple"),
+cfg_if::cfg_if! {
+ if #[cfg(any(
+ target_vendor = "apple",
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "vita",
+ all(target_os = "netbsd", not(netbsd10)),
+ target_os = "fuchsia",
+ target_os = "vxworks",
+ ))] {
+ // Some systems have a syscall that directly retrieves random data.
+ // If that is guaranteed to be available, use it.
+ use imp::syscall as read;
+ } else {
+ // Otherwise, try the syscall to see if it exists only on some systems
+ // and fall back to reading from the random device otherwise.
+ fn read(bytes: &mut [u8]) -> crate::io::Result<()> {
+ use crate::fs::File;
+ use crate::io::Read;
+ use crate::sync::OnceLock;
+
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "solaris",
+ target_os = "illumos",
+ netbsd10,
+ ))]
+ if let Some(res) = imp::syscall(bytes) {
+ return res;
+ }
+
+ const PATH: &'static str = if cfg!(target_os = "redox") {
+ "/scheme/rand"
+ } else {
+ "/dev/urandom"
+ };
+
+ static FILE: OnceLock<File> = OnceLock::new();
+
+ FILE.get_or_try_init(|| File::open(PATH))?.read_exact(bytes)
+ }
+ }
+}
+
+// All these systems a `getrandom` syscall.
+//
+// It is not guaranteed to be available, so return None to fallback to the file
+// implementation.
+#[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "espidf",
+ target_os = "horizon",
+ target_os = "freebsd",
+ target_os = "dragonfly",
+ target_os = "solaris",
+ target_os = "illumos",
+ netbsd10,
))]
mod imp {
- use crate::fs::File;
- use crate::io::Read;
-
- #[cfg(any(target_os = "linux", target_os = "android"))]
- use crate::sys::weak::syscall;
+ use crate::io::{Error, Result};
+ use crate::sync::atomic::{AtomicBool, Ordering};
+ use crate::sys::os::errno;
#[cfg(any(target_os = "linux", target_os = "android"))]
fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
- use crate::sync::atomic::{AtomicBool, Ordering};
- use crate::sys::os::errno;
+ use crate::sys::weak::syscall;
// A weak symbol allows interposition, e.g. for perf measurements that want to
// disable randomness for consistency. Otherwise, we'll try a raw syscall.
@@ -60,6 +112,7 @@ fn getrandom(
}
#[cfg(any(
+ target_os = "dragonfly",
target_os = "espidf",
target_os = "horizon",
target_os = "freebsd",
@@ -71,51 +124,11 @@ fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
}
- #[cfg(target_os = "dragonfly")]
- fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
- extern "C" {
- fn getrandom(
- buf: *mut libc::c_void,
- buflen: libc::size_t,
- flags: libc::c_uint,
- ) -> libc::ssize_t;
- }
- unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
- }
-
- #[cfg(not(any(
- target_os = "linux",
- target_os = "android",
- target_os = "espidf",
- target_os = "horizon",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "solaris",
- target_os = "illumos",
- netbsd10
- )))]
- fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
- false
- }
-
- #[cfg(any(
- target_os = "linux",
- target_os = "android",
- target_os = "espidf",
- target_os = "horizon",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "solaris",
- target_os = "illumos",
- netbsd10
- ))]
- fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
- use crate::sync::atomic::{AtomicBool, Ordering};
- use crate::sys::os::errno;
-
+ pub fn syscall(v: &mut [u8]) -> Option<Result<()>> {
static GETRANDOM_UNAVAILABLE: AtomicBool = AtomicBool::new(false);
+
if GETRANDOM_UNAVAILABLE.load(Ordering::Relaxed) {
- return false;
+ return None;
}
let mut read = 0;
@@ -126,8 +139,7 @@ fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
if err == libc::EINTR {
continue;
} else if err == libc::ENOSYS || err == libc::EPERM {
- // Fall back to reading /dev/urandom if `getrandom` is not
- // supported on the current kernel.
+ // `getrandom` is not supported on the current system.
//
// Also fall back in case it is disabled by something like
// seccomp or inside of docker.
@@ -143,122 +155,83 @@ fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
// https://github.com/moby/moby/issues/42680
//
GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
- return false;
+ return None;
} else if err == libc::EAGAIN {
- return false;
+ // getrandom has failed because it would have blocked as the
+ // non-blocking pool (urandom) has not been initialized in
+ // the kernel yet due to a lack of entropy. Fallback to
+ // reading from `/dev/urandom` which will return potentially
+ // insecure random data to avoid blocking applications which
+ // could depend on this call without ever knowing they do and
+ // don't have a work around.
+ return None;
} else {
- panic!("unexpected getrandom error: {err}");
+ return Some(Err(Error::from_raw_os_error(err)));
}
} else {
read += result as usize;
}
}
- true
- }
- pub fn fill_bytes(v: &mut [u8]) {
- // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN,
- // meaning it would have blocked because the non-blocking pool (urandom)
- // has not initialized in the kernel yet due to a lack of entropy. The
- // fallback we do here is to avoid blocking applications which could
- // depend on this call without ever knowing they do and don't have a
- // work around. The PRNG of /dev/urandom will still be used but over a
- // possibly predictable entropy pool.
- if getrandom_fill_bytes(v) {
- return;
- }
-
- // getrandom failed because it is permanently or temporarily (because
- // of missing entropy) unavailable. Open /dev/urandom, read from it,
- // and close it again.
- let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom");
- file.read_exact(v).expect("failed to read /dev/urandom")
+ Some(Ok(()))
}
}
-#[cfg(target_vendor = "apple")]
+#[cfg(any(
+ target_os = "macos", // Supported since macOS 10.12+.
+ target_os = "openbsd",
+ target_os = "emscripten",
+ target_os = "vita",
+))]
mod imp {
- use crate::io;
- use libc::{c_int, c_void, size_t};
+ use crate::io::{Error, Result};
- #[inline(always)]
- fn random_failure() -> ! {
- panic!("unexpected random generation error: {}", io::Error::last_os_error());
- }
-
- #[cfg(target_os = "macos")]
- fn getentropy_fill_bytes(v: &mut [u8]) {
- extern "C" {
- fn getentropy(bytes: *mut c_void, count: size_t) -> c_int;
- }
-
+ pub fn syscall(v: &mut [u8]) -> Result<()> {
// getentropy(2) permits a maximum buffer size of 256 bytes
for s in v.chunks_mut(256) {
- let ret = unsafe { getentropy(s.as_mut_ptr().cast(), s.len()) };
+ let ret = unsafe { libc::getentropy(s.as_mut_ptr().cast(), s.len()) };
if ret == -1 {
- random_failure()
+ return Err(Error::last_os_error());
}
}
- }
- #[cfg(not(target_os = "macos"))]
- fn ccrandom_fill_bytes(v: &mut [u8]) {
+ Ok(())
+ }
+}
+
+// On Apple platforms, `CCRandomGenerateBytes` and `SecRandomCopyBytes` simply
+// call into `CCRandomCopyBytes` with `kCCRandomDefault`. `CCRandomCopyBytes`
+// manages a CSPRNG which is seeded from the kernel's CSPRNG and which runs on
+// its own thread accessed via GCD. This seems needlessly heavyweight for our purposes
+// so we only use it when `getentropy` is blocked, which appears to be the case
+// on all platforms except macOS (see #102643).
+//
+// `CCRandomGenerateBytes` is used instead of `SecRandomCopyBytes` because the former is accessible
+// via `libSystem` (libc) while the other needs to link to `Security.framework`.
+#[cfg(all(target_vendor = "apple", not(target_os = "macos")))]
+mod imp {
+ use libc::size_t;
+
+ use crate::ffi::{c_int, c_void};
+ use crate::io::{Error, Result};
+
+ pub fn syscall(v: &mut [u8]) -> Result<()> {
extern "C" {
fn CCRandomGenerateBytes(bytes: *mut c_void, count: size_t) -> c_int;
}
let ret = unsafe { CCRandomGenerateBytes(v.as_mut_ptr().cast(), v.len()) };
- if ret == -1 {
- random_failure()
- }
- }
-
- pub fn fill_bytes(v: &mut [u8]) {
- // All supported versions of macOS (10.12+) support getentropy.
- //
- // `getentropy` is measurably faster (via Divan) then the other alternatives so its preferred
- // when usable.
- #[cfg(target_os = "macos")]
- getentropy_fill_bytes(v);
-
- // On Apple platforms, `CCRandomGenerateBytes` and `SecRandomCopyBytes` simply
- // call into `CCRandomCopyBytes` with `kCCRandomDefault`. `CCRandomCopyBytes`
- // manages a CSPRNG which is seeded from the kernel's CSPRNG and which runs on
- // its own thread accessed via GCD. This seems needlessly heavyweight for our purposes
- // so we only use it on non-Mac OSes where the better entrypoints are blocked.
- //
- // `CCRandomGenerateBytes` is used instead of `SecRandomCopyBytes` because the former is accessible
- // via `libSystem` (libc) while the other needs to link to `Security.framework`.
- //
- // Note that while `getentropy` has a available attribute in the macOS headers, the lack
- // of a header in the iOS (and others) SDK means that its can cause app store rejections.
- // Just use `CCRandomGenerateBytes` instead.
- #[cfg(not(target_os = "macos"))]
- ccrandom_fill_bytes(v);
- }
-}
-
-#[cfg(any(target_os = "openbsd", target_os = "emscripten", target_os = "vita"))]
-mod imp {
- use crate::sys::os::errno;
-
- pub fn fill_bytes(v: &mut [u8]) {
- // getentropy(2) permits a maximum buffer size of 256 bytes
- for s in v.chunks_mut(256) {
- let ret = unsafe { libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len()) };
- if ret == -1 {
- panic!("unexpected getentropy error: {}", errno());
- }
- }
+ if ret != -1 { Ok(()) } else { Err(Error::last_os_error()) }
}
}
// FIXME: once the 10.x release becomes the minimum, this can be dropped for simplification.
#[cfg(all(target_os = "netbsd", not(netbsd10)))]
mod imp {
+ use crate::io::{Error, Result};
use crate::ptr;
- pub fn fill_bytes(v: &mut [u8]) {
+ pub fn syscall(v: &mut [u8]) -> Result<()> {
let mib = [libc::CTL_KERN, libc::KERN_ARND];
// kern.arandom permits a maximum buffer size of 256 bytes
for s in v.chunks_mut(256) {
@@ -273,64 +246,57 @@ pub fn fill_bytes(v: &mut [u8]) {
0,
)
};
- if ret == -1 || s_len != s.len() {
- panic!(
- "kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})",
- ret,
- s.len(),
- s_len
- );
+ if ret == -1 {
+ return Err(Error::last_os_error());
+ } else if s_len != s.len() {
+ // FIXME(joboet): this can't actually happen, can it?
+ panic!("read less bytes than requested from kern.arandom");
}
}
+
+ Ok(())
}
}
#[cfg(target_os = "fuchsia")]
mod imp {
+ use crate::io::Result;
+
#[link(name = "zircon")]
extern "C" {
fn zx_cprng_draw(buffer: *mut u8, len: usize);
}
- pub fn fill_bytes(v: &mut [u8]) {
- unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
- }
-}
-
-#[cfg(target_os = "redox")]
-mod imp {
- use crate::fs::File;
- use crate::io::Read;
-
- pub fn fill_bytes(v: &mut [u8]) {
- // Open rand:, read from it, and close it again.
- let mut file = File::open("rand:").expect("failed to open rand:");
- file.read_exact(v).expect("failed to read rand:")
+ pub fn syscall(v: &mut [u8]) -> Result<()> {
+ unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) };
+ Ok(())
}
}
#[cfg(target_os = "vxworks")]
mod imp {
- use crate::io;
- use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
+ use core::sync::atomic::AtomicBool;
+ use core::sync::atomic::Ordering::Relaxed;
- pub fn fill_bytes(v: &mut [u8]) {
+ use crate::io::{Error, Result};
+
+ pub fn syscall(v: &mut [u8]) -> Result<()> {
static RNG_INIT: AtomicBool = AtomicBool::new(false);
while !RNG_INIT.load(Relaxed) {
let ret = unsafe { libc::randSecure() };
if ret < 0 {
- panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
+ return Err(Error::last_os_error());
} else if ret > 0 {
RNG_INIT.store(true, Relaxed);
break;
}
+
unsafe { libc::usleep(10) };
}
+
let ret = unsafe {
libc::randABytes(v.as_mut_ptr() as *mut libc::c_uchar, v.len() as libc::c_int)
};
- if ret < 0 {
- panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
- }
+ if ret >= 0 { Ok(()) } else { Err(Error::last_os_error()) }
}
}
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 6eeec48..9ff44b5 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -1,10 +1,8 @@
#![cfg_attr(test, allow(dead_code))]
+pub use self::imp::{cleanup, init};
use self::imp::{drop_handler, make_handler};
-pub use self::imp::cleanup;
-pub use self::imp::init;
-
pub struct Handler {
data: *mut libc::c_void,
}
@@ -37,24 +35,23 @@ fn drop(&mut self) {
target_os = "solaris"
))]
mod imp {
- use super::Handler;
- use crate::cell::Cell;
- use crate::io;
- use crate::mem;
- use crate::ops::Range;
- use crate::ptr;
- use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
- use crate::sync::OnceLock;
- use crate::sys::pal::unix::os;
- use crate::thread;
-
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::{mmap as mmap64, mprotect, munmap};
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::{mmap64, mprotect, munmap};
- use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSEGV, SIG_DFL};
- use libc::{sigaltstack, SS_DISABLE};
- use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
+ use libc::{
+ sigaction, sigaltstack, sighandler_t, MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE,
+ PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSEGV, SIG_DFL,
+ SS_DISABLE,
+ };
+
+ use super::Handler;
+ use crate::cell::Cell;
+ use crate::ops::Range;
+ use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
+ use crate::sync::OnceLock;
+ use crate::sys::pal::unix::os;
+ use crate::{io, mem, ptr, thread};
// We use a TLS variable to store the address of the guard page. While TLS
// variables are not guaranteed to be signal-safe, this works out in practice
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 483697b..0fa610e 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -1,16 +1,13 @@
-use crate::cmp;
use crate::ffi::CStr;
-use crate::io;
use crate::mem::{self, ManuallyDrop};
use crate::num::NonZero;
-use crate::ptr;
-use crate::sys::{os, stack_overflow};
-use crate::time::Duration;
-
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use crate::sys::weak::dlsym;
-#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
+#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))]
use crate::sys::weak::weak;
+use crate::sys::{os, stack_overflow};
+use crate::time::Duration;
+use crate::{cmp, io, ptr};
#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#[cfg(target_os = "l4re")]
@@ -215,17 +212,31 @@ pub fn set_name(name: &CStr) {
}
}
+ #[cfg(target_os = "vxworks")]
+ pub fn set_name(name: &CStr) {
+ // FIXME(libc): adding real STATUS, ERROR type eventually.
+ extern "C" {
+ fn taskNameSet(task_id: libc::TASK_ID, task_name: *mut libc::c_char) -> libc::c_int;
+ }
+
+ // VX_TASK_NAME_LEN is 31 in VxWorks 7.
+ const VX_TASK_NAME_LEN: usize = 31;
+
+ let mut name = truncate_cstr::<{ VX_TASK_NAME_LEN }>(name);
+ let res = unsafe { taskNameSet(libc::taskIdSelf(), name.as_mut_ptr()) };
+ debug_assert_eq!(res, libc::OK);
+ }
+
#[cfg(any(
target_env = "newlib",
target_os = "l4re",
target_os = "emscripten",
target_os = "redox",
- target_os = "vxworks",
target_os = "hurd",
target_os = "aix",
))]
pub fn set_name(_name: &CStr) {
- // Newlib, Emscripten, and VxWorks have no way to set a thread name.
+ // Newlib and Emscripten have no way to set a thread name.
}
#[cfg(not(target_os = "espidf"))]
@@ -294,6 +305,7 @@ fn drop(&mut self) {
target_os = "nto",
target_os = "solaris",
target_os = "illumos",
+ target_os = "vxworks",
target_vendor = "apple",
))]
fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
@@ -458,8 +470,20 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
Ok(NonZero::new_unchecked(sinfo.cpu_count as usize))
}
+ } else if #[cfg(target_os = "vxworks")] {
+ // Note: there is also `vxCpuConfiguredGet`, closer to _SC_NPROCESSORS_CONF
+ // expectations than the actual cores availability.
+ extern "C" {
+ fn vxCpuEnabledGet() -> libc::cpuset_t;
+ }
+
+ // SAFETY: `vxCpuEnabledGet` always fetches a mask with at least one bit set
+ unsafe{
+ let set = vxCpuEnabledGet();
+ Ok(NonZero::new_unchecked(set.count_ones() as usize))
+ }
} else {
- // FIXME: implement on vxWorks, Redox, l4re
+ // FIXME: implement on Redox, l4re
Err(io::const_io_error!(io::ErrorKind::Unsupported, "Getting the number of hardware threads is not supported on the target platform"))
}
}
@@ -475,11 +499,9 @@ mod cgroups {
use crate::borrow::Cow;
use crate::ffi::OsString;
use crate::fs::{exists, File};
- use crate::io::Read;
- use crate::io::{BufRead, BufReader};
+ use crate::io::{BufRead, BufReader, Read};
use crate::os::unix::ffi::OsStringExt;
- use crate::path::Path;
- use crate::path::PathBuf;
+ use crate::path::{Path, PathBuf};
use crate::str::from_utf8;
#[derive(PartialEq)]
diff --git a/library/std/src/sys/pal/unix/thread_parking.rs b/library/std/src/sys/pal/unix/thread_parking.rs
index 1366410..1da5fce 100644
--- a/library/std/src/sys/pal/unix/thread_parking.rs
+++ b/library/std/src/sys/pal/unix/thread_parking.rs
@@ -2,10 +2,11 @@
// separate modules for each platform.
#![cfg(target_os = "netbsd")]
+use libc::{_lwp_self, c_long, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC};
+
use crate::ffi::{c_int, c_void};
use crate::ptr;
use crate::time::Duration;
-use libc::{_lwp_self, c_long, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC};
extern "C" {
fn ___lwp_park60(
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index 4765a28..35762f5 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -23,9 +23,8 @@
use crate::ffi::CStr;
use crate::marker::PhantomData;
-use crate::mem;
-use crate::ptr;
use crate::sync::atomic::{self, AtomicPtr, Ordering};
+use crate::{mem, ptr};
// We can use true weak linkage on ELF targets.
#[cfg(all(unix, not(target_vendor = "apple")))]
@@ -169,14 +168,7 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
if let Some(fun) = $name.get() {
fun($($arg_name),*)
} else {
- // This looks like a hack, but concat_idents only accepts idents
- // (not paths).
- use libc::*;
-
- syscall(
- concat_idents!(SYS_, $name),
- $($arg_name),*
- ) as $ret
+ libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
}
}
)
@@ -186,14 +178,7 @@ unsafe fn $name($($arg_name:$t),*) -> $ret {
pub(crate) macro raw_syscall {
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
unsafe fn $name($($arg_name:$t),*) -> $ret {
- // This looks like a hack, but concat_idents only accepts idents
- // (not paths).
- use libc::*;
-
- syscall(
- concat_idents!(SYS_, $name),
- $($arg_name),*
- ) as $ret
+ libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret
}
)
}
diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs
index 3be9889..481fd62 100644
--- a/library/std/src/sys/pal/unsupported/os.rs
+++ b/library/std/src/sys/pal/unsupported/os.rs
@@ -1,10 +1,9 @@
use super::unsupported;
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
+use crate::{fmt, io};
pub fn errno() -> i32 {
0
diff --git a/library/std/src/sys/pal/unsupported/pipe.rs b/library/std/src/sys/pal/unsupported/pipe.rs
index 781eafe..6799d21 100644
--- a/library/std/src/sys/pal/unsupported/pipe.rs
+++ b/library/std/src/sys/pal/unsupported/pipe.rs
@@ -1,7 +1,5 @@
-use crate::{
- fmt,
- io::{self, BorrowedCursor, IoSlice, IoSliceMut},
-};
+use crate::fmt;
+use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
pub struct AnonPipe(!);
diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/pal/unsupported/process.rs
index 2445d90..40231bf 100644
--- a/library/std/src/sys/pal/unsupported/process.rs
+++ b/library/std/src/sys/pal/unsupported/process.rs
@@ -1,14 +1,12 @@
+pub use crate::ffi::OsString as EnvKey;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::num::NonZero;
use crate::path::Path;
use crate::sys::fs::File;
use crate::sys::pipe::AnonPipe;
use crate::sys::unsupported;
use crate::sys_common::process::{CommandEnv, CommandEnvs};
-
-pub use crate::ffi::OsString as EnvKey;
+use crate::{fmt, io};
////////////////////////////////////////////////////////////////////////////////
// Command
diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/pal/wasi/args.rs
index c42c310..6b6d1b8 100644
--- a/library/std/src/sys/pal/wasi/args.rs
+++ b/library/std/src/sys/pal/wasi/args.rs
@@ -1,9 +1,8 @@
#![deny(unsafe_op_in_unsafe_fn)]
use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt;
use crate::os::wasi::ffi::OsStrExt;
-use crate::vec;
+use crate::{fmt, vec};
pub struct Args {
iter: vec::IntoIter<OsString>,
diff --git a/library/std/src/sys/pal/wasi/fs.rs b/library/std/src/sys/pal/wasi/fs.rs
index c58e6a0..1190088 100644
--- a/library/std/src/sys/pal/wasi/fs.rs
+++ b/library/std/src/sys/pal/wasi/fs.rs
@@ -2,22 +2,19 @@
use super::fd::WasiFd;
use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
-use crate::iter;
use crate::mem::{self, ManuallyDrop};
use crate::os::raw::c_int;
use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::path::{Path, PathBuf};
-use crate::ptr;
use crate::sync::Arc;
use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
-
pub use crate::sys_common::fs::exists;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::{fmt, iter, ptr};
pub struct File {
fd: WasiFd,
diff --git a/library/std/src/sys/pal/wasi/helpers.rs b/library/std/src/sys/pal/wasi/helpers.rs
index 82149ce..4b770ee 100644
--- a/library/std/src/sys/pal/wasi/helpers.rs
+++ b/library/std/src/sys/pal/wasi/helpers.rs
@@ -1,5 +1,4 @@
-use crate::io as std_io;
-use crate::mem;
+use crate::{io as std_io, mem};
#[inline]
pub fn is_interrupted(errno: i32) -> bool {
diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs
index d8fe06d..f4dc3eb 100644
--- a/library/std/src/sys/pal/wasi/mod.rs
+++ b/library/std/src/sys/pal/wasi/mod.rs
@@ -48,8 +48,5 @@
// import conflict rules. If we glob export `helpers` and `common` together,
// then the compiler complains about conflicts.
-pub use helpers::abort_internal;
-pub use helpers::decode_error_kind;
use helpers::err2io;
-pub use helpers::hashmap_random_keys;
-pub use helpers::is_interrupted;
+pub use helpers::{abort_internal, decode_error_kind, hashmap_random_keys, is_interrupted};
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
index e962969..f5b17d9 100644
--- a/library/std/src/sys/pal/wasi/os.rs
+++ b/library/std/src/sys/pal/wasi/os.rs
@@ -1,18 +1,16 @@
#![deny(unsafe_op_in_unsafe_fn)]
+use core::slice::memchr;
+
use crate::error::Error as StdError;
use crate::ffi::{CStr, OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::ops::Drop;
use crate::os::wasi::prelude::*;
use crate::path::{self, PathBuf};
-use crate::str;
use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
use crate::sys::unsupported;
-use crate::vec;
-use core::slice::memchr;
+use crate::{fmt, io, str, vec};
// Add a few symbols not in upstream `libc` just yet.
mod libc {
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index 2a3a39a..c37acd8 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -1,9 +1,8 @@
use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
use crate::num::NonZero;
use crate::sys::unsupported;
use crate::time::Duration;
+use crate::{io, mem};
cfg_if::cfg_if! {
if #[cfg(target_feature = "atomics")] {
diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs
index 0930d2e..f20630e 100644
--- a/library/std/src/sys/pal/wasip2/mod.rs
+++ b/library/std/src/sys/pal/wasip2/mod.rs
@@ -51,10 +51,7 @@
// import conflict rules. If we glob export `helpers` and `common` together,
// then the compiler complains about conflicts.
-pub use helpers::abort_internal;
-pub use helpers::decode_error_kind;
use helpers::err2io;
-pub use helpers::hashmap_random_keys;
-pub use helpers::is_interrupted;
+pub use helpers::{abort_internal, decode_error_kind, hashmap_random_keys, is_interrupted};
mod cabi_realloc;
diff --git a/library/std/src/sys/pal/wasm/alloc.rs b/library/std/src/sys/pal/wasm/alloc.rs
index b74ce0d..ef9d753 100644
--- a/library/std/src/sys/pal/wasm/alloc.rs
+++ b/library/std/src/sys/pal/wasm/alloc.rs
@@ -57,10 +57,8 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
#[cfg(target_feature = "atomics")]
mod lock {
- use crate::sync::atomic::{
- AtomicI32,
- Ordering::{Acquire, Release},
- };
+ use crate::sync::atomic::AtomicI32;
+ use crate::sync::atomic::Ordering::{Acquire, Release};
static LOCKED: AtomicI32 = AtomicI32::new(0);
diff --git a/library/std/src/sys/pal/wasm/atomics/futex.rs b/library/std/src/sys/pal/wasm/atomics/futex.rs
index 3584138..42913a9 100644
--- a/library/std/src/sys/pal/wasm/atomics/futex.rs
+++ b/library/std/src/sys/pal/wasm/atomics/futex.rs
@@ -24,7 +24,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
}
}
-/// Wake up one thread that's blocked on futex_wait on this futex.
+/// Wakes up one thread that's blocked on `futex_wait` on this futex.
///
/// Returns true if this actually woke up such a thread,
/// or false if no thread was waiting on this futex.
@@ -32,7 +32,7 @@ pub fn futex_wake(futex: &AtomicU32) -> bool {
unsafe { wasm::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1) > 0 }
}
-/// Wake up all threads that are waiting on futex_wait on this futex.
+/// Wakes up all threads that are waiting on `futex_wait` on this futex.
pub fn futex_wake_all(futex: &AtomicU32) {
unsafe {
wasm::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, i32::MAX as u32);
diff --git a/library/std/src/sys/pal/windows/alloc.rs b/library/std/src/sys/pal/windows/alloc.rs
index 020a2a4..92b68b2 100644
--- a/library/std/src/sys/pal/windows/alloc.rs
+++ b/library/std/src/sys/pal/windows/alloc.rs
@@ -1,10 +1,11 @@
+use core::mem::MaybeUninit;
+
use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ffi::c_void;
use crate::ptr;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys::c::{self, windows_targets};
use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
-use core::mem::MaybeUninit;
#[cfg(test)]
mod tests;
diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs
index 5098c05..66e75a8 100644
--- a/library/std/src/sys/pal/windows/args.rs
+++ b/library/std/src/sys/pal/windows/args.rs
@@ -8,8 +8,6 @@
use super::os::current_exe;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::num::NonZero;
use crate::os::windows::prelude::*;
use crate::path::{Path, PathBuf};
@@ -18,9 +16,7 @@
use crate::sys::{c, to_u16s};
use crate::sys_common::wstr::WStrUnits;
use crate::sys_common::AsInner;
-use crate::vec;
-
-use crate::iter;
+use crate::{fmt, io, iter, vec};
/// This is the const equivalent to `NonZero::new(n).unwrap()`
///
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index f7ec17f..08b7518 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -6,8 +6,7 @@
#![allow(clippy::style)]
use core::ffi::{c_uint, c_ulong, c_ushort, c_void, CStr};
-use core::mem;
-use core::ptr;
+use core::{mem, ptr};
pub(super) mod windows_targets;
diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs
index ea19bd1..d99d493 100644
--- a/library/std/src/sys/pal/windows/fs.rs
+++ b/library/std/src/sys/pal/windows/fs.rs
@@ -1,26 +1,21 @@
use core::ptr::addr_of;
-use crate::os::windows::prelude::*;
-
+use super::api::{self, WinError};
+use super::{to_u16s, IoResult};
use crate::borrow::Cow;
use crate::ffi::{c_void, OsStr, OsString};
-use crate::fmt;
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
use crate::mem::{self, MaybeUninit};
use crate::os::windows::io::{AsHandle, BorrowedHandle};
+use crate::os::windows::prelude::*;
use crate::path::{Path, PathBuf};
-use crate::ptr;
-use crate::slice;
use crate::sync::Arc;
use crate::sys::handle::Handle;
+use crate::sys::path::maybe_verbatim;
use crate::sys::time::SystemTime;
use crate::sys::{c, cvt, Align8};
use crate::sys_common::{AsInner, FromInner, IntoInner};
-use crate::thread;
-
-use super::api::{self, WinError};
-use super::{to_u16s, IoResult};
-use crate::sys::path::maybe_verbatim;
+use crate::{fmt, ptr, slice, thread};
pub struct File {
handle: Handle,
@@ -637,7 +632,7 @@ pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
Ok(())
}
- /// Get only basic file information such as attributes and file times.
+ /// Gets only basic file information such as attributes and file times.
fn basic_info(&self) -> io::Result<c::FILE_BASIC_INFO> {
unsafe {
let mut info: c::FILE_BASIC_INFO = mem::zeroed();
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
index c54810e..8c5081a 100644
--- a/library/std/src/sys/pal/windows/futex.rs
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -1,14 +1,13 @@
-use super::api::{self, WinError};
-use crate::sys::c;
-use crate::sys::dur2timeout;
use core::ffi::c_void;
-use core::mem;
-use core::ptr;
use core::sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
};
use core::time::Duration;
+use core::{mem, ptr};
+
+use super::api::{self, WinError};
+use crate::sys::{c, dur2timeout};
/// An atomic for use as a futex that is at least 8-bits but may be larger.
pub type SmallAtomic = AtomicU8;
diff --git a/library/std/src/sys/pal/windows/handle.rs b/library/std/src/sys/pal/windows/handle.rs
index e5b2da6..82a880f 100644
--- a/library/std/src/sys/pal/windows/handle.rs
+++ b/library/std/src/sys/pal/windows/handle.rs
@@ -3,17 +3,15 @@
#[cfg(test)]
mod tests;
+use core::ffi::c_void;
+use core::{cmp, mem, ptr};
+
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut, Read};
use crate::os::windows::io::{
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle,
};
-use crate::sys::c;
-use crate::sys::cvt;
+use crate::sys::{c, cvt};
use crate::sys_common::{AsInner, FromInner, IntoInner};
-use core::cmp;
-use core::ffi::c_void;
-use core::mem;
-use core::ptr;
/// An owned container for `HANDLE` object, closing them on Drop.
///
diff --git a/library/std/src/sys/pal/windows/io.rs b/library/std/src/sys/pal/windows/io.rs
index bf3dfdf..785a3f6 100644
--- a/library/std/src/sys/pal/windows/io.rs
+++ b/library/std/src/sys/pal/windows/io.rs
@@ -1,9 +1,10 @@
+use core::ffi::c_void;
+
use crate::marker::PhantomData;
use crate::mem::size_of;
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
use crate::slice;
use crate::sys::c;
-use core::ffi::c_void;
#[derive(Copy, Clone)]
#[repr(transparent)]
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index 881ca17..6ed77fb 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -1,6 +1,7 @@
#![allow(missing_docs, nonstandard_style)]
#![forbid(unsafe_op_in_unsafe_fn)]
+pub use self::rand::hashmap_random_keys;
use crate::ffi::{OsStr, OsString};
use crate::io::ErrorKind;
use crate::mem::MaybeUninit;
@@ -9,8 +10,6 @@
use crate::sys::pal::windows::api::wide_str;
use crate::time::Duration;
-pub use self::rand::hashmap_random_keys;
-
#[macro_use]
pub mod compat;
diff --git a/library/std/src/sys/pal/windows/net.rs b/library/std/src/sys/pal/windows/net.rs
index b7ecff0..ce995f5 100644
--- a/library/std/src/sys/pal/windows/net.rs
+++ b/library/std/src/sys/pal/windows/net.rs
@@ -1,21 +1,17 @@
#![unstable(issue = "none", feature = "windows_net")]
-use crate::cmp;
+use core::ffi::{c_int, c_long, c_ulong, c_ushort};
+
use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut, Read};
-use crate::mem;
use crate::net::{Shutdown, SocketAddr};
use crate::os::windows::io::{
AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
};
-use crate::ptr;
use crate::sync::OnceLock;
-use crate::sys;
use crate::sys::c;
-use crate::sys_common::net;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{net, AsInner, FromInner, IntoInner};
use crate::time::Duration;
-
-use core::ffi::{c_int, c_long, c_ulong, c_ushort};
+use crate::{cmp, mem, ptr, sys};
#[allow(non_camel_case_types)]
pub type wrlen_t = i32;
@@ -25,9 +21,10 @@ pub mod netc {
//!
//! Some Windows API types are not quite what's expected by our cross-platform
//! net code. E.g. naming differences or different pointer types.
- use crate::sys::c::{self, ADDRESS_FAMILY, ADDRINFOA, SOCKADDR, SOCKET};
+
use core::ffi::{c_char, c_int, c_uint, c_ulong, c_ushort, c_void};
+ use crate::sys::c::{self, ADDRESS_FAMILY, ADDRINFOA, SOCKADDR, SOCKET};
// re-exports from Windows API bindings.
pub use crate::sys::c::{
bind, connect, freeaddrinfo, getpeername, getsockname, getsockopt, listen, setsockopt,
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index f1f4d3a..5242bc9 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -5,20 +5,15 @@
#[cfg(test)]
mod tests;
-use crate::os::windows::prelude::*;
-
-use crate::error::Error as StdError;
-use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
-use crate::os::windows::ffi::EncodeWide;
-use crate::path::{self, PathBuf};
-use crate::ptr;
-use crate::slice;
-use crate::sys::{c, cvt};
-
use super::api::{self, WinError};
use super::to_u16s;
+use crate::error::Error as StdError;
+use crate::ffi::{OsStr, OsString};
+use crate::os::windows::ffi::EncodeWide;
+use crate::os::windows::prelude::*;
+use crate::path::{self, PathBuf};
+use crate::sys::{c, cvt};
+use crate::{fmt, io, ptr, slice};
pub fn errno() -> i32 {
api::get_last_error().code as i32
diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs
index 01433d6..7d1b5ac 100644
--- a/library/std/src/sys/pal/windows/pipe.rs
+++ b/library/std/src/sys/pal/windows/pipe.rs
@@ -1,18 +1,15 @@
-use crate::os::windows::prelude::*;
-
use crate::ffi::OsStr;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
-use crate::mem;
+use crate::os::windows::prelude::*;
use crate::path::Path;
-use crate::ptr;
use crate::sync::atomic::AtomicUsize;
use crate::sync::atomic::Ordering::Relaxed;
-use crate::sys::c;
use crate::sys::fs::{File, OpenOptions};
use crate::sys::handle::Handle;
-use crate::sys::hashmap_random_keys;
use crate::sys::pal::windows::api::{self, WinError};
+use crate::sys::{c, hashmap_random_keys};
use crate::sys_common::{FromInner, IntoInner};
+use crate::{mem, ptr};
////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
@@ -39,23 +36,6 @@ pub struct Pipes {
pub theirs: AnonPipe,
}
-/// Create true unnamed anonymous pipe.
-pub fn unnamed_anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
- let mut read_pipe = c::INVALID_HANDLE_VALUE;
- let mut write_pipe = c::INVALID_HANDLE_VALUE;
-
- let ret = unsafe { c::CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) };
-
- if ret == 0 {
- Err(io::Error::last_os_error())
- } else {
- Ok((
- AnonPipe::from_inner(unsafe { Handle::from_raw_handle(read_pipe) }),
- AnonPipe::from_inner(unsafe { Handle::from_raw_handle(write_pipe) }),
- ))
- }
-}
-
/// Although this looks similar to `anon_pipe` in the Unix module it's actually
/// subtly different. Here we'll return two pipes in the `Pipes` return value,
/// but one is intended for "us" where as the other is intended for "someone
diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs
index 76d2cb7..06eae5a 100644
--- a/library/std/src/sys/pal/windows/process.rs
+++ b/library/std/src/sys/pal/windows/process.rs
@@ -3,35 +3,28 @@
#[cfg(test)]
mod tests;
-use crate::cmp;
+use core::ffi::c_void;
+
+use super::api::{self, WinError};
use crate::collections::BTreeMap;
-use crate::env;
use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX};
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
use crate::io::{self, Error, ErrorKind};
-use crate::mem;
use crate::mem::MaybeUninit;
use crate::num::NonZero;
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle};
use crate::path::{Path, PathBuf};
-use crate::ptr;
use crate::sync::Mutex;
use crate::sys::args::{self, Arg};
use crate::sys::c::{self, EXIT_FAILURE, EXIT_SUCCESS};
-use crate::sys::cvt;
use crate::sys::fs::{File, OpenOptions};
use crate::sys::handle::Handle;
-use crate::sys::path;
use crate::sys::pipe::{self, AnonPipe};
-use crate::sys::stdio;
+use crate::sys::{cvt, path, stdio};
use crate::sys_common::process::{CommandEnv, CommandEnvs};
use crate::sys_common::IntoInner;
-
-use core::ffi::c_void;
-
-use super::api::{self, WinError};
+use crate::{cmp, env, fmt, mem, ptr};
////////////////////////////////////////////////////////////////////////////////
// Command
@@ -549,7 +542,7 @@ fn search_paths<Paths, Exists>(
None
}
-/// Check if a file exists without following symlinks.
+/// Checks if a file exists without following symlinks.
fn program_exists(path: &Path) -> Option<Vec<u16>> {
unsafe {
let path = args::to_user_path(path).ok()?;
@@ -571,7 +564,7 @@ fn to_handle(&self, stdio_id: u32, pipe: &mut Option<AnonPipe>) -> io::Result<Ha
Ok(io) => unsafe {
let io = Handle::from_raw_handle(io);
let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS);
- io.into_raw_handle();
+ let _ = io.into_raw_handle(); // Don't close the handle
ret
},
// If no stdio handle is available, then propagate the null value.
diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/pal/windows/process/tests.rs
index 3fc0c75..65325fa 100644
--- a/library/std/src/sys/pal/windows/process/tests.rs
+++ b/library/std/src/sys/pal/windows/process/tests.rs
@@ -1,5 +1,4 @@
-use super::make_command_line;
-use super::Arg;
+use super::{make_command_line, Arg};
use crate::env;
use crate::ffi::{OsStr, OsString};
use crate::process::Command;
diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs
index c6a2166..575f225 100644
--- a/library/std/src/sys/pal/windows/stdio.rs
+++ b/library/std/src/sys/pal/windows/stdio.rs
@@ -1,16 +1,13 @@
#![unstable(issue = "none", feature = "windows_stdio")]
+use core::str::utf8_char_width;
+
use super::api::{self, WinError};
-use crate::cmp;
-use crate::io;
use crate::mem::MaybeUninit;
use crate::os::windows::io::{FromRawHandle, IntoRawHandle};
-use crate::ptr;
-use crate::str;
-use crate::sys::c;
-use crate::sys::cvt;
use crate::sys::handle::Handle;
-use core::str::utf8_char_width;
+use crate::sys::{c, cvt};
+use crate::{cmp, io, ptr, str};
#[cfg(test)]
mod tests;
@@ -97,7 +94,7 @@ fn write(handle_id: u32, data: &[u8], incomplete_utf8: &mut IncompleteUtf8) -> i
unsafe {
let handle = Handle::from_raw_handle(handle);
let ret = handle.write(data);
- handle.into_raw_handle(); // Don't close the handle
+ let _ = handle.into_raw_handle(); // Don't close the handle
return ret;
}
}
@@ -246,7 +243,7 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
unsafe {
let handle = Handle::from_raw_handle(handle);
let ret = handle.read(buf);
- handle.into_raw_handle(); // Don't close the handle
+ let _ = handle.into_raw_handle(); // Don't close the handle
return ret;
}
}
diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs
index 668a3c0..28bce52 100644
--- a/library/std/src/sys/pal/windows/thread.rs
+++ b/library/std/src/sys/pal/windows/thread.rs
@@ -1,18 +1,15 @@
-use crate::ffi::CStr;
-use crate::io;
-use crate::num::NonZero;
-use crate::os::windows::io::AsRawHandle;
-use crate::os::windows::io::HandleOrNull;
-use crate::ptr;
-use crate::sys::c;
-use crate::sys::handle::Handle;
-use crate::sys::stack_overflow;
-use crate::sys_common::FromInner;
-use crate::time::Duration;
use core::ffi::c_void;
use super::time::WaitableTimer;
use super::to_u16s;
+use crate::ffi::CStr;
+use crate::num::NonZero;
+use crate::os::windows::io::{AsRawHandle, HandleOrNull};
+use crate::sys::handle::Handle;
+use crate::sys::{c, stack_overflow};
+use crate::sys_common::FromInner;
+use crate::time::Duration;
+use crate::{io, ptr};
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs
index b853dae..d9010e3 100644
--- a/library/std/src/sys/pal/windows/time.rs
+++ b/library/std/src/sys/pal/windows/time.rs
@@ -1,13 +1,12 @@
+use core::hash::{Hash, Hasher};
+use core::ops::Neg;
+
use crate::cmp::Ordering;
-use crate::fmt;
-use crate::mem;
use crate::ptr::null;
use crate::sys::c;
use crate::sys_common::IntoInner;
use crate::time::Duration;
-
-use core::hash::{Hash, Hasher};
-use core::ops::Neg;
+use crate::{fmt, mem};
const NANOS_PER_SEC: u64 = 1_000_000_000;
const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100;
@@ -166,8 +165,7 @@ fn intervals2dur(intervals: u64) -> Duration {
mod perf_counter {
use super::NANOS_PER_SEC;
use crate::sync::atomic::{AtomicU64, Ordering};
- use crate::sys::c;
- use crate::sys::cvt;
+ use crate::sys::{c, cvt};
use crate::sys_common::mul_div_u64;
use crate::time::Duration;
@@ -230,7 +228,7 @@ pub(super) struct WaitableTimer {
handle: c::HANDLE,
}
impl WaitableTimer {
- /// Create a high-resolution timer. Will fail before Windows 10, version 1803.
+ /// Creates a high-resolution timer. Will fail before Windows 10, version 1803.
pub fn high_resolution() -> Result<Self, ()> {
let handle = unsafe {
c::CreateWaitableTimerExW(
diff --git a/library/std/src/sys/pal/xous/alloc.rs b/library/std/src/sys/pal/xous/alloc.rs
index 6014111..9ea4344 100644
--- a/library/std/src/sys/pal/xous/alloc.rs
+++ b/library/std/src/sys/pal/xous/alloc.rs
@@ -46,10 +46,8 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
}
mod lock {
- use crate::sync::atomic::{
- AtomicI32,
- Ordering::{Acquire, Release},
- };
+ use crate::sync::atomic::AtomicI32;
+ use crate::sync::atomic::Ordering::{Acquire, Release};
static LOCKED: AtomicI32 = AtomicI32::new(0);
diff --git a/library/std/src/sys/pal/xous/net/dns.rs b/library/std/src/sys/pal/xous/net/dns.rs
index 6305632..50efe97 100644
--- a/library/std/src/sys/pal/xous/net/dns.rs
+++ b/library/std/src/sys/pal/xous/net/dns.rs
@@ -1,8 +1,9 @@
+use core::convert::{TryFrom, TryInto};
+
use crate::io;
use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use crate::os::xous::ffi::lend_mut;
use crate::os::xous::services::{dns_server, DnsLendMut};
-use core::convert::{TryFrom, TryInto};
pub struct DnsError {
pub code: u8,
diff --git a/library/std/src/sys/pal/xous/net/tcplistener.rs b/library/std/src/sys/pal/xous/net/tcplistener.rs
index 4730501..ddfb289 100644
--- a/library/std/src/sys/pal/xous/net/tcplistener.rs
+++ b/library/std/src/sys/pal/xous/net/tcplistener.rs
@@ -1,11 +1,11 @@
+use core::convert::TryInto;
+use core::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
+
use super::*;
-use crate::fmt;
-use crate::io;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use crate::os::xous::services;
use crate::sync::Arc;
-use core::convert::TryInto;
-use core::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
+use crate::{fmt, io};
macro_rules! unimpl {
() => {
diff --git a/library/std/src/sys/pal/xous/net/tcpstream.rs b/library/std/src/sys/pal/xous/net/tcpstream.rs
index 0ad8811..03442cf 100644
--- a/library/std/src/sys/pal/xous/net/tcpstream.rs
+++ b/library/std/src/sys/pal/xous/net/tcpstream.rs
@@ -1,3 +1,5 @@
+use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
+
use super::*;
use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
@@ -5,7 +7,6 @@
use crate::os::xous::services;
use crate::sync::Arc;
use crate::time::Duration;
-use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering};
macro_rules! unimpl {
() => {
diff --git a/library/std/src/sys/pal/xous/net/udp.rs b/library/std/src/sys/pal/xous/net/udp.rs
index 3d0522b..de51332 100644
--- a/library/std/src/sys/pal/xous/net/udp.rs
+++ b/library/std/src/sys/pal/xous/net/udp.rs
@@ -1,13 +1,13 @@
+use core::convert::TryInto;
+use core::sync::atomic::{AtomicUsize, Ordering};
+
use super::*;
use crate::cell::Cell;
-use crate::fmt;
-use crate::io;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use crate::os::xous::services;
use crate::sync::Arc;
use crate::time::Duration;
-use core::convert::TryInto;
-use core::sync::atomic::{AtomicUsize, Ordering};
+use crate::{fmt, io};
macro_rules! unimpl {
() => {
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index 9be09ee..8f8f354 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -1,11 +1,10 @@
use super::unsupported;
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::os::xous::ffi::Error as XousError;
use crate::path::{self, PathBuf};
+use crate::{fmt, io};
#[cfg(not(test))]
#[cfg(feature = "panic_unwind")]
diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs
index 279f24f..a95b0aa 100644
--- a/library/std/src/sys/pal/xous/thread.rs
+++ b/library/std/src/sys/pal/xous/thread.rs
@@ -1,3 +1,5 @@
+use core::arch::asm;
+
use crate::ffi::CStr;
use crate::io;
use crate::num::NonZero;
@@ -7,7 +9,6 @@
};
use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
use crate::time::Duration;
-use core::arch::asm;
pub struct Thread {
tid: ThreadId,
diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/pal/xous/time.rs
index 4e4ae67..ae8be81 100644
--- a/library/std/src/sys/pal/xous/time.rs
+++ b/library/std/src/sys/pal/xous/time.rs
@@ -1,7 +1,7 @@
use crate::os::xous::ffi::blocking_scalar;
-use crate::os::xous::services::{
- systime_server, ticktimer_server, SystimeScalar::GetUtcTimeMs, TicktimerScalar::ElapsedMs,
-};
+use crate::os::xous::services::SystimeScalar::GetUtcTimeMs;
+use crate::os::xous::services::TicktimerScalar::ElapsedMs;
+use crate::os::xous::services::{systime_server, ticktimer_server};
use crate::time::Duration;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs
index e7d6cd5..68d91a1 100644
--- a/library/std/src/sys/pal/zkvm/os.rs
+++ b/library/std/src/sys/pal/zkvm/os.rs
@@ -1,12 +1,11 @@
use super::{abi, unsupported, WORD_SIZE};
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::sys::os_str;
use crate::sys_common::FromInner;
+use crate::{fmt, io};
pub fn errno() -> i32 {
0
diff --git a/library/std/src/sys/pal/zkvm/stdio.rs b/library/std/src/sys/pal/zkvm/stdio.rs
index e771ed0..dd218c8 100644
--- a/library/std/src/sys/pal/zkvm/stdio.rs
+++ b/library/std/src/sys/pal/zkvm/stdio.rs
@@ -1,4 +1,5 @@
-use super::{abi, abi::fileno};
+use super::abi;
+use super::abi::fileno;
use crate::io;
pub struct Stdin;
diff --git a/library/std/src/sys/path/unix.rs b/library/std/src/sys/path/unix.rs
index 837f68d..2a7c025 100644
--- a/library/std/src/sys/path/unix.rs
+++ b/library/std/src/sys/path/unix.rs
@@ -1,7 +1,6 @@
-use crate::env;
use crate::ffi::OsStr;
-use crate::io;
use crate::path::{Path, PathBuf, Prefix};
+use crate::{env, io};
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs
index cebc791..21841eb 100644
--- a/library/std/src/sys/path/windows.rs
+++ b/library/std/src/sys/path/windows.rs
@@ -1,8 +1,7 @@
use crate::ffi::{OsStr, OsString};
-use crate::io;
use crate::path::{Path, PathBuf, Prefix};
-use crate::ptr;
use crate::sys::pal::{c, fill_utf16_buf, os2path, to_u16s};
+use crate::{io, ptr};
#[cfg(test)]
mod tests;
@@ -218,7 +217,7 @@ pub(crate) fn maybe_verbatim(path: &Path) -> io::Result<Vec<u16>> {
get_long_path(path, true)
}
-/// Get a normalized absolute path that can bypass path length limits.
+/// Gets a normalized absolute path that can bypass path length limits.
///
/// Setting prefer_verbatim to true suggests a stronger preference for verbatim
/// paths even when not strictly necessary. This allows the Windows API to avoid
diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs
index ff88ef4..c37c3e4 100644
--- a/library/std/src/sys/personality/dwarf/eh.rs
+++ b/library/std/src/sys/personality/dwarf/eh.rs
@@ -12,9 +12,9 @@
#![allow(non_upper_case_globals)]
#![allow(unused)]
+use core::{mem, ptr};
+
use super::DwarfReader;
-use core::mem;
-use core::ptr;
pub const DW_EH_PE_omit: u8 = 0xFF;
pub const DW_EH_PE_absptr: u8 = 0x00;
@@ -70,45 +70,51 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
let func_start = context.func_start;
let mut reader = DwarfReader::new(lsda);
-
- let start_encoding = reader.read::<u8>();
- // base address for landing pad offsets
- let lpad_base = if start_encoding != DW_EH_PE_omit {
- read_encoded_pointer(&mut reader, context, start_encoding)?
- } else {
- func_start
+ let lpad_base = unsafe {
+ let start_encoding = reader.read::<u8>();
+ // base address for landing pad offsets
+ if start_encoding != DW_EH_PE_omit {
+ read_encoded_pointer(&mut reader, context, start_encoding)?
+ } else {
+ func_start
+ }
};
+ let call_site_encoding = unsafe {
+ let ttype_encoding = reader.read::<u8>();
+ if ttype_encoding != DW_EH_PE_omit {
+ // Rust doesn't analyze exception types, so we don't care about the type table
+ reader.read_uleb128();
+ }
- let ttype_encoding = reader.read::<u8>();
- if ttype_encoding != DW_EH_PE_omit {
- // Rust doesn't analyze exception types, so we don't care about the type table
- reader.read_uleb128();
- }
-
- let call_site_encoding = reader.read::<u8>();
- let call_site_table_length = reader.read_uleb128();
- let action_table = reader.ptr.add(call_site_table_length as usize);
+ reader.read::<u8>()
+ };
+ let action_table = unsafe {
+ let call_site_table_length = reader.read_uleb128();
+ reader.ptr.add(call_site_table_length as usize)
+ };
let ip = context.ip;
if !USING_SJLJ_EXCEPTIONS {
// read the callsite table
while reader.ptr < action_table {
- // these are offsets rather than pointers;
- let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?;
- let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?;
- let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?;
- let cs_action_entry = reader.read_uleb128();
- // Callsite table is sorted by cs_start, so if we've passed the ip, we
- // may stop searching.
- if ip < func_start.wrapping_add(cs_start) {
- break;
- }
- if ip < func_start.wrapping_add(cs_start + cs_len) {
- if cs_lpad == 0 {
- return Ok(EHAction::None);
- } else {
- let lpad = lpad_base.wrapping_add(cs_lpad);
- return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
+ unsafe {
+ // these are offsets rather than pointers;
+ let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?;
+ let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?;
+ let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?;
+ let cs_action_entry = reader.read_uleb128();
+ // Callsite table is sorted by cs_start, so if we've passed the ip, we
+ // may stop searching.
+ if ip < func_start.wrapping_add(cs_start) {
+ break;
+ }
+ if ip < func_start.wrapping_add(cs_start + cs_len) {
+ if cs_lpad == 0 {
+ return Ok(EHAction::None);
+ } else {
+ let lpad = lpad_base.wrapping_add(cs_lpad);
+ return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
+ }
}
}
}
@@ -125,15 +131,15 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
}
let mut idx = ip.addr();
loop {
- let cs_lpad = reader.read_uleb128();
- let cs_action_entry = reader.read_uleb128();
+ let cs_lpad = unsafe { reader.read_uleb128() };
+ let cs_action_entry = unsafe { reader.read_uleb128() };
idx -= 1;
if idx == 0 {
// Can never have null landing pad for sjlj -- that would have
// been indicated by a -1 call site index.
// FIXME(strict provenance)
let lpad = ptr::with_exposed_provenance((cs_lpad + 1) as usize);
- return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
+ return Ok(unsafe { interpret_cs_action(action_table, cs_action_entry, lpad) });
}
}
}
@@ -151,9 +157,9 @@ unsafe fn interpret_cs_action(
} else {
// If lpad != 0 and cs_action_entry != 0, we have to check ttype_index.
// If ttype_index == 0 under the condition, we take cleanup action.
- let action_record = action_table.offset(cs_action_entry as isize - 1);
+ let action_record = unsafe { action_table.offset(cs_action_entry as isize - 1) };
let mut action_reader = DwarfReader::new(action_record);
- let ttype_index = action_reader.read_sleb128();
+ let ttype_index = unsafe { action_reader.read_sleb128() };
if ttype_index == 0 {
EHAction::Cleanup(lpad)
} else if ttype_index > 0 {
@@ -170,7 +176,7 @@ fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> {
if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) }
}
-/// Read a offset (`usize`) from `reader` whose encoding is described by `encoding`.
+/// Reads an offset (`usize`) from `reader` whose encoding is described by `encoding`.
///
/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext].
/// In addition the upper ("application") part must be zero.
@@ -186,23 +192,25 @@ unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result<
if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 {
return Err(());
}
- let result = match encoding & 0x0F {
- // despite the name, LLVM also uses absptr for offsets instead of pointers
- DW_EH_PE_absptr => reader.read::<usize>(),
- DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
- DW_EH_PE_udata2 => reader.read::<u16>() as usize,
- DW_EH_PE_udata4 => reader.read::<u32>() as usize,
- DW_EH_PE_udata8 => reader.read::<u64>() as usize,
- DW_EH_PE_sleb128 => reader.read_sleb128() as usize,
- DW_EH_PE_sdata2 => reader.read::<i16>() as usize,
- DW_EH_PE_sdata4 => reader.read::<i32>() as usize,
- DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
- _ => return Err(()),
+ let result = unsafe {
+ match encoding & 0x0F {
+ // despite the name, LLVM also uses absptr for offsets instead of pointers
+ DW_EH_PE_absptr => reader.read::<usize>(),
+ DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
+ DW_EH_PE_udata2 => reader.read::<u16>() as usize,
+ DW_EH_PE_udata4 => reader.read::<u32>() as usize,
+ DW_EH_PE_udata8 => reader.read::<u64>() as usize,
+ DW_EH_PE_sleb128 => reader.read_sleb128() as usize,
+ DW_EH_PE_sdata2 => reader.read::<i16>() as usize,
+ DW_EH_PE_sdata4 => reader.read::<i32>() as usize,
+ DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
+ _ => return Err(()),
+ }
};
Ok(result)
}
-/// Read a pointer from `reader` whose encoding is described by `encoding`.
+/// Reads a pointer from `reader` whose encoding is described by `encoding`.
///
/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext].
///
@@ -250,14 +258,14 @@ unsafe fn read_encoded_pointer(
if encoding & 0x0F != DW_EH_PE_absptr {
return Err(());
}
- reader.read::<*const u8>()
+ unsafe { reader.read::<*const u8>() }
} else {
- let offset = read_encoded_offset(reader, encoding & 0x0F)?;
+ let offset = unsafe { read_encoded_offset(reader, encoding & 0x0F)? };
base_ptr.wrapping_add(offset)
};
if encoding & DW_EH_PE_indirect != 0 {
- ptr = *(ptr.cast::<*const u8>());
+ ptr = unsafe { *(ptr.cast::<*const u8>()) };
}
Ok(ptr)
diff --git a/library/std/src/sys/personality/dwarf/mod.rs b/library/std/src/sys/personality/dwarf/mod.rs
index 89f7f13..5c52d96 100644
--- a/library/std/src/sys/personality/dwarf/mod.rs
+++ b/library/std/src/sys/personality/dwarf/mod.rs
@@ -5,6 +5,7 @@
// This module is used only by x86_64-pc-windows-gnu for now, but we
// are compiling it everywhere to avoid regressions.
#![allow(unused)]
+#![forbid(unsafe_op_in_unsafe_fn)]
#[cfg(test)]
mod tests;
@@ -17,7 +18,6 @@ pub struct DwarfReader {
pub ptr: *const u8,
}
-#[forbid(unsafe_op_in_unsafe_fn)]
impl DwarfReader {
pub fn new(ptr: *const u8) -> DwarfReader {
DwarfReader { ptr }
diff --git a/library/std/src/sys/personality/emcc.rs b/library/std/src/sys/personality/emcc.rs
index cb52ae8..d374e3a 100644
--- a/library/std/src/sys/personality/emcc.rs
+++ b/library/std/src/sys/personality/emcc.rs
@@ -1,9 +1,10 @@
//! On Emscripten Rust panics are wrapped in C++ exceptions, so we just forward
//! to `__gxx_personality_v0` which is provided by Emscripten.
-use crate::ffi::c_int;
use unwind as uw;
+use crate::ffi::c_int;
+
// This is required by the compiler to exist (e.g., it's a lang item), but it's
// never actually called by the compiler. Emscripten EH doesn't use a
// personality function at all, it instead uses __cxa_find_matching_catch.
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index 1fb85a1..f6b1844 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -37,9 +37,10 @@
//! and the last personality routine transfers control to the catch block.
#![forbid(unsafe_op_in_unsafe_fn)]
+use unwind as uw;
+
use super::dwarf::eh::{self, EHAction, EHContext};
use crate::ffi::c_int;
-use unwind as uw;
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
// and TargetLowering::getExceptionSelectorRegister() for each architecture,
diff --git a/library/std/src/sys/sync/condvar/futex.rs b/library/std/src/sys/sync/condvar/futex.rs
index 4586d0f..39cd97c 100644
--- a/library/std/src/sys/sync/condvar/futex.rs
+++ b/library/std/src/sys/sync/condvar/futex.rs
@@ -1,4 +1,5 @@
-use crate::sync::atomic::{AtomicU32, Ordering::Relaxed};
+use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::Ordering::Relaxed;
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
use crate::sys::sync::Mutex;
use crate::time::Duration;
diff --git a/library/std/src/sys/sync/condvar/itron.rs b/library/std/src/sys/sync/condvar/itron.rs
index 3a30398..f6f2b69 100644
--- a/library/std/src/sys/sync/condvar/itron.rs
+++ b/library/std/src/sys/sync/condvar/itron.rs
@@ -1,9 +1,13 @@
//! POSIX conditional variable implementation based on user-space wait queues.
-use crate::sys::pal::itron::{
- abi, error::expect_success_aborting, spin::SpinMutex, task, time::with_tmos_strong,
-};
-use crate::{mem::replace, ptr::NonNull, sys::sync::Mutex, time::Duration};
+use crate::mem::replace;
+use crate::ptr::NonNull;
+use crate::sys::pal::itron::error::expect_success_aborting;
+use crate::sys::pal::itron::spin::SpinMutex;
+use crate::sys::pal::itron::time::with_tmos_strong;
+use crate::sys::pal::itron::{abi, task};
+use crate::sys::sync::Mutex;
+use crate::time::Duration;
// The implementation is inspired by the queue-based implementation shown in
// Andrew D. Birrell's paper "Implementing Condition Variables with Semaphores"
diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs
index a2a9641..2b4bdfe 100644
--- a/library/std/src/sys/sync/condvar/pthread.rs
+++ b/library/std/src/sys/sync/condvar/pthread.rs
@@ -1,6 +1,7 @@
use crate::cell::UnsafeCell;
use crate::ptr;
-use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::Relaxed;
use crate::sys::sync::{mutex, Mutex};
#[cfg(not(target_os = "nto"))]
use crate::sys::time::TIMESPEC_MAX;
diff --git a/library/std/src/sys/sync/condvar/teeos.rs b/library/std/src/sys/sync/condvar/teeos.rs
index 6457da9..943867c 100644
--- a/library/std/src/sys/sync/condvar/teeos.rs
+++ b/library/std/src/sys/sync/condvar/teeos.rs
@@ -1,6 +1,7 @@
use crate::cell::UnsafeCell;
use crate::ptr;
-use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::Relaxed;
use crate::sys::sync::mutex::{self, Mutex};
use crate::sys::time::TIMESPEC_MAX;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
diff --git a/library/std/src/sys/sync/condvar/windows7.rs b/library/std/src/sys/sync/condvar/windows7.rs
index 07fa5fd..56eeeda 100644
--- a/library/std/src/sys/sync/condvar/windows7.rs
+++ b/library/std/src/sys/sync/condvar/windows7.rs
@@ -1,7 +1,6 @@
use crate::cell::UnsafeCell;
-use crate::sys::c;
-use crate::sys::os;
use crate::sys::sync::{mutex, Mutex};
+use crate::sys::{c, os};
use crate::time::Duration;
pub struct Condvar {
diff --git a/library/std/src/sys/sync/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs
index 7b21881..0073834 100644
--- a/library/std/src/sys/sync/condvar/xous.rs
+++ b/library/std/src/sys/sync/condvar/xous.rs
@@ -1,8 +1,9 @@
+use core::sync::atomic::{AtomicUsize, Ordering};
+
use crate::os::xous::ffi::{blocking_scalar, scalar};
use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
use crate::sys::sync::Mutex;
use crate::time::Duration;
-use core::sync::atomic::{AtomicUsize, Ordering};
// The implementation is inspired by Andrew D. Birrell's paper
// "Implementing Condition Variables with Semaphores"
diff --git a/library/std/src/sys/sync/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs
index 5d89e5a..81a6361 100644
--- a/library/std/src/sys/sync/mutex/fuchsia.rs
+++ b/library/std/src/sys/sync/mutex/fuchsia.rs
@@ -37,10 +37,8 @@
//!
//! [mutex in Fuchsia's libsync]: https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/ulib/sync/mutex.c
-use crate::sync::atomic::{
- AtomicU32,
- Ordering::{Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sys::futex::zircon::{
zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, zx_thread_self, ZX_ERR_BAD_HANDLE,
ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE, ZX_OK,
diff --git a/library/std/src/sys/sync/mutex/itron.rs b/library/std/src/sys/sync/mutex/itron.rs
index b29c7e1..8440ffd 100644
--- a/library/std/src/sys/sync/mutex/itron.rs
+++ b/library/std/src/sys/sync/mutex/itron.rs
@@ -2,18 +2,16 @@
//! `TA_INHERIT` are available.
#![forbid(unsafe_op_in_unsafe_fn)]
-use crate::sys::pal::itron::{
- abi,
- error::{expect_success, expect_success_aborting, fail, ItronError},
- spin::SpinIdOnceCell,
-};
+use crate::sys::pal::itron::abi;
+use crate::sys::pal::itron::error::{expect_success, expect_success_aborting, fail, ItronError};
+use crate::sys::pal::itron::spin::SpinIdOnceCell;
pub struct Mutex {
/// The ID of the underlying mutex object
mtx: SpinIdOnceCell<()>,
}
-/// Create a mutex object. This function never panics.
+/// Creates a mutex object. This function never panics.
fn new_mtx() -> Result<abi::ID, ItronError> {
ItronError::err_if_negative(unsafe {
abi::acre_mtx(&abi::T_CMTX {
@@ -31,7 +29,7 @@ pub const fn new() -> Mutex {
Mutex { mtx: SpinIdOnceCell::new() }
}
- /// Get the inner mutex's ID, which is lazily created.
+ /// Gets the inner mutex's ID, which is lazily created.
fn raw(&self) -> abi::ID {
match self.mtx.get_or_try_init(|| new_mtx().map(|id| (id, ()))) {
Ok((id, ())) => id,
diff --git a/library/std/src/sys/sync/mutex/xous.rs b/library/std/src/sys/sync/mutex/xous.rs
index 1426e48..63efa5a 100644
--- a/library/std/src/sys/sync/mutex/xous.rs
+++ b/library/std/src/sys/sync/mutex/xous.rs
@@ -1,9 +1,7 @@
use crate::os::xous::ffi::{blocking_scalar, do_yield};
use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
-use crate::sync::atomic::{
- AtomicBool, AtomicUsize,
- Ordering::{Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{AtomicBool, AtomicUsize};
pub struct Mutex {
/// The "locked" value indicates how many threads are waiting on this
diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs
index 8a231e6..2c8a054 100644
--- a/library/std/src/sys/sync/once/futex.rs
+++ b/library/std/src/sys/sync/once/futex.rs
@@ -1,14 +1,12 @@
use crate::cell::Cell;
use crate::sync as public;
-use crate::sync::atomic::{
- AtomicU32,
- Ordering::{Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sync::once::ExclusiveState;
use crate::sys::futex::{futex_wait, futex_wake_all};
// On some platforms, the OS is very nice and handles the waiter queue for us.
-// This means we only need one atomic value with 5 states:
+// This means we only need one atomic value with 4 states:
/// No initialization has run yet, and no thread is currently using the Once.
const INCOMPLETE: u32 = 0;
@@ -19,16 +17,20 @@
/// Some thread is currently attempting to run initialization. It may succeed,
/// so all future threads need to wait for it to finish.
const RUNNING: u32 = 2;
-/// Some thread is currently attempting to run initialization and there are threads
-/// waiting for it to finish.
-const QUEUED: u32 = 3;
/// Initialization has completed and all future calls should finish immediately.
-const COMPLETE: u32 = 4;
+const COMPLETE: u32 = 3;
-// Threads wait by setting the state to QUEUED and calling `futex_wait` on the state
+// An additional bit indicates whether there are waiting threads:
+
+/// May only be set if the state is not COMPLETE.
+const QUEUED: u32 = 4;
+
+// Threads wait by setting the QUEUED bit and calling `futex_wait` on the state
// variable. When the running thread finishes, it will wake all waiting threads using
// `futex_wake_all`.
+const STATE_MASK: u32 = 0b11;
+
pub struct OnceState {
poisoned: bool,
set_state_to: Cell<u32>,
@@ -47,7 +49,7 @@ pub fn poison(&self) {
}
struct CompletionGuard<'a> {
- state: &'a AtomicU32,
+ state_and_queued: &'a AtomicU32,
set_state_on_drop_to: u32,
}
@@ -56,32 +58,32 @@ fn drop(&mut self) {
// Use release ordering to propagate changes to all threads checking
// up on the Once. `futex_wake_all` does its own synchronization, hence
// we do not need `AcqRel`.
- if self.state.swap(self.set_state_on_drop_to, Release) == QUEUED {
- futex_wake_all(self.state);
+ if self.state_and_queued.swap(self.set_state_on_drop_to, Release) & QUEUED != 0 {
+ futex_wake_all(self.state_and_queued);
}
}
}
pub struct Once {
- state: AtomicU32,
+ state_and_queued: AtomicU32,
}
impl Once {
#[inline]
pub const fn new() -> Once {
- Once { state: AtomicU32::new(INCOMPLETE) }
+ Once { state_and_queued: AtomicU32::new(INCOMPLETE) }
}
#[inline]
pub fn is_completed(&self) -> bool {
// Use acquire ordering to make all initialization changes visible to the
// current thread.
- self.state.load(Acquire) == COMPLETE
+ self.state_and_queued.load(Acquire) == COMPLETE
}
#[inline]
pub(crate) fn state(&mut self) -> ExclusiveState {
- match *self.state.get_mut() {
+ match *self.state_and_queued.get_mut() {
INCOMPLETE => ExclusiveState::Incomplete,
POISONED => ExclusiveState::Poisoned,
COMPLETE => ExclusiveState::Complete,
@@ -89,31 +91,73 @@ pub(crate) fn state(&mut self) -> ExclusiveState {
}
}
- // This uses FnMut to match the API of the generic implementation. As this
- // implementation is quite light-weight, it is generic over the closure and
- // so avoids the cost of dynamic dispatch.
#[cold]
#[track_caller]
- pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
- let mut state = self.state.load(Acquire);
+ pub fn wait(&self, ignore_poisoning: bool) {
+ let mut state_and_queued = self.state_and_queued.load(Acquire);
loop {
+ let state = state_and_queued & STATE_MASK;
+ let queued = state_and_queued & QUEUED != 0;
match state {
+ COMPLETE => return,
+ POISONED if !ignore_poisoning => {
+ // Panic to propagate the poison.
+ panic!("Once instance has previously been poisoned");
+ }
+ _ => {
+ // Set the QUEUED bit if it has not already been set.
+ if !queued {
+ state_and_queued += QUEUED;
+ if let Err(new) = self.state_and_queued.compare_exchange_weak(
+ state,
+ state_and_queued,
+ Relaxed,
+ Acquire,
+ ) {
+ state_and_queued = new;
+ continue;
+ }
+ }
+
+ futex_wait(&self.state_and_queued, state_and_queued, None);
+ state_and_queued = self.state_and_queued.load(Acquire);
+ }
+ }
+ }
+ }
+
+ #[cold]
+ #[track_caller]
+ pub fn call(&self, ignore_poisoning: bool, f: &mut dyn FnMut(&public::OnceState)) {
+ let mut state_and_queued = self.state_and_queued.load(Acquire);
+ loop {
+ let state = state_and_queued & STATE_MASK;
+ let queued = state_and_queued & QUEUED != 0;
+ match state {
+ COMPLETE => return,
POISONED if !ignore_poisoning => {
// Panic to propagate the poison.
panic!("Once instance has previously been poisoned");
}
INCOMPLETE | POISONED => {
// Try to register the current thread as the one running.
- if let Err(new) =
- self.state.compare_exchange_weak(state, RUNNING, Acquire, Acquire)
- {
- state = new;
+ let next = RUNNING + if queued { QUEUED } else { 0 };
+ if let Err(new) = self.state_and_queued.compare_exchange_weak(
+ state_and_queued,
+ next,
+ Acquire,
+ Acquire,
+ ) {
+ state_and_queued = new;
continue;
}
+
// `waiter_queue` will manage other waiting threads, and
// wake them up on drop.
- let mut waiter_queue =
- CompletionGuard { state: &self.state, set_state_on_drop_to: POISONED };
+ let mut waiter_queue = CompletionGuard {
+ state_and_queued: &self.state_and_queued,
+ set_state_on_drop_to: POISONED,
+ };
// Run the function, letting it know if we're poisoned or not.
let f_state = public::OnceState {
inner: OnceState {
@@ -125,21 +169,27 @@ pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState
waiter_queue.set_state_on_drop_to = f_state.inner.set_state_to.get();
return;
}
- RUNNING | QUEUED => {
- // Set the state to QUEUED if it is not already.
- if state == RUNNING
- && let Err(new) =
- self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire)
- {
- state = new;
- continue;
+ _ => {
+ // All other values must be RUNNING.
+ assert!(state == RUNNING);
+
+ // Set the QUEUED bit if it is not already set.
+ if !queued {
+ state_and_queued += QUEUED;
+ if let Err(new) = self.state_and_queued.compare_exchange_weak(
+ state,
+ state_and_queued,
+ Relaxed,
+ Acquire,
+ ) {
+ state_and_queued = new;
+ continue;
+ }
}
- futex_wait(&self.state, QUEUED, None);
- state = self.state.load(Acquire);
+ futex_wait(&self.state_and_queued, state_and_queued, None);
+ state_and_queued = self.state_and_queued.load(Acquire);
}
- COMPLETE => return,
- _ => unreachable!("state is never set to invalid values"),
}
}
}
diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs
index 11fde18..12c1d9f 100644
--- a/library/std/src/sys/sync/once/no_threads.rs
+++ b/library/std/src/sys/sync/once/no_threads.rs
@@ -57,6 +57,12 @@ pub(crate) fn state(&mut self) -> ExclusiveState {
#[cold]
#[track_caller]
+ pub fn wait(&self, _ignore_poisoning: bool) {
+ panic!("not implementable on this target");
+ }
+
+ #[cold]
+ #[track_caller]
pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
let state = self.state.get();
match state {
diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs
index 730cdb7..86f72c8 100644
--- a/library/std/src/sys/sync/once/queue.rs
+++ b/library/std/src/sys/sync/once/queue.rs
@@ -56,22 +56,21 @@
// allowed, so no need for `SeqCst`.
use crate::cell::Cell;
-use crate::fmt;
-use crate::ptr;
-use crate::sync as public;
-use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
+use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release};
+use crate::sync::atomic::{AtomicBool, AtomicPtr};
use crate::sync::once::ExclusiveState;
use crate::thread::{self, Thread};
+use crate::{fmt, ptr, sync as public};
-type Masked = ();
+type StateAndQueue = *mut ();
pub struct Once {
- state_and_queue: AtomicPtr<Masked>,
+ state_and_queue: AtomicPtr<()>,
}
pub struct OnceState {
poisoned: bool,
- set_state_on_drop_to: Cell<*mut Masked>,
+ set_state_on_drop_to: Cell<StateAndQueue>,
}
// Four states that a Once can be in, encoded into the lower bits of
@@ -83,7 +82,8 @@ pub struct OnceState {
// Mask to learn about the state. All other bits are the queue of waiters if
// this is in the RUNNING state.
-const STATE_MASK: usize = 0x3;
+const STATE_MASK: usize = 0b11;
+const QUEUE_MASK: usize = !STATE_MASK;
// Representation of a node in the linked list of waiters, used while in the
// RUNNING state.
@@ -95,15 +95,23 @@ pub struct OnceState {
struct Waiter {
thread: Cell<Option<Thread>>,
signaled: AtomicBool,
- next: *const Waiter,
+ next: Cell<*const Waiter>,
}
// Head of a linked list of waiters.
// Every node is a struct on the stack of a waiting thread.
// Will wake up the waiters when it gets dropped, i.e. also on panic.
struct WaiterQueue<'a> {
- state_and_queue: &'a AtomicPtr<Masked>,
- set_state_on_drop_to: *mut Masked,
+ state_and_queue: &'a AtomicPtr<()>,
+ set_state_on_drop_to: StateAndQueue,
+}
+
+fn to_queue(current: StateAndQueue) -> *const Waiter {
+ current.mask(QUEUE_MASK).cast()
+}
+
+fn to_state(current: StateAndQueue) -> usize {
+ current.addr() & STATE_MASK
}
impl Once {
@@ -119,7 +127,7 @@ pub fn is_completed(&self) -> bool {
// operations visible to us, and, this being a fast path, weaker
// ordering helps with performance. This `Acquire` synchronizes with
// `Release` operations on the slow path.
- self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE
+ self.state_and_queue.load(Acquire).addr() == COMPLETE
}
#[inline]
@@ -132,6 +140,25 @@ pub(crate) fn state(&mut self) -> ExclusiveState {
}
}
+ #[cold]
+ #[track_caller]
+ pub fn wait(&self, ignore_poisoning: bool) {
+ let mut current = self.state_and_queue.load(Acquire);
+ loop {
+ let state = to_state(current);
+ match state {
+ COMPLETE => return,
+ POISONED if !ignore_poisoning => {
+ // Panic to propagate the poison.
+ panic!("Once instance has previously been poisoned");
+ }
+ _ => {
+ current = wait(&self.state_and_queue, current, !ignore_poisoning);
+ }
+ }
+ }
+ }
+
// This is a non-generic function to reduce the monomorphization cost of
// using `call_once` (this isn't exactly a trivial or small implementation).
//
@@ -146,9 +173,10 @@ pub(crate) fn state(&mut self) -> ExclusiveState {
#[cold]
#[track_caller]
pub fn call(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&public::OnceState)) {
- let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire);
+ let mut current = self.state_and_queue.load(Acquire);
loop {
- match state_and_queue.addr() {
+ let state = to_state(current);
+ match state {
COMPLETE => break,
POISONED if !ignore_poisoning => {
// Panic to propagate the poison.
@@ -156,16 +184,16 @@ pub fn call(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&public::OnceSta
}
POISONED | INCOMPLETE => {
// Try to register this thread as the one RUNNING.
- let exchange_result = self.state_and_queue.compare_exchange(
- state_and_queue,
- ptr::without_provenance_mut(RUNNING),
- Ordering::Acquire,
- Ordering::Acquire,
- );
- if let Err(old) = exchange_result {
- state_and_queue = old;
+ if let Err(new) = self.state_and_queue.compare_exchange_weak(
+ current,
+ current.mask(QUEUE_MASK).wrapping_byte_add(RUNNING),
+ Acquire,
+ Acquire,
+ ) {
+ current = new;
continue;
}
+
// `waiter_queue` will manage other waiting threads, and
// wake them up on drop.
let mut waiter_queue = WaiterQueue {
@@ -176,54 +204,57 @@ pub fn call(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&public::OnceSta
// poisoned or not.
let init_state = public::OnceState {
inner: OnceState {
- poisoned: state_and_queue.addr() == POISONED,
+ poisoned: state == POISONED,
set_state_on_drop_to: Cell::new(ptr::without_provenance_mut(COMPLETE)),
},
};
init(&init_state);
waiter_queue.set_state_on_drop_to = init_state.inner.set_state_on_drop_to.get();
- break;
+ return;
}
_ => {
// All other values must be RUNNING with possibly a
// pointer to the waiter queue in the more significant bits.
- assert!(state_and_queue.addr() & STATE_MASK == RUNNING);
- wait(&self.state_and_queue, state_and_queue);
- state_and_queue = self.state_and_queue.load(Ordering::Acquire);
+ assert!(state == RUNNING);
+ current = wait(&self.state_and_queue, current, true);
}
}
}
}
}
-fn wait(state_and_queue: &AtomicPtr<Masked>, mut current_state: *mut Masked) {
- // Note: the following code was carefully written to avoid creating a
- // mutable reference to `node` that gets aliased.
+fn wait(
+ state_and_queue: &AtomicPtr<()>,
+ mut current: StateAndQueue,
+ return_on_poisoned: bool,
+) -> StateAndQueue {
+ let node = &Waiter {
+ thread: Cell::new(Some(thread::current())),
+ signaled: AtomicBool::new(false),
+ next: Cell::new(ptr::null()),
+ };
+
loop {
- // Don't queue this thread if the status is no longer running,
- // otherwise we will not be woken up.
- if current_state.addr() & STATE_MASK != RUNNING {
- return;
+ let state = to_state(current);
+ let queue = to_queue(current);
+
+ // If initialization has finished, return.
+ if state == COMPLETE || (return_on_poisoned && state == POISONED) {
+ return current;
}
- // Create the node for our current thread.
- let node = Waiter {
- thread: Cell::new(Some(thread::current())),
- signaled: AtomicBool::new(false),
- next: current_state.with_addr(current_state.addr() & !STATE_MASK) as *const Waiter,
- };
- let me = core::ptr::addr_of!(node) as *const Masked as *mut Masked;
+ // Update the node for our current thread.
+ node.next.set(queue);
// Try to slide in the node at the head of the linked list, making sure
// that another thread didn't just replace the head of the linked list.
- let exchange_result = state_and_queue.compare_exchange(
- current_state,
- me.with_addr(me.addr() | RUNNING),
- Ordering::Release,
- Ordering::Relaxed,
- );
- if let Err(old) = exchange_result {
- current_state = old;
+ if let Err(new) = state_and_queue.compare_exchange_weak(
+ current,
+ ptr::from_ref(node).wrapping_byte_add(state) as StateAndQueue,
+ Release,
+ Acquire,
+ ) {
+ current = new;
continue;
}
@@ -232,14 +263,15 @@ fn wait(state_and_queue: &AtomicPtr<Masked>, mut current_state: *mut Masked) {
// would drop our `Waiter` node and leave a hole in the linked list
// (and a dangling reference). Guard against spurious wakeups by
// reparking ourselves until we are signaled.
- while !node.signaled.load(Ordering::Acquire) {
+ while !node.signaled.load(Acquire) {
// If the managing thread happens to signal and unpark us before we
// can park ourselves, the result could be this thread never gets
// unparked. Luckily `park` comes with the guarantee that if it got
// an `unpark` just before on an unparked thread it does not park.
thread::park();
}
- break;
+
+ return state_and_queue.load(Acquire);
}
}
@@ -253,11 +285,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
impl Drop for WaiterQueue<'_> {
fn drop(&mut self) {
// Swap out our state with however we finished.
- let state_and_queue =
- self.state_and_queue.swap(self.set_state_on_drop_to, Ordering::AcqRel);
+ let current = self.state_and_queue.swap(self.set_state_on_drop_to, AcqRel);
// We should only ever see an old state which was RUNNING.
- assert_eq!(state_and_queue.addr() & STATE_MASK, RUNNING);
+ assert_eq!(current.addr() & STATE_MASK, RUNNING);
// Walk the entire linked list of waiters and wake them up (in lifo
// order, last to register is first to wake up).
@@ -266,16 +297,13 @@ fn drop(&mut self) {
// free `node` if there happens to be has a spurious wakeup.
// So we have to take out the `thread` field and copy the pointer to
// `next` first.
- let mut queue =
- state_and_queue.with_addr(state_and_queue.addr() & !STATE_MASK) as *const Waiter;
+ let mut queue = to_queue(current);
while !queue.is_null() {
- let next = (*queue).next;
+ let next = (*queue).next.get();
let thread = (*queue).thread.take().unwrap();
- (*queue).signaled.store(true, Ordering::Release);
- // ^- FIXME (maybe): This is another case of issue #55005
- // `store()` has a potentially dangling ref to `signaled`.
- queue = next;
+ (*queue).signaled.store(true, Release);
thread.unpark();
+ queue = next;
}
}
}
diff --git a/library/std/src/sys/sync/rwlock/futex.rs b/library/std/src/sys/sync/rwlock/futex.rs
index aa0de90..75ecc2a 100644
--- a/library/std/src/sys/sync/rwlock/futex.rs
+++ b/library/std/src/sys/sync/rwlock/futex.rs
@@ -1,7 +1,5 @@
-use crate::sync::atomic::{
- AtomicU32,
- Ordering::{Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::AtomicU32;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
pub struct RwLock {
@@ -222,7 +220,7 @@ fn write_contended(&self) {
}
}
- /// Wake up waiting threads after unlocking.
+ /// Wakes up waiting threads after unlocking.
///
/// If both are waiting, this will wake up only one writer, but will fall
/// back to waking up readers if there was no writer to wake up.
diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs
index 337cc6c..458c165 100644
--- a/library/std/src/sys/sync/rwlock/queue.rs
+++ b/library/std/src/sys/sync/rwlock/queue.rs
@@ -111,10 +111,8 @@
use crate::hint::spin_loop;
use crate::mem;
use crate::ptr::{self, null_mut, without_provenance_mut, NonNull};
-use crate::sync::atomic::{
- AtomicBool, AtomicPtr,
- Ordering::{AcqRel, Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
+use crate::sync::atomic::{AtomicBool, AtomicPtr};
use crate::thread::{self, Thread};
// Locking uses exponential backoff. `SPIN_COUNT` indicates how many times the
@@ -186,7 +184,7 @@ struct Node {
}
impl Node {
- /// Create a new queue node.
+ /// Creates a new queue node.
fn new(write: bool) -> Node {
Node {
next: AtomicLink::new(None),
diff --git a/library/std/src/sys/sync/rwlock/solid.rs b/library/std/src/sys/sync/rwlock/solid.rs
index a8fef68..0537140 100644
--- a/library/std/src/sys/sync/rwlock/solid.rs
+++ b/library/std/src/sys/sync/rwlock/solid.rs
@@ -1,13 +1,9 @@
//! A readers-writer lock implementation backed by the SOLID kernel extension.
#![forbid(unsafe_op_in_unsafe_fn)]
-use crate::sys::pal::{
- abi,
- itron::{
- error::{expect_success, expect_success_aborting, fail, ItronError},
- spin::SpinIdOnceCell,
- },
-};
+use crate::sys::pal::abi;
+use crate::sys::pal::itron::error::{expect_success, expect_success_aborting, fail, ItronError};
+use crate::sys::pal::itron::spin::SpinIdOnceCell;
pub struct RwLock {
/// The ID of the underlying mutex object
@@ -28,7 +24,7 @@ pub const fn new() -> RwLock {
RwLock { rwl: SpinIdOnceCell::new() }
}
- /// Get the inner mutex's ID, which is lazily created.
+ /// Gets the inner mutex's ID, which is lazily created.
fn raw(&self) -> abi::ID {
match self.rwl.get_or_try_init(|| new_rwl().map(|id| (id, ()))) {
Ok((id, ())) => id,
diff --git a/library/std/src/sys/sync/thread_parking/darwin.rs b/library/std/src/sys/sync/thread_parking/darwin.rs
index 973c08f..96e3d23 100644
--- a/library/std/src/sys/sync/thread_parking/darwin.rs
+++ b/library/std/src/sys/sync/thread_parking/darwin.rs
@@ -13,10 +13,8 @@
#![allow(non_camel_case_types)]
use crate::pin::Pin;
-use crate::sync::atomic::{
- AtomicI8,
- Ordering::{Acquire, Release},
-};
+use crate::sync::atomic::AtomicI8;
+use crate::sync::atomic::Ordering::{Acquire, Release};
use crate::time::Duration;
type dispatch_semaphore_t = *mut crate::ffi::c_void;
diff --git a/library/std/src/sys/sync/thread_parking/futex.rs b/library/std/src/sys/sync/thread_parking/futex.rs
index 034eece..ce852ea 100644
--- a/library/std/src/sys/sync/thread_parking/futex.rs
+++ b/library/std/src/sys/sync/thread_parking/futex.rs
@@ -36,7 +36,7 @@ pub struct Parker {
// Ordering::Release when writing NOTIFIED (the 'token') in unpark(), and using
// Ordering::Acquire when checking for this state in park().
impl Parker {
- /// Construct the futex parker. The UNIX parker implementation
+ /// Constructs the futex parker. The UNIX parker implementation
/// requires this to happen in-place.
pub unsafe fn new_in_place(parker: *mut Parker) {
unsafe { parker.write(Self { state: Atomic::new(EMPTY) }) };
diff --git a/library/std/src/sys/sync/thread_parking/id.rs b/library/std/src/sys/sync/thread_parking/id.rs
index 0466743..a7b07b5 100644
--- a/library/std/src/sys/sync/thread_parking/id.rs
+++ b/library/std/src/sys/sync/thread_parking/id.rs
@@ -9,10 +9,8 @@
use crate::cell::UnsafeCell;
use crate::pin::Pin;
-use crate::sync::atomic::{
- fence, AtomicI8,
- Ordering::{Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{fence, AtomicI8};
use crate::sys::thread_parking::{current, park, park_timeout, unpark, ThreadId};
use crate::time::Duration;
@@ -30,7 +28,7 @@ pub fn new() -> Parker {
Parker { state: AtomicI8::new(EMPTY), tid: UnsafeCell::new(None) }
}
- /// Create a new thread parker. UNIX requires this to happen in-place.
+ /// Creates a new thread parker. UNIX requires this to happen in-place.
pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Parker::new())
}
diff --git a/library/std/src/sys/sync/thread_parking/pthread.rs b/library/std/src/sys/sync/thread_parking/pthread.rs
index fdac109..c64600e 100644
--- a/library/std/src/sys/sync/thread_parking/pthread.rs
+++ b/library/std/src/sys/sync/thread_parking/pthread.rs
@@ -92,7 +92,7 @@ pub struct Parker {
}
impl Parker {
- /// Construct the UNIX parker in-place.
+ /// Constructs the UNIX parker in-place.
///
/// # Safety
/// The constructed parker must never be moved.
diff --git a/library/std/src/sys/sync/thread_parking/windows7.rs b/library/std/src/sys/sync/thread_parking/windows7.rs
index 3a8d40d..1000b63 100644
--- a/library/std/src/sys/sync/thread_parking/windows7.rs
+++ b/library/std/src/sys/sync/thread_parking/windows7.rs
@@ -57,14 +57,13 @@
// [3]: https://docs.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c
// [4]: Windows Internals, Part 1, ISBN 9780735671300
+use core::ffi::c_void;
+
use crate::pin::Pin;
-use crate::sync::atomic::{
- AtomicI8,
- Ordering::{Acquire, Release},
-};
+use crate::sync::atomic::AtomicI8;
+use crate::sync::atomic::Ordering::{Acquire, Release};
use crate::sys::{c, dur2timeout};
use crate::time::Duration;
-use core::ffi::c_void;
pub struct Parker {
state: AtomicI8,
@@ -95,7 +94,7 @@ pub struct Parker {
// Ordering::Release when writing NOTIFIED (the 'token') in unpark(), and using
// Ordering::Acquire when reading this state in park() after waking up.
impl Parker {
- /// Construct the Windows parker. The UNIX parker implementation
+ /// Constructs the Windows parker. The UNIX parker implementation
/// requires this to happen in-place.
pub unsafe fn new_in_place(parker: *mut Parker) {
parker.write(Self { state: AtomicI8::new(EMPTY) });
@@ -185,16 +184,15 @@ fn ptr(&self) -> *const c_void {
#[cfg(target_vendor = "win7")]
mod keyed_events {
- use super::{Parker, EMPTY, NOTIFIED};
- use crate::sys::c;
use core::pin::Pin;
use core::ptr;
- use core::sync::atomic::{
- AtomicPtr,
- Ordering::{Acquire, Relaxed},
- };
+ use core::sync::atomic::AtomicPtr;
+ use core::sync::atomic::Ordering::{Acquire, Relaxed};
use core::time::Duration;
+ use super::{Parker, EMPTY, NOTIFIED};
+ use crate::sys::c;
+
pub unsafe fn park(parker: Pin<&Parker>) {
// Wait for unpark() to produce this event.
c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut());
diff --git a/library/std/src/sys/sync/thread_parking/xous.rs b/library/std/src/sys/sync/thread_parking/xous.rs
index 0bd0462..64b6f73 100644
--- a/library/std/src/sys/sync/thread_parking/xous.rs
+++ b/library/std/src/sys/sync/thread_parking/xous.rs
@@ -2,10 +2,8 @@
use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
use crate::pin::Pin;
use crate::ptr;
-use crate::sync::atomic::{
- AtomicI8,
- Ordering::{Acquire, Release},
-};
+use crate::sync::atomic::AtomicI8;
+use crate::sync::atomic::Ordering::{Acquire, Release};
use crate::time::Duration;
const NOTIFIED: i8 = 1;
diff --git a/library/std/src/sys/thread_local/guard/solid.rs b/library/std/src/sys/thread_local/guard/solid.rs
index b65d00c..054b2d5 100644
--- a/library/std/src/sys/thread_local/guard/solid.rs
+++ b/library/std/src/sys/thread_local/guard/solid.rs
@@ -3,7 +3,8 @@
//! destructors for terminated tasks, we still keep our own list.
use crate::cell::Cell;
-use crate::sys::pal::{abi, itron::task};
+use crate::sys::pal::abi;
+use crate::sys::pal::itron::task;
use crate::sys::thread_local::destructors;
pub fn enable() {
diff --git a/library/std/src/sys/thread_local/guard/windows.rs b/library/std/src/sys/thread_local/guard/windows.rs
index e08ac44..bf94f7d 100644
--- a/library/std/src/sys/thread_local/guard/windows.rs
+++ b/library/std/src/sys/thread_local/guard/windows.rs
@@ -63,9 +63,10 @@
//! [1]: https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
//! [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base/threading/thread_local_storage_win.cc#L42
+use core::ffi::c_void;
+
use crate::ptr;
use crate::sys::c;
-use core::ffi::c_void;
pub fn enable() {
// When destructors are used, we don't want LLVM eliminating CALLBACK for any
diff --git a/library/std/src/sys/thread_local/key/windows.rs b/library/std/src/sys/thread_local/key/windows.rs
index 8b43e55..f4e0f25 100644
--- a/library/std/src/sys/thread_local/key/windows.rs
+++ b/library/std/src/sys/thread_local/key/windows.rs
@@ -26,10 +26,8 @@
use crate::cell::UnsafeCell;
use crate::ptr;
-use crate::sync::atomic::{
- AtomicPtr, AtomicU32,
- Ordering::{AcqRel, Acquire, Relaxed, Release},
-};
+use crate::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release};
+use crate::sync::atomic::{AtomicPtr, AtomicU32};
use crate::sys::c;
use crate::sys::thread_local::guard;
diff --git a/library/std/src/sys/thread_local/key/xous.rs b/library/std/src/sys/thread_local/key/xous.rs
index 5a837a3..4fb2fdc 100644
--- a/library/std/src/sys/thread_local/key/xous.rs
+++ b/library/std/src/sys/thread_local/key/xous.rs
@@ -36,14 +36,13 @@
// FIXME(joboet): implement support for native TLS instead.
-use crate::mem::ManuallyDrop;
-use crate::ptr;
-use crate::sync::atomic::AtomicPtr;
-use crate::sync::atomic::AtomicUsize;
-use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use core::arch::asm;
+use crate::mem::ManuallyDrop;
use crate::os::xous::ffi::{map_memory, unmap_memory, MemoryFlags};
+use crate::ptr;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::sync::atomic::{AtomicPtr, AtomicUsize};
pub type Key = usize;
pub type Dtor = unsafe extern "C" fn(*mut u8);
@@ -79,7 +78,7 @@ fn tls_ptr_addr() -> *mut *mut u8 {
core::ptr::with_exposed_provenance_mut::<*mut u8>(tp)
}
-/// Create an area of memory that's unique per thread. This area will
+/// Creates an area of memory that's unique per thread. This area will
/// contain all thread local pointers.
fn tls_table() -> &'static mut [*mut u8] {
let tp = tls_ptr_addr();
diff --git a/library/std/src/sys/thread_local/native/eager.rs b/library/std/src/sys/thread_local/native/eager.rs
index 99e5ae7..fd48c4f 100644
--- a/library/std/src/sys/thread_local/native/eager.rs
+++ b/library/std/src/sys/thread_local/native/eager.rs
@@ -1,7 +1,6 @@
use crate::cell::{Cell, UnsafeCell};
use crate::ptr::{self, drop_in_place};
-use crate::sys::thread_local::abort_on_dtor_unwind;
-use crate::sys::thread_local::destructors;
+use crate::sys::thread_local::{abort_on_dtor_unwind, destructors};
#[derive(Clone, Copy)]
enum State {
@@ -21,7 +20,7 @@ pub const fn new(val: T) -> Storage<T> {
Storage { state: Cell::new(State::Initial), val: UnsafeCell::new(val) }
}
- /// Get a pointer to the TLS value. If the TLS variable has been destroyed,
+ /// Gets a pointer to the TLS value. If the TLS variable has been destroyed,
/// a null pointer is returned.
///
/// The resulting pointer may not be used after thread destruction has
diff --git a/library/std/src/sys/thread_local/native/lazy.rs b/library/std/src/sys/thread_local/native/lazy.rs
index 9d47e8e..5129428 100644
--- a/library/std/src/sys/thread_local/native/lazy.rs
+++ b/library/std/src/sys/thread_local/native/lazy.rs
@@ -1,8 +1,7 @@
use crate::cell::UnsafeCell;
use crate::hint::unreachable_unchecked;
use crate::ptr;
-use crate::sys::thread_local::abort_on_dtor_unwind;
-use crate::sys::thread_local::destructors;
+use crate::sys::thread_local::{abort_on_dtor_unwind, destructors};
pub unsafe trait DestroyedState: Sized {
fn register_dtor<T>(s: &Storage<T, Self>);
@@ -39,7 +38,7 @@ pub const fn new() -> Storage<T, D> {
Storage { state: UnsafeCell::new(State::Initial) }
}
- /// Get a pointer to the TLS value, potentially initializing it with the
+ /// Gets a pointer to the TLS value, potentially initializing it with the
/// provided parameters. If the TLS variable has been destroyed, a null
/// pointer is returned.
///
diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs
index e06185f..e27b47c 100644
--- a/library/std/src/sys/thread_local/os.rs
+++ b/library/std/src/sys/thread_local/os.rs
@@ -60,7 +60,7 @@ pub const fn new() -> Storage<T> {
Storage { key: LazyKey::new(Some(destroy_value::<T>)), marker: PhantomData }
}
- /// Get a pointer to the TLS value, potentially initializing it with the
+ /// Gets a pointer to the TLS value, potentially initializing it with the
/// provided parameters. If the TLS variable has been destroyed, a null
/// pointer is returned.
///
diff --git a/library/std/src/sys/thread_local/statik.rs b/library/std/src/sys/thread_local/statik.rs
index 0f08cab..a3451ab 100644
--- a/library/std/src/sys/thread_local/statik.rs
+++ b/library/std/src/sys/thread_local/statik.rs
@@ -63,7 +63,7 @@ pub const fn new() -> LazyStorage<T> {
LazyStorage { value: UnsafeCell::new(None) }
}
- /// Get a pointer to the TLS value, potentially initializing it with the
+ /// Gets a pointer to the TLS value, potentially initializing it with the
/// provided parameters.
///
/// The resulting pointer may not be used after reentrant inialialization
diff --git a/library/std/src/sys_common/io.rs b/library/std/src/sys_common/io.rs
index 4a42ff3..e386c95 100644
--- a/library/std/src/sys_common/io.rs
+++ b/library/std/src/sys_common/io.rs
@@ -5,12 +5,11 @@
#[cfg(test)]
#[allow(dead_code)] // not used on emscripten
pub mod test {
- use crate::env;
- use crate::fs;
- use crate::path::{Path, PathBuf};
- use crate::thread;
use rand::RngCore;
+ use crate::path::{Path, PathBuf};
+ use crate::{env, fs, thread};
+
pub struct TempDir(PathBuf);
impl TempDir {
diff --git a/library/std/src/sys_common/lazy_box.rs b/library/std/src/sys_common/lazy_box.rs
index 63c3316..b45b05f 100644
--- a/library/std/src/sys_common/lazy_box.rs
+++ b/library/std/src/sys_common/lazy_box.rs
@@ -5,10 +5,8 @@
use crate::marker::PhantomData;
use crate::ops::{Deref, DerefMut};
use crate::ptr::null_mut;
-use crate::sync::atomic::{
- AtomicPtr,
- Ordering::{AcqRel, Acquire},
-};
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::{AcqRel, Acquire};
pub(crate) struct LazyBox<T: LazyInit> {
ptr: AtomicPtr<T>,
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 0a82b50..25ebeb3 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -1,19 +1,14 @@
#[cfg(test)]
mod tests;
-use crate::cmp;
-use crate::fmt;
+use crate::ffi::{c_int, c_void};
use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
-use crate::mem;
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::ptr;
use crate::sys::common::small_c_string::run_with_cstr;
-use crate::sys::net::netc as c;
-use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
+use crate::sys::net::{cvt, cvt_gai, cvt_r, init, netc as c, wrlen_t, Socket};
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
-
-use crate::ffi::{c_int, c_void};
+use crate::{cmp, fmt, mem, ptr};
cfg_if::cfg_if! {
if #[cfg(any(
diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs
index 4d295cf..5333ee1 100644
--- a/library/std/src/sys_common/process.rs
+++ b/library/std/src/sys_common/process.rs
@@ -2,12 +2,10 @@
#![unstable(feature = "process_internals", issue = "none")]
use crate::collections::BTreeMap;
-use crate::env;
use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
use crate::sys::pipe::read2;
use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes};
+use crate::{env, fmt, io};
// Stores a set of changes to an environment
#[derive(Clone)]
diff --git a/library/std/src/sys_common/wstr.rs b/library/std/src/sys_common/wstr.rs
index 8eae160..f9a171f 100644
--- a/library/std/src/sys_common/wstr.rs
+++ b/library/std/src/sys_common/wstr.rs
@@ -15,7 +15,7 @@ pub struct WStrUnits<'a> {
}
impl WStrUnits<'_> {
- /// Create the iterator. Returns `None` if `lpwstr` is null.
+ /// Creates the iterator. Returns `None` if `lpwstr` is null.
///
/// SAFETY: `lpwstr` must point to a null-terminated wide string that lives
/// at least as long as the lifetime of this struct.
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 6aeeb62..277c950 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -23,16 +23,12 @@
use crate::borrow::Cow;
use crate::collections::TryReserveError;
-use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::iter::FusedIterator;
-use crate::mem;
-use crate::ops;
use crate::rc::Rc;
-use crate::slice;
-use crate::str;
use crate::sync::Arc;
use crate::sys_common::AsInner;
+use crate::{fmt, mem, ops, slice, str};
const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}";
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 40c0d44..88b31cd 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -160,24 +160,19 @@
use crate::any::Any;
use crate::cell::{Cell, OnceCell, UnsafeCell};
-use crate::env;
use crate::ffi::CStr;
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::mem::{self, forget, ManuallyDrop};
use crate::num::NonZero;
-use crate::panic;
-use crate::panicking;
use crate::pin::Pin;
use crate::ptr::addr_of_mut;
-use crate::str;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sync::Arc;
use crate::sys::sync::Parker;
use crate::sys::thread as imp;
use crate::sys_common::{AsInner, IntoInner};
use crate::time::{Duration, Instant};
+use crate::{env, fmt, io, panic, panicking, str};
#[stable(feature = "scoped_threads", since = "1.63.0")]
mod scoped;
@@ -439,25 +434,24 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
///
/// [`io::Result`]: crate::io::Result
#[unstable(feature = "thread_spawn_unchecked", issue = "55132")]
- pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>>
+ pub unsafe fn spawn_unchecked<F, T>(self, f: F) -> io::Result<JoinHandle<T>>
where
F: FnOnce() -> T,
- F: Send + 'a,
- T: Send + 'a,
+ F: Send,
+ T: Send,
{
Ok(JoinHandle(unsafe { self.spawn_unchecked_(f, None) }?))
}
- unsafe fn spawn_unchecked_<'a, 'scope, F, T>(
+ unsafe fn spawn_unchecked_<'scope, F, T>(
self,
f: F,
scope_data: Option<Arc<scoped::ScopeData>>,
) -> io::Result<JoinInner<'scope, T>>
where
F: FnOnce() -> T,
- F: Send + 'a,
- T: Send + 'a,
- 'scope: 'a,
+ F: Send,
+ T: Send,
{
let Builder { name, stack_size } = self;
@@ -537,7 +531,7 @@ fn drop(&mut self) {
// will call `decrement_num_running_threads` and therefore signal that this thread is
// done.
drop(their_packet);
- // Here, the lifetime `'a` and even `'scope` can end. `main` keeps running for a bit
+ // Here, the lifetime `'scope` can end. `main` keeps running for a bit
// after that before returning itself.
};
@@ -849,7 +843,7 @@ pub fn panicking() -> bool {
panicking::panicking()
}
-/// Use [`sleep`].
+/// Uses [`sleep`].
///
/// Puts the current thread to sleep for at least the specified amount of time.
///
@@ -1120,7 +1114,7 @@ pub fn park() {
forget(guard);
}
-/// Use [`park_timeout`].
+/// Uses [`park_timeout`].
///
/// Blocks unless or until the current thread's token is made available or
/// the specified duration has been reached (may wake spuriously).
@@ -1292,9 +1286,10 @@ enum ThreadName {
// This module ensures private fields are kept private, which is necessary to enforce the safety requirements.
mod thread_name_string {
+ use core::str;
+
use super::ThreadName;
use crate::ffi::{CStr, CString};
- use core::str;
/// Like a `String` it's guaranteed UTF-8 and like a `CString` it's null terminated.
pub(crate) struct ThreadNameString {
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs
index e2e22e5..ba27c92 100644
--- a/library/std/src/thread/scoped.rs
+++ b/library/std/src/thread/scoped.rs
@@ -1,10 +1,9 @@
use super::{current, park, Builder, JoinInner, Result, Thread};
-use crate::fmt;
-use crate::io;
use crate::marker::PhantomData;
use crate::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use crate::sync::Arc;
+use crate::{fmt, io};
/// A scope to spawn scoped threads in.
///
@@ -67,7 +66,7 @@ pub(super) fn decrement_num_running_threads(&self, panic: bool) {
}
}
-/// Create a scope for spawning scoped threads.
+/// Creates a scope for spawning scoped threads.
///
/// The function passed to `scope` will be provided a [`Scope`] object,
/// through which scoped threads can be [spawned][`Scope::spawn`].
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 1fb1333..aa464d5 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -1,16 +1,12 @@
use super::Builder;
use crate::any::Any;
-use crate::mem;
use crate::panic::panic_any;
-use crate::result;
-use crate::sync::{
- atomic::{AtomicBool, Ordering},
- mpsc::{channel, Sender},
- Arc, Barrier,
-};
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::mpsc::{channel, Sender};
+use crate::sync::{Arc, Barrier};
use crate::thread::{self, Scope, ThreadId};
-use crate::time::Duration;
-use crate::time::Instant;
+use crate::time::{Duration, Instant};
+use crate::{mem, result};
// !!! These tests are dangerous. If something is buggy, they will hang, !!!
// !!! instead of exiting cleanly. This might wedge the buildbots. !!!
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 6f1a354..ae46670 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -34,18 +34,17 @@
#[cfg(test)]
mod tests;
+#[stable(feature = "time", since = "1.3.0")]
+pub use core::time::Duration;
+#[stable(feature = "duration_checked_float", since = "1.66.0")]
+pub use core::time::TryFromFloatSecsError;
+
use crate::error::Error;
use crate::fmt;
use crate::ops::{Add, AddAssign, Sub, SubAssign};
use crate::sys::time;
use crate::sys_common::{FromInner, IntoInner};
-#[stable(feature = "time", since = "1.3.0")]
-pub use core::time::Duration;
-
-#[stable(feature = "duration_checked_float", since = "1.66.0")]
-pub use core::time::TryFromFloatSecsError;
-
/// A measurement of a monotonically nondecreasing clock.
/// Opaque and useful only with [`Duration`].
///
diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs
index 6ed8480..de36dc4 100644
--- a/library/std/src/time/tests.rs
+++ b/library/std/src/time/tests.rs
@@ -1,8 +1,10 @@
-use super::{Duration, Instant, SystemTime, UNIX_EPOCH};
use core::fmt::Debug;
+
#[cfg(not(target_arch = "wasm32"))]
use test::{black_box, Bencher};
+use super::{Duration, Instant, SystemTime, UNIX_EPOCH};
+
macro_rules! assert_almost_eq {
($a:expr, $b:expr) => {{
let (a, b) = ($a, $b);
diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs
index 1aad654..7cf70c7 100644
--- a/library/std/tests/common/mod.rs
+++ b/library/std/tests/common/mod.rs
@@ -1,10 +1,9 @@
#![allow(unused)]
-use rand::RngCore;
-use std::env;
-use std::fs;
use std::path::{Path, PathBuf};
-use std::thread;
+use std::{env, fs, thread};
+
+use rand::RngCore;
/// Copied from `std::test_helpers::test_rng`, since these tests rely on the
/// seed not being the same for every RNG invocation too.
diff --git a/library/std/tests/create_dir_all_bare.rs b/library/std/tests/create_dir_all_bare.rs
index 79c3c8f..8becf71 100644
--- a/library/std/tests/create_dir_all_bare.rs
+++ b/library/std/tests/create_dir_all_bare.rs
@@ -3,9 +3,8 @@
//! Note that this test changes the current directory so
//! should not be in the same process as other tests.
-use std::env;
-use std::fs;
use std::path::{Path, PathBuf};
+use std::{env, fs};
mod common;
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index a1ca85c..4e472b4 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -4,9 +4,10 @@
use rand::distributions::{Alphanumeric, DistString};
mod common;
-use common::test_rng;
use std::thread;
+use common::test_rng;
+
#[track_caller]
fn make_rand_name() -> OsString {
let n = format!("TEST{}", Alphanumeric.sample_string(&mut test_rng(), 10));
diff --git a/library/std/tests/pipe_subprocess.rs b/library/std/tests/pipe_subprocess.rs
index c227809..1535742 100644
--- a/library/std/tests/pipe_subprocess.rs
+++ b/library/std/tests/pipe_subprocess.rs
@@ -3,7 +3,9 @@
fn main() {
#[cfg(all(not(miri), any(unix, windows)))]
{
- use std::{env, io::Read, pipe::pipe, process};
+ use std::io::Read;
+ use std::pipe::pipe;
+ use std::{env, process};
if env::var("I_AM_THE_CHILD").is_ok() {
child();
diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs
index c56c111..d249eb7 100644
--- a/library/std/tests/process_spawning.rs
+++ b/library/std/tests/process_spawning.rs
@@ -1,9 +1,6 @@
#![cfg(not(target_env = "sgx"))]
-use std::env;
-use std::fs;
-use std::process;
-use std::str;
+use std::{env, fs, process, str};
mod common;
diff --git a/library/std/tests/switch-stdout.rs b/library/std/tests/switch-stdout.rs
index 0afe180..42011a9 100644
--- a/library/std/tests/switch-stdout.rs
+++ b/library/std/tests/switch-stdout.rs
@@ -5,11 +5,10 @@
mod common;
-#[cfg(windows)]
-use std::os::windows::io::OwnedHandle;
-
#[cfg(unix)]
use std::os::fd::OwnedFd;
+#[cfg(windows)]
+use std::os::windows::io::OwnedHandle;
#[cfg(unix)]
fn switch_stdout_to(file: OwnedFd) -> OwnedFd {
diff --git a/library/std/tests/windows.rs b/library/std/tests/windows.rs
index 9f7596f..dab3182 100644
--- a/library/std/tests/windows.rs
+++ b/library/std/tests/windows.rs
@@ -1,7 +1,9 @@
#![cfg(windows)]
//! An external tests
-use std::{ffi::OsString, os::windows::ffi::OsStringExt, path::PathBuf};
+use std::ffi::OsString;
+use std::os::windows::ffi::OsStringExt;
+use std::path::PathBuf;
#[test]
#[should_panic]
diff --git a/library/stdarch b/library/stdarch
index df3618d..47b929d 160000
--- a/library/stdarch
+++ b/library/stdarch
@@ -1 +1 @@
-Subproject commit df3618d9f35165f4bc548114e511c49c29e1fd9b
+Subproject commit 47b929ddc521a78b0f699ba8d5c274d28593448a
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index 169eeec..7165c3e 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -16,8 +16,8 @@
compiler-builtins-c = ["std/compiler-builtins-c"]
compiler-builtins-mem = ["std/compiler-builtins-mem"]
compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
+compiler-builtins-no-f16-f128 = ["std/compiler-builtins-no-f16-f128"]
compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
-compiler-builtins-weak-intrinsics = ["std/compiler-builtins-weak-intrinsics"]
llvm-libunwind = ["std/llvm-libunwind"]
system-llvm-libunwind = ["std/system-llvm-libunwind"]
panic-unwind = ["std/panic_unwind"]
diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs
index 9f34f54..b71def3 100644
--- a/library/test/src/bench.rs
+++ b/library/test/src/bench.rs
@@ -1,19 +1,16 @@
//! Benchmarking module.
-use super::{
- event::CompletedTest,
- options::BenchMode,
- test_result::TestResult,
- types::{TestDesc, TestId},
- Sender,
-};
-
-use crate::stats;
-use std::cmp;
-use std::io;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
+use std::{cmp, io};
+
+use super::event::CompletedTest;
+use super::options::BenchMode;
+use super::test_result::TestResult;
+use super::types::{TestDesc, TestId};
+use super::Sender;
+use crate::stats;
/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index b7d2440..4ccd825 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -1,11 +1,11 @@
//! Module converting command-line arguments into test configuration.
use std::env;
+use std::io::{self, IsTerminal};
use std::path::PathBuf;
use super::options::{ColorConfig, Options, OutputFormat, RunIgnored};
use super::time::TestTimeOptions;
-use std::io::{self, IsTerminal};
#[derive(Debug)]
pub struct TestOpts {
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index 7e224d6..4d4cdcf 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -5,19 +5,19 @@
use std::io::prelude::Write;
use std::time::Instant;
-use super::{
- bench::fmt_bench_samples,
- cli::TestOpts,
- event::{CompletedTest, TestEvent},
- filter_tests,
- formatters::{JsonFormatter, JunitFormatter, OutputFormatter, PrettyFormatter, TerseFormatter},
- helpers::{concurrency::get_concurrency, metrics::MetricMap},
- options::{Options, OutputFormat},
- run_tests, term,
- test_result::TestResult,
- time::{TestExecTime, TestSuiteExecTime},
- types::{NamePadding, TestDesc, TestDescAndFn},
+use super::bench::fmt_bench_samples;
+use super::cli::TestOpts;
+use super::event::{CompletedTest, TestEvent};
+use super::formatters::{
+ JsonFormatter, JunitFormatter, OutputFormatter, PrettyFormatter, TerseFormatter,
};
+use super::helpers::concurrency::get_concurrency;
+use super::helpers::metrics::MetricMap;
+use super::options::{Options, OutputFormat};
+use super::test_result::TestResult;
+use super::time::{TestExecTime, TestSuiteExecTime};
+use super::types::{NamePadding, TestDesc, TestDescAndFn};
+use super::{filter_tests, run_tests, term};
/// Generic wrapper over stdout.
pub enum OutputLocation<T> {
diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs
index 6245aae..aa1c506 100644
--- a/library/test/src/formatters/json.rs
+++ b/library/test/src/formatters/json.rs
@@ -1,12 +1,12 @@
-use std::{borrow::Cow, io, io::prelude::Write};
+use std::borrow::Cow;
+use std::io;
+use std::io::prelude::Write;
use super::OutputFormatter;
-use crate::{
- console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation},
- test_result::TestResult,
- time,
- types::TestDesc,
-};
+use crate::console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation};
+use crate::test_result::TestResult;
+use crate::time;
+use crate::types::TestDesc;
pub(crate) struct JsonFormatter<T> {
out: OutputLocation<T>,
diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs
index a211ebf..96b4320 100644
--- a/library/test/src/formatters/junit.rs
+++ b/library/test/src/formatters/junit.rs
@@ -1,13 +1,12 @@
-use std::io::{self, prelude::Write};
+use std::io::prelude::Write;
+use std::io::{self};
use std::time::Duration;
use super::OutputFormatter;
-use crate::{
- console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation},
- test_result::TestResult,
- time,
- types::{TestDesc, TestType},
-};
+use crate::console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation};
+use crate::test_result::TestResult;
+use crate::time;
+use crate::types::{TestDesc, TestType};
pub struct JunitFormatter<T> {
out: OutputLocation<T>,
diff --git a/library/test/src/formatters/mod.rs b/library/test/src/formatters/mod.rs
index bc6ffeb..f1225fe 100644
--- a/library/test/src/formatters/mod.rs
+++ b/library/test/src/formatters/mod.rs
@@ -1,11 +1,10 @@
-use std::{io, io::prelude::Write};
+use std::io;
+use std::io::prelude::Write;
-use crate::{
- console::{ConsoleTestDiscoveryState, ConsoleTestState},
- test_result::TestResult,
- time,
- types::{TestDesc, TestName},
-};
+use crate::console::{ConsoleTestDiscoveryState, ConsoleTestState};
+use crate::test_result::TestResult;
+use crate::time;
+use crate::types::{TestDesc, TestName};
mod json;
mod junit;
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs
index 22654a3..7089eae 100644
--- a/library/test/src/formatters/pretty.rs
+++ b/library/test/src/formatters/pretty.rs
@@ -1,14 +1,12 @@
-use std::{io, io::prelude::Write};
+use std::io;
+use std::io::prelude::Write;
use super::OutputFormatter;
-use crate::{
- bench::fmt_bench_samples,
- console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation},
- term,
- test_result::TestResult,
- time,
- types::TestDesc,
-};
+use crate::bench::fmt_bench_samples;
+use crate::console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation};
+use crate::test_result::TestResult;
+use crate::types::TestDesc;
+use crate::{term, time};
pub(crate) struct PrettyFormatter<T> {
out: OutputLocation<T>,
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 875c66e..534aa2f 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -1,15 +1,12 @@
-use std::{io, io::prelude::Write};
+use std::io;
+use std::io::prelude::Write;
use super::OutputFormatter;
-use crate::{
- bench::fmt_bench_samples,
- console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation},
- term,
- test_result::TestResult,
- time,
- types::NamePadding,
- types::TestDesc,
-};
+use crate::bench::fmt_bench_samples;
+use crate::console::{ConsoleTestDiscoveryState, ConsoleTestState, OutputLocation};
+use crate::test_result::TestResult;
+use crate::types::{NamePadding, TestDesc};
+use crate::{term, time};
// We insert a '\n' when the output hits 100 columns in quiet mode. 88 test
// result chars leaves 12 chars for a progress count like " 11704/12853".
diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs
index 1854c6a..b1545cb 100644
--- a/library/test/src/helpers/concurrency.rs
+++ b/library/test/src/helpers/concurrency.rs
@@ -1,7 +1,8 @@
//! Helper module which helps to determine amount of threads to be used
//! during tests execution.
-use std::{env, num::NonZero, thread};
+use std::num::NonZero;
+use std::{env, thread};
pub fn get_concurrency() -> usize {
if let Ok(value) = env::var("RUST_TEST_THREADS") {
diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs
index 2ac3bfb..14389eb 100644
--- a/library/test/src/helpers/shuffle.rs
+++ b/library/test/src/helpers/shuffle.rs
@@ -1,8 +1,9 @@
-use crate::cli::TestOpts;
-use crate::types::{TestDescAndFn, TestId, TestName};
use std::hash::{DefaultHasher, Hasher};
use std::time::{SystemTime, UNIX_EPOCH};
+use crate::cli::TestOpts;
+use crate::types::{TestDescAndFn, TestId, TestName};
+
pub fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> {
opts.shuffle_seed.or_else(|| {
if opts.shuffle {
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 71cb796..632f8d1 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -24,6 +24,9 @@
#![feature(panic_can_unwind)]
#![feature(test)]
#![allow(internal_features)]
+#![warn(rustdoc::unescaped_backticks)]
+
+pub use cli::TestOpts;
pub use self::bench::{black_box, Bencher};
pub use self::console::run_tests_console;
@@ -31,39 +34,31 @@
pub use self::types::TestName::*;
pub use self::types::*;
pub use self::ColorConfig::*;
-pub use cli::TestOpts;
// Module to be used by rustc to compile tests in libtest
pub mod test {
- pub use crate::{
- assert_test_result,
- bench::Bencher,
- cli::{parse_opts, TestOpts},
- filter_tests,
- helpers::metrics::{Metric, MetricMap},
- options::{Options, RunIgnored, RunStrategy, ShouldPanic},
- run_test, test_main, test_main_static,
- test_result::{TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk},
- time::{TestExecTime, TestTimeOptions},
- types::{
- DynTestFn, DynTestName, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc,
- TestDescAndFn, TestId, TestName, TestType,
- },
+ pub use crate::bench::Bencher;
+ pub use crate::cli::{parse_opts, TestOpts};
+ pub use crate::helpers::metrics::{Metric, MetricMap};
+ pub use crate::options::{Options, RunIgnored, RunStrategy, ShouldPanic};
+ pub use crate::test_result::{TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk};
+ pub use crate::time::{TestExecTime, TestTimeOptions};
+ pub use crate::types::{
+ DynTestFn, DynTestName, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc,
+ TestDescAndFn, TestId, TestName, TestType,
};
+ pub use crate::{assert_test_result, filter_tests, run_test, test_main, test_main_static};
}
-use std::{
- collections::VecDeque,
- env, io,
- io::prelude::Write,
- mem::ManuallyDrop,
- panic::{self, catch_unwind, AssertUnwindSafe, PanicHookInfo},
- process::{self, Command, Termination},
- sync::mpsc::{channel, Sender},
- sync::{Arc, Mutex},
- thread,
- time::{Duration, Instant},
-};
+use std::collections::VecDeque;
+use std::io::prelude::Write;
+use std::mem::ManuallyDrop;
+use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicHookInfo};
+use std::process::{self, Command, Termination};
+use std::sync::mpsc::{channel, Sender};
+use std::sync::{Arc, Mutex};
+use std::time::{Duration, Instant};
+use std::{env, io, thread};
pub mod bench;
mod cli;
@@ -82,6 +77,7 @@ pub mod test {
mod tests;
use core::any::Any;
+
use event::{CompletedTest, TestEvent};
use helpers::concurrency::get_concurrency;
use helpers::shuffle::{get_shuffle_seed, shuffle_tests};
diff --git a/library/test/src/stats.rs b/library/test/src/stats.rs
index b33b080..71c944a 100644
--- a/library/test/src/stats.rs
+++ b/library/test/src/stats.rs
@@ -116,7 +116,7 @@ pub struct Summary {
}
impl Summary {
- /// Construct a new summary of a sample set.
+ /// Constructs a new summary of a sample set.
pub fn new(samples: &[f64]) -> Summary {
Summary {
sum: samples.sum(),
diff --git a/library/test/src/stats/tests.rs b/library/test/src/stats/tests.rs
index 3a6e840..4b209dc 100644
--- a/library/test/src/stats/tests.rs
+++ b/library/test/src/stats/tests.rs
@@ -1,10 +1,11 @@
use super::*;
extern crate test;
-use self::test::test::Bencher;
use std::io;
use std::io::prelude::*;
+use self::test::test::Bencher;
+
// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
macro_rules! assert_approx_eq {
diff --git a/library/test/src/term.rs b/library/test/src/term.rs
index a14b0d4..e736e85 100644
--- a/library/test/src/term.rs
+++ b/library/test/src/term.rs
@@ -12,7 +12,8 @@
#![deny(missing_docs)]
-use std::io::{self, prelude::*};
+use std::io::prelude::*;
+use std::io::{self};
pub(crate) use terminfo::TerminfoTerminal;
#[cfg(windows)]
diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs
index 67ba894..67eec3c 100644
--- a/library/test/src/term/terminfo/mod.rs
+++ b/library/test/src/term/terminfo/mod.rs
@@ -1,20 +1,18 @@
//! Terminfo database interface.
use std::collections::HashMap;
-use std::env;
-use std::error;
-use std::fmt;
use std::fs::File;
-use std::io::{self, prelude::*, BufReader};
+use std::io::prelude::*;
+use std::io::{self, BufReader};
use std::path::Path;
-
-use super::color;
-use super::Terminal;
+use std::{env, error, fmt};
use parm::{expand, Param, Variables};
use parser::compiled::{msys_terminfo, parse};
use searcher::get_dbpath_for_term;
+use super::{color, Terminal};
+
/// A parsed terminfo database entry.
#[allow(unused)]
#[derive(Debug)]
diff --git a/library/test/src/term/terminfo/parm.rs b/library/test/src/term/terminfo/parm.rs
index c5b4ef0..529ec0c 100644
--- a/library/test/src/term/terminfo/parm.rs
+++ b/library/test/src/term/terminfo/parm.rs
@@ -1,10 +1,10 @@
//! Parameterized string expansion
+use std::iter::repeat;
+
use self::Param::*;
use self::States::*;
-use std::iter::repeat;
-
#[cfg(test)]
mod tests;
diff --git a/library/test/src/term/terminfo/parser/compiled.rs b/library/test/src/term/terminfo/parser/compiled.rs
index 5d40b79..e687b3b 100644
--- a/library/test/src/term/terminfo/parser/compiled.rs
+++ b/library/test/src/term/terminfo/parser/compiled.rs
@@ -2,11 +2,12 @@
//! ncurses-compatible compiled terminfo format parsing (term(5))
-use super::super::TermInfo;
use std::collections::HashMap;
use std::io;
use std::io::prelude::*;
+use super::super::TermInfo;
+
#[cfg(test)]
mod tests;
diff --git a/library/test/src/term/terminfo/searcher.rs b/library/test/src/term/terminfo/searcher.rs
index 3e8ccc9..1b29598 100644
--- a/library/test/src/term/terminfo/searcher.rs
+++ b/library/test/src/term/terminfo/searcher.rs
@@ -2,14 +2,13 @@
//!
//! Does not support hashed database, only filesystem!
-use std::env;
-use std::fs;
use std::path::PathBuf;
+use std::{env, fs};
#[cfg(test)]
mod tests;
-/// Return path to database entry for `term`
+/// Returns path to database entry for `term`
#[allow(deprecated)]
pub(crate) fn get_dbpath_for_term(term: &str) -> Option<PathBuf> {
let mut dirs_to_search = Vec::new();
diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs
index 65764c0..ce9cad3 100644
--- a/library/test/src/term/win.rs
+++ b/library/test/src/term/win.rs
@@ -5,8 +5,7 @@
use std::io;
use std::io::prelude::*;
-use super::color;
-use super::Terminal;
+use super::{color, Terminal};
/// A Terminal implementation that uses the Win32 Console API.
pub(crate) struct WinConsole<T> {
diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs
index 98c54f0..c5f4b03 100644
--- a/library/test/src/test_result.rs
+++ b/library/test/src/test_result.rs
@@ -1,16 +1,14 @@
use std::any::Any;
-use std::process::ExitStatus;
-
#[cfg(unix)]
use std::os::unix::process::ExitStatusExt;
+use std::process::ExitStatus;
+pub use self::TestResult::*;
use super::bench::BenchSamples;
use super::options::ShouldPanic;
use super::time;
use super::types::TestDesc;
-pub use self::TestResult::*;
-
// Return code for secondary process.
// Start somewhere other than 0 so we know the return code means what we think
// it means.
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs
index 43a906a..ba2f353 100644
--- a/library/test/src/tests.rs
+++ b/library/test/src/tests.rs
@@ -1,5 +1,4 @@
use super::*;
-
use crate::{
console::OutputLocation,
formatters::PrettyFormatter,
@@ -237,8 +236,9 @@ fn f() -> Result<(), String> {
#[cfg(not(target_os = "emscripten"))]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_should_panic_non_string_message_type() {
- use crate::tests::TrFailedMsg;
use std::any::TypeId;
+
+ use crate::tests::TrFailedMsg;
fn f() -> Result<(), String> {
std::panic::panic_any(1i32);
}
diff --git a/library/test/src/time.rs b/library/test/src/time.rs
index 7fd69d7..02ae050 100644
--- a/library/test/src/time.rs
+++ b/library/test/src/time.rs
@@ -5,10 +5,9 @@
//! - Provide helpers for `report-time` and `measure-time` options.
//! - Provide newtypes for executions times.
-use std::env;
-use std::fmt;
use std::str::FromStr;
use std::time::{Duration, Instant};
+use std::{env, fmt};
use super::types::{TestDesc, TestType};
@@ -24,9 +23,10 @@
/// Example of the expected format is `RUST_TEST_TIME_xxx=100,200`, where 100 means
/// warn time, and 200 means critical time.
pub mod time_constants {
- use super::TEST_WARN_TIMEOUT_S;
use std::time::Duration;
+ use super::TEST_WARN_TIMEOUT_S;
+
/// Environment variable for overriding default threshold for unit-tests.
pub const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT";
diff --git a/library/test/src/types.rs b/library/test/src/types.rs
index 6a7035a..c3be346 100644
--- a/library/test/src/types.rs
+++ b/library/test/src/types.rs
@@ -4,15 +4,14 @@
use std::fmt;
use std::sync::mpsc::Sender;
-use super::__rust_begin_short_backtrace;
-use super::bench::Bencher;
-use super::event::CompletedTest;
-use super::options;
-
pub use NamePadding::*;
pub use TestFn::*;
pub use TestName::*;
+use super::bench::Bencher;
+use super::event::CompletedTest;
+use super::{__rust_begin_short_backtrace, options};
+
/// Type of the test according to the [Rust book](https://doc.rust-lang.org/cargo/guide/tests.html)
/// conventions.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 45a1c33..b3de71f 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -2,7 +2,6 @@
#![unstable(feature = "panic_unwind", issue = "32837")]
#![feature(link_cfg)]
#![feature(staged_api)]
-#![cfg_attr(bootstrap, feature(c_unwind))]
#![feature(strict_provenance)]
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs
index 083acae..b346079 100644
--- a/library/unwind/src/unwinding.rs
+++ b/library/unwind/src/unwinding.rs
@@ -28,9 +28,7 @@ pub enum _Unwind_Reason_Code {
_URC_FAILURE = 9, // used only by ARM EHABI
}
pub use _Unwind_Reason_Code::*;
-
-pub use unwinding::abi::UnwindContext;
-pub use unwinding::abi::UnwindException;
+pub use unwinding::abi::{UnwindContext, UnwindException};
pub enum _Unwind_Context {}
pub use unwinding::custom_eh_frame_finder::{
diff --git a/rustfmt.toml b/rustfmt.toml
index 8c1d3b9..60cd034 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -2,6 +2,8 @@
version = "Two"
use_small_heuristics = "Max"
merge_derives = false
+group_imports = "StdExternalCrate"
+imports_granularity = "Module"
# Files to ignore. Each entry uses gitignore syntax, but `!` prefixes aren't allowed.
ignore = [
@@ -22,8 +24,6 @@
"/tests/rustdoc-ui/", # Some have syntax errors, some are whitespace-sensitive.
"/tests/ui/", # Some have syntax errors, some are whitespace-sensitive.
"/tests/ui-fulldeps/", # Some are whitespace-sensitive (e.g. `// ~ERROR` comments).
- # #[cfg(bootstrap)] so that t-release sees this when they search for it
- "/tests/rustdoc-json/impl-trait-precise-capturing.rs",
# Do not format submodules.
# FIXME: sync submodule list with tidy/bootstrap/etc
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index de0924c..6045376 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -65,7 +65,7 @@
"termcolor",
"toml",
"walkdir",
- "windows",
+ "windows 0.52.0",
"xz2",
]
@@ -379,12 +379,6 @@
]
[[package]]
-name = "once_cell"
-version = "1.19.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
-
-[[package]]
name = "opener"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -549,16 +543,15 @@
[[package]]
name = "sysinfo"
-version = "0.30.5"
+version = "0.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2"
+checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab"
dependencies = [
- "cfg-if",
"core-foundation-sys",
"libc",
+ "memchr",
"ntapi",
- "once_cell",
- "windows",
+ "windows 0.57.0",
]
[[package]]
@@ -655,7 +648,17 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
- "windows-core",
+ "windows-core 0.52.0",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
+dependencies = [
+ "windows-core 0.57.0",
"windows-targets",
]
@@ -669,6 +672,49 @@
]
[[package]]
+name = "windows-core"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-result",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -679,13 +725,14 @@
[[package]]
name = "windows-targets"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
+ "windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
@@ -694,45 +741,51 @@
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.52.0"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "xattr"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index f723407..84262c1 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -63,7 +63,7 @@
xz2 = "0.1"
# Dependencies needed by the build-metrics feature
-sysinfo = { version = "0.30", default-features = false, optional = true }
+sysinfo = { version = "0.31.2", default-features = false, optional = true, features = ["system"] }
[target.'cfg(windows)'.dependencies.junction]
version = "1.0.0"
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 258a034..1131600 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/126298
+Last change is for: https://github.com/rust-lang/rust/pull/125642
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index a7d21ba..f03f03e 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -5,23 +5,25 @@
//! parent directory, and otherwise documentation can be found throughout the `build`
//! directory in each respective module.
-use std::io::Write;
-use std::process;
+use std::fs::{self, OpenOptions};
+use std::io::{self, BufRead, BufReader, IsTerminal, Write};
use std::str::FromStr;
-use std::{
- env,
- fs::{self, OpenOptions},
- io::{self, BufRead, BufReader, IsTerminal},
-};
+use std::{env, process};
use bootstrap::{
- find_recent_config_change_ids, human_readable_changes, t, Build, Config, Subcommand,
+ find_recent_config_change_ids, human_readable_changes, t, Build, Config, Flags, Subcommand,
CONFIG_CHANGE_HISTORY,
};
fn main() {
let args = env::args().skip(1).collect::<Vec<_>>();
- let config = Config::parse(&args);
+
+ if Flags::try_parse_verbose_help(&args) {
+ return;
+ }
+
+ let flags = Flags::parse(&args);
+ let config = Config::parse(flags);
let mut build_lock;
let _build_lock_guard;
@@ -30,10 +32,7 @@ fn main() {
// Display PID of process holding the lock
// PID will be stored in a lock file
let lock_path = config.out.join("lock");
- let pid = match fs::read_to_string(&lock_path) {
- Ok(contents) => contents,
- Err(_) => String::new(),
- };
+ let pid = fs::read_to_string(&lock_path).unwrap_or_default();
build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new()
.write(true)
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 46e845f..d04e2fb 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -89,6 +89,25 @@ fn main() {
rustc_real
};
+ // Get the name of the crate we're compiling, if any.
+ let crate_name = parse_value_from_args(&orig_args, "--crate-name");
+
+ // When statically linking `std` into `rustc_driver`, remove `-C prefer-dynamic`
+ if env::var("RUSTC_LINK_STD_INTO_RUSTC_DRIVER").unwrap() == "1"
+ && crate_name == Some("rustc_driver")
+ && stage != "0"
+ {
+ if let Some(pos) = args.iter().enumerate().position(|(i, a)| {
+ a == "-C" && args.get(i + 1).map(|a| a == "prefer-dynamic").unwrap_or(false)
+ }) {
+ args.remove(pos);
+ args.remove(pos);
+ }
+ if let Some(pos) = args.iter().position(|a| a == "-Cprefer-dynamic") {
+ args.remove(pos);
+ }
+ }
+
let mut cmd = match env::var_os("RUSTC_WRAPPER_REAL") {
Some(wrapper) if !wrapper.is_empty() => {
let mut cmd = Command::new(wrapper);
@@ -99,9 +118,6 @@ fn main() {
};
cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
- // Get the name of the crate we're compiling, if any.
- let crate_name = parse_value_from_args(&orig_args, "--crate-name");
-
if let Some(crate_name) = crate_name {
if let Some(target) = env::var_os("RUSTC_TIME") {
if target == "all"
@@ -315,12 +331,10 @@ fn format_rusage_data(_child: Child) -> Option<String> {
fn format_rusage_data(child: Child) -> Option<String> {
use std::os::windows::io::AsRawHandle;
- use windows::{
- Win32::Foundation::HANDLE,
- Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
- Win32::System::Threading::GetProcessTimes,
- Win32::System::Time::FileTimeToSystemTime,
- };
+ use windows::Win32::Foundation::HANDLE;
+ use windows::Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS};
+ use windows::Win32::System::Threading::GetProcessTimes;
+ use windows::Win32::System::Time::FileTimeToSystemTime;
let handle = HANDLE(child.as_raw_handle() as isize);
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index ed5b9ed..7f7faf0 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -1,7 +1,9 @@
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
+use std::path::PathBuf;
+
use crate::core::build_steps::compile::{
- add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
+ add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
};
use crate::core::build_steps::tool::{prepare_tool_cargo, SourceType};
use crate::core::builder::{
@@ -9,17 +11,6 @@
};
use crate::core::config::TargetSelection;
use crate::{Compiler, Mode, Subcommand};
-use std::path::{Path, PathBuf};
-
-pub fn cargo_subcommand(kind: Kind) -> &'static str {
- match kind {
- Kind::Check
- // We ensure check steps for both std and rustc from build_steps/clippy, so handle `Kind::Clippy` as well.
- | Kind::Clippy => "check",
- Kind::Fix => "fix",
- _ => unreachable!(),
- }
-}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Std {
@@ -30,11 +21,18 @@ pub struct Std {
///
/// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
crates: Vec<String>,
+ /// Override `Builder::kind` on cargo invocations.
+ ///
+ /// By default, `Builder::kind` is propagated as the subcommand to the cargo invocations.
+ /// However, there are cases when this is not desirable. For example, when running `x clippy $tool_name`,
+ /// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
+ /// which is not useful if we only want to lint a few crates with specific rules.
+ override_build_kind: Option<Kind>,
}
impl Std {
- pub fn new(target: TargetSelection) -> Self {
- Self { target, crates: vec![] }
+ pub fn new_with_build_kind(target: TargetSelection, kind: Option<Kind>) -> Self {
+ Self { target, crates: vec![], override_build_kind: kind }
}
}
@@ -47,12 +45,12 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- let crates = run.make_run_crates(Alias::Library);
- run.builder.ensure(Std { target: run.target, crates });
+ let crates = std_crates_for_run_make(&run);
+ run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
}
fn run(self, builder: &Builder<'_>) {
- builder.update_submodule(&Path::new("library").join("stdarch"));
+ builder.require_submodule("library/stdarch", None);
let target = self.target;
let compiler = builder.compiler(builder.top_stage, builder.config.build);
@@ -63,7 +61,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Std,
SourceType::InTree,
target,
- cargo_subcommand(builder.kind),
+ self.override_build_kind.unwrap_or(builder.kind),
);
std_cargo(builder, target, compiler.stage, &mut cargo);
@@ -117,7 +115,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Std,
SourceType::InTree,
target,
- cargo_subcommand(builder.kind),
+ self.override_build_kind.unwrap_or(builder.kind),
);
// If we're not in stage 0, tests and examples will fail to compile
@@ -158,16 +156,31 @@ pub struct Rustc {
///
/// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
crates: Vec<String>,
+ /// Override `Builder::kind` on cargo invocations.
+ ///
+ /// By default, `Builder::kind` is propagated as the subcommand to the cargo invocations.
+ /// However, there are cases when this is not desirable. For example, when running `x clippy $tool_name`,
+ /// passing `Builder::kind` to cargo invocations would run clippy on the entire compiler and library,
+ /// which is not useful if we only want to lint a few crates with specific rules.
+ override_build_kind: Option<Kind>,
}
impl Rustc {
pub fn new(target: TargetSelection, builder: &Builder<'_>) -> Self {
+ Self::new_with_build_kind(target, builder, None)
+ }
+
+ pub fn new_with_build_kind(
+ target: TargetSelection,
+ builder: &Builder<'_>,
+ kind: Option<Kind>,
+ ) -> Self {
let crates = builder
.in_tree_crates("rustc-main", Some(target))
.into_iter()
.map(|krate| krate.name.to_string())
.collect();
- Self { target, crates }
+ Self { target, crates, override_build_kind: kind }
}
}
@@ -182,7 +195,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
let crates = run.make_run_crates(Alias::Compiler);
- run.builder.ensure(Rustc { target: run.target, crates });
+ run.builder.ensure(Rustc { target: run.target, crates, override_build_kind: None });
}
/// Builds the compiler.
@@ -203,7 +216,7 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(crate::core::build_steps::compile::Std::new(compiler, compiler.host));
builder.ensure(crate::core::build_steps::compile::Std::new(compiler, target));
} else {
- builder.ensure(Std::new(target));
+ builder.ensure(Std::new_with_build_kind(target, self.override_build_kind));
}
let mut cargo = builder::Cargo::new(
@@ -212,7 +225,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Rustc,
SourceType::InTree,
target,
- cargo_subcommand(builder.kind),
+ self.override_build_kind.unwrap_or(builder.kind),
);
rustc_cargo(builder, &mut cargo, target, &compiler);
@@ -290,7 +303,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Codegen,
SourceType::InTree,
target,
- cargo_subcommand(builder.kind),
+ builder.kind,
);
cargo
@@ -348,7 +361,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
target,
- cargo_subcommand(builder.kind),
+ builder.kind,
"src/tools/rust-analyzer",
SourceType::InTree,
&["in-rust-tree".to_owned()],
@@ -416,7 +429,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
target,
- cargo_subcommand(builder.kind),
+ builder.kind,
$path,
$source_type,
&[],
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index a4be6bc..f608e5d 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -11,7 +11,7 @@
use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
use crate::utils::helpers::t;
-use crate::{Build, Compiler, Mode, Subcommand};
+use crate::{Build, Compiler, Kind, Mode, Subcommand};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CleanAll {}
@@ -66,7 +66,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> Self::Output {
let compiler = self.compiler;
let target = compiler.host;
- let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean");
+ let mut cargo = builder.bare_cargo(compiler, $mode, target, Kind::Clean);
// Since https://github.com/rust-lang/rust/pull/111076 enables
// unstable cargo feature (`public-dependency`), we need to ensure
@@ -121,7 +121,7 @@ fn clean(build: &Build, all: bool, stage: Option<u32>) {
fn clean_specific_stage(build: &Build, stage: u32) {
for host in &build.hosts {
- let entries = match build.out.join(host.triple).read_dir() {
+ let entries = match build.out.join(host).read_dir() {
Ok(iter) => iter,
Err(_) => continue,
};
@@ -148,7 +148,7 @@ fn clean_default(build: &Build) {
rm_rf(&build.out.join("bootstrap-shims-dump"));
rm_rf(&build.out.join("rustfmt.stamp"));
- let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t.triple)).collect();
+ let mut hosts: Vec<_> = build.hosts.iter().map(|t| build.out.join(t)).collect();
// After cross-compilation, artifacts of the host architecture (which may differ from build.host)
// might not get removed.
// Adding its path (linked one for easier accessibility) will solve this problem.
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index ee7fb36..4ee9fbc 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -1,28 +1,13 @@
//! Implementation of running clippy on the compiler, standard library and various tools.
-use std::path::Path;
-
-use crate::builder::Builder;
-use crate::builder::ShouldRun;
+use super::compile::{librustc_stamp, libstd_stamp, run_cargo, rustc_cargo, std_cargo};
+use super::tool::{prepare_tool_cargo, SourceType};
+use super::{check, compile};
+use crate::builder::{Builder, ShouldRun};
+use crate::core::build_steps::compile::std_crates_for_run_make;
use crate::core::builder;
-use crate::core::builder::crate_description;
-use crate::core::builder::Alias;
-use crate::core::builder::Kind;
-use crate::core::builder::RunConfig;
-use crate::core::builder::Step;
-use crate::Mode;
-use crate::Subcommand;
-use crate::TargetSelection;
-
-use super::check;
-use super::compile;
-use super::compile::librustc_stamp;
-use super::compile::libstd_stamp;
-use super::compile::run_cargo;
-use super::compile::rustc_cargo;
-use super::compile::std_cargo;
-use super::tool::prepare_tool_cargo;
-use super::tool::SourceType;
+use crate::core::builder::{crate_description, Alias, Kind, RunConfig, Step};
+use crate::{Mode, Subcommand, TargetSelection};
/// Disable the most spammy clippy lints
const IGNORED_RULES_FOR_STD_AND_RUSTC: &[&str] = &[
@@ -122,18 +107,24 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
- let crates = run.make_run_crates(Alias::Library);
+ let crates = std_crates_for_run_make(&run);
run.builder.ensure(Std { target: run.target, crates });
}
fn run(self, builder: &Builder<'_>) {
- builder.update_submodule(&Path::new("library").join("stdarch"));
+ builder.require_submodule("library/stdarch", None);
let target = self.target;
let compiler = builder.compiler(builder.top_stage, builder.config.build);
- let mut cargo =
- builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, "clippy");
+ let mut cargo = builder::Cargo::new(
+ builder,
+ compiler,
+ Mode::Std,
+ SourceType::InTree,
+ target,
+ Kind::Clippy,
+ );
std_cargo(builder, target, compiler.stage, &mut cargo);
@@ -194,7 +185,7 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(compile::Std::new(compiler, compiler.host));
builder.ensure(compile::Std::new(compiler, target));
} else {
- builder.ensure(check::Std::new(target));
+ builder.ensure(check::Std::new_with_build_kind(target, Some(Kind::Check)));
}
let mut cargo = builder::Cargo::new(
@@ -203,7 +194,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Rustc,
SourceType::InTree,
target,
- "clippy",
+ Kind::Clippy,
);
rustc_cargo(builder, &mut cargo, target, &compiler);
@@ -261,14 +252,14 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
let compiler = builder.compiler(builder.top_stage, builder.config.build);
let target = self.target;
- builder.ensure(check::Rustc::new(target, builder));
+ builder.ensure(check::Rustc::new_with_build_kind(target, builder, Some(Kind::Check)));
let cargo = prepare_tool_cargo(
builder,
compiler,
Mode::ToolRustc,
target,
- "clippy",
+ Kind::Clippy,
$path,
SourceType::InTree,
&[],
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 25adaa0..4353cfa 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -8,31 +8,28 @@
use std::borrow::Cow;
use std::collections::HashSet;
-use std::env;
use std::ffi::OsStr;
-use std::fs;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::process::Stdio;
-use std::str;
+use std::{env, fs, str};
use serde_derive::Deserialize;
-use crate::core::build_steps::dist;
-use crate::core::build_steps::llvm;
use crate::core::build_steps::tool::SourceType;
+use crate::core::build_steps::{dist, llvm};
use crate::core::builder;
-use crate::core::builder::crate_description;
-use crate::core::builder::Cargo;
-use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath};
+use crate::core::builder::{
+ crate_description, Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath,
+};
use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
use crate::utils::exec::command;
use crate::utils::helpers::{
- exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
+ self, exe, get_clang_cl_resource_dir, get_closest_merge_base_commit, is_debug_info, is_dylib,
+ symlink_dir, t, up_to_date,
};
-use crate::LLVM_TOOLS;
-use crate::{CLang, Compiler, DependencyType, GitRepo, Mode};
+use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Std {
@@ -118,25 +115,43 @@ impl Step for Std {
const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- // When downloading stage1, the standard library has already been copied to the sysroot, so
- // there's no need to rebuild it.
- let builder = run.builder;
- run.crate_or_deps("sysroot")
- .path("library")
- .lazy_default_condition(Box::new(|| !builder.download_rustc()))
+ run.crate_or_deps("sysroot").path("library")
}
fn make_run(run: RunConfig<'_>) {
- // If the paths include "library", build the entire standard library.
- let has_alias =
- run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
- let crates = if has_alias { Default::default() } else { run.cargo_crates_in_set() };
+ let crates = std_crates_for_run_make(&run);
+ let builder = run.builder;
+
+ // Force compilation of the standard library from source if the `library` is modified. This allows
+ // library team to compile the standard library without needing to compile the compiler with
+ // the `rust.download-rustc=true` option.
+ let force_recompile =
+ if builder.rust_info().is_managed_git_subrepository() && builder.download_rustc() {
+ let closest_merge_commit = get_closest_merge_base_commit(
+ Some(&builder.src),
+ &builder.config.git_config(),
+ &builder.config.stage0_metadata.config.git_merge_commit_email,
+ &[],
+ )
+ .unwrap();
+
+ // Check if `library` has changes (returns false otherwise)
+ !t!(helpers::git(Some(&builder.src))
+ .args(["diff-index", "--quiet", &closest_merge_commit])
+ .arg("--")
+ .arg(builder.src.join("library"))
+ .as_command_mut()
+ .status())
+ .success()
+ } else {
+ false
+ };
run.builder.ensure(Std {
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
target: run.target,
crates,
- force_recompile: false,
+ force_recompile,
extra_rust_args: &[],
is_for_mir_opt_tests: false,
});
@@ -182,11 +197,16 @@ fn run(self, builder: &Builder<'_>) {
return;
}
- builder.update_submodule(&Path::new("library").join("stdarch"));
+ builder.require_submodule("library/stdarch", None);
// Profiler information requires LLVM's compiler-rt
if builder.config.profiler {
- builder.update_submodule(Path::new("src/llvm-project"));
+ builder.require_submodule(
+ "src/llvm-project",
+ Some(
+ "The `build.profiler` config option requires `compiler-rt` sources from LLVM.",
+ ),
+ );
}
let mut target_deps = builder.ensure(StartupObjects { compiler, target });
@@ -226,7 +246,7 @@ fn run(self, builder: &Builder<'_>) {
.rustc_snapshot_sysroot()
.join("lib")
.join("rustlib")
- .join(compiler.host.triple)
+ .join(compiler.host)
.join("bin");
if src_sysroot_bin.exists() {
let target_sysroot_bin =
@@ -246,7 +266,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Std,
SourceType::InTree,
target,
- "check",
+ Kind::Check,
);
cargo.rustflag("-Zalways-encode-mir");
cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
@@ -258,7 +278,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Std,
SourceType::InTree,
target,
- "build",
+ Kind::Build,
);
std_cargo(builder, target, compiler.stage, &mut cargo);
for krate in &*self.crates {
@@ -412,7 +432,7 @@ fn copy_self_contained_objects(
DependencyType::TargetSelfContained,
);
}
- } else if target.ends_with("windows-gnu") {
+ } else if target.is_windows_gnu() {
for obj in ["crt2.o", "dllcrt2.o"].iter() {
let src = compiler_file(builder, &builder.cc(target), target, CLang::C, obj);
let target = libdir_self_contained.join(obj);
@@ -424,6 +444,28 @@ fn copy_self_contained_objects(
target_deps
}
+/// Resolves standard library crates for `Std::run_make` for any build kind (like check, build, clippy, etc.).
+pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec<String> {
+ // FIXME: Extend builder tests to cover the `crates` field of `Std` instances.
+ if cfg!(feature = "bootstrap-self-test") {
+ return vec![];
+ }
+
+ let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
+ let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
+
+ // For no_std targets, do not add any additional crates to the compilation other than what `compile::std_cargo` already adds for no_std targets.
+ if target_is_no_std {
+ vec![]
+ }
+ // If the paths include "library", build the entire standard library.
+ else if has_alias {
+ run.make_run_crates(builder::Alias::Library)
+ } else {
+ run.cargo_crates_in_set()
+ }
+}
+
/// Configure cargo to compile the standard library, adding appropriate env vars
/// and such.
pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {
@@ -456,13 +498,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
// That's probably ok? At least, the difference wasn't enforced before. There's a comment in
// the compiler_builtins build script that makes me nervous, though:
// https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
- builder.update_submodule(&Path::new("src").join("llvm-project"));
+ builder.require_submodule(
+ "src/llvm-project",
+ Some(
+ "The `build.optimized-compiler-builtins` config option \
+ requires `compiler-rt` sources from LLVM.",
+ ),
+ );
let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
- if !compiler_builtins_root.exists() {
- panic!(
- "need LLVM sources available to build `compiler-rt`, but they weren't present; consider enabling `build.submodules = true` or disabling `optimized-compiler-builtins`"
- );
- }
+ assert!(compiler_builtins_root.exists());
// Note that `libprofiler_builtins/build.rs` also computes this so if
// you're changing something here please also change that.
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
@@ -607,8 +651,8 @@ fn run(self, builder: &Builder<'_>) {
compiler: self.compiler,
force_recompile: self.force_recompile,
});
- let libdir = sysroot.join(lib).join("rustlib").join(target.triple).join("lib");
- let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host.triple).join("lib");
+ let libdir = sysroot.join(lib).join("rustlib").join(target).join("lib");
+ let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host).join("lib");
(libdir, hostdir)
} else {
let libdir = builder.sysroot_libdir(target_compiler, target);
@@ -626,12 +670,12 @@ fn run(self, builder: &Builder<'_>) {
.build
.config
.initial_rustc
- .starts_with(builder.out.join(compiler.host.triple).join("stage0/bin"))
+ .starts_with(builder.out.join(compiler.host).join("stage0/bin"))
{
// Copy bin files from stage0/bin to stage0-sysroot/bin
- let sysroot = builder.out.join(compiler.host.triple).join("stage0-sysroot");
+ let sysroot = builder.out.join(compiler.host).join("stage0-sysroot");
- let host = compiler.host.triple;
+ let host = compiler.host;
let stage0_bin_dir = builder.out.join(host).join("stage0/bin");
let sysroot_bin_dir = sysroot.join("bin");
t!(fs::create_dir_all(&sysroot_bin_dir));
@@ -749,7 +793,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
let for_compiler = self.compiler;
let target = self.target;
- if !target.ends_with("windows-gnu") {
+ if !target.is_windows_gnu() {
return vec![];
}
@@ -916,7 +960,7 @@ fn run(self, builder: &Builder<'_>) -> u32 {
Mode::Rustc,
SourceType::InTree,
target,
- "build",
+ Kind::Build,
);
rustc_cargo(builder, &mut cargo, target, &compiler);
@@ -1356,7 +1400,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Codegen,
SourceType::InTree,
target,
- "build",
+ Kind::Build,
);
cargo
.arg("--manifest-path")
@@ -1510,7 +1554,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
/// For all other stages, it's the same stage directory that the compiler lives in.
fn run(self, builder: &Builder<'_>) -> PathBuf {
let compiler = self.compiler;
- let host_dir = builder.out.join(compiler.host.triple);
+ let host_dir = builder.out.join(compiler.host);
let sysroot_dir = |stage| {
if stage == 0 {
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4076ed0..530eb9b 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -9,19 +9,17 @@
//! pieces of `rustup.rs`!
use std::collections::HashSet;
-use std::env;
use std::ffi::OsStr;
-use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
+use std::{env, fs};
use object::read::archive::ArchiveFile;
use object::BinaryFormat;
-use crate::core::build_steps::compile;
use crate::core::build_steps::doc::DocumentationFormat;
-use crate::core::build_steps::llvm;
use crate::core::build_steps::tool::{self, Tool};
+use crate::core::build_steps::{compile, llvm};
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::utils::channel::{self, Info};
@@ -108,7 +106,6 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
builder.ensure(crate::core::build_steps::doc::Std::new(
builder.top_stage,
host,
- builder,
DocumentationFormat::Json,
));
@@ -278,12 +275,8 @@ fn make_win_dist(
}
//Copy platform tools to platform-specific bin directory
- let target_bin_dir = plat_root
- .join("lib")
- .join("rustlib")
- .join(target.triple)
- .join("bin")
- .join("self-contained");
+ let target_bin_dir =
+ plat_root.join("lib").join("rustlib").join(target).join("bin").join("self-contained");
fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
for src in target_tools {
builder.copy_link_to_folder(&src, &target_bin_dir);
@@ -298,12 +291,8 @@ fn make_win_dist(
);
//Copy platform libs to platform-specific lib directory
- let target_lib_dir = plat_root
- .join("lib")
- .join("rustlib")
- .join(target.triple)
- .join("lib")
- .join("self-contained");
+ let target_lib_dir =
+ plat_root.join("lib").join("rustlib").join(target).join("lib").join("self-contained");
fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
for src in target_libs {
builder.copy_link_to_folder(&src, &target_lib_dir);
@@ -453,7 +442,7 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
// component for now.
maybe_install_llvm_runtime(builder, host, image);
- let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin");
+ let dst_dir = image.join("lib/rustlib").join(host).join("bin");
t!(fs::create_dir_all(&dst_dir));
// Copy over lld if it's there
@@ -610,7 +599,7 @@ fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp
/// Copy stamped files into an image's `target/lib` directory.
fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
- let dst = image.join("lib/rustlib").join(target.triple).join("lib");
+ let dst = image.join("lib/rustlib").join(target).join("lib");
let self_contained_dst = dst.join("self-contained");
t!(fs::create_dir_all(&dst));
t!(fs::create_dir_all(&self_contained_dst));
@@ -772,7 +761,7 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let src = builder
.stage_out(compiler, Mode::Std)
- .join(target.triple)
+ .join(target)
.join(builder.cargo_dir())
.join("deps")
.join("save-analysis");
@@ -907,7 +896,7 @@ fn make_run(run: RunConfig<'_>) {
/// Creates the `rust-src` installer component
fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
if !builder.config.dry_run() {
- builder.update_submodule(Path::new("src/llvm-project"));
+ builder.require_submodule("src/llvm-project", None);
}
let tarball = Tarball::new_targetless(builder, "rust-src");
@@ -921,7 +910,6 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
// translation code in `imported_source_files` in `src/librustc_metadata/rmeta/decoder.rs`
let dst_src = tarball.image_dir().join("lib/rustlib/src/rust");
- let src_files = ["Cargo.lock"];
// This is the reduced set of paths which will become the rust-src component
// (essentially libstd and all of its path dependencies).
copy_src_dirs(
@@ -940,9 +928,6 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
],
&dst_src,
);
- for file in src_files.iter() {
- builder.copy_link(&builder.src.join(file), &dst_src.join(file));
- }
tarball.generate()
}
@@ -1022,10 +1007,7 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
// FIXME: This code looks _very_ similar to what we have in `src/core/build_steps/vendor.rs`
// perhaps it should be removed in favor of making `dist` perform the `vendor` step?
- // Ensure we have all submodules from src and other directories checked out.
- for submodule in build_helper::util::parse_gitmodules(&builder.src) {
- builder.update_submodule(Path::new(submodule));
- }
+ builder.require_and_update_all_submodules();
// Vendor all Cargo dependencies
let mut cmd = command(&builder.initial_cargo);
@@ -1040,6 +1022,8 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
.arg("--sync")
.arg(builder.src.join("./compiler/rustc_codegen_gcc/Cargo.toml"))
.arg("--sync")
+ .arg(builder.src.join("./library/Cargo.toml"))
+ .arg("--sync")
.arg(builder.src.join("./src/bootstrap/Cargo.toml"))
.arg("--sync")
.arg(builder.src.join("./src/tools/opt-dist/Cargo.toml"))
@@ -1517,7 +1501,7 @@ macro_rules! add_component {
tarballs.push(builder.ensure(Rustc { compiler: builder.compiler(stage, target) }));
tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
- if target.ends_with("windows-gnu") {
+ if target.is_windows_gnu() {
tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
}
@@ -1691,7 +1675,7 @@ fn filter(contents: &str, marker: &str) -> String {
prepare(tool);
}
}
- if target.ends_with("windows-gnu") {
+ if target.is_windows_gnu() {
prepare("rust-mingw");
}
@@ -1838,7 +1822,7 @@ fn filter(contents: &str, marker: &str) -> String {
.arg("-t")
.arg(etc.join("msi/remove-duplicates.xsl"))
.run(builder);
- if target.ends_with("windows-gnu") {
+ if target.is_windows_gnu() {
command(&heat)
.current_dir(&exe)
.arg("dir")
@@ -1884,7 +1868,7 @@ fn filter(contents: &str, marker: &str) -> String {
if built_tools.contains("miri") {
cmd.arg("-dMiriDir=miri");
}
- if target.ends_with("windows-gnu") {
+ if target.is_windows_gnu() {
cmd.arg("-dGccDir=rust-mingw");
}
cmd.run(builder);
@@ -1909,7 +1893,7 @@ fn filter(contents: &str, marker: &str) -> String {
}
candle("AnalysisGroup.wxs".as_ref());
- if target.ends_with("windows-gnu") {
+ if target.is_windows_gnu() {
candle("GccGroup.wxs".as_ref());
}
@@ -1949,7 +1933,7 @@ fn filter(contents: &str, marker: &str) -> String {
cmd.arg("DocsGroup.wixobj");
}
- if target.ends_with("windows-gnu") {
+ if target.is_windows_gnu() {
cmd.arg("GccGroup.wixobj");
}
// ICE57 wrongly complains about the shortcuts
@@ -1981,7 +1965,7 @@ fn add_env(builder: &Builder<'_>, cmd: &mut BootstrapCommand, target: TargetSele
if target.contains("windows-gnullvm") {
cmd.env("CFG_MINGW", "1").env("CFG_ABI", "LLVM");
- } else if target.contains("windows-gnu") {
+ } else if target.is_windows_gnu() {
cmd.env("CFG_MINGW", "1").env("CFG_ABI", "GNU");
} else {
cmd.env("CFG_MINGW", "0").env("CFG_ABI", "MSVC");
@@ -2095,7 +2079,7 @@ fn maybe_install_llvm(
/// Maybe add libLLVM.so to the target lib-dir for linking.
pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
- let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib");
+ let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
// We do not need to copy LLVM files into the sysroot if it is not
// dynamically linked; it is already included into librustc_llvm
// statically.
@@ -2128,8 +2112,13 @@ impl Step for LlvmTools {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let default = should_build_extended_tool(run.builder, "llvm-tools");
- // FIXME: allow using the names of the tools themselves?
- run.alias("llvm-tools").default_condition(default)
+
+ let mut run = run.alias("llvm-tools");
+ for tool in LLVM_TOOLS {
+ run = run.alias(tool);
+ }
+
+ run.default_condition(default)
}
fn make_run(run: RunConfig<'_>) {
@@ -2137,6 +2126,32 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
+ fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> {
+ let mut tools = vec![];
+
+ for path in paths {
+ let path = path.to_str().unwrap();
+
+ // Include all tools if path is 'llvm-tools'.
+ if path == "llvm-tools" {
+ return LLVM_TOOLS.to_owned();
+ }
+
+ for tool in LLVM_TOOLS {
+ if path == *tool {
+ tools.push(*tool);
+ }
+ }
+ }
+
+ // If no specific tool is requested, include all tools.
+ if tools.is_empty() {
+ tools = LLVM_TOOLS.to_owned();
+ }
+
+ tools
+ }
+
let target = self.target;
/* run only if llvm-config isn't used */
@@ -2157,7 +2172,7 @@ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
// Prepare the image directory
let src_bindir = builder.llvm_out(target).join("bin");
let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
- for tool in LLVM_TOOLS {
+ for tool in tools_to_install(&builder.paths) {
let exe = src_bindir.join(exe(tool, target));
tarball.add_file(&exe, &dst_bindir, 0o755);
}
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index d8204ea..3016335 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -9,14 +9,15 @@
use std::io::{self, Write};
use std::path::{Path, PathBuf};
-use std::{fs, mem};
+use std::{env, fs, mem};
use crate::core::build_steps::compile;
use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool};
-use crate::core::builder::{self, crate_description};
-use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
+use crate::core::builder::{
+ self, crate_description, Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step,
+};
use crate::core::config::{Config, TargetSelection};
-use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date};
+use crate::utils::helpers::{symlink_dir, t, up_to_date};
use crate::Mode;
macro_rules! submodule_helper {
@@ -53,8 +54,8 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) {
$(
- let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
- builder.update_submodule(&path);
+ let path = submodule_helper!( $path, submodule $( = $submodule )? );
+ builder.require_submodule(path, None);
)?
builder.ensure(RustbookSrc {
target: self.target,
@@ -62,6 +63,7 @@ fn run(self, builder: &Builder<'_>) {
src: builder.src.join($path),
parent: Some(self),
languages: $lang.into(),
+ rustdoc: None,
})
}
}
@@ -80,7 +82,6 @@ fn run(self, builder: &Builder<'_>) {
EditionGuide, "src/doc/edition-guide", "edition-guide", &[], submodule;
EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[], submodule;
Nomicon, "src/doc/nomicon", "nomicon", &[], submodule;
- Reference, "src/doc/reference", "reference", &[], submodule;
RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja"], submodule;
RustdocBook, "src/doc/rustdoc", "rustdoc", &[];
StyleGuide, "src/doc/style-guide", "style-guide", &[];
@@ -112,6 +113,7 @@ fn run(self, builder: &Builder<'_>) {
src: builder.md_doc_out(self.target).join("unstable-book"),
parent: Some(self),
languages: vec![],
+ rustdoc: None,
})
}
}
@@ -123,6 +125,7 @@ struct RustbookSrc<P: Step> {
src: PathBuf,
parent: Option<P>,
languages: Vec<&'static str>,
+ rustdoc: Option<PathBuf>,
}
impl<P: Step> Step for RustbookSrc<P> {
@@ -153,13 +156,18 @@ fn run(self, builder: &Builder<'_>) {
builder.info(&format!("Rustbook ({target}) - {name}"));
let _ = fs::remove_dir_all(&out);
- builder
- .tool_cmd(Tool::Rustbook)
- .arg("build")
- .arg(&src)
- .arg("-d")
- .arg(&out)
- .run(builder);
+ let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
+ if let Some(mut rustdoc) = self.rustdoc {
+ rustdoc.pop();
+ let old_path = env::var_os("PATH").unwrap_or_default();
+ let new_path =
+ env::join_paths(std::iter::once(rustdoc).chain(env::split_paths(&old_path)))
+ .expect("could not add rustdoc to PATH");
+
+ rustbook_cmd.env("PATH", new_path);
+ }
+
+ rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).run(builder);
for lang in &self.languages {
let out = out.join(lang);
@@ -217,22 +225,14 @@ fn make_run(run: RunConfig<'_>) {
/// * Index page
/// * Redirect pages
fn run(self, builder: &Builder<'_>) {
- let relative_path = Path::new("src").join("doc").join("book");
- builder.update_submodule(&relative_path);
+ builder.require_submodule("src/doc/book", None);
let compiler = self.compiler;
let target = self.target;
- let absolute_path = builder.src.join(&relative_path);
+ let absolute_path = builder.src.join("src/doc/book");
let redirect_path = absolute_path.join("redirects");
- if !absolute_path.exists()
- || !redirect_path.exists()
- || dir_is_empty(&absolute_path)
- || dir_is_empty(&redirect_path)
- {
- eprintln!("Please checkout submodule: {}", relative_path.display());
- crate::exit!(1);
- }
+
// build book
builder.ensure(RustbookSrc {
target,
@@ -240,6 +240,7 @@ fn run(self, builder: &Builder<'_>) {
src: absolute_path.clone(),
parent: Some(self),
languages: vec![],
+ rustdoc: None,
});
// building older edition redirects
@@ -252,6 +253,7 @@ fn run(self, builder: &Builder<'_>) {
// treat the other editions as not having a parent.
parent: Option::<Self>::None,
languages: vec![],
+ rustdoc: None,
});
}
@@ -562,18 +564,8 @@ pub struct Std {
}
impl Std {
- pub(crate) fn new(
- stage: u32,
- target: TargetSelection,
- builder: &Builder<'_>,
- format: DocumentationFormat,
- ) -> Self {
- let crates = builder
- .in_tree_crates("sysroot", Some(target))
- .into_iter()
- .map(|krate| krate.name.to_string())
- .collect();
- Std { stage, target, format, crates }
+ pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
+ Std { stage, target, format, crates: vec![] }
}
}
@@ -587,6 +579,7 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
+ let crates = compile::std_crates_for_run_make(&run);
run.builder.ensure(Std {
stage: run.builder.top_stage,
target: run.target,
@@ -595,7 +588,7 @@ fn make_run(run: RunConfig<'_>) {
} else {
DocumentationFormat::Html
},
- crates: run.make_run_crates(Alias::Library),
+ crates,
});
}
@@ -606,6 +599,16 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
+ let crates = if self.crates.is_empty() {
+ builder
+ .in_tree_crates("sysroot", Some(target))
+ .iter()
+ .map(|c| c.name.to_string())
+ .collect()
+ } else {
+ self.crates
+ };
+
let out = match self.format {
DocumentationFormat::Html => builder.doc_out(target),
DocumentationFormat::Json => builder.json_doc_out(target),
@@ -634,7 +637,7 @@ fn run(self, builder: &Builder<'_>) {
extra_args.push("--disable-minification");
}
- doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates);
+ doc_std(builder, self.format, stage, target, &out, &extra_args, &crates);
// Don't open if the format is json
if let DocumentationFormat::Json = self.format {
@@ -646,7 +649,7 @@ fn run(self, builder: &Builder<'_>) {
let index = out.join("std").join("index.html");
builder.open_in_browser(index);
} else {
- for requested_crate in &*self.crates {
+ for requested_crate in crates {
if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) {
let index = out.join(requested_crate).join("index.html");
builder.open_in_browser(index);
@@ -693,26 +696,18 @@ fn doc_std(
extra_args: &[&str],
requested_crates: &[String],
) {
- if builder.no_std(target) == Some(true) {
- panic!(
- "building std documentation for no_std target {target} is not supported\n\
- Set `docs = false` in the config to disable documentation, or pass `--skip library`."
- );
- }
-
let compiler = builder.compiler(stage, builder.config.build);
let target_doc_dir_name = if format == DocumentationFormat::Json { "json-doc" } else { "doc" };
- let target_dir =
- builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name);
+ let target_dir = builder.stage_out(compiler, Mode::Std).join(target).join(target_doc_dir_name);
// This is directory where the compiler will place the output of the command.
// We will then copy the files from this directory into the final `out` directory, the specified
// as a function parameter.
- let out_dir = target_dir.join(target.triple).join("doc");
+ let out_dir = target_dir.join(target).join("doc");
let mut cargo =
- builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, "doc");
+ builder::Cargo::new(builder, compiler, Mode::Std, SourceType::InTree, target, Kind::Doc);
compile::std_cargo(builder, target, compiler.stage, &mut cargo);
cargo
@@ -814,8 +809,14 @@ fn run(self, builder: &Builder<'_>) {
);
// Build cargo command.
- let mut cargo =
- builder::Cargo::new(builder, compiler, Mode::Rustc, SourceType::InTree, target, "doc");
+ let mut cargo = builder::Cargo::new(
+ builder,
+ compiler,
+ Mode::Rustc,
+ SourceType::InTree,
+ target,
+ Kind::Doc,
+ );
cargo.rustdocflag("--document-private-items");
// Since we always pass --document-private-items, there's no need to warn about linking to private items.
@@ -844,7 +845,7 @@ fn run(self, builder: &Builder<'_>) {
let mut to_open = None;
- let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc");
+ let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc");
for krate in &*self.crates {
// Create all crate output directories first to make sure rustdoc uses
// relative links.
@@ -932,8 +933,8 @@ fn run(self, builder: &Builder<'_>) {
let _ = source_type; // silence the "unused variable" warning
let source_type = SourceType::Submodule;
- let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? ));
- builder.update_submodule(&path);
+ let path = submodule_helper!( $path, submodule $( = $submodule )? );
+ builder.require_submodule(path, None);
)?
let stage = builder.top_stage;
@@ -962,7 +963,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
target,
- "doc",
+ Kind::Doc,
$path,
source_type,
&[],
@@ -990,7 +991,7 @@ fn run(self, builder: &Builder<'_>) {
// see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222
// cargo.rustdocflag("--generate-link-to-definition");
- let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc");
+ let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target).join("doc");
$(for krate in $crates {
let dir_name = krate.replace("-", "_");
t!(fs::create_dir_all(out_dir.join(&*dir_name)));
@@ -1172,12 +1173,6 @@ fn make_run(run: RunConfig<'_>) {
/// in the "md-doc" directory in the build output directory. Then
/// "rustbook" is used to convert it to HTML.
fn run(self, builder: &Builder<'_>) {
- // These submodules are required to be checked out to build rustbook
- // because they have Cargo dependencies that are needed.
- #[allow(clippy::single_element_loop)] // This will change soon.
- for path in ["src/doc/book"] {
- builder.update_submodule(Path::new(path));
- }
let out_base = builder.md_doc_out(self.target).join("rustc");
t!(fs::create_dir_all(&out_base));
let out_listing = out_base.join("src/lints");
@@ -1228,6 +1223,50 @@ fn run(self, builder: &Builder<'_>) {
src: out_base,
parent: Some(self),
languages: vec![],
+ rustdoc: None,
+ });
+ }
+}
+
+#[derive(Ord, PartialOrd, Debug, Clone, Hash, PartialEq, Eq)]
+pub struct Reference {
+ pub compiler: Compiler,
+ pub target: TargetSelection,
+}
+
+impl Step for Reference {
+ type Output = ();
+ const DEFAULT: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ let builder = run.builder;
+ run.path("src/doc/reference").default_condition(builder.config.docs)
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(Reference {
+ compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
+ target: run.target,
+ });
+ }
+
+ /// Builds the reference book.
+ fn run(self, builder: &Builder<'_>) {
+ builder.require_submodule("src/doc/reference", None);
+
+ // This is needed for generating links to the standard library using
+ // the mdbook-spec plugin.
+ builder.ensure(compile::Std::new(self.compiler, builder.config.build));
+ let rustdoc = builder.rustdoc(self.compiler);
+
+ // Run rustbook/mdbook to generate the HTML pages.
+ builder.ensure(RustbookSrc {
+ target: self.target,
+ name: "reference".to_owned(),
+ src: builder.src.join("src/doc/reference"),
+ parent: Some(self),
+ languages: vec![],
+ rustdoc: Some(rustdoc),
});
}
}
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index f254c05..8c52df7 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -1,17 +1,19 @@
//! Runs rustfmt on the repository.
-use crate::core::builder::Builder;
-use crate::utils::exec::command;
-use crate::utils::helpers::{self, program_out_of_date, t};
-use build_helper::ci::CiEnv;
-use build_helper::git::get_git_modified_files;
-use ignore::WalkBuilder;
use std::collections::VecDeque;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::mpsc::SyncSender;
use std::sync::Mutex;
+use build_helper::ci::CiEnv;
+use build_helper::git::get_git_modified_files;
+use ignore::WalkBuilder;
+
+use crate::core::builder::Builder;
+use crate::utils::exec::command;
+use crate::utils::helpers::{self, program_out_of_date, t};
+
fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl FnMut(bool) -> bool {
let mut cmd = Command::new(rustfmt);
// Avoid the submodule config paths from coming into play. We only allow a single global config
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index d3e9d6d..0ce86ea 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -3,9 +3,8 @@
//! This module is responsible for installing the standard library,
//! compiler, and documentation.
-use std::env;
-use std::fs;
use std::path::{Component, Path, PathBuf};
+use std::{env, fs};
use crate::core::build_steps::dist;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index af987c5..c5a1ab7 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -8,25 +8,24 @@
//! LLVM and compiler-rt are essentially just wired up to everything else to
//! ensure that they're always in place if needed.
-use std::env;
use std::env::consts::EXE_EXTENSION;
use std::ffi::{OsStr, OsString};
use std::fs::{self, File};
-use std::io;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
+use std::{env, io};
+
+use build_helper::ci::CiEnv;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
use crate::utils::channel;
+use crate::utils::exec::command;
use crate::utils::helpers::{
self, exe, get_clang_cl_resource_dir, output, t, unhashed_basename, up_to_date,
};
use crate::{generate_smart_stamp_hash, CLang, GitRepo, Kind};
-use crate::utils::exec::command;
-use build_helper::ci::CiEnv;
-
#[derive(Clone)]
pub struct LlvmResult {
/// Path to llvm-config binary.
@@ -89,7 +88,7 @@ fn push_all(&mut self, s: impl AsRef<OsStr>) {
/// if not).
pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> LlvmBuildStatus {
// If we have llvm submodule initialized already, sync it.
- builder.update_existing_submodule(&Path::new("src").join("llvm-project"));
+ builder.update_existing_submodule("src/llvm-project");
builder.config.maybe_download_ci_llvm();
@@ -110,7 +109,8 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L
}
// Initialize the llvm submodule if not initialized already.
- builder.update_submodule(&Path::new("src").join("llvm-project"));
+ // If submodules are disabled, this does nothing.
+ builder.update_submodule("src/llvm-project");
let root = "src/llvm-project/llvm";
let out_dir = builder.llvm_out(target);
@@ -194,6 +194,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
let supported_platforms = [
// tier 1
("aarch64-unknown-linux-gnu", false),
+ ("aarch64-apple-darwin", false),
("i686-pc-windows-gnu", false),
("i686-pc-windows-msvc", false),
("i686-unknown-linux-gnu", false),
@@ -202,7 +203,6 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
("x86_64-pc-windows-gnu", true),
("x86_64-pc-windows-msvc", true),
// tier 2 with host tools
- ("aarch64-apple-darwin", false),
("aarch64-pc-windows-msvc", false),
("aarch64-unknown-linux-musl", false),
("arm-unknown-linux-gnueabi", false),
@@ -368,9 +368,7 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
cfg.define("LLVM_PROFDATA_FILE", path);
}
- // Disable zstd to avoid a dependency on libzstd.so.
- cfg.define("LLVM_ENABLE_ZSTD", "OFF");
-
+ // Libraries for ELF section compression.
if !target.is_windows() {
cfg.define("LLVM_ENABLE_ZLIB", "ON");
} else {
@@ -824,6 +822,14 @@ fn configure_llvm(builder: &Builder<'_>, target: TargetSelection, cfg: &mut cmak
}
}
+ // Libraries for ELF section compression.
+ if builder.config.llvm_libzstd {
+ cfg.define("LLVM_ENABLE_ZSTD", "FORCE_ON");
+ cfg.define("LLVM_USE_STATIC_ZSTD", "TRUE");
+ } else {
+ cfg.define("LLVM_ENABLE_ZSTD", "OFF");
+ }
+
if let Some(ref linker) = builder.config.llvm_use_linker {
cfg.define("LLVM_USE_LINKER", linker);
}
@@ -1197,7 +1203,10 @@ fn make_run(run: RunConfig<'_>) {
/// Build crtbegin.o/crtend.o for musl target.
fn run(self, builder: &Builder<'_>) -> Self::Output {
- builder.update_submodule(Path::new("src/llvm-project"));
+ builder.require_submodule(
+ "src/llvm-project",
+ Some("The LLVM sources are required for the CRT from `compiler-rt`."),
+ );
let out_dir = builder.native_dir(self.target).join("crt");
@@ -1270,7 +1279,10 @@ fn make_run(run: RunConfig<'_>) {
/// Build libunwind.a
fn run(self, builder: &Builder<'_>) -> Self::Output {
- builder.update_submodule(Path::new("src/llvm-project"));
+ builder.require_submodule(
+ "src/llvm-project",
+ Some("The LLVM sources are required for libunwind."),
+ );
if builder.config.dry_run() {
return PathBuf::new();
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index b3ddb02..65d635c 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -8,7 +8,7 @@
use crate::core::build_steps::dist::distdir;
use crate::core::build_steps::test;
use crate::core::build_steps::tool::{self, SourceType, Tool};
-use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::flags::get_completion;
use crate::core::config::TargetSelection;
use crate::utils::exec::command;
@@ -142,7 +142,7 @@ fn run(self, builder: &Builder<'_>) {
host_compiler,
Mode::ToolRustc,
host,
- "run",
+ Kind::Run,
"src/tools/miri",
SourceType::InTree,
&[],
@@ -212,11 +212,13 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
let license_metadata = builder.ensure(CollectLicenseMetadata);
// Temporary location, it will be moved to the proper one once it's accurate.
- let dest = builder.out.join("COPYRIGHT.md");
+ let dest = builder.out.join("COPYRIGHT.html");
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
cmd.env("LICENSE_METADATA", &license_metadata);
cmd.env("DEST", &dest);
+ cmd.env("OUT_DIR", &builder.out);
+ cmd.env("CARGO", &builder.initial_cargo);
cmd.run(builder);
dest
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 7da91b8..8cd9ba5 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -5,13 +5,6 @@
//! allows setting up things that cannot be simply captured inside the config.toml, in addition to
//! leading people away from manually editing most of the config.toml values.
-use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
-use crate::t;
-use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY;
-use crate::utils::exec::command;
-use crate::utils::helpers::{self, hex_encode};
-use crate::Config;
-use sha2::Digest;
use std::env::consts::EXE_SUFFIX;
use std::fmt::Write as _;
use std::fs::File;
@@ -20,6 +13,14 @@
use std::str::FromStr;
use std::{fmt, fs, io};
+use sha2::Digest;
+
+use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY;
+use crate::utils::exec::command;
+use crate::utils::helpers::{self, hex_encode};
+use crate::{t, Config};
+
#[cfg(test)]
mod tests;
diff --git a/src/bootstrap/src/core/build_steps/setup/tests.rs b/src/bootstrap/src/core/build_steps/setup/tests.rs
index 3e4d66c..3552224 100644
--- a/src/bootstrap/src/core/build_steps/setup/tests.rs
+++ b/src/bootstrap/src/core/build_steps/setup/tests.rs
@@ -1,6 +1,7 @@
+use sha2::Digest;
+
use super::{RUST_ANALYZER_SETTINGS, SETTINGS_HASHES};
use crate::utils::helpers::hex_encode;
-use sha2::Digest;
#[test]
fn check_matching_settings_hash() {
diff --git a/src/bootstrap/src/core/build_steps/suggest.rs b/src/bootstrap/src/core/build_steps/suggest.rs
index 0f4765f..8aaffab 100644
--- a/src/bootstrap/src/core/build_steps/suggest.rs
+++ b/src/bootstrap/src/core/build_steps/suggest.rs
@@ -2,10 +2,11 @@
#![cfg_attr(feature = "build-metrics", allow(unused))]
-use clap::Parser;
use std::path::PathBuf;
use std::str::FromStr;
+use clap::Parser;
+
use crate::core::build_steps::tool::Tool;
use crate::core::builder::Builder;
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 9de92d4..cc01afd 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3,27 +3,22 @@
//! `./x.py test` (aka [`Kind::Test`]) is currently allowed to reach build steps in other modules.
//! However, this contains ~all test parts we expect people to be able to build and run locally.
-use std::env;
-use std::ffi::OsStr;
-use std::ffi::OsString;
-use std::fs;
-use std::iter;
+use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
+use std::{env, fs, iter};
use clap_complete::shells;
-use crate::core::build_steps::compile;
-use crate::core::build_steps::dist;
use crate::core::build_steps::doc::DocumentationFormat;
-use crate::core::build_steps::llvm;
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
use crate::core::build_steps::tool::{self, SourceType, Tool};
use crate::core::build_steps::toolstate::ToolState;
+use crate::core::build_steps::{compile, dist, llvm};
use crate::core::builder;
-use crate::core::builder::crate_description;
-use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
-use crate::core::config::flags::get_completion;
-use crate::core::config::flags::Subcommand;
+use crate::core::builder::{
+ crate_description, Builder, Compiler, Kind, RunConfig, ShouldRun, Step,
+};
+use crate::core::config::flags::{get_completion, Subcommand};
use crate::core::config::TargetSelection;
use crate::utils::exec::{command, BootstrapCommand};
use crate::utils::helpers::{
@@ -73,7 +68,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolBootstrap,
bootstrap_host,
- "test",
+ Kind::Test,
path,
SourceType::InTree,
&[],
@@ -124,7 +119,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolBootstrap,
bootstrap_host,
- "test",
+ Kind::Test,
"src/tools/linkchecker",
SourceType::InTree,
&[],
@@ -154,7 +149,7 @@ fn run(self, builder: &Builder<'_>) {
let _guard =
builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host);
let _time = helpers::timeit(builder);
- linkchecker.delay_failure().arg(builder.out.join(host.triple).join("doc")).run(builder);
+ linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder);
}
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -289,7 +284,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
self.host,
- "test",
+ Kind::Test,
"src/tools/cargo",
SourceType::Submodule,
&[],
@@ -360,7 +355,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
host,
- "test",
+ Kind::Test,
crate_path,
SourceType::InTree,
&["in-rust-tree".to_owned()],
@@ -412,7 +407,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
host,
- "test",
+ Kind::Test,
"src/tools/rustfmt",
SourceType::InTree,
&[],
@@ -439,15 +434,15 @@ pub fn build_miri_sysroot(
builder: &Builder<'_>,
compiler: Compiler,
target: TargetSelection,
- ) -> String {
- let miri_sysroot = builder.out.join(compiler.host.triple).join("miri-sysroot");
+ ) -> PathBuf {
+ let miri_sysroot = builder.out.join(compiler.host).join("miri-sysroot");
let mut cargo = builder::Cargo::new(
builder,
compiler,
Mode::Std,
SourceType::Submodule,
target,
- "miri-setup",
+ Kind::MiriSetup,
);
// Tell `cargo miri setup` where to find the sources.
@@ -472,7 +467,7 @@ pub fn build_miri_sysroot(
// Output is "<sysroot>\n".
let sysroot = stdout.trim_end();
builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
- sysroot.to_owned()
+ PathBuf::from(sysroot)
}
}
@@ -525,6 +520,16 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(compile::Std::new(target_compiler, host));
let host_sysroot = builder.sysroot(target_compiler);
+ // Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared when
+ // the sysroot gets rebuilt, to avoid "found possibly newer version of crate `std`" errors.
+ if !builder.config.dry_run() {
+ let ui_test_dep_dir = builder.stage_out(host_compiler, Mode::ToolStd).join("miri_ui");
+ // The mtime of `miri_sysroot` changes when the sysroot gets rebuilt (also see
+ // <https://github.com/RalfJung/rustc-build-sysroot/commit/10ebcf60b80fe2c3dc765af0ff19fdc0da4b7466>).
+ // We can hence use that directly as a signal to clear the ui test dir.
+ builder.clear_if_dirty(&ui_test_dep_dir, &miri_sysroot);
+ }
+
// Run `cargo test`.
// This is with the Miri crate, so it uses the host compiler.
let mut cargo = tool::prepare_tool_cargo(
@@ -532,7 +537,7 @@ fn run(self, builder: &Builder<'_>) {
host_compiler,
Mode::ToolRustc,
host,
- "test",
+ Kind::Test,
"src/tools/miri",
SourceType::InTree,
&[],
@@ -622,7 +627,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolStd, // it's unclear what to use here, we're not building anything just doing a smoke test!
target,
- "miri-test",
+ Kind::MiriTest,
"src/tools/miri/test-cargo-miri",
SourceType::Submodule,
&[],
@@ -682,7 +687,7 @@ fn run(self, builder: &Builder<'_>) {
// when std sources change.
Mode::ToolStd,
host,
- "test",
+ Kind::Test,
"src/tools/compiletest",
SourceType::InTree,
&[],
@@ -732,7 +737,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
host,
- "test",
+ Kind::Test,
"src/tools/clippy",
SourceType::InTree,
&[],
@@ -852,7 +857,6 @@ fn run(self, builder: &Builder<'_>) {
builder.ensure(crate::core::build_steps::doc::Std::new(
builder.top_stage,
self.target,
- builder,
DocumentationFormat::Html,
));
let _guard = builder.msg(
@@ -1111,7 +1115,7 @@ fn make_run(run: RunConfig<'_>) {
}
fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf {
- builder.out.join(host.triple).join("test")
+ builder.out.join(host).join("test")
}
macro_rules! default_test {
@@ -1282,7 +1286,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
self.compiler,
Mode::ToolStd,
self.target,
- "build",
+ Kind::Build,
"src/tools/run-make-support",
SourceType::InTree,
&[],
@@ -1326,7 +1330,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolBootstrap,
host,
- "test",
+ Kind::Test,
"src/tools/run-make-support",
SourceType::InTree,
&[],
@@ -1372,7 +1376,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolBootstrap,
host,
- "test",
+ Kind::Test,
"src/tools/build_helper",
SourceType::InTree,
&[],
@@ -1813,7 +1817,7 @@ fn run(self, builder: &Builder<'_>) {
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
- flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string()));
+ flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
if suite != "mir-opt" {
if let Some(linker) = builder.linker(target) {
@@ -2092,7 +2096,7 @@ fn run(self, builder: &Builder<'_>) {
let git_config = builder.config.git_config();
cmd.arg("--git-repository").arg(git_config.git_repository);
cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
- cmd.force_coloring_in_ci(builder.ci_env);
+ cmd.force_coloring_in_ci();
#[cfg(feature = "build-metrics")]
builder.metrics.begin_test_suite(
@@ -2254,7 +2258,12 @@ fn run_local_doc(self, builder: &Builder<'_>) {
}
macro_rules! test_book {
- ($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => {
+ ($(
+ $name:ident, $path:expr, $book_name:expr,
+ default=$default:expr
+ $(,submodules = $submodules:expr)?
+ ;
+ )+) => {
$(
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct $name {
@@ -2277,6 +2286,11 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) {
+ $(
+ for submodule in $submodules {
+ builder.require_submodule(submodule, None);
+ }
+ )*
builder.ensure(BookTest {
compiler: self.compiler,
path: PathBuf::from($path),
@@ -2290,15 +2304,15 @@ fn run(self, builder: &Builder<'_>) {
}
test_book!(
- Nomicon, "src/doc/nomicon", "nomicon", default=false;
- Reference, "src/doc/reference", "reference", default=false;
+ Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"];
+ Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"];
RustdocBook, "src/doc/rustdoc", "rustdoc", default=true;
RustcBook, "src/doc/rustc", "rustc", default=true;
- RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false;
- EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false;
- TheBook, "src/doc/book", "book", default=false;
+ RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"];
+ EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"];
+ TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"];
UnstableBook, "src/doc/unstable-book", "unstable-book", default=true;
- EditionGuide, "src/doc/edition-guide", "edition-guide", default=false;
+ EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"];
);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -2396,8 +2410,8 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) {
- let relative_path = Path::new("src").join("doc").join("rustc-dev-guide");
- builder.update_submodule(&relative_path);
+ let relative_path = "src/doc/rustc-dev-guide";
+ builder.require_submodule(relative_path, None);
let src = builder.src.join(relative_path);
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook).delay_failure();
@@ -2626,7 +2640,7 @@ fn run(self, builder: &Builder<'_>) {
mode,
SourceType::InTree,
target,
- "miri-test",
+ Kind::MiriTest,
);
// This hack helps bootstrap run standard library tests in Miri. The issue is as
// follows: when running `cargo miri test` on libcore, cargo builds a local copy of core
@@ -2649,14 +2663,7 @@ fn run(self, builder: &Builder<'_>) {
}
// Build `cargo test` command
- builder::Cargo::new(
- builder,
- compiler,
- mode,
- SourceType::InTree,
- target,
- builder.kind.as_str(),
- )
+ builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind)
};
match mode {
@@ -2678,7 +2685,7 @@ fn run(self, builder: &Builder<'_>) {
if builder.download_rustc() && compiler.stage > 0 {
let sysroot = builder
.out
- .join(compiler.host.triple)
+ .join(compiler.host)
.join(format!("stage{}-test-sysroot", compiler.stage));
cargo.env("RUSTC_SYSROOT", sysroot);
}
@@ -2748,7 +2755,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
target,
- builder.kind.as_str(),
+ builder.kind,
"src/tools/rustdoc",
SourceType::InTree,
&[],
@@ -2840,7 +2847,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolRustc,
target,
- builder.kind.as_str(),
+ builder.kind,
"src/rustdoc-json-types",
SourceType::InTree,
&[],
@@ -3003,7 +3010,7 @@ fn run(self, builder: &Builder<'_>) {
let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host);
// Some tests require cargo submodule to be present.
- builder.build.update_submodule(Path::new("src/tools/cargo"));
+ builder.build.require_submodule("src/tools/cargo", None);
let mut check_bootstrap = command(builder.python());
check_bootstrap
@@ -3074,7 +3081,7 @@ fn run(self, builder: &Builder<'_>) {
self.compiler,
Mode::ToolStd,
self.compiler.host,
- "run",
+ Kind::Run,
"src/tools/tier-check",
SourceType::InTree,
&[],
@@ -3146,7 +3153,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolBootstrap,
bootstrap_host,
- "test",
+ Kind::Test,
"src/tools/rust-installer",
SourceType::InTree,
&[],
@@ -3316,7 +3323,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works
SourceType::InTree,
target,
- "run",
+ Kind::Run,
);
cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
@@ -3448,7 +3455,7 @@ fn run(self, builder: &Builder<'_>) {
Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works
SourceType::InTree,
target,
- "run",
+ Kind::Run,
);
cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc"));
@@ -3536,7 +3543,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolStd,
bootstrap_host,
- "test",
+ Kind::Test,
path,
SourceType::InTree,
&[],
@@ -3559,7 +3566,7 @@ fn run(self, builder: &Builder<'_>) {
compiler,
Mode::ToolStd,
bootstrap_host,
- "run",
+ Kind::Run,
path,
SourceType::InTree,
&[],
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 06bb825..4d573b1 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -1,6 +1,5 @@
-use std::env;
-use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
+use std::{env, fs};
use crate::core::build_steps::compile;
use crate::core::build_steps::toolstate::ToolState;
@@ -10,9 +9,7 @@
use crate::utils::channel::GitInfo;
use crate::utils::exec::{command, BootstrapCommand};
use crate::utils::helpers::{add_dylib_path, exe, get_closest_merge_base_commit, git, t};
-use crate::Compiler;
-use crate::Mode;
-use crate::{gha, Kind};
+use crate::{gha, Compiler, Kind, Mode};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum SourceType {
@@ -93,7 +90,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
compiler,
self.mode,
target,
- "build",
+ Kind::Build,
path,
self.source_type,
&self.extra_features,
@@ -139,12 +136,12 @@ pub fn prepare_tool_cargo(
compiler: Compiler,
mode: Mode,
target: TargetSelection,
- command: &'static str,
+ cmd_kind: Kind,
path: &str,
source_type: SourceType,
extra_features: &[String],
) -> CargoCommand {
- let mut cargo = builder::Cargo::new(builder, compiler, mode, source_type, target, command);
+ let mut cargo = builder::Cargo::new(builder, compiler, mode, source_type, target, cmd_kind);
let dir = builder.src.join(path);
cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
@@ -241,6 +238,7 @@ macro_rules! bootstrap_tool {
$(,is_external_tool = $external:expr)*
$(,is_unstable_tool = $unstable:expr)*
$(,allow_features = $allow_features:expr)?
+ $(,submodules = $submodules:expr)?
;
)+) => {
#[derive(PartialEq, Eq, Clone)]
@@ -287,6 +285,11 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
+ $(
+ for submodule in $submodules {
+ builder.require_submodule(submodule, None);
+ }
+ )*
builder.ensure(ToolBuild {
compiler: self.compiler,
target: self.target,
@@ -314,7 +317,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
}
bootstrap_tool!(
- Rustbook, "src/tools/rustbook", "rustbook";
+ Rustbook, "src/tools/rustbook", "rustbook", submodules = SUBMODULES_FOR_RUSTBOOK;
UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen";
Tidy, "src/tools/tidy", "tidy";
Linkchecker, "src/tools/linkchecker", "linkchecker";
@@ -340,6 +343,10 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
);
+/// These are the submodules that are required for rustbook to work due to
+/// depending on mdbook plugins.
+pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"];
+
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct OptimizedDist {
pub compiler: Compiler,
@@ -363,7 +370,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> PathBuf {
// We need to ensure the rustc-perf submodule is initialized when building opt-dist since
// the tool requires it to be in place to run.
- builder.update_submodule(Path::new("src/tools/rustc-perf"));
+ builder.require_submodule("src/tools/rustc-perf", None);
builder.ensure(ToolBuild {
compiler: self.compiler,
@@ -404,7 +411,7 @@ fn make_run(run: RunConfig<'_>) {
fn run(self, builder: &Builder<'_>) -> PathBuf {
// We need to ensure the rustc-perf submodule is initialized.
- builder.update_submodule(Path::new("src/tools/rustc-perf"));
+ builder.require_submodule("src/tools/rustc-perf", None);
let tool = ToolBuild {
compiler: self.compiler,
@@ -639,7 +646,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
build_compiler,
Mode::ToolRustc,
target,
- "build",
+ Kind::Build,
"src/tools/rustdoc",
SourceType::InTree,
features.as_slice(),
@@ -704,7 +711,7 @@ fn make_run(run: RunConfig<'_>) {
}
fn run(self, builder: &Builder<'_>) -> PathBuf {
- builder.build.update_submodule(Path::new("src/tools/cargo"));
+ builder.build.require_submodule("src/tools/cargo", None);
builder.ensure(ToolBuild {
compiler: self.compiler,
@@ -898,7 +905,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
self.compiler,
Mode::ToolRustc,
self.target,
- "build",
+ Kind::Build,
"src/tools/llvm-bitcode-linker",
SourceType::InTree,
&self.extra_features,
@@ -1086,8 +1093,6 @@ fn run(mut $sel, $builder: &Builder<'_>) -> PathBuf {
// NOTE: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs`
// to make `./x.py build <tool>` work.
-// NOTE: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to
-// invoke Cargo to build bootstrap. See the comment there for more details.
tool_extended!((self, builder),
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true;
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true;
diff --git a/src/bootstrap/src/core/build_steps/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs
index 912cd4b..b739610 100644
--- a/src/bootstrap/src/core/build_steps/toolstate.rs
+++ b/src/bootstrap/src/core/build_steps/toolstate.rs
@@ -4,16 +4,15 @@
//!
//! [Toolstate]: https://forge.rust-lang.org/infra/toolstate.html
-use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
-use crate::utils::helpers::{self, t};
-use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
-use std::env;
-use std::fmt;
-use std::fs;
use std::io::{Seek, SeekFrom};
use std::path::{Path, PathBuf};
-use std::time;
+use std::{env, fmt, fs, time};
+
+use serde_derive::{Deserialize, Serialize};
+
+use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::utils::helpers::{self, t};
// Each cycle is 42 days long (6 weeks); the last week is 35..=42 then.
const BETA_WEEK_START: u64 = 35;
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index e6b3cb3..3376846 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -1,6 +1,8 @@
+use std::path::PathBuf;
+
+use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::utils::exec::command;
-use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub(crate) struct Vendor {
@@ -35,8 +37,8 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
}
// These submodules must be present for `x vendor` to work.
- for path in ["src/tools/cargo", "src/doc/book"] {
- builder.build.update_submodule(Path::new(path));
+ for submodule in SUBMODULES_FOR_RUSTBOOK.iter().chain(["src/tools/cargo"].iter()) {
+ builder.build.require_submodule(submodule, None);
}
// Sync these paths by default.
@@ -45,6 +47,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
"src/tools/rust-analyzer/Cargo.toml",
"compiler/rustc_codegen_cranelift/Cargo.toml",
"compiler/rustc_codegen_gcc/Cargo.toml",
+ "library/Cargo.toml",
"src/bootstrap/Cargo.toml",
"src/tools/rustbook/Cargo.toml",
] {
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index d21ddc5..454cc20 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -1,15 +1,16 @@
use std::any::{type_name, Any};
use std::cell::{Cell, RefCell};
use std::collections::BTreeSet;
-use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt::{Debug, Write};
-use std::fs;
use std::hash::Hash;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use std::time::{Duration, Instant};
+use std::{env, fs};
+
+use clap::ValueEnum;
use crate::core::build_steps::tool::{self, SourceType};
use crate::core::build_steps::{
@@ -17,17 +18,16 @@
};
use crate::core::config::flags::{Color, Subcommand};
use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
-use crate::prepare_behaviour_dump_dir;
use crate::utils::cache::Cache;
-use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, linker_args};
-use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, t, LldThreads};
-use crate::EXTRA_CHECK_CFGS;
-use crate::{Build, CLang, Crate, DocTests, GitRepo, Mode};
-
use crate::utils::exec::{command, BootstrapCommand};
+use crate::utils::helpers::{
+ self, add_dylib_path, add_link_lib_path, check_cfg_arg, exe, libdir, linker_args, linker_flags,
+ t, LldThreads,
+};
pub use crate::Compiler;
-
-use clap::ValueEnum;
+use crate::{
+ prepare_behaviour_dump_dir, Build, CLang, Crate, DocTests, GitRepo, Mode, EXTRA_CHECK_CFGS,
+};
#[cfg(test)]
mod tests;
@@ -689,7 +689,7 @@ fn pathset_for_paths_removing_matches(
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
+#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord, ValueEnum)]
pub enum Kind {
#[value(alias = "b")]
Build,
@@ -701,6 +701,8 @@ pub enum Kind {
#[value(alias = "t")]
Test,
Miri,
+ MiriSetup,
+ MiriTest,
Bench,
#[value(alias = "d")]
Doc,
@@ -725,6 +727,8 @@ pub fn as_str(&self) -> &'static str {
Kind::Format => "fmt",
Kind::Test => "test",
Kind::Miri => "miri",
+ Kind::MiriSetup => panic!("`as_str` is not supported for `Kind::MiriSetup`."),
+ Kind::MiriTest => panic!("`as_str` is not supported for `Kind::MiriTest`."),
Kind::Bench => "bench",
Kind::Doc => "doc",
Kind::Clean => "clean",
@@ -1000,6 +1004,7 @@ macro_rules! describe {
Kind::Vendor => describe!(vendor::Vendor),
// special-cased in Build::build()
Kind::Format | Kind::Suggest | Kind::Perf => vec![],
+ Kind::MiriTest | Kind::MiriSetup => unreachable!(),
}
}
@@ -1101,6 +1106,12 @@ fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
StepDescription::run(v, self, paths);
}
+ /// Returns if `std` should be statically linked into `rustc_driver`.
+ /// It's currently not done on `windows-gnu` due to linker bugs.
+ pub fn link_std_into_rustc_driver(&self, target: TargetSelection) -> bool {
+ !target.triple.ends_with("-windows-gnu")
+ }
+
/// Obtain a compiler at a given stage and for a given host (i.e., this is the target that the
/// compiler will run on, *not* the target it will build code for). Explicitly does not take
/// `Compiler` since all `Compiler` instances are meant to be obtained through this function,
@@ -1160,7 +1171,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
.sysroot(self.compiler)
.join(lib)
.join("rustlib")
- .join(self.target.triple)
+ .join(self.target)
.join("lib");
// Avoid deleting the rustlib/ directory we just copied
// (in `impl Step for Sysroot`).
@@ -1243,7 +1254,7 @@ pub fn rustc_lib_paths(&self, compiler: Compiler) -> Vec<PathBuf> {
// Ensure that the downloaded LLVM libraries can be found.
if self.config.llvm_from_ci {
- let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib");
+ let ci_llvm_lib = self.out.join(compiler.host).join("ci-llvm").join("lib");
dylib_dirs.push(ci_llvm_lib);
}
@@ -1386,23 +1397,30 @@ pub fn bare_cargo(
compiler: Compiler,
mode: Mode,
target: TargetSelection,
- cmd: &str, // FIXME make this properly typed
+ cmd_kind: Kind,
) -> BootstrapCommand {
- let mut cargo;
- if cmd == "clippy" {
- cargo = self.cargo_clippy_cmd(compiler);
- cargo.arg(cmd);
- } else if let Some(subcmd) = cmd.strip_prefix("miri") {
- // Command must be "miri-X".
- let subcmd = subcmd
- .strip_prefix('-')
- .unwrap_or_else(|| panic!("expected `miri-$subcommand`, but got {}", cmd));
- cargo = self.cargo_miri_cmd(compiler);
- cargo.arg("miri").arg(subcmd);
- } else {
- cargo = command(&self.initial_cargo);
- cargo.arg(cmd);
- }
+ let mut cargo = match cmd_kind {
+ Kind::Clippy => {
+ let mut cargo = self.cargo_clippy_cmd(compiler);
+ cargo.arg(cmd_kind.as_str());
+ cargo
+ }
+ Kind::MiriSetup => {
+ let mut cargo = self.cargo_miri_cmd(compiler);
+ cargo.arg("miri").arg("setup");
+ cargo
+ }
+ Kind::MiriTest => {
+ let mut cargo = self.cargo_miri_cmd(compiler);
+ cargo.arg("miri").arg("test");
+ cargo
+ }
+ _ => {
+ let mut cargo = command(&self.initial_cargo);
+ cargo.arg(cmd_kind.as_str());
+ cargo
+ }
+ };
// Run cargo from the source root so it can find .cargo/config.
// This matters when using vendoring and the working directory is outside the repository.
@@ -1431,7 +1449,7 @@ pub fn bare_cargo(
Color::Auto => {} // nothing to do
}
- if cmd != "install" {
+ if cmd_kind != Kind::Install {
cargo.arg("--target").arg(target.rustc_target_arg());
} else {
assert_eq!(target, compiler.host);
@@ -1440,8 +1458,11 @@ pub fn bare_cargo(
if self.config.rust_optimize.is_release() {
// FIXME: cargo bench/install do not accept `--release`
// and miri doesn't want it
- if cmd != "bench" && cmd != "install" && !cmd.starts_with("miri-") {
- cargo.arg("--release");
+ match cmd_kind {
+ Kind::Bench | Kind::Install | Kind::Miri | Kind::MiriSetup | Kind::MiriTest => {}
+ _ => {
+ cargo.arg("--release");
+ }
}
}
@@ -1464,9 +1485,9 @@ fn cargo(
mode: Mode,
source_type: SourceType,
target: TargetSelection,
- cmd: &str, // FIXME make this properly typed
+ cmd_kind: Kind,
) -> Cargo {
- let mut cargo = self.bare_cargo(compiler, mode, target, cmd);
+ let mut cargo = self.bare_cargo(compiler, mode, target, cmd_kind);
let out_dir = self.stage_out(compiler, mode);
let mut hostflags = HostFlags::default();
@@ -1477,15 +1498,15 @@ fn cargo(
self.clear_if_dirty(&out_dir, &backend);
}
- if cmd == "doc" || cmd == "rustdoc" {
+ if cmd_kind == Kind::Doc {
let my_out = match mode {
// This is the intended out directory for compiler documentation.
Mode::Rustc | Mode::ToolRustc => self.compiler_doc_out(target),
Mode::Std => {
if self.config.cmd.json() {
- out_dir.join(target.triple).join("json-doc")
+ out_dir.join(target).join("json-doc")
} else {
- out_dir.join(target.triple).join("doc")
+ out_dir.join(target).join("doc")
}
}
_ => panic!("doc mode {mode:?} not expected"),
@@ -1508,7 +1529,7 @@ fn cargo(
// Set a flag for `check`/`clippy`/`fix`, so that certain build
// scripts can do less work (i.e. not building/requiring LLVM).
- if cmd == "check" || cmd == "clippy" || cmd == "fix" {
+ if matches!(cmd_kind, Kind::Check | Kind::Clippy | Kind::Fix) {
// If we've not yet built LLVM, or it's stale, then bust
// the rustc_llvm cache. That will always work, even though it
// may mean that on the next non-check build we'll need to rebuild
@@ -1558,7 +1579,7 @@ fn cargo(
rustflags.arg("--cfg=bootstrap");
}
- if cmd == "clippy" {
+ if cmd_kind == Kind::Clippy {
// clippy overwrites sysroot if we pass it to cargo.
// Pass it directly to clippy instead.
// NOTE: this can't be fixed in clippy because we explicitly don't set `RUSTC`,
@@ -1654,7 +1675,7 @@ fn cargo(
Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
// Build proc macros both for the host and the target
- if target != compiler.host && cmd != "check" {
+ if target != compiler.host && cmd_kind != Kind::Check {
cargo.arg("-Zdual-proc-macros");
rustflags.arg("-Zdual-proc-macros");
}
@@ -1739,7 +1760,7 @@ fn cargo(
}
cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata);
- if cmd == "clippy" {
+ if cmd_kind == Kind::Clippy {
rustflags.arg("-Zforce-unstable-if-unmarked");
}
@@ -1755,10 +1776,15 @@ fn cargo(
//
// Only clear out the directory if we're compiling std; otherwise, we
// should let Cargo take care of things for us (via depdep info)
- if !self.config.dry_run() && mode == Mode::Std && cmd == "build" {
+ if !self.config.dry_run() && mode == Mode::Std && cmd_kind == Kind::Build {
self.clear_if_dirty(&out_dir, &self.rustc(compiler));
}
+ let rustdoc_path = match cmd_kind {
+ Kind::Doc | Kind::Test | Kind::MiriTest => self.rustdoc(compiler),
+ _ => PathBuf::from("/path/to/nowhere/rustdoc/not/required"),
+ };
+
// Customize the compiler we're running. Specify the compiler to cargo
// as our shim and then pass it some various options used to configure
// how the actual compiler itself is called.
@@ -1772,15 +1798,7 @@ fn cargo(
.env("RUSTC_SYSROOT", sysroot)
.env("RUSTC_LIBDIR", libdir)
.env("RUSTDOC", self.bootstrap_out.join("rustdoc"))
- .env(
- "RUSTDOC_REAL",
- // Make sure to handle both `test` and `miri-test` commands.
- if cmd == "doc" || cmd == "rustdoc" || (cmd.ends_with("test") && want_rustdoc) {
- self.rustdoc(compiler)
- } else {
- PathBuf::from("/path/to/nowhere/rustdoc/not/required")
- },
- )
+ .env("RUSTDOC_REAL", rustdoc_path)
.env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir())
.env("RUSTC_BREAK_ON_ICE", "1");
@@ -1799,7 +1817,7 @@ fn cargo(
}
// If this is for `miri-test`, prepare the sysroots.
- if cmd == "miri-test" {
+ if cmd_kind == Kind::MiriTest {
self.ensure(compile::Std::new(compiler, compiler.host));
let host_sysroot = self.sysroot(compiler);
let miri_sysroot = test::Miri::build_miri_sysroot(self, compiler, target);
@@ -1813,7 +1831,8 @@ fn cargo(
rustflags.arg(&format!("-Zstack-protector={stack_protector}"));
}
- if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc {
+ if !matches!(cmd_kind, Kind::Build | Kind::Check | Kind::Clippy | Kind::Fix) && want_rustdoc
+ {
cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
}
@@ -2144,14 +2163,22 @@ fn cargo(
// Try to use a sysroot-relative bindir, in case it was configured absolutely.
cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative());
- cargo.force_coloring_in_ci(self.ci_env);
+ cargo.force_coloring_in_ci();
// When we build Rust dylibs they're all intended for intermediate
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
// linking all deps statically into the dylib.
- if matches!(mode, Mode::Std | Mode::Rustc) {
+ if matches!(mode, Mode::Std) {
rustflags.arg("-Cprefer-dynamic");
}
+ if matches!(mode, Mode::Rustc) && !self.link_std_into_rustc_driver(target) {
+ rustflags.arg("-Cprefer-dynamic");
+ }
+
+ cargo.env(
+ "RUSTC_LINK_STD_INTO_RUSTC_DRIVER",
+ if self.link_std_into_rustc_driver(target) { "1" } else { "0" },
+ );
// When building incrementally we default to a lower ThinLTO import limit
// (unless explicitly specified otherwise). This will produce a somewhat
@@ -2199,11 +2226,6 @@ fn cargo(
rustdocflags.arg("--cfg=parallel_compiler");
}
- // Pass the value of `--rustc-args` from test command. If it's not a test command, this won't set anything.
- self.config.cmd.rustc_args().iter().for_each(|v| {
- rustflags.arg(v);
- });
-
Cargo {
command: cargo,
compiler,
@@ -2430,9 +2452,9 @@ pub fn new(
mode: Mode,
source_type: SourceType,
target: TargetSelection,
- cmd: &str, // FIXME make this properly typed
+ cmd_kind: Kind,
) -> Cargo {
- let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd);
+ let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind);
cargo.configure_linker(builder);
cargo
}
@@ -2448,9 +2470,9 @@ pub fn new_for_mir_opt_tests(
mode: Mode,
source_type: SourceType,
target: TargetSelection,
- cmd: &str, // FIXME make this properly typed
+ cmd_kind: Kind,
) -> Cargo {
- builder.cargo(compiler, mode, source_type, target, cmd)
+ builder.cargo(compiler, mode, source_type, target, cmd_kind)
}
pub fn rustdocflag(&mut self, arg: &str) -> &mut Cargo {
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 97c9ece..c554684 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -1,27 +1,32 @@
+use std::thread;
+
use super::*;
use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::config::Config;
-use std::thread;
+use crate::Flags;
fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
configure_with_args(&[cmd.to_owned()], host, target)
}
fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config {
- let mut config = Config::parse(cmd);
+ let mut config = Config::parse(Flags::parse(cmd));
// don't save toolstates
config.save_toolstates = None;
config.dry_run = DryRun::SelfCheck;
- // Ignore most submodules, since we don't need them for a dry run.
- // But make sure to check out the `doc` and `rust-analyzer` submodules, since some steps need them
- // just to know which commands to run.
+ // Ignore most submodules, since we don't need them for a dry run, and the
+ // tests run much faster without them.
+ //
+ // The src/doc/book submodule is needed because TheBook step tries to
+ // access files even during a dry-run (may want to consider just skipping
+ // that in a dry run).
let submodule_build = Build::new(Config {
// don't include LLVM, so CI doesn't require ninja/cmake to be installed
rust_codegen_backends: vec![],
- ..Config::parse(&["check".to_owned()])
+ ..Config::parse(Flags::parse(&["check".to_owned()]))
});
- submodule_build.update_submodule(Path::new("src/doc/book"));
+ submodule_build.require_submodule("src/doc/book", None);
config.submodules = Some(false);
config.ninja_in_file = false;
@@ -75,13 +80,9 @@ macro_rules! std {
macro_rules! doc_std {
($host:ident => $target:ident, stage = $stage:literal) => {{
- let config = configure("doc", &["A-A"], &["A-A"]);
- let build = Build::new(config);
- let builder = Builder::new(&build);
doc::Std::new(
$stage,
TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
- &builder,
DocumentationFormat::Html,
)
}};
@@ -212,10 +213,11 @@ fn alias_and_path_for_library() {
}
mod defaults {
+ use pretty_assertions::assert_eq;
+
use super::{configure, first, run_build};
use crate::core::builder::*;
use crate::Config;
- use pretty_assertions::assert_eq;
#[test]
fn build_default() {
@@ -323,9 +325,10 @@ fn doc_default() {
}
mod dist {
+ use pretty_assertions::assert_eq;
+
use super::{first, run_build, Config};
use crate::core::builder::*;
- use pretty_assertions::assert_eq;
fn configure(host: &[&str], target: &[&str]) -> Config {
Config { stage: 2, ..super::configure("dist", host, target) }
@@ -630,7 +633,7 @@ fn test_with_no_doc_stage0() {
config.paths = vec!["library/std".into()];
config.cmd = Subcommand::Test {
test_args: vec![],
- rustc_args: vec![],
+ compiletest_rustc_args: vec![],
no_fail_fast: false,
no_doc: true,
doc: false,
@@ -701,7 +704,7 @@ fn test_docs() {
let mut config = configure(&["A-A"], &["A-A"]);
config.cmd = Subcommand::Test {
test_args: vec![],
- rustc_args: vec![],
+ compiletest_rustc_args: vec![],
no_fail_fast: false,
doc: true,
no_doc: false,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index e32288e..36de832 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -4,29 +4,27 @@
//! how the build runs.
use std::cell::{Cell, RefCell};
-use std::cmp;
use std::collections::{HashMap, HashSet};
-use std::env;
use std::fmt::{self, Display};
-use std::fs;
use std::io::IsTerminal;
use std::path::{absolute, Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::sync::OnceLock;
+use std::{cmp, env, fs};
+
+use build_helper::exit;
+use build_helper::git::GitConfig;
+use serde::{Deserialize, Deserializer};
+use serde_derive::Deserialize;
use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
use crate::core::build_steps::llvm;
+pub use crate::core::config::flags::Subcommand;
use crate::core::config::flags::{Color, Flags, Warnings};
use crate::utils::cache::{Interned, INTERNER};
use crate::utils::channel::{self, GitInfo};
use crate::utils::helpers::{self, exe, get_closest_merge_base_commit, output, t};
-use build_helper::exit;
-use serde::{Deserialize, Deserializer};
-use serde_derive::Deserialize;
-
-pub use crate::core::config::flags::Subcommand;
-use build_helper::git::GitConfig;
macro_rules! check_ci_llvm {
($name:expr) => {
@@ -220,6 +218,7 @@ pub struct Config {
pub llvm_thin_lto: bool,
pub llvm_release_debuginfo: bool,
pub llvm_static_stdcpp: bool,
+ pub llvm_libzstd: bool,
/// `None` if `llvm_from_ci` is true and we haven't yet downloaded llvm.
#[cfg(not(test))]
llvm_link_shared: Cell<Option<bool>>,
@@ -514,6 +513,15 @@ pub fn is_msvc(&self) -> bool {
pub fn is_windows(&self) -> bool {
self.contains("windows")
}
+
+ pub fn is_windows_gnu(&self) -> bool {
+ self.ends_with("windows-gnu")
+ }
+
+ /// Path to the file defining the custom target, if any.
+ pub fn filepath(&self) -> Option<&Path> {
+ self.file.as_ref().map(Path::new)
+ }
}
impl fmt::Display for TargetSelection {
@@ -538,6 +546,14 @@ fn eq(&self, other: &&str) -> bool {
}
}
+// Targets are often used as directory names throughout bootstrap.
+// This impl makes it more ergonomics to use them as such.
+impl AsRef<Path> for TargetSelection {
+ fn as_ref(&self) -> &Path {
+ self.triple.as_ref()
+ }
+}
+
/// Per-target configuration stored in the global configuration structure.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Target {
@@ -875,6 +891,7 @@ struct Llvm {
plugins: Option<bool> = "plugins",
ccache: Option<StringOrBool> = "ccache",
static_libstdcpp: Option<bool> = "static-libstdcpp",
+ libzstd: Option<bool> = "libzstd",
ninja: Option<bool> = "ninja",
targets: Option<String> = "targets",
experimental_targets: Option<String> = "experimental-targets",
@@ -1150,6 +1167,7 @@ pub fn default_opts() -> Config {
llvm_optimize: true,
ninja_in_file: true,
llvm_static_stdcpp: false,
+ llvm_libzstd: false,
backtrace: true,
rust_optimize: RustOptimize::Bool(true),
rust_optimize_tests: true,
@@ -1185,7 +1203,7 @@ pub fn default_opts() -> Config {
}
}
- pub fn parse(args: &[String]) -> Config {
+ pub fn parse(flags: Flags) -> Config {
#[cfg(test)]
fn get_toml(_: &Path) -> TomlConfig {
TomlConfig::default()
@@ -1215,11 +1233,10 @@ fn get_toml(file: &Path) -> TomlConfig {
exit!(2);
})
}
- Self::parse_inner(args, get_toml)
+ Self::parse_inner(flags, get_toml)
}
- pub(crate) fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
- let mut flags = Flags::parse(args);
+ pub(crate) fn parse_inner(mut flags: Flags, get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
let mut config = Config::default_opts();
// Set flags.
@@ -1322,7 +1339,11 @@ pub(crate) fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfi
// Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
// but not if `config.toml` hasn't been created.
let mut toml = if !using_default_path || toml_path.exists() {
- config.config = Some(toml_path.clone());
+ config.config = Some(if cfg!(not(feature = "bootstrap-self-test")) {
+ toml_path.canonicalize().unwrap()
+ } else {
+ toml_path.clone()
+ });
get_toml(&toml_path)
} else {
config.config = None;
@@ -1460,7 +1481,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.download_beta_toolchain();
config
.out
- .join(config.build.triple)
+ .join(config.build)
.join("stage0")
.join("bin")
.join(exe("rustc", config.build))
@@ -1475,7 +1496,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.download_beta_toolchain();
config
.out
- .join(config.build.triple)
+ .join(config.build)
.join("stage0")
.join("bin")
.join(exe("cargo", config.build))
@@ -1784,6 +1805,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
plugins,
ccache,
static_libstdcpp,
+ libzstd,
ninja,
targets,
experimental_targets,
@@ -1818,6 +1840,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
set(&mut config.llvm_thin_lto, thin_lto);
set(&mut config.llvm_release_debuginfo, release_debuginfo);
set(&mut config.llvm_static_stdcpp, static_libstdcpp);
+ set(&mut config.llvm_libzstd, libzstd);
if let Some(v) = link_shared {
config.llvm_link_shared.set(Some(v));
}
@@ -1842,6 +1865,23 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.llvm_from_ci = config.parse_download_ci_llvm(download_ci_llvm, asserts);
if config.llvm_from_ci {
+ let warn = |option: &str| {
+ println!(
+ "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build."
+ );
+ println!(
+ "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false."
+ );
+ };
+
+ if static_libstdcpp.is_some() {
+ warn("static-libstdcpp");
+ }
+
+ if link_shared.is_some() {
+ warn("link-shared");
+ }
+
// None of the LLVM options, except assertions, are supported
// when using downloaded LLVM. We could just ignore these but
// that's potentially confusing, so force them to not be
@@ -1851,9 +1891,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
check_ci_llvm!(optimize_toml);
check_ci_llvm!(thin_lto);
check_ci_llvm!(release_debuginfo);
- // CI-built LLVM can be either dynamic or static. We won't know until we download it.
- check_ci_llvm!(link_shared);
- check_ci_llvm!(static_libstdcpp);
+ check_ci_llvm!(libzstd);
check_ci_llvm!(targets);
check_ci_llvm!(experimental_targets);
check_ci_llvm!(clang_cl);
@@ -2094,7 +2132,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
// CI should always run stage 2 builds, unless it specifically states otherwise
#[cfg(not(test))]
- if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None {
+ if flags.stage.is_none() && build_helper::ci::CiEnv::is_ci() {
match config.cmd {
Subcommand::Test { .. }
| Subcommand::Miri { .. }
@@ -2251,13 +2289,13 @@ pub fn libdir_relative(&self) -> Option<&Path> {
/// The absolute path to the downloaded LLVM artifacts.
pub(crate) fn ci_llvm_root(&self) -> PathBuf {
assert!(self.llvm_from_ci);
- self.out.join(&*self.build.triple).join("ci-llvm")
+ self.out.join(self.build).join("ci-llvm")
}
/// Directory where the extracted `rustc-dev` component is stored.
pub(crate) fn ci_rustc_dir(&self) -> PathBuf {
assert!(self.download_rustc());
- self.out.join(self.build.triple).join("ci-rustc")
+ self.out.join(self.build).join("ci-rustc")
}
/// Determine whether llvm should be linked dynamically.
@@ -2404,8 +2442,11 @@ pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo {
.unwrap_or_else(|| SplitDebuginfo::default_for_platform(target))
}
- pub fn submodules(&self, rust_info: &GitInfo) -> bool {
- self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
+ /// Returns whether or not submodules should be managed by bootstrap.
+ pub fn submodules(&self) -> bool {
+ // If not specified in config, the default is to only manage
+ // submodules if we're currently inside a git repository.
+ self.submodules.unwrap_or(self.rust_info.is_managed_git_subrepository())
}
pub fn codegen_backends(&self, target: TargetSelection) -> &[String] {
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index 19f752d..c3f1740 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -183,9 +183,9 @@ pub struct Flags {
}
impl Flags {
- pub fn parse(args: &[String]) -> Self {
- let first = String::from("x.py");
- let it = std::iter::once(&first).chain(args.iter());
+ /// Check if `<cmd> -h -v` was passed.
+ /// If yes, print the available paths and return `true`.
+ pub fn try_parse_verbose_help(args: &[String]) -> bool {
// We need to check for `<cmd> -h -v`, in which case we list the paths
#[derive(Parser)]
#[command(disable_help_flag(true))]
@@ -198,10 +198,10 @@ struct HelpVerboseOnly {
cmd: Kind,
}
if let Ok(HelpVerboseOnly { help: true, verbose: 1.., cmd: subcommand }) =
- HelpVerboseOnly::try_parse_from(it.clone())
+ HelpVerboseOnly::try_parse_from(normalize_args(args))
{
println!("NOTE: updating submodules before printing available paths");
- let config = Config::parse(&[String::from("build")]);
+ let config = Config::parse(Self::parse(&[String::from("build")]));
let build = Build::new(config);
let paths = Builder::get_help(&build, subcommand);
if let Some(s) = paths {
@@ -209,11 +209,21 @@ struct HelpVerboseOnly {
} else {
panic!("No paths available for subcommand `{}`", subcommand.as_str());
}
- crate::exit!(0);
+ true
+ } else {
+ false
}
-
- Flags::parse_from(it)
}
+
+ pub fn parse(args: &[String]) -> Self {
+ Flags::parse_from(normalize_args(args))
+ }
+}
+
+fn normalize_args(args: &[String]) -> Vec<String> {
+ let first = String::from("x.py");
+ let it = std::iter::once(first).chain(args.iter().cloned());
+ it.collect()
}
#[derive(Debug, Clone, Default, clap::Subcommand)]
@@ -347,9 +357,9 @@ pub enum Subcommand {
/// extra arguments to be passed for the test tool being used
/// (e.g. libtest, compiletest or rustdoc)
test_args: Vec<String>,
- /// extra options to pass the compiler when running tests
+ /// extra options to pass the compiler when running compiletest tests
#[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
- rustc_args: Vec<String>,
+ compiletest_rustc_args: Vec<String>,
#[arg(long)]
/// do not run doc tests
no_doc: bool,
@@ -392,9 +402,6 @@ pub enum Subcommand {
/// extra arguments to be passed for the test tool being used
/// (e.g. libtest, compiletest or rustdoc)
test_args: Vec<String>,
- /// extra options to pass the compiler when running tests
- #[arg(long, value_name = "ARGS", allow_hyphen_values(true))]
- rustc_args: Vec<String>,
#[arg(long)]
/// do not run doc tests
no_doc: bool,
@@ -499,10 +506,10 @@ pub fn kind(&self) -> Kind {
}
}
- pub fn rustc_args(&self) -> Vec<&str> {
+ pub fn compiletest_rustc_args(&self) -> Vec<&str> {
match *self {
- Subcommand::Test { ref rustc_args, .. } | Subcommand::Miri { ref rustc_args, .. } => {
- rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
+ Subcommand::Test { ref compiletest_rustc_args, .. } => {
+ compiletest_rustc_args.iter().flat_map(|s| s.split_whitespace()).collect()
}
_ => vec![],
}
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index 23556e8..9f09dd1 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -1,6 +1,6 @@
#[allow(clippy::module_inception)]
mod config;
-pub(crate) mod flags;
+pub mod flags;
#[cfg(test)]
mod tests;
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index bfb2c02..40f3e5e 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -1,22 +1,21 @@
-use super::{flags::Flags, ChangeIdWrapper, Config};
-use crate::core::build_steps::clippy::get_clippy_rules_in_order;
-use crate::core::config::Target;
-use crate::core::config::TargetSelection;
-use crate::core::config::{LldMode, TomlConfig};
+use std::env;
+use std::fs::{remove_file, File};
+use std::io::Write;
+use std::path::Path;
use clap::CommandFactory;
use serde::Deserialize;
-use std::{
- env,
- fs::{remove_file, File},
- io::Write,
- path::Path,
-};
+
+use super::flags::Flags;
+use super::{ChangeIdWrapper, Config};
+use crate::core::build_steps::clippy::get_clippy_rules_in_order;
+use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
fn parse(config: &str) -> Config {
- Config::parse_inner(&["check".to_string(), "--config=/does/not/exist".to_string()], |&_| {
- toml::from_str(&config).unwrap()
- })
+ Config::parse_inner(
+ Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]),
+ |&_| toml::from_str(&config).unwrap(),
+ )
}
#[test]
@@ -110,7 +109,7 @@ fn clap_verify() {
#[test]
fn override_toml() {
let config = Config::parse_inner(
- &[
+ Flags::parse(&[
"check".to_owned(),
"--config=/does/not/exist".to_owned(),
"--set=change-id=1".to_owned(),
@@ -123,7 +122,7 @@ fn override_toml() {
"--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(),
"--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(),
"--set=target.aarch64-apple-darwin.runner=apple".to_owned(),
- ],
+ ]),
|&_| {
toml::from_str(
r#"
@@ -203,12 +202,12 @@ fn override_toml() {
#[should_panic]
fn override_toml_duplicate() {
Config::parse_inner(
- &[
+ Flags::parse(&[
"check".to_owned(),
"--config=/does/not/exist".to_string(),
"--set=change-id=1".to_owned(),
"--set=change-id=2".to_owned(),
- ],
+ ]),
|&_| toml::from_str("change-id = 0").unwrap(),
);
}
@@ -228,7 +227,7 @@ fn get_toml(file: &Path) -> TomlConfig {
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
.unwrap()
}
- Config::parse_inner(&["check".to_owned()], get_toml);
+ Config::parse_inner(Flags::parse(&["check".to_owned()]), get_toml);
}
#[test]
@@ -303,7 +302,7 @@ fn order_of_clippy_rules() {
"-Aclippy::foo1".to_string(),
"-Aclippy::foo2".to_string(),
];
- let config = Config::parse(&args);
+ let config = Config::parse(Flags::parse(&args));
let actual = match &config.cmd {
crate::Subcommand::Clippy { allow, deny, warn, forbid, .. } => {
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index 56a8528..8131666 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -1,19 +1,16 @@
-use std::{
- env,
- ffi::OsString,
- fs::{self, File},
- io::{BufRead, BufReader, BufWriter, ErrorKind, Write},
- path::{Path, PathBuf},
- process::{Command, Stdio},
- sync::OnceLock,
-};
+use std::env;
+use std::ffi::OsString;
+use std::fs::{self, File};
+use std::io::{BufRead, BufReader, BufWriter, ErrorKind, Write};
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
+use std::sync::OnceLock;
use build_helper::ci::CiEnv;
use xz2::bufread::XzDecoder;
use crate::utils::exec::{command, BootstrapCommand};
-use crate::utils::helpers::hex_encode;
-use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
+use crate::utils::helpers::{check_run, exe, hex_encode, move_file, program_out_of_date};
use crate::{t, Config};
static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new();
@@ -382,7 +379,7 @@ pub(crate) fn download_clippy(&self) -> PathBuf {
let version = &self.stage0_metadata.compiler.version;
let host = self.build;
- let bin_root = self.out.join(host.triple).join("stage0");
+ let bin_root = self.out.join(host).join("stage0");
let clippy_stamp = bin_root.join(".clippy-stamp");
let cargo_clippy = bin_root.join("bin").join(exe("cargo-clippy", host));
if cargo_clippy.exists() && !program_out_of_date(&clippy_stamp, date) {
@@ -415,7 +412,7 @@ pub(crate) fn maybe_download_rustfmt(&self) -> Option<PathBuf> {
let channel = format!("{version}-{date}");
let host = self.build;
- let bin_root = self.out.join(host.triple).join("rustfmt");
+ let bin_root = self.out.join(host).join("rustfmt");
let rustfmt_path = bin_root.join("bin").join(exe("rustfmt", host));
let rustfmt_stamp = bin_root.join(".rustfmt-stamp");
if rustfmt_path.exists() && !program_out_of_date(&rustfmt_stamp, &channel) {
@@ -522,7 +519,7 @@ fn download_toolchain(
extra_components: &[&str],
download_component: fn(&Config, String, &str, &str),
) {
- let host = self.build.triple;
+ let host = self.build;
let bin_root = self.out.join(host).join(sysroot);
let rustc_stamp = bin_root.join(".rustc-stamp");
@@ -595,7 +592,7 @@ fn download_component(
t!(fs::create_dir_all(&cache_dir));
}
- let bin_root = self.out.join(self.build.triple).join(destination);
+ let bin_root = self.out.join(self.build).join(destination);
let tarball = cache_dir.join(&filename);
let (base_url, url, should_verify) = match mode {
DownloadSource::CI => {
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 9b4c85e..1016607 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -86,6 +86,9 @@ fn workspace_members(build: &Build) -> Vec<Package> {
packages
};
- // Collects `metadata.packages` from all workspaces.
- collect_metadata("Cargo.toml")
+ // Collects `metadata.packages` from the root and library workspaces.
+ let mut packages = vec![];
+ packages.extend(collect_metadata("Cargo.toml"));
+ packages.extend(collect_metadata("library/Cargo.toml"));
+ packages
}
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 8aa0c43..c42d4c5 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -9,19 +9,17 @@
//! practice that's likely not true!
use std::collections::HashMap;
-use std::env;
+#[cfg(not(feature = "bootstrap-self-test"))]
+use std::collections::HashSet;
use std::ffi::{OsStr, OsString};
-use std::fs;
use std::path::PathBuf;
+use std::{env, fs};
#[cfg(not(feature = "bootstrap-self-test"))]
use crate::builder::Builder;
+use crate::builder::Kind;
#[cfg(not(feature = "bootstrap-self-test"))]
use crate::core::build_steps::tool;
-#[cfg(not(feature = "bootstrap-self-test"))]
-use std::collections::HashSet;
-
-use crate::builder::Kind;
use crate::core::config::Target;
use crate::utils::exec::command;
use crate::Build;
@@ -262,7 +260,9 @@ pub fn check(build: &mut Build) {
if !has_target {
// This might also be a custom target, so check the target file that could have been specified by the user.
- if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") {
+ if target.filepath().is_some_and(|p| p.exists()) {
+ has_target = true;
+ } else if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") {
let mut target_filename = OsString::from(&target_str);
// Target filename ends with `.json`.
target_filename.push(".json");
@@ -277,8 +277,12 @@ pub fn check(build: &mut Build) {
if !has_target {
panic!(
- "No such target exists in the target list,
- specify a correct location of the JSON specification file for custom targets!"
+ "No such target exists in the target list,\n\
+ make sure to correctly specify the location \
+ of the JSON specification file \
+ for custom targets!\n\
+ Use BOOTSTRAP_SKIP_TARGET_SANITY=1 to \
+ bypass this check."
);
}
}
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 1bcae25..bfd0e42 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -18,17 +18,15 @@
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
-use std::env;
use std::fmt::Display;
use std::fs::{self, File};
-use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
-use std::str;
use std::sync::OnceLock;
use std::time::SystemTime;
+use std::{env, io, str};
-use build_helper::ci::{gha, CiEnv};
+use build_helper::ci::gha;
use build_helper::exit;
use sha2::digest::Digest;
use termcolor::{ColorChoice, StandardStream, WriteColor};
@@ -37,9 +35,7 @@
use crate::core::builder;
use crate::core::builder::{Builder, Kind};
-use crate::core::config::{flags, LldMode};
-use crate::core::config::{DryRun, Target};
-use crate::core::config::{LlvmLibunwind, TargetSelection};
+use crate::core::config::{flags, DryRun, LldMode, LlvmLibunwind, Target, TargetSelection};
use crate::utils::exec::{command, BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode};
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
@@ -47,8 +43,9 @@
mod utils;
pub use core::builder::PathSet;
-pub use core::config::flags::Subcommand;
+pub use core::config::flags::{Flags, Subcommand};
pub use core::config::Config;
+
pub use utils::change_tracker::{
find_recent_config_change_ids, human_readable_changes, CONFIG_CHANGE_HISTORY,
};
@@ -171,7 +168,6 @@ pub struct Build {
crates: HashMap<String, Crate>,
crate_paths: HashMap<PathBuf, String>,
is_sudo: bool,
- ci_env: CiEnv,
delayed_failures: RefCell<Vec<String>>,
prerelease_version: Cell<Option<u32>>,
@@ -403,7 +399,6 @@ pub fn new(mut config: Config) -> Build {
crates: HashMap::new(),
crate_paths: HashMap::new(),
is_sudo,
- ci_env: CiEnv::current(),
delayed_failures: RefCell::new(Vec::new()),
prerelease_version: Cell::new(None),
@@ -441,7 +436,13 @@ pub fn new(mut config: Config) -> Build {
// Cargo.toml files.
let rust_submodules = ["library/backtrace", "library/stdarch"];
for s in rust_submodules {
- build.update_submodule(Path::new(s));
+ build.require_submodule(
+ s,
+ Some(
+ "The submodule is required for the standard library \
+ and the main Cargo workspace.",
+ ),
+ );
}
// Now, update all existing submodules.
build.update_existing_submodules();
@@ -451,7 +452,7 @@ pub fn new(mut config: Config) -> Build {
}
// Make a symbolic link so we can use a consistent directory in the documentation.
- let build_triple = build.out.join(build.build.triple);
+ let build_triple = build.out.join(build.build);
t!(fs::create_dir_all(&build_triple));
let host = build.out.join("host");
if host.is_symlink() {
@@ -470,12 +471,17 @@ pub fn new(mut config: Config) -> Build {
build
}
- // modified from `check_submodule` and `update_submodule` in bootstrap.py
/// Given a path to the directory of a submodule, update it.
///
/// `relative_path` should be relative to the root of the git repository, not an absolute path.
- pub(crate) fn update_submodule(&self, relative_path: &Path) {
- if !self.config.submodules(self.rust_info()) {
+ ///
+ /// This *does not* update the submodule if `config.toml` explicitly says
+ /// not to, or if we're not in a git repository (like a plain source
+ /// tarball). Typically [`Build::require_submodule`] should be
+ /// used instead to provide a nice error to the user if the submodule is
+ /// missing.
+ fn update_submodule(&self, relative_path: &str) {
+ if !self.config.submodules() {
return;
}
@@ -522,7 +528,7 @@ pub(crate) fn update_submodule(&self, relative_path: &Path) {
return;
}
- println!("Updating submodule {}", relative_path.display());
+ println!("Updating submodule {relative_path}");
helpers::git(Some(&self.src))
.run_always()
.args(["submodule", "-q", "sync"])
@@ -576,11 +582,53 @@ pub(crate) fn update_submodule(&self, relative_path: &Path) {
}
}
+ /// Updates a submodule, and exits with a failure if submodule management
+ /// is disabled and the submodule does not exist.
+ ///
+ /// The given submodule name should be its path relative to the root of
+ /// the main repository.
+ ///
+ /// The given `err_hint` will be shown to the user if the submodule is not
+ /// checked out and submodule management is disabled.
+ pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) {
+ // When testing bootstrap itself, it is much faster to ignore
+ // submodules. Almost all Steps work fine without their submodules.
+ if cfg!(test) && !self.config.submodules() {
+ return;
+ }
+ self.update_submodule(submodule);
+ let absolute_path = self.config.src.join(submodule);
+ if dir_is_empty(&absolute_path) {
+ let maybe_enable = if !self.config.submodules()
+ && self.config.rust_info.is_managed_git_subrepository()
+ {
+ "\nConsider setting `build.submodules = true` or manually initializing the submodules."
+ } else {
+ ""
+ };
+ let err_hint = err_hint.map_or_else(String::new, |e| format!("\n{e}"));
+ eprintln!(
+ "submodule {submodule} does not appear to be checked out, \
+ but it is required for this step{maybe_enable}{err_hint}"
+ );
+ exit!(1);
+ }
+ }
+
+ /// Updates all submodules, and exits with an error if submodule
+ /// management is disabled and the submodule does not exist.
+ pub fn require_and_update_all_submodules(&self) {
+ for submodule in build_helper::util::parse_gitmodules(&self.src) {
+ self.require_submodule(submodule, None);
+ }
+ }
+
/// If any submodule has been initialized already, sync it unconditionally.
/// This avoids contributors checking in a submodule change by accident.
- pub fn update_existing_submodules(&self) {
- // Avoid running git when there isn't a git checkout.
- if !self.config.submodules(self.rust_info()) {
+ fn update_existing_submodules(&self) {
+ // Avoid running git when there isn't a git checkout, or the user has
+ // explicitly disabled submodules in `config.toml`.
+ if !self.config.submodules() {
return;
}
let output = helpers::git(Some(&self.src))
@@ -592,22 +640,23 @@ pub fn update_existing_submodules(&self) {
for line in output.lines() {
// Look for `submodule.$name.path = $path`
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
- let submodule = Path::new(line.split_once(' ').unwrap().1);
+ let submodule = line.split_once(' ').unwrap().1;
+ let path = Path::new(submodule);
// Don't update the submodule unless it's already been cloned.
- if GitInfo::new(false, submodule).is_managed_git_subrepository() {
+ if GitInfo::new(false, path).is_managed_git_subrepository() {
self.update_submodule(submodule);
}
}
}
/// Updates the given submodule only if it's initialized already; nothing happens otherwise.
- pub fn update_existing_submodule(&self, submodule: &Path) {
+ pub fn update_existing_submodule(&self, submodule: &str) {
// Avoid running git when there isn't a git checkout.
- if !self.config.submodules(self.rust_info()) {
+ if !self.config.submodules() {
return;
}
- if GitInfo::new(false, submodule).is_managed_git_subrepository() {
+ if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
self.update_submodule(submodule);
}
}
@@ -758,10 +807,7 @@ fn cargo_dir(&self) -> &'static str {
}
fn tools_dir(&self, compiler: Compiler) -> PathBuf {
- let out = self
- .out
- .join(&*compiler.host.triple)
- .join(format!("stage{}-tools-bin", compiler.stage));
+ let out = self.out.join(compiler.host).join(format!("stage{}-tools-bin", compiler.stage));
t!(fs::create_dir_all(&out));
out
}
@@ -778,14 +824,14 @@ fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
Mode::ToolBootstrap => "-bootstrap-tools",
Mode::ToolStd | Mode::ToolRustc => "-tools",
};
- self.out.join(&*compiler.host.triple).join(format!("stage{}{}", compiler.stage, suffix))
+ self.out.join(compiler.host).join(format!("stage{}{}", compiler.stage, suffix))
}
/// Returns the root output directory for all Cargo output in a given stage,
/// running a particular compiler, whether or not we're building the
/// standard library, and targeting the specified architecture.
fn cargo_out(&self, compiler: Compiler, mode: Mode, target: TargetSelection) -> PathBuf {
- self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir())
+ self.stage_out(compiler, mode).join(target).join(self.cargo_dir())
}
/// Root output directory of LLVM for `target`
@@ -796,36 +842,36 @@ fn llvm_out(&self, target: TargetSelection) -> PathBuf {
if self.config.llvm_from_ci && self.config.build == target {
self.config.ci_llvm_root()
} else {
- self.out.join(&*target.triple).join("llvm")
+ self.out.join(target).join("llvm")
}
}
fn lld_out(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("lld")
+ self.out.join(target).join("lld")
}
/// Output directory for all documentation for a target
fn doc_out(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("doc")
+ self.out.join(target).join("doc")
}
/// Output directory for all JSON-formatted documentation for a target
fn json_doc_out(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("json-doc")
+ self.out.join(target).join("json-doc")
}
fn test_out(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("test")
+ self.out.join(target).join("test")
}
/// Output directory for all documentation for a target
fn compiler_doc_out(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("compiler-doc")
+ self.out.join(target).join("compiler-doc")
}
/// Output directory for some generated md crate documentation for a target (temporary)
fn md_doc_out(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("md-doc")
+ self.out.join(target).join("md-doc")
}
/// Returns `true` if this is an external version of LLVM not managed by bootstrap.
@@ -905,7 +951,7 @@ fn llvm_filecheck(&self, target: TargetSelection) -> PathBuf {
/// Directory for libraries built from C/C++ code and shared between stages.
fn native_dir(&self, target: TargetSelection) -> PathBuf {
- self.out.join(&*target.triple).join("native")
+ self.out.join(target).join("native")
}
/// Root output directory for rust_test_helpers library compiled for
@@ -937,7 +983,8 @@ fn rustc_snapshot_sysroot(&self) -> &Path {
}
/// Execute a command and return its output.
- /// This method should be used for all command executions in bootstrap.
+ /// Note: Ideally, you should use one of the BootstrapCommand::run* functions to
+ /// execute commands. They internally call this method.
#[track_caller]
fn run(
&self,
@@ -1008,20 +1055,28 @@ fn run(
CommandOutput::did_not_start(stdout, stderr)
}
};
+
+ let fail = |message: &str| {
+ if self.is_verbose() {
+ println!("{message}");
+ } else {
+ println!("Command has failed. Rerun with -v to see more details.");
+ }
+ exit!(1);
+ };
+
if !output.is_success() {
match command.failure_behavior {
BehaviorOnFailure::DelayFail => {
if self.fail_fast {
- println!("{message}");
- exit!(1);
+ fail(&message);
}
let mut failures = self.delayed_failures.borrow_mut();
failures.push(message);
}
BehaviorOnFailure::Exit => {
- println!("{message}");
- exit!(1);
+ fail(&message);
}
BehaviorOnFailure::Ignore => {
// If failures are allowed, either the error has been printed already
diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs
index d60b54d..3f78b04 100644
--- a/src/bootstrap/src/utils/cache.rs
+++ b/src/bootstrap/src/utils/cache.rs
@@ -3,13 +3,12 @@
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::HashMap;
-use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
-use std::mem;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::{LazyLock, Mutex};
+use std::{fmt, mem};
use crate::core::builder::Step;
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index b8f70fd..c629f04 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -220,4 +220,14 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
severity: ChangeSeverity::Warning,
summary: "For tarball sources, default value for `rust.channel` will be taken from `src/ci/channel` file.",
},
+ ChangeInfo {
+ change_id: 125642,
+ severity: ChangeSeverity::Info,
+ summary: "New option `llvm.libzstd` to control whether llvm is built with zstd support.",
+ },
+ ChangeInfo {
+ change_id: 128841,
+ severity: ChangeSeverity::Warning,
+ summary: "./x test --rustc-args was renamed to --compiletest-rustc-args as it only applies there. ./x miri --rustc-args was also removed.",
+ },
];
diff --git a/src/bootstrap/src/utils/channel.rs b/src/bootstrap/src/utils/channel.rs
index f8bcb58..3ae512e 100644
--- a/src/bootstrap/src/utils/channel.rs
+++ b/src/bootstrap/src/utils/channel.rs
@@ -8,11 +8,10 @@
use std::fs;
use std::path::Path;
+use super::helpers;
use crate::utils::helpers::{output, t};
use crate::Build;
-use super::helpers;
-
#[derive(Clone, Default)]
pub enum GitInfo {
/// This is not a git repository.
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 627ea05..9f0d0b7 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -1,11 +1,13 @@
-use crate::Build;
-use build_helper::ci::CiEnv;
-use build_helper::drop_bomb::DropBomb;
use std::ffi::OsStr;
use std::fmt::{Debug, Formatter};
use std::path::Path;
use std::process::{Command, CommandArgs, CommandEnvs, ExitStatus, Output, Stdio};
+use build_helper::ci::CiEnv;
+use build_helper::drop_bomb::DropBomb;
+
+use crate::Build;
+
/// What should be done when the command fails.
#[derive(Debug, Copy, Clone)]
pub enum BehaviorOnFailure {
@@ -173,8 +175,8 @@ pub fn get_created_location(&self) -> std::panic::Location<'static> {
}
/// If in a CI environment, forces the command to run with colors.
- pub fn force_coloring_in_ci(&mut self, ci_env: CiEnv) {
- if ci_env != CiEnv::None {
+ pub fn force_coloring_in_ci(&mut self) {
+ if CiEnv::is_ci() {
// Due to use of stamp/docker, the output stream of bootstrap is not
// a TTY in CI, so coloring is by-default turned off.
// The explicit `TERM=xterm` environment is needed for
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 51c14ff..65e75f1 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -3,23 +3,20 @@
//! Simple things like testing the various filesystem operations here and there,
//! not a lot of interesting happenings here unfortunately.
-use build_helper::git::{get_git_merge_base, output_result, GitConfig};
-use build_helper::util::fail;
-use std::env;
use std::ffi::OsStr;
-use std::fs;
-use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
-use std::str;
use std::sync::OnceLock;
use std::time::{Instant, SystemTime, UNIX_EPOCH};
+use std::{env, fs, io, str};
+
+use build_helper::git::{get_git_merge_base, output_result, GitConfig};
+use build_helper::util::fail;
use crate::core::builder::Builder;
use crate::core::config::{Config, TargetSelection};
-use crate::LldMode;
-
pub use crate::utils::shared_helpers::{dylib_path, dylib_path_var};
+use crate::LldMode;
#[cfg(test)]
mod tests;
@@ -48,9 +45,10 @@ macro_rules! t {
}
};
}
-use crate::utils::exec::{command, BootstrapCommand};
pub use t;
+use crate::utils::exec::{command, BootstrapCommand};
+
pub fn exe(name: &str, target: TargetSelection) -> String {
crate::utils::shared_helpers::exe(name, &target.triple)
}
@@ -538,8 +536,7 @@ pub fn get_closest_merge_base_commit(
let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into());
- git.arg(Path::new("rev-list"));
- git.args([&format!("--author={author}"), "-n1", "--first-parent", &merge_base]);
+ git.args(["rev-list", &format!("--author={author}"), "-n1", "--first-parent", &merge_base]);
if !target_paths.is_empty() {
git.arg("--").args(target_paths);
diff --git a/src/bootstrap/src/utils/helpers/tests.rs b/src/bootstrap/src/utils/helpers/tests.rs
index 2ab3952..103c4d2 100644
--- a/src/bootstrap/src/utils/helpers/tests.rs
+++ b/src/bootstrap/src/utils/helpers/tests.rs
@@ -1,14 +1,11 @@
-use crate::{
- utils::helpers::{
- check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir,
- },
- Config,
+use std::fs::{self, remove_file, File};
+use std::io::Write;
+use std::path::PathBuf;
+
+use crate::utils::helpers::{
+ check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir,
};
-use std::{
- fs::{self, remove_file, File},
- io::Write,
- path::PathBuf,
-};
+use crate::{Config, Flags};
#[test]
fn test_make() {
@@ -61,7 +58,8 @@ fn test_check_cfg_arg() {
#[test]
fn test_program_out_of_date() {
- let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]);
+ let config =
+ Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]));
let tempfile = config.tempdir().join(".tmp-stamp-file");
File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap();
assert!(tempfile.exists());
@@ -76,7 +74,8 @@ fn test_program_out_of_date() {
#[test]
fn test_symlink_dir() {
- let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]);
+ let config =
+ Config::parse(Flags::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]));
let tempdir = config.tempdir().join(".tmp-dir");
let link_path = config.tempdir().join(".tmp-link");
diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs
index d7d20e5..4012f51 100644
--- a/src/bootstrap/src/utils/job.rs
+++ b/src/bootstrap/src/utils/job.rs
@@ -40,27 +40,24 @@ pub unsafe fn setup(build: &mut crate::Build) {
/// Note that this is a Windows specific module as none of this logic is required on Unix.
#[cfg(windows)]
mod for_windows {
- use crate::Build;
- use std::env;
use std::ffi::c_void;
- use std::io;
- use std::mem;
+ use std::{env, io, mem};
- use windows::{
- core::PCWSTR,
- Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE},
- Win32::System::Diagnostics::Debug::{
- SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE,
- },
- Win32::System::JobObjects::{
- AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation,
- SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
- JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS,
- },
- Win32::System::Threading::{
- GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
- },
+ use windows::core::PCWSTR;
+ use windows::Win32::Foundation::{CloseHandle, DuplicateHandle, DUPLICATE_SAME_ACCESS, HANDLE};
+ use windows::Win32::System::Diagnostics::Debug::{
+ SetErrorMode, SEM_NOGPFAULTERRORBOX, THREAD_ERROR_MODE,
};
+ use windows::Win32::System::JobObjects::{
+ AssignProcessToJobObject, CreateJobObjectW, JobObjectExtendedLimitInformation,
+ SetInformationJobObject, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
+ JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_PRIORITY_CLASS,
+ };
+ use windows::Win32::System::Threading::{
+ GetCurrentProcess, OpenProcess, BELOW_NORMAL_PRIORITY_CLASS, PROCESS_DUP_HANDLE,
+ };
+
+ use crate::Build;
pub unsafe fn setup(build: &mut Build) {
// Enable the Windows Error Reporting dialog which msys disables,
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index 697dd2f..e9acb93 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -4,18 +4,20 @@
//! As this module requires additional dependencies not present during local builds, it's cfg'd
//! away whenever the `build.metrics` config option is not set to `true`.
-use crate::core::builder::{Builder, Step};
-use crate::utils::helpers::t;
-use crate::Build;
-use build_helper::metrics::{
- JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test,
- TestOutcome, TestSuite, TestSuiteMetadata,
-};
use std::cell::RefCell;
use std::fs::File;
use std::io::BufWriter;
use std::time::{Duration, Instant, SystemTime};
-use sysinfo::System;
+
+use build_helper::metrics::{
+ JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test,
+ TestOutcome, TestSuite, TestSuiteMetadata,
+};
+use sysinfo::{CpuRefreshKind, RefreshKind, System};
+
+use crate::core::builder::{Builder, Step};
+use crate::utils::helpers::t;
+use crate::Build;
// Update this number whenever a breaking change is made to the build metrics.
//
@@ -53,7 +55,9 @@ pub(crate) fn init() -> Self {
finished_steps: Vec::new(),
running_steps: Vec::new(),
- system_info: System::new(),
+ system_info: System::new_with_specifics(
+ RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
+ ),
timer_start: None,
invocation_timer_start: Instant::now(),
invocation_start: SystemTime::now(),
@@ -75,7 +79,7 @@ pub(crate) fn enter_step<S: Step>(&self, step: &S, builder: &Builder<'_>) {
self.collect_stats(&mut *state);
}
- state.system_info.refresh_cpu();
+ state.system_info.refresh_cpu_usage();
state.timer_start = Some(Instant::now());
state.running_steps.push(StepMetrics {
@@ -108,7 +112,7 @@ pub(crate) fn exit_step(&self, builder: &Builder<'_>) {
state.running_steps.last_mut().unwrap().children.push(step);
// Start collecting again for the parent step.
- state.system_info.refresh_cpu();
+ state.system_info.refresh_cpu_usage();
state.timer_start = Some(Instant::now());
}
}
@@ -146,7 +150,7 @@ fn collect_stats(&self, state: &mut MetricsState) {
let elapsed = state.timer_start.unwrap().elapsed();
step.duration_excluding_children_sec += elapsed;
- state.system_info.refresh_cpu();
+ state.system_info.refresh_cpu_usage();
let cpu = state.system_info.cpus().iter().map(|p| p.cpu_usage()).sum::<f32>();
step.cpu_usage_time_sec += cpu as f64 / 100.0 * elapsed.as_secs_f64();
}
@@ -157,8 +161,9 @@ pub(crate) fn persist(&self, build: &Build) {
let dest = build.out.join("metrics.json");
- let mut system = System::new();
- system.refresh_cpu();
+ let mut system =
+ System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything()));
+ system.refresh_cpu_usage();
system.refresh_memory();
let system_stats = JsonInvocationSystemStats {
diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs
index a3d0d36..b8aebc2 100644
--- a/src/bootstrap/src/utils/render_tests.rs
+++ b/src/bootstrap/src/utils/render_tests.rs
@@ -6,13 +6,15 @@
//! and rustc) libtest doesn't include the rendered human-readable output as a JSON field. We had
//! to reimplement all the rendering logic in this module because of that.
-use crate::core::builder::Builder;
-use crate::utils::exec::BootstrapCommand;
use std::io::{BufRead, BufReader, Read, Write};
use std::process::{ChildStdout, Stdio};
use std::time::Duration;
+
use termcolor::{Color, ColorSpec, WriteColor};
+use crate::core::builder::Builder;
+use crate::utils::exec::BootstrapCommand;
+
const TERSE_TESTS_PER_LINE: usize = 88;
pub(crate) fn add_flags_and_try_run_tests(
diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs
index cef67ae..3f7f621 100644
--- a/src/bootstrap/src/utils/tarball.rs
+++ b/src/bootstrap/src/utils/tarball.rs
@@ -7,8 +7,8 @@
use std::path::{Path, PathBuf};
-use crate::core::builder::Builder;
-use crate::core::{build_steps::dist::distdir, builder::Kind};
+use crate::core::build_steps::dist::distdir;
+use crate::core::builder::{Builder, Kind};
use crate::utils::exec::BootstrapCommand;
use crate::utils::helpers::{move_file, t};
use crate::utils::{channel, helpers};
@@ -317,6 +317,12 @@ fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut BootstrapCommand)) -> Gen
channel::write_commit_hash_file(&self.overlay_dir, &info.sha);
channel::write_commit_info_file(&self.overlay_dir, info);
}
+
+ // Add config file if present.
+ if let Some(config) = &self.builder.config.config {
+ self.add_renamed_file(config, &self.overlay_dir, "builder-config");
+ }
+
for file in self.overlay.legal_and_readme() {
self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644);
}
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 2621e9a..1b98d54 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -24,7 +24,8 @@
# Needed for apt-key to work:
dirmngr \
gpg-agent \
- g++-9-arm-linux-gnueabi
+ g++-9-arm-linux-gnueabi \
+ g++-11-riscv64-linux-gnu
RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486
RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main'
@@ -73,6 +74,10 @@
CC=arm-linux-gnueabi-gcc-9 CFLAGS="-march=armv7-a" \
CXX=arm-linux-gnueabi-g++-9 CXXFLAGS="-march=armv7-a" \
bash musl.sh armv7 && \
+ env \
+ CC=riscv64-linux-gnu-gcc-11 \
+ CXX=riscv64-linux-gnu-g++-11 \
+ bash musl.sh riscv64gc && \
rm -rf /build/*
WORKDIR /tmp
@@ -125,6 +130,7 @@
ENV TARGETS=$TARGETS,aarch64-unknown-uefi
ENV TARGETS=$TARGETS,i686-unknown-uefi
ENV TARGETS=$TARGETS,x86_64-unknown-uefi
+ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl
# As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
# we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the
@@ -132,7 +138,11 @@
# Luckily one of the folders is /usr/local/include so symlink /usr/include/x86_64-linux-gnu/asm there
RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm
+# musl-gcc can't find libgcc_s.so.1 since it doesn't use the standard search paths.
+RUN ln -s /usr/riscv64-linux-gnu/lib/libgcc_s.so.1 /usr/lib/gcc-cross/riscv64-linux-gnu/11/
+
ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \
- --musl-root-armv7=/musl-armv7
+ --musl-root-armv7=/musl-armv7 \
+ --musl-root-riscv64gc=/musl-riscv64gc
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 4aa1a3c..61e9694 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -62,6 +62,10 @@
RUN ./build-clang.sh
ENV CC=clang CXX=clang++
+# rustc's LLVM needs zstd.
+COPY scripts/zstd.sh /tmp/
+RUN ./zstd.sh
+
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
@@ -79,6 +83,7 @@
--set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
--set llvm.thin-lto=true \
--set llvm.ninja=false \
+ --set llvm.libzstd=true \
--set rust.jemalloc \
--set rust.use-lld=true \
--set rust.lto=thin \
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs
index 2ec554c..d75ee14 100644
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs
+++ b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs
@@ -5,6 +5,7 @@
#![no_std]
use core::{panic, ptr};
+
use r_efi::efi::{Char16, Handle, Status, SystemTable, RESET_SHUTDOWN};
#[panic_handler]
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index 9025e9b..1968331 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -17,6 +17,8 @@
pkg-config \
xz-utils \
mingw-w64 \
+ zlib1g-dev \
+ libzstd-dev \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index 00269e6..a5458b8 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -571,6 +571,19 @@
)
# Start repository server
+ # Note that we must first enable the repository server daemon.
+ check_call_with_logging(
+ [
+ ffx_path,
+ "config",
+ "set",
+ "repository.server.enabled",
+ "true",
+ ],
+ env=ffx_env,
+ stdout_handler=self.subprocess_logger.debug,
+ stderr_handler=self.subprocess_logger.debug,
+ )
check_call_with_logging(
[
ffx_path,
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index da7b029..d690aac 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,7 +2,7 @@
set -euo pipefail
-LINUX_VERSION=c13320499ba0efd93174ef6462ae8a7a2933f6e7
+LINUX_VERSION=v6.11-rc1
# Build rustc, rustdoc and cargo
../x.py build --stage 1 library rustdoc
@@ -65,4 +65,8 @@
make -C linux LLVM=1 -j$(($(nproc) + 1)) \
samples/rust/rust_minimal.o \
samples/rust/rust_print.o \
- drivers/net/phy/ax88796b_rust.o
+ drivers/net/phy/ax88796b_rust.o \
+ rust/doctests_kernel_generated.o
+
+make -C linux LLVM=1 -j$(($(nproc) + 1)) \
+ rustdoc
diff --git a/src/ci/docker/scripts/x86_64-gnu-llvm.sh b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
index b3921f1..98290f5 100755
--- a/src/ci/docker/scripts/x86_64-gnu-llvm.sh
+++ b/src/ci/docker/scripts/x86_64-gnu-llvm.sh
@@ -18,9 +18,9 @@
# compiler, and is sensitive to the addition of new flags.
../x.py --stage 1 test tests/ui-fulldeps
- # The tests are run a second time with the size optimizations enabled.
- ../x.py --stage 1 test library/std library/alloc library/core \
- --rustc-args "--cfg feature=\"optimize_for_size\""
+ # Rebuild the stdlib with the size optimizations enabled and run tests again.
+ RUSTFLAGS_NOT_BOOTSTRAP="--cfg feature=\"optimize_for_size\"" ../x.py --stage 1 test \
+ library/std library/alloc library/core
fi
# NOTE: intentionally uses all of `x.py`, `x`, and `x.ps1` to make sure they all work on Linux.
diff --git a/src/ci/docker/scripts/zstd.sh b/src/ci/docker/scripts/zstd.sh
new file mode 100755
index 0000000..a3d37cc
--- /dev/null
+++ b/src/ci/docker/scripts/zstd.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/zstd_build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ "$@" &> /tmp/zstd_build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ rm /tmp/zstd_build.log
+ set -x
+}
+
+ZSTD=1.5.6
+curl -L https://github.com/facebook/zstd/releases/download/v$ZSTD/zstd-$ZSTD.tar.gz | tar xzf -
+
+cd zstd-$ZSTD
+CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1
+hide_output make install
+
+cd ..
+rm -rf zstd-$ZSTD
diff --git a/src/doc/reference b/src/doc/reference
index e2f0bdc..2e19181 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit e2f0bdc4031866734661dcdb548184bde1450baf
+Subproject commit 2e191814f163ee1e77e2d6094eee4dd78a289c5b
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 292b603..467fd6f 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -65,6 +65,8 @@
- [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
+ - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
+ - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
@@ -74,6 +76,7 @@
- [*-unknown-openbsd](platform-support/openbsd.md)
- [*-unknown-redox](platform-support/redox.md)
- [\*-unknown-uefi](platform-support/unknown-uefi.md)
+ - [\*-wrs-vxworks](platform-support/vxworks.md)
- [wasm32-wasip1](platform-support/wasm32-wasip1.md)
- [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index 72ab8ab..fa23e3e 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -96,9 +96,7 @@
to `/WHOLEARCHIVE` for `link.exe`, and to `-force_load` for `ld64`.
The modifier does nothing for linkers that don't support it.
-The default for this modifier is `-whole-archive`. \
-NOTE: The default may currently be different in some cases for backward compatibility,
-but it is not guaranteed. If you need whole archive semantics use `+whole-archive` explicitly.
+The default for this modifier is `-whole-archive`.
### Linking modifiers: `bundle`
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 0c7f4e7..bd12172 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -33,6 +33,7 @@
target | notes
-------|-------
`aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+)
+[`aarch64-apple-darwin`](platform-support/apple-darwin.md) | ARM64 macOS (11.0+, Big Sur+)
`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+, Windows Server 2016+) [^x86_32-floats-return-ABI]
`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+, Windows Server 2016+) [^x86_32-floats-return-ABI]
`i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]
@@ -86,7 +87,6 @@
target | notes
-------|-------
-[`aarch64-apple-darwin`](platform-support/apple-darwin.md) | ARM64 macOS (11.0+, Big Sur+)
`aarch64-pc-windows-msvc` | ARM64 Windows MSVC
`aarch64-unknown-linux-musl` | ARM64 Linux with musl 1.2.3
`arm-unknown-linux-gnueabi` | Armv6 Linux (kernel 3.2, glibc 2.17)
@@ -97,7 +97,8 @@
`powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17)
`powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17)
`powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
-`riscv64gc-unknown-linux-gnu` | RISC-V Linux (kernel 4.20, glibc 2.29)
+[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29)
+[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3)
`s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17)
`x86_64-unknown-freebsd` | 64-bit FreeBSD
`x86_64-unknown-illumos` | illumos
@@ -263,7 +264,7 @@
[`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
[`aarch64-unknown-redox`](platform-support/redox.md) | ✓ | | ARM64 Redox OS
`aarch64-uwp-windows-msvc` | ✓ | |
-`aarch64-wrs-vxworks` | ? | |
+[`aarch64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | ARM64 VxWorks OS
`aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
`aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
[`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian)
@@ -281,7 +282,7 @@
[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat
`armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD
[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float
-`armv7-wrs-vxworks-eabihf` | ? | | Armv7-A for VxWorks
+[`armv7-wrs-vxworks-eabihf`](platform-support/vxworks.md) | ✓ | | Armv7-A for VxWorks
[`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3
[`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat
[`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare Armv7-A, hardfloat
@@ -307,7 +308,7 @@
`i686-uwp-windows-gnu` | ✓ | | [^x86_32-floats-return-ABI]
`i686-uwp-windows-msvc` | ✓ | | [^x86_32-floats-return-ABI]
[`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
-`i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI]
+[`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [^x86_32-floats-return-ABI]
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.3
@@ -333,13 +334,13 @@
`powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3
[`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems
[`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | |
-`powerpc-wrs-vxworks-spe` | ? | |
-`powerpc-wrs-vxworks` | ? | |
+[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |
+[`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
`powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD
`powerpc-unknown-freebsd` | | | PowerPC FreeBSD
`powerpc64-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3
-`powerpc64-wrs-vxworks` | ? | |
+[`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`powerpc64le-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3, Little Endian
[`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer)
@@ -354,7 +355,6 @@
[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
-`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.3)
[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android
@@ -383,7 +383,7 @@
`x86_64-uwp-windows-gnu` | ✓ | |
`x86_64-uwp-windows-msvc` | ✓ | |
[`x86_64-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 64-bit Windows 7 support
-`x86_64-wrs-vxworks` | ? | |
+[`x86_64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell)
[`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc
[`xtensa-esp32-none-elf`](platform-support/xtensa.md) | * | | Xtensa ESP32
diff --git a/src/doc/rustc/src/platform-support/apple-darwin.md b/src/doc/rustc/src/platform-support/apple-darwin.md
index 0fb8694..c3a7b81 100644
--- a/src/doc/rustc/src/platform-support/apple-darwin.md
+++ b/src/doc/rustc/src/platform-support/apple-darwin.md
@@ -5,9 +5,6 @@
**Tier: 1**
- `x86_64-apple-darwin`: macOS on 64-bit x86.
-
-**Tier: 2 (with Host Tools)**
-
- `aarch64-apple-darwin`: macOS on ARM64 (M1-family or later Apple Silicon CPUs).
## Target maintainers
diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md
new file mode 100644
index 0000000..1acc058
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md
@@ -0,0 +1,129 @@
+# `riscv64gc-unknown-linux-gnu`
+
+**Tier: 2 (with Host Tools)**
+
+RISC-V targets using the *RV64I* base instruction set with the *G* collection of extensions, as well as the *C* extension.
+
+
+## Target maintainers
+
+- Kito Cheng, <kito.cheng@gmail.com>, [@kito-cheng](https://github.com/kito-cheng)
+- Michael Maitland, <michaeltmaitland@gmail.com>, [@michaelmaitland](https://github.com/michaelmaitland)
+- Robin Randhawa, <robin.randhawa@sifive.com>, [@robin-randhawa-sifive](https://github.com/robin-randhawa-sifive)
+- Craig Topper, <craig.topper@sifive.com>, [@topperc](https://github.com/topperc)
+
+## Requirements
+
+This target requires:
+
+* Linux Kernel version 4.20 or later
+* glibc 2.17 or later
+
+
+## Building the target
+
+These targets are distributed through `rustup`, and otherwise require no
+special configuration.
+
+If you need to build your own Rust for some reason though, the targets can be
+enabled in `config.toml`. For example:
+
+```toml
+[build]
+target = ["riscv64gc-unknown-linux-gnu"]
+```
+
+
+## Building Rust programs
+
+
+On a RISC-V host, the `riscv64gc-unknown-linux-gnu` target should be automatically
+installed and used by default.
+
+On a non-RISC-V host, add the target:
+
+```bash
+rustup target add riscv64gc-unknown-linux-gnu
+```
+
+Then cross compile crates with:
+
+```bash
+cargo build --target riscv64gc-unknown-linux-gnu
+```
+
+
+## Testing
+
+There are no special requirements for testing and running the targets.
+For testing cross builds on the host, please refer to the "Cross-compilation
+toolchains and C code"
+section below.
+
+
+## Cross-compilation toolchains and C code
+
+A RISC-V toolchain can be obtained for Windows/Mac/Linux from the
+[`riscv-gnu-toolchain`](https://github.com/riscv-collab/riscv-gnu-toolchain)
+repostory. Binaries are available via
+[embecosm](https://www.embecosm.com/resources/tool-chain-downloads/#riscv-linux),
+and may also be available from your OS's package manager.
+
+On Ubuntu, a RISC-V toolchain can be installed with:
+
+```bash
+apt install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu libc6-dev-riscv64-cross
+```
+
+Depending on your system, you may need to configure the target to use the GNU
+GCC linker. To use it, add the following to your `.cargo/config.toml`:
+
+```toml
+[target.riscv64gc-unknown-linux-gnu]
+linker = "riscv64-linux-gnu-gcc"
+```
+
+If your `riscv64-linux-gnu-*` toolchain is not in your `PATH` you may need to
+configure additional settings:
+
+```toml
+[target.riscv64gc-unknown-linux-gnu]
+# Adjust the paths to point at your toolchain
+cc = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-gcc"
+cxx = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-g++"
+ar = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-ar"
+ranlib = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-ranlib"
+linker = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-gcc"
+```
+
+To test cross compiled binaries on a non-RISCV-V host, you can use
+[`qemu`](https://www.qemu.org/docs/master/system/target-riscv.html).
+On Ubuntu, a RISC-V emulator can be obtained with:
+
+```bash
+apt install qemu-system-riscv64
+```
+
+Then, in `.cargo/config.toml` set the `runner`:
+
+```toml
+[target.riscv64gc-unknown-linux-gnu]
+runner = "qemu-riscv64-static -L /usr/riscv64-linux-gnu -cpu rv64"
+```
+
+On Mac and Linux, it's also possible to use
+[`lima`](https://github.com/lima-vm/lima) to emulate RISC-V in a similar way to
+how WSL2 works on Windows:
+
+```bash
+limactl start template://riscv
+limactl shell riscv
+```
+
+Using [Docker (with BuildKit)](https://docs.docker.com/build/buildkit/) the
+[`riscv64/ubuntu`](https://hub.docker.com/r/riscv64/ubuntu) image can be used
+to buiild or run `riscv64gc-unknown-linux-gnu` binaries.
+
+```bash
+docker run --platform linux/riscv64 -ti --rm --mount "type=bind,src=$(pwd),dst=/checkout" riscv64/ubuntu bash
+```
diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md
new file mode 100644
index 0000000..5b3dc68
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md
@@ -0,0 +1,47 @@
+# riscv64gc-unknown-linux-musl
+
+**Tier: 2**
+
+Target for RISC-V Linux programs using musl libc.
+
+## Target maintainers
+
+- [@Amanieu](https://github.com/Amanieu)
+- [@kraj](https://github.com/kraj)
+
+## Requirements
+
+Building the target itself requires a RISC-V compiler that is supported by `cc-rs`.
+
+## Building the target
+
+The target can be built by enabling it for a `rustc` build.
+
+```toml
+[build]
+target = ["riscv64gc-unknown-linux-musl"]
+```
+
+Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`:
+
+```toml
+[target.riscv64gc-unknown-linux-musl]
+cc = "riscv64-linux-gnu-gcc"
+cxx = "riscv64-linux-gnu-g++"
+ar = "riscv64-linux-gnu-ar"
+linker = "riscv64-linux-gnu-gcc"
+```
+
+## Building Rust programs
+
+This target are distributed through `rustup`, and otherwise require no
+special configuration.
+
+## Cross-compilation
+
+This target can be cross-compiled from any host.
+
+## Testing
+
+This target can be tested as normal with `x.py` on a RISC-V host or via QEMU
+emulation.
diff --git a/src/doc/rustc/src/platform-support/vxworks.md b/src/doc/rustc/src/platform-support/vxworks.md
new file mode 100644
index 0000000..f186034
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/vxworks.md
@@ -0,0 +1,59 @@
+# `*-wrs-vxworks`
+
+**Tier: 3**
+
+Targets for the VxWorks operating
+system.
+
+Target triplets available:
+
+- `x86_64-wrs-vxworks`
+- `aarch64-wrs-vxworks`
+- `i686-wrs-vxworks`
+- `armv7-wrs-vxworks-eabihf`
+- `powerpc-wrs-vxworks`
+- `powerpc64-wrs-vxworks`
+- `powerpc-wrs-vxworks-spe`
+
+## Target maintainers
+
+- B I Mohammed Abbas ([@biabbas](https://github.com/biabbas))
+
+## Requirements
+
+### OS version
+
+The minimum supported version is VxWorks 7.
+
+## Building
+
+Rust for each target can be cross-compiled with its specific target vsb configuration. Std support is added but not yet fully tested.
+
+## Building the target
+
+You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. In addition the workbench and wr-cc have to configured and activated.
+
+```toml
+[build]
+build-stage = 1
+target = [
+ "<HOST_TARGET>",
+ "x86_64-wrs-vxworks",
+ "aarch64-wrs-vxworks",
+ "i686-wrs-vxworks",
+ "armv7-wrs-vxworks-eabihf",
+ "powerpc-wrs-vxworks",
+ "powerpc64-wrs-vxworks",
+ "powerpc-wrs-vxworks-spe",
+]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for VxWorks.
+
+The easiest way to build and test programs for VxWorks is to use the shipped rustc and cargo in VxWorks workbench, following the official windriver guidelines.
+
+## Cross-compilation toolchains and C code
+
+The target supports C code. Pre-compiled C toolchains can be found in provided VxWorks workbench.
diff --git a/src/doc/unstable-book/src/language-features/rustc-private.md b/src/doc/unstable-book/src/language-features/rustc-private.md
new file mode 100644
index 0000000..97fce59
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/rustc-private.md
@@ -0,0 +1,11 @@
+# `rustc_private`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
+
+This feature allows access to unstable internal compiler crates.
+
+Additionally it changes the linking behavior of crates which have this feature enabled. It will prevent linking to a dylib if there's a static variant of it already statically linked into another dylib dependency. This is required to successfully link to `rustc_driver`.
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 805fc8a..297dc11 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -266,7 +266,7 @@
complete -c x.py -n "__fish_seen_subcommand_from doc" -l skip-stage0-validation -d 'Skip stage0 compiler validation'
complete -c x.py -n "__fish_seen_subcommand_from doc" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r
-complete -c x.py -n "__fish_seen_subcommand_from test" -l rustc-args -d 'extra options to pass the compiler when running tests' -r
+complete -c x.py -n "__fish_seen_subcommand_from test" -l compiletest-rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r
complete -c x.py -n "__fish_seen_subcommand_from test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r
complete -c x.py -n "__fish_seen_subcommand_from test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r
complete -c x.py -n "__fish_seen_subcommand_from test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r
@@ -313,7 +313,6 @@
complete -c x.py -n "__fish_seen_subcommand_from test" -l skip-stage0-validation -d 'Skip stage0 compiler validation'
complete -c x.py -n "__fish_seen_subcommand_from test" -s h -l help -d 'Print help (see more with \'--help\')'
complete -c x.py -n "__fish_seen_subcommand_from miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r
-complete -c x.py -n "__fish_seen_subcommand_from miri" -l rustc-args -d 'extra options to pass the compiler when running tests' -r
complete -c x.py -n "__fish_seen_subcommand_from miri" -l config -d 'TOML configuration file for build' -r -F
complete -c x.py -n "__fish_seen_subcommand_from miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
complete -c x.py -n "__fish_seen_subcommand_from miri" -l build -d 'build target of the stage0 compiler' -r -f
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index ce590d2..4b42447 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -338,7 +338,7 @@
}
'x.py;test' {
[CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)')
- [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests')
+ [CompletionResult]::new('--compiletest-rustc-args', 'compiletest-rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests')
[CompletionResult]::new('--extra-checks', 'extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)')
[CompletionResult]::new('--compare-mode', 'compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to')
[CompletionResult]::new('--pass', 'pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode')
@@ -392,7 +392,6 @@
}
'x.py;miri' {
[CompletionResult]::new('--test-args', 'test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)')
- [CompletionResult]::new('--rustc-args', 'rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running tests')
[CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
[CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
[CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index a423490..60ba8d3 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -1300,7 +1300,7 @@
return 0
;;
x.py__miri)
- opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1310,10 +1310,6 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
- --rustc-args)
- COMPREPLY=($(compgen -f "${cur}"))
- return 0
- ;;
--config)
COMPREPLY=($(compgen -f "${cur}"))
return 0
@@ -1862,7 +1858,7 @@
return 0
;;
x.py__test)
- opts="-v -i -j -h --no-fail-fast --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+ opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -1872,7 +1868,7 @@
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
- --rustc-args)
+ --compiletest-rustc-args)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh
index fc8be4f..688f692 100644
--- a/src/etc/completions/x.py.zsh
+++ b/src/etc/completions/x.py.zsh
@@ -337,7 +337,7 @@
(test)
_arguments "${_arguments_options[@]}" \
'*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \
-'*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \
+'*--compiletest-rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS: ' \
'--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS: ' \
'--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE: ' \
'--pass=[force {check,build,run}-pass tests to this mode]:check | build | run: ' \
@@ -393,7 +393,6 @@
(miri)
_arguments "${_arguments_options[@]}" \
'*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS: ' \
-'*--rustc-args=[extra options to pass the compiler when running tests]:ARGS: ' \
'--config=[TOML configuration file for build]:FILE:_files' \
'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \
'--build=[build target of the stage0 compiler]:BUILD:( )' \
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
index 227695c..e8f9dee 100644
--- a/src/etc/gdb_providers.py
+++ b/src/etc/gdb_providers.py
@@ -56,7 +56,7 @@
self._valobj = valobj
vec = valobj["vec"]
self._length = int(vec["len"])
- self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
+ self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"])
def to_string(self):
return self._data_ptr.lazy_string(encoding="utf-8", length=self._length)
@@ -74,7 +74,7 @@
vec = buf[ZERO_FIELD] if is_windows else buf
self._length = int(vec["len"])
- self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
+ self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"])
def to_string(self):
return self._data_ptr.lazy_string(encoding="utf-8", length=self._length)
@@ -96,6 +96,7 @@
def display_hint():
return "string"
+
def _enumerate_array_elements(element_ptrs):
for (i, element_ptr) in enumerate(element_ptrs):
key = "[{}]".format(i)
@@ -112,6 +113,7 @@
yield key, element
+
class StdSliceProvider(printer_base):
def __init__(self, valobj):
self._valobj = valobj
@@ -130,11 +132,14 @@
def display_hint():
return "array"
+
class StdVecProvider(printer_base):
def __init__(self, valobj):
self._valobj = valobj
self._length = int(valobj["len"])
- self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
+ self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["inner"]["ptr"])
+ ptr_ty = gdb.Type.pointer(valobj.type.template_argument(0))
+ self._data_ptr = self._data_ptr.reinterpret_cast(ptr_ty)
def to_string(self):
return "Vec(size={})".format(self._length)
@@ -155,11 +160,13 @@
self._head = int(valobj["head"])
self._size = int(valobj["len"])
# BACKCOMPAT: rust 1.75
- cap = valobj["buf"]["cap"]
+ cap = valobj["buf"]["inner"]["cap"]
if cap.type.code != gdb.TYPE_CODE_INT:
cap = cap[ZERO_FIELD]
self._cap = int(cap)
- self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
+ self._data_ptr = unwrap_unique_or_non_null(valobj["buf"]["inner"]["ptr"])
+ ptr_ty = gdb.Type.pointer(valobj.type.template_argument(0))
+ self._data_ptr = self._data_ptr.reinterpret_cast(ptr_ty)
def to_string(self):
return "VecDeque(size={})".format(self._size)
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
index c633011..8750d76 100644
--- a/src/etc/lldb_providers.py
+++ b/src/etc/lldb_providers.py
@@ -389,11 +389,11 @@
def update(self):
# type: () -> None
self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
- self.buf = self.valobj.GetChildMemberWithName("buf")
+ self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner")
self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
- self.element_type = self.data_ptr.GetType().GetPointeeType()
+ self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
self.element_type_size = self.element_type.GetByteSize()
def has_children(self):
@@ -474,7 +474,7 @@
# type: () -> None
self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned()
self.size = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
- self.buf = self.valobj.GetChildMemberWithName("buf")
+ self.buf = self.valobj.GetChildMemberWithName("buf").GetChildMemberWithName("inner")
cap = self.buf.GetChildMemberWithName("cap")
if cap.GetType().num_fields == 1:
cap = cap.GetChildAtIndex(0)
@@ -482,7 +482,7 @@
self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
- self.element_type = self.data_ptr.GetType().GetPointeeType()
+ self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
self.element_type_size = self.element_type.GetByteSize()
def has_children(self):
diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis
index da30780..49d82df 100644
--- a/src/etc/natvis/liballoc.natvis
+++ b/src/etc/natvis/liballoc.natvis
@@ -4,10 +4,10 @@
<DisplayString>{{ len={len} }}</DisplayString>
<Expand>
<Item Name="[len]" ExcludeView="simple">len</Item>
- <Item Name="[capacity]" ExcludeView="simple">buf.cap.__0</Item>
+ <Item Name="[capacity]" ExcludeView="simple">buf.inner.cap.__0</Item>
<ArrayItems>
<Size>len</Size>
- <ValuePointer>buf.ptr.pointer.pointer</ValuePointer>
+ <ValuePointer>($T1*)buf.inner.ptr.pointer.pointer</ValuePointer>
</ArrayItems>
</Expand>
</Type>
@@ -15,7 +15,7 @@
<DisplayString>{{ len={len} }}</DisplayString>
<Expand>
<Item Name="[len]" ExcludeView="simple">len</Item>
- <Item Name="[capacity]" ExcludeView="simple">buf.cap.__0</Item>
+ <Item Name="[capacity]" ExcludeView="simple">buf.inner.cap.__0</Item>
<CustomListItems>
<Variable Name="i" InitialValue="0" />
<Size>len</Size>
@@ -23,7 +23,7 @@
<If Condition="i == len">
<Break/>
</If>
- <Item>buf.ptr.pointer.pointer[(i + head) % buf.cap.__0]</Item>
+ <Item>(($T1*)buf.inner.ptr.pointer.pointer)[(i + head) % buf.inner.cap.__0]</Item>
<Exec>i = i + 1</Exec>
</Loop>
</CustomListItems>
@@ -41,17 +41,17 @@
</Expand>
</Type>
<Type Name="alloc::string::String">
- <DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
- <StringView>(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8</StringView>
+ <DisplayString>{(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
+ <StringView>(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8</StringView>
<Expand>
<Item Name="[len]" ExcludeView="simple">vec.len</Item>
- <Item Name="[capacity]" ExcludeView="simple">vec.buf.cap.__0</Item>
+ <Item Name="[capacity]" ExcludeView="simple">vec.buf.inner.cap.__0</Item>
<Synthetic Name="[chars]">
- <DisplayString>{(char*)vec.buf.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
+ <DisplayString>{(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8}</DisplayString>
<Expand>
<ArrayItems>
<Size>vec.len</Size>
- <ValuePointer>(char*)vec.buf.ptr.pointer.pointer</ValuePointer>
+ <ValuePointer>(char*)vec.buf.inner.ptr.pointer.pointer</ValuePointer>
</ArrayItems>
</Expand>
</Synthetic>
diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis
index 4371b99..4719a47 100644
--- a/src/etc/natvis/libstd.natvis
+++ b/src/etc/natvis/libstd.natvis
@@ -104,14 +104,14 @@
</Type>
<Type Name="std::ffi::os_str::OsString">
- <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
+ <DisplayString>{(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
<Expand>
<Synthetic Name="[chars]">
- <DisplayString>{(char*)inner.inner.bytes.buf.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
+ <DisplayString>{(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]}</DisplayString>
<Expand>
<ArrayItems>
<Size>inner.inner.bytes.len</Size>
- <ValuePointer>(char*)inner.inner.bytes.buf.ptr.pointer.pointer</ValuePointer>
+ <ValuePointer>(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer</ValuePointer>
</ArrayItems>
</Expand>
</Synthetic>
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index fe531f0..b3fccbf 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -8,7 +8,7 @@
[dependencies]
arrayvec = { version = "0.7", default-features = false }
-rinja = { version = "0.2", default-features = false, features = ["config"] }
+rinja = { version = "0.3", default-features = false, features = ["config"] }
base64 = "0.21.7"
itertools = "0.12"
indexmap = "2"
@@ -23,6 +23,7 @@
tracing = "0.1"
tracing-tree = "0.3.0"
threadpool = "1.8.1"
+unicode-segmentation = "1.9"
[dependencies.tracing-subscriber]
version = "0.3.3"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index ac927e9..f46ffea 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -6,13 +6,11 @@
use rustc_span::def_id::DefId;
use rustc_span::symbol::{kw, Symbol};
use rustc_trait_selection::traits::auto_trait::{self, RegionTarget};
-
use thin_vec::ThinVec;
-use crate::clean::{self, simplify, Lifetime};
use crate::clean::{
- clean_generic_param_def, clean_middle_ty, clean_predicate, clean_trait_ref_with_constraints,
- clean_ty_generics,
+ self, clean_generic_param_def, clean_middle_ty, clean_predicate,
+ clean_trait_ref_with_constraints, clean_ty_generics, simplify, Lifetime,
};
use crate::core::DocContext;
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 4c7a2ec..48c3fb6 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -5,7 +5,6 @@
use rustc_span::def_id::DefId;
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-
use thin_vec::ThinVec;
use crate::clean;
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 2814e83..fb9754c 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -4,15 +4,13 @@
// switch to use those structures instead.
use std::fmt::{self, Write};
-use std::mem;
-use std::ops;
+use std::{mem, ops};
use rustc_ast::{LitKind, MetaItem, MetaItemKind, NestedMetaItem};
use rustc_data_structures::fx::FxHashSet;
use rustc_feature::Features;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::{sym, Symbol};
-
use rustc_span::Span;
use crate::html::escape::Escape;
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index 2857f74..a9b3aba 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -1,11 +1,10 @@
-use super::*;
-
use rustc_ast::{MetaItemLit, Path, Safety, StrStyle};
-use rustc_span::create_default_session_globals_then;
use rustc_span::symbol::{kw, Ident};
-use rustc_span::DUMMY_SP;
+use rustc_span::{create_default_session_globals_then, DUMMY_SP};
use thin_vec::thin_vec;
+use super::*;
+
fn word_cfg(s: &str) -> Cfg {
Cfg::Cfg(Symbol::intern(s), None)
}
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 0024e24..f8953f0 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -3,11 +3,7 @@
use std::iter::once;
use std::sync::Arc;
-use thin_vec::{thin_vec, ThinVec};
-
-use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, DefIdSet, LocalModDefId};
use rustc_hir::Mutability;
@@ -16,8 +12,11 @@
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{sym, Symbol};
+use thin_vec::{thin_vec, ThinVec};
+use {rustc_ast as ast, rustc_hir as hir};
+use super::Item;
use crate::clean::{
self, clean_bound_vars, clean_generics, clean_impl_item, clean_middle_assoc_item,
clean_middle_field, clean_middle_ty, clean_poly_fn_sig, clean_trait_ref_with_constraints,
@@ -27,8 +26,6 @@
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
-use super::Item;
-
/// Attempt to inline a definition into this AST.
///
/// This function will fetch the definition specified, and if it is
@@ -131,8 +128,8 @@ pub(crate) fn try_inline(
Res::Def(DefKind::Const, did) => {
record_extern_fqn(cx, did, ItemType::Constant);
cx.with_param_env(did, |cx| {
- let (generics, ty, ct) = build_const_item(cx, did);
- clean::ConstantItem(generics, Box::new(ty), ct)
+ let ct = build_const_item(cx, did);
+ clean::ConstantItem(Box::new(ct))
})
}
Res::Def(DefKind::Macro(kind), did) => {
@@ -720,10 +717,7 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
}
}
-fn build_const_item(
- cx: &mut DocContext<'_>,
- def_id: DefId,
-) -> (clean::Generics, clean::Type, clean::Constant) {
+fn build_const_item(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
let mut generics =
clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
clean::simplify::move_bounds_to_generic_parameters(&mut generics);
@@ -733,17 +727,17 @@ fn build_const_item(
None,
None,
);
- (generics, ty, clean::Constant { kind: clean::ConstantKind::Extern { def_id } })
+ clean::Constant { generics, type_: ty, kind: clean::ConstantKind::Extern { def_id } }
}
fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
clean::Static {
- type_: clean_middle_ty(
+ type_: Box::new(clean_middle_ty(
ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()),
cx,
Some(did),
None,
- ),
+ )),
mutability: if mutable { Mutability::Mut } else { Mutability::Not },
expr: None,
}
@@ -798,11 +792,7 @@ fn build_macro(
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
for pred in &mut g.where_predicates {
match *pred {
- clean::WherePredicate::BoundPredicate {
- ty: clean::Generic(ref s),
- ref mut bounds,
- ..
- } if *s == kw::SelfUpper => {
+ clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => {
bounds.retain(|bound| match bound {
clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => {
trait_.def_id() != trait_did
@@ -818,13 +808,13 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
clean::WherePredicate::BoundPredicate {
ty:
clean::QPath(box clean::QPathData {
- self_type: clean::Generic(ref s),
+ self_type: clean::Generic(_),
trait_: Some(trait_),
..
}),
bounds,
..
- } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
+ } => !bounds.is_empty() && trait_.def_id() != trait_did,
_ => true,
});
g
@@ -838,9 +828,7 @@ fn separate_supertrait_bounds(
) -> (clean::Generics, Vec<clean::GenericBound>) {
let mut ty_bounds = Vec::new();
g.where_predicates.retain(|pred| match *pred {
- clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
- if *s == kw::SelfUpper =>
- {
+ clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
ty_bounds.extend(bounds.iter().cloned());
false
}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2601192..cffadc7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -30,41 +30,36 @@
pub(crate) mod types;
pub(crate) mod utils;
-use rustc_ast as ast;
+use std::borrow::Cow;
+use std::collections::BTreeMap;
+use std::mem;
+
use rustc_ast::token::{Token, TokenKind};
use rustc_ast::tokenstream::{TokenStream, TokenTree};
-use rustc_attr as attr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
-use rustc_errors::{codes::*, struct_span_code_err, FatalError};
-use rustc_hir as hir;
+use rustc_errors::codes::*;
+use rustc_errors::{struct_span_code_err, FatalError};
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
use rustc_hir::PredicateOrigin;
use rustc_hir_analysis::lower_ty;
use rustc_middle::metadata::Reexport;
use rustc_middle::middle::resolve_bound_vars as rbv;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{AstPass, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::ExpnKind;
use rustc_trait_selection::traits::wf::object_region_bounds;
-
-use std::borrow::Cow;
-use std::collections::BTreeMap;
-use std::mem;
use thin_vec::ThinVec;
-
-use crate::core::DocContext;
-use crate::formats::item_type::ItemType;
-use crate::visit_ast::Module as DocModule;
-
use utils::*;
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
pub(crate) use self::types::*;
pub(crate) use self::utils::{krate, register_res, synthesize_auto_trait_and_blanket_impls};
+use crate::core::DocContext;
+use crate::formats::item_type::ItemType;
+use crate::visit_ast::Module as DocModule;
pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
let mut items: Vec<Item> = vec![];
@@ -287,23 +282,21 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
pub(crate) fn clean_const<'tcx>(
constant: &hir::ConstArg<'tcx>,
_cx: &mut DocContext<'tcx>,
-) -> Constant {
+) -> ConstantKind {
match &constant.kind {
hir::ConstArgKind::Path(qpath) => {
- Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } }
+ ConstantKind::Path { path: qpath_to_string(&qpath).into() }
}
- hir::ConstArgKind::Anon(anon) => {
- Constant { kind: ConstantKind::Anonymous { body: anon.body } }
- }
+ hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
}
}
pub(crate) fn clean_middle_const<'tcx>(
constant: ty::Binder<'tcx, ty::Const<'tcx>>,
_cx: &mut DocContext<'tcx>,
-) -> Constant {
+) -> ConstantKind {
// FIXME: instead of storing the stringified expression, store `self` directly instead.
- Constant { kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } }
+ ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }
}
pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
@@ -1230,14 +1223,11 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
let local_did = trait_item.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match trait_item.kind {
- hir::TraitItemKind::Const(ty, Some(default)) => {
- let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
- AssocConstItem(
- generics,
- Box::new(clean_ty(ty, cx)),
- ConstantKind::Local { def_id: local_did, body: default },
- )
- }
+ hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(Box::new(Constant {
+ generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
+ kind: ConstantKind::Local { def_id: local_did, body: default },
+ type_: clean_ty(ty, cx),
+ })),
hir::TraitItemKind::Const(ty, None) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
TyAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
@@ -1282,11 +1272,11 @@ pub(crate) fn clean_impl_item<'tcx>(
let local_did = impl_.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match impl_.kind {
- hir::ImplItemKind::Const(ty, expr) => {
- let generics = clean_generics(impl_.generics, cx);
- let default = ConstantKind::Local { def_id: local_did, body: expr };
- AssocConstItem(generics, Box::new(clean_ty(ty, cx)), default)
- }
+ hir::ImplItemKind::Const(ty, expr) => AssocConstItem(Box::new(Constant {
+ generics: clean_generics(impl_.generics, cx),
+ kind: ConstantKind::Local { def_id: local_did, body: expr },
+ type_: clean_ty(ty, cx),
+ })),
hir::ImplItemKind::Fn(ref sig, body) => {
let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
let defaultness = cx.tcx.defaultness(impl_.owner_id);
@@ -1320,12 +1310,12 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let tcx = cx.tcx;
let kind = match assoc_item.kind {
ty::AssocKind::Const => {
- let ty = Box::new(clean_middle_ty(
+ let ty = clean_middle_ty(
ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()),
cx,
Some(assoc_item.def_id),
None,
- ));
+ );
let mut generics = clean_ty_generics(
cx,
@@ -1339,9 +1329,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(),
};
if provided {
- AssocConstItem(generics, ty, ConstantKind::Extern { def_id: assoc_item.def_id })
+ AssocConstItem(Box::new(Constant {
+ generics,
+ kind: ConstantKind::Extern { def_id: assoc_item.def_id },
+ type_: ty,
+ }))
} else {
- TyAssocConstItem(generics, ty)
+ TyAssocConstItem(generics, Box::new(ty))
}
}
ty::AssocKind::Fn => {
@@ -1357,11 +1351,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
let self_arg_ty =
tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
if self_arg_ty == self_ty {
- item.decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
+ item.decl.inputs.values[0].type_ = SelfTy;
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
if ty == self_ty {
match item.decl.inputs.values[0].type_ {
- BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper),
+ BorrowedRef { ref mut type_, .. } => **type_ = SelfTy,
_ => unreachable!(),
}
}
@@ -1397,7 +1391,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
{
true
}
- (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind {
+ (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &**c {
ConstantKind::TyConst { expr } => **expr == *param.name.as_str(),
_ => false,
},
@@ -1445,9 +1439,8 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
if trait_.def_id() != assoc_item.container_id(tcx) {
return true;
}
- match *self_type {
- Generic(ref s) if *s == kw::SelfUpper => {}
- _ => return true,
+ if *self_type != SelfTy {
+ return true;
}
match &assoc.args {
GenericArgs::AngleBracketed { args, constraints } => {
@@ -2234,6 +2227,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
ImplTrait(bounds)
+ } else if p.name == kw::SelfUpper {
+ SelfTy
} else {
Generic(p.name)
}
@@ -2744,18 +2739,19 @@ fn clean_maybe_renamed_item<'tcx>(
let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
- ItemKind::Static(ty, mutability, body_id) => {
- StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
- }
- ItemKind::Const(ty, generics, body_id) => ConstantItem(
- clean_generics(generics, cx),
- Box::new(clean_ty(ty, cx)),
- Constant { kind: ConstantKind::Local { body: body_id, def_id } },
- ),
- ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
- bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
- generics: clean_generics(ty.generics, cx),
+ ItemKind::Static(ty, mutability, body_id) => StaticItem(Static {
+ type_: Box::new(clean_ty(ty, cx)),
+ mutability,
+ expr: Some(body_id),
}),
+ ItemKind::Const(ty, generics, body_id) => ConstantItem(Box::new(Constant {
+ generics: clean_generics(generics, cx),
+ type_: clean_ty(ty, cx),
+ kind: ConstantKind::Local { body: body_id, def_id },
+ })),
+ // clean_ty changes types which reference an OpaqueTy item to instead be
+ // an ImplTrait, so it's ok to return nothing here.
+ ItemKind::OpaqueTy(_) => return vec![],
ItemKind::TyAlias(hir_ty, generics) => {
*cx.current_type_aliases.entry(def_id).or_insert(0) += 1;
let rustdoc_ty = clean_ty(hir_ty, cx);
@@ -2838,7 +2834,7 @@ fn clean_maybe_renamed_item<'tcx>(
ItemKind::Use(path, kind) => {
return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default());
}
- _ => unreachable!("not yet converted"),
+ _ => span_bug!(item.span, "not yet converted"),
};
vec![generate_item_with_correct_attrs(
@@ -3109,7 +3105,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
ForeignFunctionItem(Box::new(Function { decl, generics }), safety)
}
hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem(
- Static { type_: clean_ty(ty, cx), mutability, expr: None },
+ Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: None },
safety,
),
hir::ForeignItemKind::Type => ForeignTypeItem,
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 1b7d84a..1d81ae3 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -18,8 +18,7 @@
use thin_vec::ThinVec;
use crate::clean;
-use crate::clean::GenericArgs as PP;
-use crate::clean::WherePredicate as WP;
+use crate::clean::{GenericArgs as PP, WherePredicate as WP};
use crate::core::DocContext;
pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec<WP>) -> ThinVec<WP> {
@@ -146,7 +145,6 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi
// should be handled when cleaning associated types.
generics.where_predicates.retain(|pred| {
if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred
- && *param != rustc_span::symbol::kw::SelfUpper
&& bounds.iter().any(|b| b.is_sized_bound(cx))
{
sized_params.insert(*param);
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 3709953..ff5c16f 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -3,19 +3,14 @@
use std::hash::Hash;
use std::path::PathBuf;
use std::rc::Rc;
-use std::sync::Arc;
-use std::sync::OnceLock as OnceCell;
+use std::sync::{Arc, OnceLock as OnceCell};
use std::{fmt, iter};
use arrayvec::ArrayVec;
-use thin_vec::ThinVec;
-
-use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel, StableSince};
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
@@ -35,7 +30,14 @@
use rustc_span::{FileName, Loc, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
+use thin_vec::ThinVec;
+use {rustc_ast as ast, rustc_hir as hir};
+pub(crate) use self::ItemKind::*;
+pub(crate) use self::Type::{
+ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
+ RawPointer, SelfTy, Slice, Tuple,
+};
use crate::clean::cfg::Cfg;
use crate::clean::clean_middle_path;
use crate::clean::inline::{self, print_inlined_const};
@@ -46,13 +48,6 @@
use crate::html::render::Context;
use crate::passes::collect_intra_doc_links::UrlFragment;
-pub(crate) use self::ItemKind::*;
-pub(crate) use self::SelfTy::*;
-pub(crate) use self::Type::{
- Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath,
- RawPointer, Slice, Tuple,
-};
-
#[cfg(test)]
mod tests;
@@ -828,7 +823,6 @@ pub(crate) enum ItemKind {
FunctionItem(Box<Function>),
ModuleItem(Module),
TypeAliasItem(Box<TypeAlias>),
- OpaqueTyItem(OpaqueTy),
StaticItem(Static),
TraitItem(Box<Trait>),
TraitAliasItem(TraitAlias),
@@ -852,9 +846,9 @@ pub(crate) enum ItemKind {
PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration.
TyAssocConstItem(Generics, Box<Type>),
- ConstantItem(Generics, Box<Type>, Constant),
+ ConstantItem(Box<Constant>),
/// An associated constant in a trait impl or a provided one in a trait declaration.
- AssocConstItem(Generics, Box<Type>, ConstantKind),
+ AssocConstItem(Box<Constant>),
/// A required associated type in a trait declaration.
///
/// The bounds may be non-empty if there is a `where` clause.
@@ -886,9 +880,8 @@ pub(crate) fn inner_items(&self) -> impl Iterator<Item = &Item> {
| ImportItem(_)
| FunctionItem(_)
| TypeAliasItem(_)
- | OpaqueTyItem(_)
| StaticItem(_)
- | ConstantItem(_, _, _)
+ | ConstantItem(_)
| TraitAliasItem(_)
| TyMethodItem(_)
| MethodItem(_, _)
@@ -920,9 +913,8 @@ pub(crate) fn is_non_assoc(&self) -> bool {
| ExternCrateItem { .. }
| FunctionItem(_)
| TypeAliasItem(_)
- | OpaqueTyItem(_)
| StaticItem(_)
- | ConstantItem(_, _, _)
+ | ConstantItem(_)
| TraitAliasItem(_)
| ForeignFunctionItem(_, _)
| ForeignStaticItem(_, _)
@@ -1391,8 +1383,8 @@ pub(crate) struct FnDecl {
}
impl FnDecl {
- pub(crate) fn self_type(&self) -> Option<SelfTy> {
- self.inputs.values.get(0).and_then(|v| v.to_self())
+ pub(crate) fn receiver_type(&self) -> Option<&Type> {
+ self.inputs.values.get(0).and_then(|v| v.to_receiver())
}
}
@@ -1410,27 +1402,9 @@ pub(crate) struct Argument {
pub(crate) is_const: bool,
}
-#[derive(Clone, PartialEq, Debug)]
-pub(crate) enum SelfTy {
- SelfValue,
- SelfBorrowed(Option<Lifetime>, Mutability),
- SelfExplicit(Type),
-}
-
impl Argument {
- pub(crate) fn to_self(&self) -> Option<SelfTy> {
- if self.name != kw::SelfLower {
- return None;
- }
- if self.type_.is_self_type() {
- return Some(SelfValue);
- }
- match self.type_ {
- BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => {
- Some(SelfBorrowed(lifetime.clone(), mutability))
- }
- _ => Some(SelfExplicit(self.type_.clone())),
- }
+ pub(crate) fn to_receiver(&self) -> Option<&Type> {
+ if self.name == kw::SelfLower { Some(&self.type_) } else { None }
}
}
@@ -1484,6 +1458,8 @@ pub(crate) enum Type {
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
/// A type parameter.
Generic(Symbol),
+ /// The `Self` type.
+ SelfTy,
/// A primitive (aka, builtin) type.
Primitive(PrimitiveType),
/// A function pointer: `extern "ABI" fn(...) -> ...`
@@ -1578,6 +1554,8 @@ pub(crate) fn is_doc_subtype_of(&self, other: &Self, cache: &Cache) -> bool {
// If both sides are generic, this returns true.
(_, Type::Generic(_)) => true,
(Type::Generic(_), _) => false,
+ // `Self` only matches itself.
+ (Type::SelfTy, Type::SelfTy) => true,
// Paths account for both the path itself and its generics.
(Type::Path { path: a }, Type::Path { path: b }) => {
a.def_id() == b.def_id()
@@ -1649,7 +1627,7 @@ pub(crate) fn is_assoc_ty(&self) -> bool {
pub(crate) fn is_self_type(&self) -> bool {
match *self {
- Generic(name) => name == kw::SelfUpper,
+ SelfTy => true,
_ => false,
}
}
@@ -1684,13 +1662,16 @@ pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
}
}
- fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
+ /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
+ ///
+ /// [clean]: crate::clean
+ pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
let t: PrimitiveType = match *self {
Type::Path { ref path } => return Some(path.def_id()),
DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()),
- Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
+ Primitive(p) => return cache.primitive_locations.get(&p).cloned(),
BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
- BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
+ BorrowedRef { ref type_, .. } => return type_.def_id(cache),
Tuple(ref tys) => {
if tys.is_empty() {
PrimitiveType::Unit
@@ -1703,17 +1684,10 @@ fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
Array(..) => PrimitiveType::Array,
Type::Pat(..) => PrimitiveType::Pat,
RawPointer(..) => PrimitiveType::RawPointer,
- QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
- Generic(_) | Infer | ImplTrait(_) => return None,
+ QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache),
+ Generic(_) | SelfTy | Infer | ImplTrait(_) => return None,
};
- cache.and_then(|c| Primitive(t).def_id(c))
- }
-
- /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
- ///
- /// [clean]: crate::clean
- pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
- self.inner_def_id(Some(cache))
+ Primitive(t).def_id(cache)
}
}
@@ -2050,7 +2024,7 @@ fn from(prim_ty: hir::PrimTy) -> PrimitiveType {
pub(crate) struct Struct {
pub(crate) ctor_kind: Option<CtorKind>,
pub(crate) generics: Generics,
- pub(crate) fields: Vec<Item>,
+ pub(crate) fields: ThinVec<Item>,
}
impl Struct {
@@ -2076,7 +2050,7 @@ pub(crate) fn has_stripped_entries(&self) -> bool {
/// only as a variant in an enum.
#[derive(Clone, Debug)]
pub(crate) struct VariantStruct {
- pub(crate) fields: Vec<Item>,
+ pub(crate) fields: ThinVec<Item>,
}
impl VariantStruct {
@@ -2110,7 +2084,7 @@ pub(crate) struct Variant {
#[derive(Clone, Debug)]
pub(crate) enum VariantKind {
CLike,
- Tuple(Vec<Item>),
+ Tuple(ThinVec<Item>),
Struct(VariantStruct),
}
@@ -2246,7 +2220,7 @@ pub(crate) fn generics(&self) -> Option<Vec<&Type>> {
pub(crate) enum GenericArg {
Lifetime(Lifetime),
Type(Type),
- Const(Box<Constant>),
+ Const(Box<ConstantKind>),
Infer,
}
@@ -2343,12 +2317,6 @@ pub(crate) struct TypeAlias {
pub(crate) item_type: Option<Type>,
}
-#[derive(Clone, Debug)]
-pub(crate) struct OpaqueTy {
- pub(crate) bounds: Vec<GenericBound>,
- pub(crate) generics: Generics,
-}
-
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) struct BareFunctionDecl {
pub(crate) safety: hir::Safety,
@@ -2359,20 +2327,22 @@ pub(crate) struct BareFunctionDecl {
#[derive(Clone, Debug)]
pub(crate) struct Static {
- pub(crate) type_: Type,
+ pub(crate) type_: Box<Type>,
pub(crate) mutability: Mutability,
pub(crate) expr: Option<BodyId>,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) struct Constant {
+ pub(crate) generics: Generics,
pub(crate) kind: ConstantKind,
+ pub(crate) type_: Type,
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub(crate) enum Term {
Type(Type),
- Constant(Constant),
+ Constant(ConstantKind),
}
impl Term {
@@ -2476,6 +2446,10 @@ pub(crate) fn provided_trait_methods(&self, tcx: TyCtxt<'_>) -> FxHashSet<Symbol
.map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect())
.unwrap_or_default()
}
+
+ pub(crate) fn is_negative_trait_impl(&self) -> bool {
+ matches!(self.polarity, ty::ImplPolarity::Negative)
+ }
}
#[derive(Clone, Debug)]
@@ -2584,8 +2558,9 @@ pub(crate) enum AssocItemConstraintKind {
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
- use super::*;
use rustc_data_structures::static_assert_size;
+
+ use super::*;
// tidy-alphabetical-start
static_assert_size!(Crate, 64); // frequently moved by-value
static_assert_size!(DocFragment, 32);
@@ -2594,7 +2569,7 @@ mod size_asserts {
static_assert_size!(GenericParamDef, 40);
static_assert_size!(Generics, 16);
static_assert_size!(Item, 56);
- static_assert_size!(ItemKind, 56);
+ static_assert_size!(ItemKind, 48);
static_assert_size!(PathSegment, 40);
static_assert_size!(Type, 32);
// tidy-alphabetical-end
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index 4befce0..ddf6a11 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -1,8 +1,8 @@
-use super::*;
-
use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragmentKind};
use rustc_span::create_default_session_globals_then;
+use super::*;
+
fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
vec![DocFragment {
span: DUMMY_SP,
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 7c83d43..68266f3 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -1,3 +1,18 @@
+use std::assert_matches::debug_assert_matches;
+use std::fmt::Write as _;
+use std::mem;
+use std::sync::LazyLock as Lazy;
+
+use rustc_ast::tokenstream::TokenTree;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
+use rustc_metadata::rendered_const;
+use rustc_middle::mir;
+use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt, TypeVisitableExt};
+use rustc_span::symbol::{kw, sym, Symbol};
+use thin_vec::{thin_vec, ThinVec};
+use {rustc_ast as ast, rustc_hir as hir};
+
use crate::clean::auto_trait::synthesize_auto_trait_impls;
use crate::clean::blanket_impl::synthesize_blanket_impls;
use crate::clean::render_macro_matchers::render_macro_matcher;
@@ -10,22 +25,6 @@
use crate::core::DocContext;
use crate::html::format::visibility_to_src_with_space;
-use rustc_ast as ast;
-use rustc_ast::tokenstream::TokenTree;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
-use rustc_metadata::rendered_const;
-use rustc_middle::mir;
-use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
-use rustc_span::symbol::{kw, sym, Symbol};
-use std::assert_matches::debug_assert_matches;
-use std::fmt::Write as _;
-use std::mem;
-use std::sync::LazyLock as Lazy;
-use thin_vec::{thin_vec, ThinVec};
-
#[cfg(test)]
mod tests;
@@ -469,7 +468,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
match path.res {
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => {
- Generic(kw::SelfUpper)
+ Type::SelfTy
}
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
_ => {
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 45bd161..9c7a9f8 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -1,38 +1,32 @@
use std::collections::BTreeMap;
use std::ffi::OsStr;
-use std::fmt;
-use std::io;
use std::io::Read;
-use std::path::Path;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::str::FromStr;
+use std::{fmt, io};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::DiagCtxtHandle;
use rustc_session::config::{
- self, parse_crate_types_from_list, parse_externs, parse_target_triple, CrateType,
+ self, get_cmd_lint_options, nightly_options, parse_crate_types_from_list, parse_externs,
+ parse_target_triple, CodegenOptions, CrateType, ErrorOutputType, Externs, Input,
+ JsonUnusedExterns, UnstableOptions,
};
-use rustc_session::config::{get_cmd_lint_options, nightly_options};
-use rustc_session::config::{CodegenOptions, ErrorOutputType, Externs, Input};
-use rustc_session::config::{JsonUnusedExterns, UnstableOptions};
-use rustc_session::getopts;
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
-use rustc_session::EarlyDiagCtxt;
+use rustc_session::{getopts, EarlyDiagCtxt};
use rustc_span::edition::Edition;
use rustc_span::FileName;
use rustc_target::spec::TargetTriple;
use crate::core::new_dcx;
use crate::externalfiles::ExternalHtml;
-use crate::html;
use crate::html::markdown::IdMap;
use crate::html::render::StylePath;
use crate::html::static_files;
-use crate::opts;
use crate::passes::{self, Condition};
use crate::scrape_examples::{AllCallLocations, ScrapeExamplesOptions};
-use crate::theme;
+use crate::{html, opts, theme};
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
pub(crate) enum OutputFormat {
@@ -368,9 +362,10 @@ pub(crate) fn from_matches(
}
let color = config::parse_color(early_dcx, matches);
- let config::JsonConfig { json_rendered, json_unused_externs, .. } =
+ let config::JsonConfig { json_rendered, json_unused_externs, json_color, .. } =
config::parse_json(early_dcx, matches);
- let error_format = config::parse_error_format(early_dcx, matches, color, json_rendered);
+ let error_format =
+ config::parse_error_format(early_dcx, matches, color, json_color, json_rendered);
let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_default();
let codegen_options = CodegenOptions::build(early_dcx, matches);
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 5d8e61f..08a4a3f 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -1,9 +1,16 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+use std::sync::atomic::AtomicBool;
+use std::sync::{Arc, LazyLock};
+use std::{io, mem};
+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::unord::UnordSet;
+use rustc_errors::codes::*;
use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter};
use rustc_errors::json::JsonEmitter;
-use rustc_errors::{codes::*, DiagCtxtHandle, ErrorGuaranteed, TerminalUrl};
+use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, TerminalUrl};
use rustc_feature::UnstableFeatures;
use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
@@ -14,25 +21,17 @@
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_session::config::{self, CrateType, ErrorOutputType, ResolveDocLinks};
-use rustc_session::lint;
-use rustc_session::Session;
+pub(crate) use rustc_session::config::{Options, UnstableOptions};
+use rustc_session::{lint, Session};
use rustc_span::symbol::sym;
use rustc_span::{source_map, Span};
-use std::cell::RefCell;
-use std::io;
-use std::mem;
-use std::rc::Rc;
-use std::sync::LazyLock;
-use std::sync::{atomic::AtomicBool, Arc};
-
use crate::clean::inline::build_external_trait;
use crate::clean::{self, ItemId};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
-use crate::passes::{self, Condition::*};
-
-pub(crate) use rustc_session::config::{Options, UnstableOptions};
+use crate::passes::Condition::*;
+use crate::passes::{self};
pub(crate) struct DocContext<'tcx> {
pub(crate) tcx: TyCtxt<'tcx>,
@@ -139,8 +138,8 @@ pub(crate) fn new_dcx(
false,
);
let emitter: Box<DynEmitter> = match error_format {
- ErrorOutputType::HumanReadable(kind) => {
- let (short, color_config) = kind.unzip();
+ ErrorOutputType::HumanReadable(kind, color_config) => {
+ let short = kind.short();
Box::new(
HumanEmitter::new(stderr_destination(color_config), fallback_bundle)
.sm(source_map.map(|sm| sm as _))
@@ -151,7 +150,7 @@ pub(crate) fn new_dcx(
.ui_testing(unstable_opts.ui_testing),
)
}
- ErrorOutputType::Json { pretty, json_rendered } => {
+ ErrorOutputType::Json { pretty, json_rendered, color_config } => {
let source_map = source_map.unwrap_or_else(|| {
Lrc::new(source_map::SourceMap::new(source_map::FilePathMapping::empty()))
});
@@ -162,6 +161,7 @@ pub(crate) fn new_dcx(
fallback_bundle,
pretty,
json_rendered,
+ color_config,
)
.ui_testing(unstable_opts.ui_testing)
.diagnostic_width(diagnostic_width)
@@ -196,6 +196,7 @@ pub(crate) fn create_config(
lint_cap,
scrape_examples_options,
expanded_args,
+ remap_path_prefix,
..
}: RustdocOptions,
RenderOptions { document_private, .. }: &RenderOptions,
@@ -248,6 +249,7 @@ pub(crate) fn create_config(
describe_lints,
crate_name,
test,
+ remap_path_prefix,
..Options::default()
};
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 1f7abdf..0ca070d 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -9,11 +9,11 @@
//! abstraction.
use std::cmp::max;
-use std::fs;
-use std::io;
use std::path::{Path, PathBuf};
use std::sync::mpsc::Sender;
use std::thread::available_parallelism;
+use std::{fs, io};
+
use threadpool::ThreadPool;
pub(crate) trait PathError {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 40cc4a9..08d6a5a 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -2,9 +2,16 @@
mod markdown;
mod rust;
+use std::fs::File;
+use std::io::{self, Write};
+use std::path::{Path, PathBuf};
+use std::process::{self, Command, Stdio};
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, Mutex};
+use std::{panic, str};
+
pub(crate) use make::make_test;
pub(crate) use markdown::test as test_markdown;
-
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{ColorConfig, DiagCtxtHandle, ErrorGuaranteed, FatalError};
@@ -17,24 +24,13 @@
use rustc_span::symbol::sym;
use rustc_span::FileName;
use rustc_target::spec::{Target, TargetTriple};
-
-use std::fs::File;
-use std::io::{self, Write};
-use std::panic;
-use std::path::{Path, PathBuf};
-use std::process::{self, Command, Stdio};
-use std::str;
-use std::sync::atomic::{AtomicUsize, Ordering};
-use std::sync::{Arc, Mutex};
-
use tempfile::{Builder as TempFileBuilder, TempDir};
+use self::rust::HirCollector;
use crate::config::Options as RustdocOptions;
use crate::html::markdown::{ErrorCodes, Ignore, LangString, MdRelLine};
use crate::lint::init_lints;
-use self::rust::HirCollector;
-
/// Options that apply to all doctests in a crate or Markdown file (for `rustdoc foo.md`).
#[derive(Clone)]
pub(crate) struct GlobalTestOptions {
@@ -426,8 +422,8 @@ fn run_test(
path_for_rustdoc.to_str().expect("target path must be valid unicode")
}
});
- if let ErrorOutputType::HumanReadable(kind) = rustdoc_options.error_format {
- let (short, color_config) = kind.unzip();
+ if let ErrorOutputType::HumanReadable(kind, color_config) = rustdoc_options.error_format {
+ let short = kind.short();
if short {
compiler.arg("--error-format").arg("short");
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index fc8e119..f179f3a 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -2,7 +2,8 @@
use std::env;
-use rustc_data_structures::{fx::FxHashSet, sync::Lrc};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lrc;
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::{self as hir, intravisit, CRATE_HIR_ID};
use rustc_middle::hir::map::Map;
@@ -14,7 +15,8 @@
use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
use super::{DoctestVisitor, ScrapedDoctest};
-use crate::clean::{types::AttributesExt, Attributes};
+use crate::clean::types::AttributesExt;
+use crate::clean::Attributes;
use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine};
struct RustCollector {
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index 9124ec6..0f13ee4 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -1,8 +1,9 @@
use std::path::PathBuf;
-use super::{make_test, GlobalTestOptions};
use rustc_span::edition::DEFAULT_EDITION;
+use super::{make_test, GlobalTestOptions};
+
/// Default [`GlobalTestOptions`] for these unit tests.
fn default_global_opts(crate_name: impl Into<String>) -> GlobalTestOptions {
GlobalTestOptions {
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 62cdc0b..b81fc5a 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -1,12 +1,12 @@
-use crate::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
+use std::path::Path;
+use std::{fs, str};
+
use rustc_errors::DiagCtxtHandle;
use rustc_span::edition::Edition;
-use std::fs;
-use std::path::Path;
-use std::str;
-
use serde::Serialize;
+use crate::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
+
#[derive(Clone, Debug, Serialize)]
pub(crate) struct ExternalHtml {
/// Content that will be included inline in the `<head>` section of a
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 346e9a4..bf82c91 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -77,9 +77,8 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
ExternCrateItem { src: _ }
| ImportItem(_)
| FunctionItem(_)
- | OpaqueTyItem(_)
| StaticItem(_)
- | ConstantItem(_, _, _)
+ | ConstantItem(..)
| TraitAliasItem(_)
| TyMethodItem(_)
| MethodItem(_, _)
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index a3b88a8..947bae9 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -5,7 +5,8 @@
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Symbol;
-use crate::clean::{self, types::ExternalLocation, ExternalCrate, ItemId, PrimitiveType};
+use crate::clean::types::ExternalLocation;
+use crate::clean::{self, ExternalCrate, ItemId, PrimitiveType};
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::formats::item_type::ItemType;
@@ -259,153 +260,21 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
}
// Index this method for searching later on.
- if let Some(s) = item.name.or_else(|| {
- if item.is_stripped() {
- None
- } else if let clean::ImportItem(ref i) = *item.kind
- && let clean::ImportKind::Simple(s) = i.kind
- {
- Some(s)
- } else {
- None
- }
- }) {
- let (parent, is_inherent_impl_item) = match *item.kind {
- clean::StrippedItem(..) => ((None, None), false),
- clean::AssocConstItem(..) | clean::AssocTypeItem(..)
- if self
- .cache
- .parent_stack
- .last()
- .is_some_and(|parent| parent.is_trait_impl()) =>
+ let search_name = if !item.is_stripped() {
+ item.name.or_else(|| {
+ if let clean::ImportItem(ref i) = *item.kind
+ && let clean::ImportKind::Simple(s) = i.kind
{
- // skip associated items in trait impls
- ((None, None), false)
+ Some(s)
+ } else {
+ None
}
- clean::TyMethodItem(..)
- | clean::TyAssocConstItem(..)
- | clean::TyAssocTypeItem(..)
- | clean::StructFieldItem(..)
- | clean::VariantItem(..) => (
- (
- Some(
- self.cache
- .parent_stack
- .last()
- .expect("parent_stack is empty")
- .item_id()
- .expect_def_id(),
- ),
- Some(&self.cache.stack[..self.cache.stack.len() - 1]),
- ),
- false,
- ),
- clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
- if self.cache.parent_stack.is_empty() {
- ((None, None), false)
- } else {
- let last = self.cache.parent_stack.last().expect("parent_stack is empty 2");
- let did = match &*last {
- ParentStackItem::Impl {
- // impl Trait for &T { fn method(self); }
- //
- // When generating a function index with the above shape, we want it
- // associated with `T`, not with the primitive reference type. It should
- // show up as `T::method`, rather than `reference::method`, in the search
- // results page.
- for_: clean::Type::BorrowedRef { type_, .. },
- ..
- } => type_.def_id(&self.cache),
- ParentStackItem::Impl { for_, .. } => for_.def_id(&self.cache),
- ParentStackItem::Type(item_id) => item_id.as_def_id(),
- };
- let path = did
- .and_then(|did| self.cache.paths.get(&did))
- // The current stack not necessarily has correlation
- // for where the type was defined. On the other
- // hand, `paths` always has the right
- // information if present.
- .map(|(fqp, _)| &fqp[..fqp.len() - 1]);
- ((did, path), true)
- }
- }
- _ => ((None, Some(&*self.cache.stack)), false),
- };
-
- match parent {
- (parent, Some(path)) if is_inherent_impl_item || !self.cache.stripped_mod => {
- debug_assert!(!item.is_stripped());
-
- // A crate has a module at its root, containing all items,
- // which should not be indexed. The crate-item itself is
- // inserted later on when serializing the search-index.
- if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root())
- && let ty = item.type_()
- && (ty != ItemType::StructField
- || u16::from_str_radix(s.as_str(), 10).is_err())
- {
- let desc =
- short_markdown_summary(&item.doc_value(), &item.link_names(self.cache));
- // For searching purposes, a re-export is a duplicate if:
- //
- // - It's either an inline, or a true re-export
- // - It's got the same name
- // - Both of them have the same exact path
- let defid = (match &*item.kind {
- &clean::ItemKind::ImportItem(ref import) => import.source.did,
- _ => None,
- })
- .or_else(|| item.item_id.as_def_id());
- // In case this is a field from a tuple struct, we don't add it into
- // the search index because its name is something like "0", which is
- // not useful for rustdoc search.
- self.cache.search_index.push(IndexItem {
- ty,
- defid,
- name: s,
- path: join_with_double_colon(path),
- desc,
- parent,
- parent_idx: None,
- exact_path: None,
- impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) =
- self.cache.parent_stack.last()
- {
- item_id.as_def_id()
- } else {
- None
- },
- search_type: get_function_type_for_search(
- &item,
- self.tcx,
- clean_impl_generics(self.cache.parent_stack.last()).as_ref(),
- parent,
- self.cache,
- ),
- aliases: item.attrs.get_doc_aliases(),
- deprecation: item.deprecation(self.tcx),
- });
- }
- }
- (Some(parent), None) if is_inherent_impl_item => {
- // We have a parent, but we don't know where they're
- // defined yet. Wait for later to index this item.
- let impl_generics = clean_impl_generics(self.cache.parent_stack.last());
- self.cache.orphan_impl_items.push(OrphanImplItem {
- parent,
- item: item.clone(),
- impl_generics,
- impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) =
- self.cache.parent_stack.last()
- {
- item_id.as_def_id()
- } else {
- None
- },
- });
- }
- _ => {}
- }
+ })
+ } else {
+ None
+ };
+ if let Some(name) = search_name {
+ add_item_to_search_index(self.tcx, &mut self.cache, &item, name)
}
// Keep track of the fully qualified path for this item.
@@ -441,16 +310,16 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
- if !self.cache.paths.contains_key(&item.item_id.expect_def_id())
+ let item_def_id = item.item_id.expect_def_id();
+ if !self.cache.paths.contains_key(&item_def_id)
|| self
.cache
.effective_visibilities
- .is_directly_public(self.tcx, item.item_id.expect_def_id())
+ .is_directly_public(self.tcx, item_def_id)
{
- self.cache.paths.insert(
- item.item_id.expect_def_id(),
- (self.cache.stack.clone(), item.type_()),
- );
+ self.cache
+ .paths
+ .insert(item_def_id, (self.cache.stack.clone(), item.type_()));
}
}
}
@@ -462,7 +331,6 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
clean::ExternCrateItem { .. }
| clean::ImportItem(..)
- | clean::OpaqueTyItem(..)
| clean::ImplItem(..)
| clean::TyMethodItem(..)
| clean::MethodItem(..)
@@ -513,9 +381,7 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
&& adt.is_fundamental()
{
for ty in generics {
- if let Some(did) = ty.def_id(self.cache) {
- dids.insert(did);
- }
+ dids.extend(ty.def_id(self.cache));
}
}
}
@@ -528,32 +394,26 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
.primitive_type()
.and_then(|t| self.cache.primitive_locations.get(&t).cloned());
- if let Some(did) = did {
- dids.insert(did);
- }
+ dids.extend(did);
}
}
if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) {
for bound in generics {
- if let Some(did) = bound.def_id(self.cache) {
- dids.insert(did);
- }
+ dids.extend(bound.def_id(self.cache));
}
}
let impl_item = Impl { impl_item: item };
- if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) {
+ let impl_did = impl_item.def_id();
+ let trait_did = impl_item.trait_did();
+ if trait_did.map_or(true, |d| self.cache.traits.contains_key(&d)) {
for did in dids {
- if self.impl_ids.entry(did).or_default().insert(impl_item.def_id()) {
- self.cache
- .impls
- .entry(did)
- .or_insert_with(Vec::new)
- .push(impl_item.clone());
+ if self.impl_ids.entry(did).or_default().insert(impl_did) {
+ self.cache.impls.entry(did).or_default().push(impl_item.clone());
}
}
} else {
- let trait_did = impl_item.trait_did().expect("no trait did");
+ let trait_did = trait_did.expect("no trait did");
self.cache.orphan_trait_impls.push((trait_did, dids, impl_item));
}
None
@@ -572,6 +432,152 @@ fn is_from_private_dep(tcx: TyCtxt<'_>, cache: &Cache, def_id: DefId) -> bool {
}
}
+fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) {
+ // Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl).
+ let item_def_id = item.item_id.as_def_id().unwrap();
+ let (parent_did, parent_path) = match *item.kind {
+ clean::StrippedItem(..) => return,
+ clean::AssocConstItem(..) | clean::AssocTypeItem(..)
+ if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
+ {
+ // skip associated items in trait impls
+ return;
+ }
+ clean::TyMethodItem(..)
+ | clean::TyAssocConstItem(..)
+ | clean::TyAssocTypeItem(..)
+ | clean::StructFieldItem(..)
+ | clean::VariantItem(..) => {
+ // Don't index if containing module is stripped (i.e., private),
+ // or if item is tuple struct/variant field (name is a number -> not useful for search).
+ if cache.stripped_mod
+ || item.type_() == ItemType::StructField
+ && name.as_str().chars().all(|c| c.is_digit(10))
+ {
+ return;
+ }
+ let parent_did =
+ cache.parent_stack.last().expect("parent_stack is empty").item_id().expect_def_id();
+ let parent_path = &cache.stack[..cache.stack.len() - 1];
+ (Some(parent_did), parent_path)
+ }
+ clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
+ let last = cache.parent_stack.last().expect("parent_stack is empty 2");
+ let parent_did = match &*last {
+ // impl Trait for &T { fn method(self); }
+ //
+ // When generating a function index with the above shape, we want it
+ // associated with `T`, not with the primitive reference type. It should
+ // show up as `T::method`, rather than `reference::method`, in the search
+ // results page.
+ ParentStackItem::Impl { for_: clean::Type::BorrowedRef { type_, .. }, .. } => {
+ type_.def_id(&cache)
+ }
+ ParentStackItem::Impl { for_, .. } => for_.def_id(&cache),
+ ParentStackItem::Type(item_id) => item_id.as_def_id(),
+ };
+ let Some(parent_did) = parent_did else { return };
+ // The current stack reflects the CacheBuilder's recursive
+ // walk over HIR. For associated items, this is the module
+ // where the `impl` block is defined. That's an implementation
+ // detail that we don't want to affect the search engine.
+ //
+ // In particular, you can arrange things like this:
+ //
+ // #![crate_name="me"]
+ // mod private_mod {
+ // impl Clone for MyThing { fn clone(&self) -> MyThing { MyThing } }
+ // }
+ // pub struct MyThing;
+ //
+ // When that happens, we need to:
+ // - ignore the `cache.stripped_mod` flag, since the Clone impl is actually
+ // part of the public API even though it's defined in a private module
+ // - present the method as `me::MyThing::clone`, its publicly-visible path
+ // - deal with the fact that the recursive walk hasn't actually reached `MyThing`
+ // until it's already past `private_mod`, since that's first, and doesn't know
+ // yet if `MyThing` will actually be public or not (it could be re-exported)
+ //
+ // We accomplish the last two points by recording children of "orphan impls"
+ // in a field of the cache whose elements are added to the search index later,
+ // after cache building is complete (see `handle_orphan_impl_child`).
+ match cache.paths.get(&parent_did) {
+ Some((fqp, _)) => (Some(parent_did), &fqp[..fqp.len() - 1]),
+ None => {
+ handle_orphan_impl_child(cache, item, parent_did);
+ return;
+ }
+ }
+ }
+ _ => {
+ // Don't index if item is crate root, which is inserted later on when serializing the index.
+ // Don't index if containing module is stripped (i.e., private),
+ if item_def_id.is_crate_root() || cache.stripped_mod {
+ return;
+ }
+ (None, &*cache.stack)
+ }
+ };
+
+ debug_assert!(!item.is_stripped());
+
+ let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache));
+ // For searching purposes, a re-export is a duplicate if:
+ //
+ // - It's either an inline, or a true re-export
+ // - It's got the same name
+ // - Both of them have the same exact path
+ let defid = match &*item.kind {
+ clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id),
+ _ => item_def_id,
+ };
+ let path = join_with_double_colon(parent_path);
+ let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
+ item_id.as_def_id()
+ } else {
+ None
+ };
+ let search_type = get_function_type_for_search(
+ &item,
+ tcx,
+ clean_impl_generics(cache.parent_stack.last()).as_ref(),
+ parent_did,
+ cache,
+ );
+ let aliases = item.attrs.get_doc_aliases();
+ let deprecation = item.deprecation(tcx);
+ let index_item = IndexItem {
+ ty: item.type_(),
+ defid: Some(defid),
+ name,
+ path,
+ desc,
+ parent: parent_did,
+ parent_idx: None,
+ exact_path: None,
+ impl_id,
+ search_type,
+ aliases,
+ deprecation,
+ };
+ cache.search_index.push(index_item);
+}
+
+/// We have a parent, but we don't know where they're
+/// defined yet. Wait for later to index this item.
+/// See [`Cache::orphan_impl_items`].
+fn handle_orphan_impl_child(cache: &mut Cache, item: &clean::Item, parent_did: DefId) {
+ let impl_generics = clean_impl_generics(cache.parent_stack.last());
+ let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() {
+ item_id.as_def_id()
+ } else {
+ None
+ };
+ let orphan_item =
+ OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id };
+ cache.orphan_impl_items.push(orphan_item);
+}
+
pub(crate) struct OrphanImplItem {
pub(crate) parent: DefId,
pub(crate) impl_id: Option<DefId>,
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index d546879..3dcef15 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -2,10 +2,9 @@
use std::fmt;
-use serde::{Serialize, Serializer};
-
use rustc_hir::def::{CtorOf, DefKind};
use rustc_span::hygiene::MacroKind;
+use serde::{Serialize, Serializer};
use crate::clean;
@@ -52,7 +51,7 @@ pub(crate) enum ItemType {
AssocConst = 19,
Union = 20,
ForeignType = 21,
- OpaqueTy = 22,
+ // OpaqueTy used to be here, but it was removed in #127276
ProcAttribute = 23,
ProcDerive = 24,
TraitAlias = 25,
@@ -85,7 +84,6 @@ fn from(item: &'a clean::Item) -> ItemType {
clean::EnumItem(..) => ItemType::Enum,
clean::FunctionItem(..) => ItemType::Function,
clean::TypeAliasItem(..) => ItemType::TypeAlias,
- clean::OpaqueTyItem(..) => ItemType::OpaqueTy,
clean::StaticItem(..) => ItemType::Static,
clean::ConstantItem(..) => ItemType::Constant,
clean::TraitItem(..) => ItemType::Trait,
@@ -192,7 +190,6 @@ pub(crate) fn as_str(&self) -> &'static str {
ItemType::AssocConst => "associatedconstant",
ItemType::ForeignType => "foreigntype",
ItemType::Keyword => "keyword",
- ItemType::OpaqueTy => "opaque",
ItemType::ProcAttribute => "attr",
ItemType::ProcDerive => "derive",
ItemType::TraitAlias => "traitalias",
diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs
index 0056fb4..84adca8 100644
--- a/src/librustdoc/formats/mod.rs
+++ b/src/librustdoc/formats/mod.rs
@@ -2,9 +2,8 @@
pub(crate) mod item_type;
pub(crate) mod renderer;
-use rustc_hir::def_id::DefId;
-
pub(crate) use renderer::{run_format, FormatRenderer};
+use rustc_hir::def_id::DefId;
use crate::clean::{self, ItemId};
use crate::html::render::Context;
diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs
index ea4b573..691f868 100644
--- a/src/librustdoc/html/escape.rs
+++ b/src/librustdoc/html/escape.rs
@@ -5,6 +5,8 @@
use std::fmt;
+use unicode_segmentation::UnicodeSegmentation;
+
/// Wrapper struct which will emit the HTML-escaped version of the contained
/// string when passed to a format string.
pub(crate) struct Escape<'a>(pub &'a str);
@@ -74,3 +76,56 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
+
+/// Wrapper struct which will emit the HTML-escaped version of the contained
+/// string when passed to a format string. This function also word-breaks
+/// CamelCase and snake_case word names.
+///
+/// This is only safe to use for text nodes. If you need your output to be
+/// safely contained in an attribute, use [`Escape`]. If you don't know the
+/// difference, use [`Escape`].
+pub(crate) struct EscapeBodyTextWithWbr<'a>(pub &'a str);
+
+impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let EscapeBodyTextWithWbr(text) = *self;
+ if text.len() < 8 {
+ return EscapeBodyText(text).fmt(fmt);
+ }
+ let mut last = 0;
+ let mut it = text.grapheme_indices(true).peekable();
+ let _ = it.next(); // don't insert wbr before first char
+ while let Some((i, s)) = it.next() {
+ let pk = it.peek();
+ if s.chars().all(|c| c.is_whitespace()) {
+ // don't need "First <wbr>Second"; the space is enough
+ EscapeBodyText(&text[last..i]).fmt(fmt)?;
+ last = i;
+ continue;
+ }
+ let is_uppercase = || s.chars().any(|c| c.is_uppercase());
+ let next_is_uppercase =
+ || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase()));
+ let next_is_underscore = || pk.map_or(true, |(_, t)| t.contains('_'));
+ let next_is_colon = || pk.map_or(true, |(_, t)| t.contains(':'));
+ if i - last > 3 && is_uppercase() && !next_is_uppercase() {
+ EscapeBodyText(&text[last..i]).fmt(fmt)?;
+ fmt.write_str("<wbr>")?;
+ last = i;
+ } else if (s.contains(':') && !next_is_colon())
+ || (s.contains('_') && !next_is_underscore())
+ {
+ EscapeBodyText(&text[last..i + 1]).fmt(fmt)?;
+ fmt.write_str("<wbr>")?;
+ last = i + 1;
+ }
+ }
+ if last < text.len() {
+ EscapeBodyText(&text[last..]).fmt(fmt)?;
+ }
+ Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustdoc/html/escape/tests.rs b/src/librustdoc/html/escape/tests.rs
new file mode 100644
index 0000000..a09649e
--- /dev/null
+++ b/src/librustdoc/html/escape/tests.rs
@@ -0,0 +1,68 @@
+// basic examples
+#[test]
+fn escape_body_text_with_wbr() {
+ use super::EscapeBodyTextWithWbr as E;
+ // extreme corner cases
+ assert_eq!(&E("").to_string(), "");
+ assert_eq!(&E("a").to_string(), "a");
+ assert_eq!(&E("A").to_string(), "A");
+ assert_eq!(&E("_").to_string(), "_");
+ assert_eq!(&E(":").to_string(), ":");
+ assert_eq!(&E(" ").to_string(), " ");
+ assert_eq!(&E("___________").to_string(), "___________");
+ assert_eq!(&E(":::::::::::").to_string(), ":::::::::::");
+ assert_eq!(&E(" ").to_string(), " ");
+ // real(istic) examples
+ assert_eq!(&E("FirstSecond").to_string(), "First<wbr>Second");
+ assert_eq!(&E("First_Second").to_string(), "First_<wbr>Second");
+ assert_eq!(&E("First Second").to_string(), "First Second");
+ assert_eq!(&E("First HSecond").to_string(), "First HSecond");
+ assert_eq!(&E("First HTTPSecond").to_string(), "First HTTP<wbr>Second");
+ assert_eq!(&E("First SecondThird").to_string(), "First Second<wbr>Third");
+ assert_eq!(&E("First<T>_Second").to_string(), "First<<wbr>T>_<wbr>Second");
+ assert_eq!(&E("first_second").to_string(), "first_<wbr>second");
+ assert_eq!(&E("first:second").to_string(), "first:<wbr>second");
+ assert_eq!(&E("first::second").to_string(), "first::<wbr>second");
+ assert_eq!(&E("MY_CONSTANT").to_string(), "MY_<wbr>CONSTANT");
+ // a string won't get wrapped if it's less than 8 bytes
+ assert_eq!(&E("HashSet").to_string(), "HashSet");
+ // an individual word won't get wrapped if it's less than 4 bytes
+ assert_eq!(&E("VecDequeue").to_string(), "VecDequeue");
+ assert_eq!(&E("VecDequeueSet").to_string(), "VecDequeue<wbr>Set");
+ // how to handle acronyms
+ assert_eq!(&E("BTreeMap").to_string(), "BTree<wbr>Map");
+ assert_eq!(&E("HTTPSProxy").to_string(), "HTTPS<wbr>Proxy");
+ // more corners
+ assert_eq!(&E("ṼẽçÑñéå").to_string(), "Ṽẽç<wbr>Ññéå");
+ assert_eq!(&E("V\u{0300}e\u{0300}c\u{0300}D\u{0300}e\u{0300}q\u{0300}u\u{0300}e\u{0300}u\u{0300}e\u{0300}").to_string(), "V\u{0300}e\u{0300}c\u{0300}<wbr>D\u{0300}e\u{0300}q\u{0300}u\u{0300}e\u{0300}u\u{0300}e\u{0300}");
+ assert_eq!(&E("LPFNACCESSIBLEOBJECTFROMWINDOW").to_string(), "LPFNACCESSIBLEOBJECTFROMWINDOW");
+}
+// property test
+#[test]
+fn escape_body_text_with_wbr_makes_sense() {
+ use itertools::Itertools as _;
+
+ use super::EscapeBodyTextWithWbr as E;
+ const C: [u8; 3] = [b'a', b'A', b'_'];
+ for chars in [
+ C.into_iter(),
+ C.into_iter(),
+ C.into_iter(),
+ C.into_iter(),
+ C.into_iter(),
+ C.into_iter(),
+ C.into_iter(),
+ C.into_iter(),
+ ]
+ .into_iter()
+ .multi_cartesian_product()
+ {
+ let s = String::from_utf8(chars).unwrap();
+ assert_eq!(s.len(), 8);
+ let esc = E(&s).to_string();
+ assert!(!esc.contains("<wbr><wbr>"));
+ assert!(!esc.ends_with("<wbr>"));
+ assert!(!esc.starts_with("<wbr>"));
+ assert_eq!(&esc.replace("<wbr>", ""), &s);
+ }
+}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 055781f..6357cfe 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -12,11 +12,10 @@
use std::fmt::{self, Display, Write};
use std::iter::{self, once};
-use rustc_ast as ast;
+use itertools::Itertools;
use rustc_attr::{ConstStability, StabilityLevel, StableSince};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_metadata::creader::{CStore, LoadedMacro};
@@ -25,21 +24,18 @@
use rustc_span::symbol::kw;
use rustc_span::{sym, Symbol};
use rustc_target::spec::abi::Abi;
+use {rustc_ast as ast, rustc_hir as hir};
-use itertools::Itertools;
-
-use crate::clean::{
- self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, PrimitiveType,
-};
+use super::url_parts_builder::{estimate_item_path_byte_length, UrlPartsBuilder};
+use crate::clean::types::ExternalLocation;
+use crate::clean::utils::find_nearest_parent_module;
+use crate::clean::{self, ExternalCrate, PrimitiveType};
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
-use crate::html::escape::Escape;
+use crate::html::escape::{Escape, EscapeBodyText};
use crate::html::render::Context;
use crate::passes::collect_intra_doc_links::UrlFragment;
-use super::url_parts_builder::estimate_item_path_byte_length;
-use super::url_parts_builder::UrlPartsBuilder;
-
pub(crate) trait Print {
fn print(self, buffer: &mut Buffer);
}
@@ -375,7 +371,7 @@ pub(crate) fn print(&self) -> impl Display + '_ {
}
}
-impl clean::Constant {
+impl clean::ConstantKind {
pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display + '_ {
let expr = self.expr(tcx);
display_fn(
@@ -992,6 +988,7 @@ pub(crate) fn anchor<'a, 'cx: 'a>(
f,
r#"<a class="{short_ty}" href="{url}" title="{short_ty} {path}">{text}</a>"#,
path = join_with_double_colon(&fqp),
+ text = EscapeBodyText(text.as_str()),
)
} else {
f.write_str(text.as_str())
@@ -1009,6 +1006,7 @@ fn fmt_type<'cx>(
match *t {
clean::Generic(name) => f.write_str(name.as_str()),
+ clean::SelfTy => f.write_str("Self"),
clean::Type::Path { ref path } => {
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
let did = path.def_id();
@@ -1287,9 +1285,8 @@ pub(crate) fn print<'a, 'tcx: 'a>(
f.write_str(" ")?;
if let Some(ref ty) = self.trait_ {
- match self.polarity {
- ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {}
- ty::ImplPolarity::Negative => write!(f, "!")?,
+ if self.is_negative_trait_impl() {
+ write!(f, "!")?;
}
ty.print(cx).fmt(f)?;
write!(f, " for ")?;
@@ -1455,29 +1452,22 @@ fn inner_full_print(
let last_input_index = self.inputs.values.len().checked_sub(1);
for (i, input) in self.inputs.values.iter().enumerate() {
- if let Some(selfty) = input.to_self() {
+ if let Some(selfty) = input.to_receiver() {
match selfty {
- clean::SelfValue => {
+ clean::SelfTy => {
write!(f, "self")?;
}
- clean::SelfBorrowed(Some(ref lt), mutability) => {
- write!(
- f,
- "{amp}{lifetime} {mutability}self",
- lifetime = lt.print(),
- mutability = mutability.print_with_space(),
- )?;
+ clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => {
+ write!(f, "{amp}")?;
+ match lifetime {
+ Some(lt) => write!(f, "{lt} ", lt = lt.print())?,
+ None => {}
+ }
+ write!(f, "{mutability}self", mutability = mutability.print_with_space())?;
}
- clean::SelfBorrowed(None, mutability) => {
- write!(
- f,
- "{amp}{mutability}self",
- mutability = mutability.print_with_space(),
- )?;
- }
- clean::SelfExplicit(ref typ) => {
+ _ => {
write!(f, "self: ")?;
- typ.print(cx).fmt(f)?;
+ selfty.print(cx).fmt(f)?;
}
}
} else {
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 336d18a..29b4889 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -5,10 +5,6 @@
//!
//! Use the `render_with_highlighting` to highlight some rust code.
-use crate::clean::PrimitiveType;
-use crate::html::escape::EscapeBodyText;
-use crate::html::render::{Context, LinkFromSrc};
-
use std::collections::VecDeque;
use std::fmt::{Display, Write};
@@ -19,6 +15,9 @@
use rustc_span::{BytePos, Span, DUMMY_SP};
use super::format::{self, Buffer};
+use crate::clean::PrimitiveType;
+use crate::html::escape::EscapeBodyText;
+use crate::html::render::{Context, LinkFromSrc};
/// This type is needed in case we want to render links on items to allow to go to their definition.
pub(crate) struct HrefContext<'a, 'tcx> {
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index 4c0874a..9d51101 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -1,9 +1,10 @@
-use super::{write_code, DecorationInfo};
-use crate::html::format::Buffer;
use expect_test::expect_file;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::create_default_session_globals_then;
+use super::{write_code, DecorationInfo};
+use crate::html::format::Buffer;
+
const STYLE: &str = r#"
<style>
.kw { color: #8959A8; }
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 22576b7..780cda9 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -1,15 +1,13 @@
use std::path::PathBuf;
+use rinja::Template;
use rustc_data_structures::fx::FxHashMap;
+use super::static_files::{StaticFiles, STATIC_FILES};
use crate::externalfiles::ExternalHtml;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};
-use rinja::Template;
-
-use super::static_files::{StaticFiles, STATIC_FILES};
-
#[derive(Clone)]
pub(crate) struct Layout {
pub(crate) logo: String,
@@ -71,6 +69,8 @@ struct PageLayout<'a> {
display_krate_version_extra: &'a str,
}
+pub(crate) use crate::html::render::sidebar::filters;
+
pub(crate) fn render<T: Print, S: Print>(
layout: &Layout,
page: &Page<'_>,
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index a7f0df5..c41db65 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -25,15 +25,6 @@
//! // ... something using html
//! ```
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Diag, DiagMessage};
-use rustc_hir::def_id::DefId;
-use rustc_middle::ty::TyCtxt;
-pub(crate) use rustc_resolve::rustdoc::main_body_opts;
-use rustc_resolve::rustdoc::may_be_doc_link;
-use rustc_span::edition::Edition;
-use rustc_span::{Span, Symbol};
-
use std::borrow::Cow;
use std::collections::VecDeque;
use std::fmt::Write;
@@ -43,6 +34,19 @@
use std::str::{self, CharIndices};
use std::sync::OnceLock;
+use pulldown_cmark::{
+ html, BrokenLink, BrokenLinkCallback, CodeBlockKind, CowStr, Event, LinkType, OffsetIter,
+ Options, Parser, Tag, TagEnd,
+};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::{Diag, DiagMessage};
+use rustc_hir::def_id::DefId;
+use rustc_middle::ty::TyCtxt;
+pub(crate) use rustc_resolve::rustdoc::main_body_opts;
+use rustc_resolve::rustdoc::may_be_doc_link;
+use rustc_span::edition::Edition;
+use rustc_span::{Span, Symbol};
+
use crate::clean::RenderedLink;
use crate::doctest;
use crate::doctest::GlobalTestOptions;
@@ -53,11 +57,6 @@
use crate::html::render::small_url_encode;
use crate::html::toc::TocBuilder;
-use pulldown_cmark::{
- html, BrokenLink, BrokenLinkCallback, CodeBlockKind, CowStr, Event, LinkType, OffsetIter,
- Options, Parser, Tag, TagEnd,
-};
-
#[cfg(test)]
mod tests;
@@ -305,7 +304,8 @@ fn next(&mut self) -> Option<Self::Item> {
Some(format!(
"<a class=\"test-arrow\" \
target=\"_blank\" \
- href=\"{url}?code={test_escaped}{channel}&edition={edition}\">Run</a>",
+ title=\"Run code\" \
+ href=\"{url}?code={test_escaped}{channel}&edition={edition}\"></a>",
))
});
@@ -925,6 +925,7 @@ pub(crate) struct TagIterator<'a, 'tcx> {
data: &'a str,
is_in_attribute_block: bool,
extra: Option<&'a ExtraInfo<'tcx>>,
+ is_error: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -951,13 +952,20 @@ struct Indices {
impl<'a, 'tcx> TagIterator<'a, 'tcx> {
pub(crate) fn new(data: &'a str, extra: Option<&'a ExtraInfo<'tcx>>) -> Self {
- Self { inner: data.char_indices().peekable(), data, is_in_attribute_block: false, extra }
+ Self {
+ inner: data.char_indices().peekable(),
+ data,
+ is_in_attribute_block: false,
+ extra,
+ is_error: false,
+ }
}
- fn emit_error(&self, err: impl Into<DiagMessage>) {
+ fn emit_error(&mut self, err: impl Into<DiagMessage>) {
if let Some(extra) = self.extra {
extra.error_invalid_codeblock_attr(err);
}
+ self.is_error = true;
}
fn skip_separators(&mut self) -> Option<usize> {
@@ -1155,6 +1163,9 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> {
type Item = LangStringToken<'a>;
fn next(&mut self) -> Option<Self::Item> {
+ if self.is_error {
+ return None;
+ }
let Some(start) = self.skip_separators() else {
if self.is_in_attribute_block {
self.emit_error("unclosed attribute block (`{}`): missing `}` at the end");
@@ -1343,14 +1354,15 @@ fn parse(
}
};
- call(&mut TagIterator::new(string, extra));
+ let mut tag_iter = TagIterator::new(string, extra);
+ call(&mut tag_iter);
// ignore-foo overrides ignore
if !ignores.is_empty() {
data.ignore = Ignore::Some(ignores);
}
- data.rust &= !seen_custom_tag && (!seen_other_tags || seen_rust_tags);
+ data.rust &= !seen_custom_tag && (!seen_other_tags || seen_rust_tags) && !tag_iter.is_error;
data
}
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index fb74c07..e490099 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -1,10 +1,10 @@
-use super::{find_testable_code, plain_text_summary, short_markdown_summary};
-use super::{
- ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, LangStringToken, Markdown,
- MarkdownItemInfo, TagIterator,
-};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
+use super::{
+ find_testable_code, plain_text_summary, short_markdown_summary, ErrorCodes, HeadingOffset,
+ IdMap, Ignore, LangString, LangStringToken, Markdown, MarkdownItemInfo, TagIterator,
+};
+
#[test]
fn test_unique_id() {
let input = [
@@ -61,7 +61,7 @@ fn t(lg: LangString) {
..Default::default()
});
// error
- t(LangString { original: "{rust}".into(), rust: true, ..Default::default() });
+ t(LangString { original: "{rust}".into(), rust: false, ..Default::default() });
t(LangString {
original: "{.rust}".into(),
rust: true,
@@ -233,7 +233,7 @@ fn t(lg: LangString) {
..Default::default()
});
// error
- t(LangString { original: "{class=first=second}".into(), rust: true, ..Default::default() });
+ t(LangString { original: "{class=first=second}".into(), rust: false, ..Default::default() });
// error
t(LangString {
original: "{class=first.second}".into(),
@@ -261,7 +261,7 @@ fn t(lg: LangString) {
..Default::default()
});
// error
- t(LangString { original: r#"{class=f"irst"}"#.into(), rust: true, ..Default::default() });
+ t(LangString { original: r#"{class=f"irst"}"#.into(), rust: false, ..Default::default() });
}
#[test]
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 7718413..0334eac 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -5,6 +5,7 @@
use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver};
+use rinja::Template;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
@@ -14,15 +15,12 @@
use super::print_item::{full_path, item_path, print_item};
use super::search_index::build_index;
+use super::sidebar::{print_sidebar, sidebar_module_like, Sidebar};
use super::write_shared::write_shared;
-use super::{
- collect_spans_and_sources, scrape_examples_help,
- sidebar::print_sidebar,
- sidebar::{sidebar_module_like, Sidebar},
- AllTypes, LinkFromSrc, StylePath,
-};
+use super::{collect_spans_and_sources, scrape_examples_help, AllTypes, LinkFromSrc, StylePath};
+use crate::clean::types::ExternalLocation;
use crate::clean::utils::has_doc_flag;
-use crate::clean::{self, types::ExternalLocation, ExternalCrate};
+use crate::clean::{self, ExternalCrate};
use crate::config::{ModuleSorting, RenderOptions};
use crate::docfs::{DocFS, PathError};
use crate::error::Error;
@@ -36,7 +34,6 @@
use crate::html::{layout, sources, static_files};
use crate::scrape_examples::AllCallLocations;
use crate::try_err;
-use rinja::Template;
/// Major driving force in all rustdoc rendering. This contains information
/// about where in the tree-like hierarchy rendering is occurring and controls
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 5b9ef67..7ce637d 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -30,21 +30,17 @@
mod context;
mod print_item;
-mod sidebar;
+pub(crate) mod sidebar;
mod span_map;
mod type_layout;
mod write_shared;
-pub(crate) use self::context::*;
-pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc};
-
use std::collections::VecDeque;
use std::fmt::{self, Write};
-use std::fs;
use std::iter::Peekable;
use std::path::PathBuf;
use std::rc::Rc;
-use std::str;
+use std::{fs, str};
use rinja::Template;
use rustc_attr::{ConstStability, DeprecatedSince, Deprecation, StabilityLevel, StableSince};
@@ -55,14 +51,14 @@
use rustc_middle::ty::print::PrintTraitRefExt;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::RustcVersion;
-use rustc_span::{
- symbol::{sym, Symbol},
- BytePos, FileName, RealFileName, DUMMY_SP,
-};
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{BytePos, FileName, RealFileName, DUMMY_SP};
use serde::ser::SerializeMap;
use serde::{Serialize, Serializer};
-use crate::clean::{self, ItemId, RenderedLink, SelfTy};
+pub(crate) use self::context::*;
+pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc};
+use crate::clean::{self, ItemId, RenderedLink};
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
@@ -73,15 +69,13 @@
print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
Buffer, Ending, HrefError, PrintWithSpace,
};
-use crate::html::highlight;
use crate::html::markdown::{
HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine,
};
-use crate::html::sources;
use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD;
+use crate::html::{highlight, sources};
use crate::scrape_examples::{CallData, CallLocation};
-use crate::try_none;
-use crate::DOC_RUST_LANG_ORG_CHANNEL;
+use crate::{try_none, DOC_RUST_LANG_ORG_CHANNEL};
pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
crate::html::format::display_fn(move |f| {
@@ -338,7 +332,6 @@ struct AllTypes {
macros: FxHashSet<ItemEntry>,
functions: FxHashSet<ItemEntry>,
type_aliases: FxHashSet<ItemEntry>,
- opaque_tys: FxHashSet<ItemEntry>,
statics: FxHashSet<ItemEntry>,
constants: FxHashSet<ItemEntry>,
attribute_macros: FxHashSet<ItemEntry>,
@@ -358,7 +351,6 @@ fn new() -> AllTypes {
macros: new_set(100),
functions: new_set(100),
type_aliases: new_set(100),
- opaque_tys: new_set(100),
statics: new_set(100),
constants: new_set(100),
attribute_macros: new_set(100),
@@ -382,7 +374,6 @@ fn append(&mut self, item_name: String, item_type: &ItemType) {
ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)),
ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)),
ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(new_url, name)),
- ItemType::OpaqueTy => self.opaque_tys.insert(ItemEntry::new(new_url, name)),
ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
ItemType::ProcAttribute => {
@@ -422,9 +413,6 @@ fn item_sections(&self) -> FxHashSet<ItemSection> {
if !self.type_aliases.is_empty() {
sections.insert(ItemSection::TypeAliases);
}
- if !self.opaque_tys.is_empty() {
- sections.insert(ItemSection::OpaqueTypes);
- }
if !self.statics.is_empty() {
sections.insert(ItemSection::Statics);
}
@@ -478,7 +466,6 @@ fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, kind: ItemSection) {
print_entries(f, &self.functions, ItemSection::Functions);
print_entries(f, &self.type_aliases, ItemSection::TypeAliases);
print_entries(f, &self.trait_aliases, ItemSection::TraitAliases);
- print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes);
print_entries(f, &self.statics, ItemSection::Statics);
print_entries(f, &self.constants, ItemSection::Constants);
}
@@ -1090,22 +1077,26 @@ fn render_assoc_item(
clean::MethodItem(m, _) => {
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
}
- kind @ (clean::TyAssocConstItem(generics, ty) | clean::AssocConstItem(generics, ty, _)) => {
- assoc_const(
- w,
- item,
- generics,
- ty,
- match kind {
- clean::TyAssocConstItem(..) => None,
- clean::AssocConstItem(.., default) => Some(default),
- _ => unreachable!(),
- },
- link,
- if parent == ItemType::Trait { 4 } else { 0 },
- cx,
- )
- }
+ clean::TyAssocConstItem(generics, ty) => assoc_const(
+ w,
+ item,
+ generics,
+ ty,
+ None,
+ link,
+ if parent == ItemType::Trait { 4 } else { 0 },
+ cx,
+ ),
+ clean::AssocConstItem(ci) => assoc_const(
+ w,
+ item,
+ &ci.generics,
+ &ci.type_,
+ Some(&ci.kind),
+ link,
+ if parent == ItemType::Trait { 4 } else { 0 },
+ cx,
+ ),
clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type(
w,
item,
@@ -1381,21 +1372,20 @@ fn render_deref_methods(
fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
let self_type_opt = match *item.kind {
- clean::MethodItem(ref method, _) => method.decl.self_type(),
- clean::TyMethodItem(ref method) => method.decl.self_type(),
+ clean::MethodItem(ref method, _) => method.decl.receiver_type(),
+ clean::TyMethodItem(ref method) => method.decl.receiver_type(),
_ => None,
};
if let Some(self_ty) = self_type_opt {
- let (by_mut_ref, by_box, by_value) = match self_ty {
- SelfTy::SelfBorrowed(_, mutability)
- | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => {
+ let (by_mut_ref, by_box, by_value) = match *self_ty {
+ clean::Type::BorrowedRef { mutability, .. } => {
(mutability == Mutability::Mut, false, false)
}
- SelfTy::SelfExplicit(clean::Type::Path { path }) => {
+ clean::Type::Path { ref path } => {
(false, Some(path.def_id()) == tcx.lang_items().owned_box(), false)
}
- SelfTy::SelfValue => (false, false, true),
+ clean::Type::SelfTy => (false, false, true),
_ => (false, false, false),
};
@@ -1690,8 +1680,7 @@ fn doc_impl_item(
w.write_str("</h4></section>");
}
}
- kind @ (clean::TyAssocConstItem(generics, ty)
- | clean::AssocConstItem(generics, ty, _)) => {
+ clean::TyAssocConstItem(generics, ty) => {
let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@@ -1706,11 +1695,29 @@ fn doc_impl_item(
item,
generics,
ty,
- match kind {
- clean::TyAssocConstItem(..) => None,
- clean::AssocConstItem(.., default) => Some(default),
- _ => unreachable!(),
- },
+ None,
+ link.anchor(if trait_.is_some() { &source_id } else { &id }),
+ 0,
+ cx,
+ );
+ w.write_str("</h4></section>");
+ }
+ clean::AssocConstItem(ci) => {
+ let source_id = format!("{item_type}.{name}");
+ let id = cx.derive_id(&source_id);
+ write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
+ render_rightside(w, cx, item, render_mode);
+ if trait_.is_some() {
+ // Anchors are only used on trait impls.
+ write!(w, "<a href=\"#{id}\" class=\"anchor\">§</a>");
+ }
+ w.write_str("<h4 class=\"code-header\">");
+ assoc_const(
+ w,
+ item,
+ &ci.generics,
+ &ci.type_,
+ Some(&ci.kind),
link.anchor(if trait_.is_some() { &source_id } else { &id }),
0,
cx,
@@ -1773,20 +1780,23 @@ fn doc_impl_item(
let mut impl_items = Buffer::empty_from(w);
let mut default_impl_items = Buffer::empty_from(w);
+ let impl_ = i.inner_impl();
- for trait_item in &i.inner_impl().items {
- doc_impl_item(
- &mut default_impl_items,
- &mut impl_items,
- cx,
- trait_item,
- if trait_.is_some() { &i.impl_item } else { parent },
- link,
- render_mode,
- false,
- trait_,
- rendering_params,
- );
+ if !impl_.is_negative_trait_impl() {
+ for trait_item in &impl_.items {
+ doc_impl_item(
+ &mut default_impl_items,
+ &mut impl_items,
+ cx,
+ trait_item,
+ if trait_.is_some() { &i.impl_item } else { parent },
+ link,
+ render_mode,
+ false,
+ trait_,
+ rendering_params,
+ );
+ }
}
fn render_default_items(
@@ -1837,13 +1847,15 @@ fn render_default_items(
// We don't emit documentation for default items if they appear in the
// Implementations on Foreign Types or Implementors sections.
if rendering_params.show_default_items {
- if let Some(t) = trait_ {
+ if let Some(t) = trait_
+ && !impl_.is_negative_trait_impl()
+ {
render_default_items(
&mut default_impl_items,
&mut impl_items,
cx,
t,
- i.inner_impl(),
+ impl_,
&i.impl_item,
render_mode,
rendering_params,
@@ -1875,7 +1887,7 @@ fn render_default_items(
}
if let Some(ref dox) = i.impl_item.opt_doc_value() {
- if trait_.is_none() && i.inner_impl().items.is_empty() {
+ if trait_.is_none() && impl_.items.is_empty() {
w.write_str(
"<div class=\"item-info\">\
<div class=\"stab empty-impl\">This impl block contains no items.</div>\
@@ -2160,7 +2172,6 @@ pub(crate) enum ItemSection {
AssociatedConstants,
ForeignTypes,
Keywords,
- OpaqueTypes,
AttributeMacros,
DeriveMacros,
TraitAliases,
@@ -2193,7 +2204,6 @@ impl ItemSection {
AssociatedConstants,
ForeignTypes,
Keywords,
- OpaqueTypes,
AttributeMacros,
DeriveMacros,
TraitAliases,
@@ -2223,7 +2233,6 @@ fn id(self) -> &'static str {
Self::AssociatedConstants => "associated-consts",
Self::ForeignTypes => "foreign-types",
Self::Keywords => "keywords",
- Self::OpaqueTypes => "opaque-types",
Self::AttributeMacros => "attributes",
Self::DeriveMacros => "derives",
Self::TraitAliases => "trait-aliases",
@@ -2253,7 +2262,6 @@ fn name(self) -> &'static str {
Self::AssociatedConstants => "Associated Constants",
Self::ForeignTypes => "Foreign Types",
Self::Keywords => "Keywords",
- Self::OpaqueTypes => "Opaque Types",
Self::AttributeMacros => "Attribute Macros",
Self::DeriveMacros => "Derive Macros",
Self::TraitAliases => "Trait Aliases",
@@ -2284,7 +2292,6 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
ItemType::AssocConst => ItemSection::AssociatedConstants,
ItemType::ForeignType => ItemSection::ForeignTypes,
ItemType::Keyword => ItemSection::Keywords,
- ItemType::OpaqueTy => ItemSection::OpaqueTypes,
ItemType::ProcAttribute => ItemSection::AttributeMacros,
ItemType::ProcDerive => ItemSection::DeriveMacros,
ItemType::TraitAlias => ItemSection::TraitAliases,
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index cf78a1d..d8b1114 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1,3 +1,10 @@
+use std::cell::{RefCell, RefMut};
+use std::cmp::Ordering;
+use std::fmt;
+use std::rc::Rc;
+
+use itertools::Itertools;
+use rinja::Template;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
@@ -8,10 +15,6 @@
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::abi::VariantIdx;
-use std::cell::{RefCell, RefMut};
-use std::cmp::Ordering;
-use std::fmt;
-use std::rc::Rc;
use super::type_layout::document_type_layout;
use super::{
@@ -26,7 +29,7 @@
use crate::config::ModuleSorting;
use crate::formats::item_type::ItemType;
use crate::formats::Impl;
-use crate::html::escape::Escape;
+use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
use crate::html::format::{
display_fn, join_with_double_colon, print_abi_with_space, print_constness_with_space,
print_where_clause, visibility_print_with_space, Buffer, Ending, PrintWithSpace,
@@ -36,9 +39,6 @@
use crate::html::render::{document_full, document_item_info};
use crate::html::url_parts_builder::UrlPartsBuilder;
-use itertools::Itertools;
-use rinja::Template;
-
/// Generates a Rinja template struct for rendering items with common methods.
///
/// Usage:
@@ -202,7 +202,6 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
clean::ConstantItem(..) => "Constant ",
clean::ForeignTypeItem => "Foreign Type ",
clean::KeywordItem => "Keyword ",
- clean::OpaqueTyItem(..) => "Opaque Type ",
clean::TraitAliasItem(..) => "Trait Alias ",
_ => {
// We don't generate pages for any other type.
@@ -267,10 +266,9 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
clean::StaticItem(ref i) => item_static(buf, cx, item, i, None),
clean::ForeignStaticItem(ref i, safety) => item_static(buf, cx, item, i, Some(*safety)),
- clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c),
+ clean::ConstantItem(ci) => item_constant(buf, cx, item, &ci.generics, &ci.type_, &ci.kind),
clean::ForeignTypeItem => item_foreign_type(buf, cx, item),
clean::KeywordItem => item_keyword(buf, cx, item),
- clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e),
clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta),
_ => {
// We don't generate pages for any other type.
@@ -423,7 +421,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
"<div class=\"item-name\"><code>{}extern crate {} as {};",
visibility_print_with_space(myitem, cx),
anchor(myitem.item_id.expect_def_id(), src, cx),
- myitem.name.unwrap(),
+ EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
),
None => write!(
w,
@@ -520,7 +518,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
{stab_tags}\
</div>\
{docs_before}{docs}{docs_after}",
- name = myitem.name.unwrap(),
+ name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
visibility_and_hidden = visibility_and_hidden,
stab_tags = extra_info_tags(myitem, item, tcx),
class = myitem.type_(),
@@ -558,7 +556,7 @@ fn tag_html<'a>(
display_fn(move |f| {
write!(
f,
- r#"<span class="stab {class}" title="{title}">{contents}</span>"#,
+ r#"<wbr><span class="stab {class}" title="{title}">{contents}</span>"#,
title = Escape(title),
)
})
@@ -1197,35 +1195,6 @@ fn item_trait_alias(
.unwrap();
}
-fn item_opaque_ty(
- w: &mut impl fmt::Write,
- cx: &mut Context<'_>,
- it: &clean::Item,
- t: &clean::OpaqueTy,
-) {
- wrap_item(w, |w| {
- write!(
- w,
- "{attrs}type {name}{generics}{where_clause} = impl {bounds};",
- attrs = render_attributes_in_pre(it, "", cx),
- name = it.name.unwrap(),
- generics = t.generics.print(cx),
- where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
- bounds = bounds(&t.bounds, false, cx),
- )
- .unwrap();
- });
-
- write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
-
- // Render any items associated directly to this alias, as otherwise they
- // won't be visible anywhere in the docs. It would be nice to also show
- // associated items from the aliased type (see discussion in #32077), but
- // we need #14072 to make sense of the generics.
- write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
- .unwrap();
-}
-
fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
wrap_item(w, |w| {
write!(
@@ -1841,7 +1810,7 @@ fn item_constant(
it: &clean::Item,
generics: &clean::Generics,
ty: &clean::Type,
- c: &clean::Constant,
+ c: &clean::ConstantKind,
) {
wrap_item(w, |w| {
let tcx = cx.tcx();
@@ -1911,7 +1880,7 @@ fn item_fields(
w: &mut Buffer,
cx: &mut Context<'_>,
it: &clean::Item,
- fields: &Vec<clean::Item>,
+ fields: &[clean::Item],
ctor_kind: Option<CtorKind>,
) {
let mut fields = fields
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 66d3f0f..8a2f31f 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -3,6 +3,7 @@
use std::collections::hash_map::Entry;
use std::collections::{BTreeMap, VecDeque};
+use encode::{bitmap_to_string, write_vlqhex_to_string};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::DefId;
@@ -19,8 +20,6 @@
use crate::html::markdown::short_markdown_summary;
use crate::html::render::{self, IndexItem, IndexItemFunctionType, RenderType, RenderTypeId};
-use encode::{bitmap_to_string, write_vlqhex_to_string};
-
/// The serialized search description sharded version
///
/// The `index` is a JSON-encoded list of names and other information.
@@ -798,7 +797,11 @@ fn get_index_type_id(
}
}
// Not supported yet
- clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None,
+ clean::Type::Pat(..)
+ | clean::Generic(_)
+ | clean::SelfTy
+ | clean::ImplTrait(_)
+ | clean::Infer => None,
}
}
@@ -851,15 +854,70 @@ fn simplify_fn_type<'tcx, 'a>(
// If this argument is a type parameter and not a trait bound or a type, we need to look
// for its bounds.
- if let Type::Generic(arg_s) = *arg {
- // First we check if the bounds are in a `where` predicate...
- let mut type_bounds = Vec::new();
- for where_pred in generics.where_predicates.iter().filter(|g| match g {
- WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s,
- _ => false,
- }) {
- let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
- for bound in bounds.iter() {
+ match *arg {
+ Type::Generic(arg_s) => {
+ // First we check if the bounds are in a `where` predicate...
+ let mut type_bounds = Vec::new();
+ for where_pred in generics.where_predicates.iter().filter(|g| match g {
+ WherePredicate::BoundPredicate { ty, .. } => *ty == *arg,
+ _ => false,
+ }) {
+ let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
+ for bound in bounds.iter() {
+ if let Some(path) = bound.get_trait_path() {
+ let ty = Type::Path { path };
+ simplify_fn_type(
+ self_,
+ generics,
+ &ty,
+ tcx,
+ recurse + 1,
+ &mut type_bounds,
+ rgen,
+ is_return,
+ cache,
+ );
+ }
+ }
+ }
+ // Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
+ if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
+ for bound in bound.get_bounds().unwrap_or(&[]) {
+ if let Some(path) = bound.get_trait_path() {
+ let ty = Type::Path { path };
+ simplify_fn_type(
+ self_,
+ generics,
+ &ty,
+ tcx,
+ recurse + 1,
+ &mut type_bounds,
+ rgen,
+ is_return,
+ cache,
+ );
+ }
+ }
+ }
+ if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) {
+ res.push(RenderType {
+ id: Some(RenderTypeId::Index(*idx)),
+ generics: None,
+ bindings: None,
+ });
+ } else {
+ let idx = -isize::try_from(rgen.len() + 1).unwrap();
+ rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds));
+ res.push(RenderType {
+ id: Some(RenderTypeId::Index(idx)),
+ generics: None,
+ bindings: None,
+ });
+ }
+ }
+ Type::ImplTrait(ref bounds) => {
+ let mut type_bounds = Vec::new();
+ for bound in bounds {
if let Some(path) = bound.get_trait_path() {
let ty = Type::Path { path };
simplify_fn_type(
@@ -875,103 +933,22 @@ fn simplify_fn_type<'tcx, 'a>(
);
}
}
- }
- // Otherwise we check if the trait bounds are "inlined" like `T: Option<u32>`...
- if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) {
- for bound in bound.get_bounds().unwrap_or(&[]) {
- if let Some(path) = bound.get_trait_path() {
- let ty = Type::Path { path };
- simplify_fn_type(
- self_,
- generics,
- &ty,
- tcx,
- recurse + 1,
- &mut type_bounds,
- rgen,
- is_return,
- cache,
- );
- }
+ if is_return && !type_bounds.is_empty() {
+ // In return position, `impl Trait` is a unique thing.
+ res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None });
+ } else {
+ // In parameter position, `impl Trait` is the same as an unnamed generic parameter.
+ let idx = -isize::try_from(rgen.len() + 1).unwrap();
+ rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds));
+ res.push(RenderType {
+ id: Some(RenderTypeId::Index(idx)),
+ generics: None,
+ bindings: None,
+ });
}
}
- if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) {
- res.push(RenderType {
- id: Some(RenderTypeId::Index(*idx)),
- generics: None,
- bindings: None,
- });
- } else {
- let idx = -isize::try_from(rgen.len() + 1).unwrap();
- rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds));
- res.push(RenderType {
- id: Some(RenderTypeId::Index(idx)),
- generics: None,
- bindings: None,
- });
- }
- } else if let Type::ImplTrait(ref bounds) = *arg {
- let mut type_bounds = Vec::new();
- for bound in bounds {
- if let Some(path) = bound.get_trait_path() {
- let ty = Type::Path { path };
- simplify_fn_type(
- self_,
- generics,
- &ty,
- tcx,
- recurse + 1,
- &mut type_bounds,
- rgen,
- is_return,
- cache,
- );
- }
- }
- if is_return && !type_bounds.is_empty() {
- // In parameter position, `impl Trait` is a unique thing.
- res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None });
- } else {
- // In parameter position, `impl Trait` is the same as an unnamed generic parameter.
- let idx = -isize::try_from(rgen.len() + 1).unwrap();
- rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds));
- res.push(RenderType {
- id: Some(RenderTypeId::Index(idx)),
- generics: None,
- bindings: None,
- });
- }
- } else if let Type::Slice(ref ty) = *arg {
- let mut ty_generics = Vec::new();
- simplify_fn_type(
- self_,
- generics,
- &ty,
- tcx,
- recurse + 1,
- &mut ty_generics,
- rgen,
- is_return,
- cache,
- );
- res.push(get_index_type(arg, ty_generics, rgen));
- } else if let Type::Array(ref ty, _) = *arg {
- let mut ty_generics = Vec::new();
- simplify_fn_type(
- self_,
- generics,
- &ty,
- tcx,
- recurse + 1,
- &mut ty_generics,
- rgen,
- is_return,
- cache,
- );
- res.push(get_index_type(arg, ty_generics, rgen));
- } else if let Type::Tuple(ref tys) = *arg {
- let mut ty_generics = Vec::new();
- for ty in tys {
+ Type::Slice(ref ty) => {
+ let mut ty_generics = Vec::new();
simplify_fn_type(
self_,
generics,
@@ -983,15 +960,14 @@ fn simplify_fn_type<'tcx, 'a>(
is_return,
cache,
);
+ res.push(get_index_type(arg, ty_generics, rgen));
}
- res.push(get_index_type(arg, ty_generics, rgen));
- } else if let Type::BareFunction(ref bf) = *arg {
- let mut ty_generics = Vec::new();
- for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) {
+ Type::Array(ref ty, _) => {
+ let mut ty_generics = Vec::new();
simplify_fn_type(
self_,
generics,
- ty,
+ &ty,
tcx,
recurse + 1,
&mut ty_generics,
@@ -999,62 +975,11 @@ fn simplify_fn_type<'tcx, 'a>(
is_return,
cache,
);
+ res.push(get_index_type(arg, ty_generics, rgen));
}
- // The search index, for simplicity's sake, represents fn pointers and closures
- // the same way: as a tuple for the parameters, and an associated type for the
- // return type.
- let mut ty_output = Vec::new();
- simplify_fn_type(
- self_,
- generics,
- &bf.decl.output,
- tcx,
- recurse + 1,
- &mut ty_output,
- rgen,
- is_return,
- cache,
- );
- let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)];
- res.push(RenderType {
- id: get_index_type_id(&arg, rgen),
- bindings: Some(ty_bindings),
- generics: Some(ty_generics),
- });
- } else if let Type::BorrowedRef { lifetime: _, mutability, ref type_ } = *arg {
- let mut ty_generics = Vec::new();
- if mutability.is_mut() {
- ty_generics.push(RenderType {
- id: Some(RenderTypeId::Mut),
- generics: None,
- bindings: None,
- });
- }
- simplify_fn_type(
- self_,
- generics,
- &type_,
- tcx,
- recurse + 1,
- &mut ty_generics,
- rgen,
- is_return,
- cache,
- );
- res.push(get_index_type(arg, ty_generics, rgen));
- } else {
- // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
- // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
- //
- // So in here, we can add it directly and look for its own type parameters (so for `Option`,
- // we will look for them but not for `T`).
- let mut ty_generics = Vec::new();
- let mut ty_constraints = Vec::new();
- if let Some(arg_generics) = arg.generic_args() {
- for ty in arg_generics.into_iter().filter_map(|param| match param {
- clean::GenericArg::Type(ty) => Some(ty),
- _ => None,
- }) {
+ Type::Tuple(ref tys) => {
+ let mut ty_generics = Vec::new();
+ for ty in tys {
simplify_fn_type(
self_,
generics,
@@ -1067,94 +992,181 @@ fn simplify_fn_type<'tcx, 'a>(
cache,
);
}
- for constraint in arg_generics.constraints() {
- simplify_fn_constraint(
+ res.push(get_index_type(arg, ty_generics, rgen));
+ }
+ Type::BareFunction(ref bf) => {
+ let mut ty_generics = Vec::new();
+ for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) {
+ simplify_fn_type(
self_,
generics,
- &constraint,
+ ty,
tcx,
recurse + 1,
- &mut ty_constraints,
+ &mut ty_generics,
rgen,
is_return,
cache,
);
}
+ // The search index, for simplicity's sake, represents fn pointers and closures
+ // the same way: as a tuple for the parameters, and an associated type for the
+ // return type.
+ let mut ty_output = Vec::new();
+ simplify_fn_type(
+ self_,
+ generics,
+ &bf.decl.output,
+ tcx,
+ recurse + 1,
+ &mut ty_output,
+ rgen,
+ is_return,
+ cache,
+ );
+ let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)];
+ res.push(RenderType {
+ id: get_index_type_id(&arg, rgen),
+ bindings: Some(ty_bindings),
+ generics: Some(ty_generics),
+ });
}
- // Every trait associated type on self gets assigned to a type parameter index
- // this same one is used later for any appearances of these types
- //
- // for example, Iterator::next is:
- //
- // trait Iterator {
- // fn next(&mut self) -> Option<Self::Item>
- // }
- //
- // Self is technically just Iterator, but we want to pretend it's more like this:
- //
- // fn next<T>(self: Iterator<Item=T>) -> Option<T>
- if is_self
- && let Type::Path { path } = arg
- && let def_id = path.def_id()
- && let Some(trait_) = cache.traits.get(&def_id)
- && trait_.items.iter().any(|at| at.is_ty_associated_type())
- {
- for assoc_ty in &trait_.items {
- if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind
- && let Some(name) = assoc_ty.name
- {
- let idx = -isize::try_from(rgen.len() + 1).unwrap();
- let (idx, stored_bounds) = rgen
- .entry(SimplifiedParam::AssociatedType(def_id, name))
- .or_insert_with(|| (idx, Vec::new()));
- let idx = *idx;
- if stored_bounds.is_empty() {
- // Can't just pass stored_bounds to simplify_fn_type,
- // because it also accepts rgen as a parameter.
- // Instead, have it fill in this local, then copy it into the map afterward.
- let mut type_bounds = Vec::new();
- for bound in bounds {
- if let Some(path) = bound.get_trait_path() {
- let ty = Type::Path { path };
- simplify_fn_type(
- self_,
- generics,
- &ty,
- tcx,
- recurse + 1,
- &mut type_bounds,
- rgen,
- is_return,
- cache,
- );
- }
- }
- let stored_bounds = &mut rgen
- .get_mut(&SimplifiedParam::AssociatedType(def_id, name))
- .unwrap()
- .1;
- if stored_bounds.is_empty() {
- *stored_bounds = type_bounds;
- }
- }
- ty_constraints.push((
- RenderTypeId::AssociatedType(name),
- vec![RenderType {
- id: Some(RenderTypeId::Index(idx)),
- generics: None,
- bindings: None,
- }],
- ))
+ Type::BorrowedRef { lifetime: _, mutability, ref type_ } => {
+ let mut ty_generics = Vec::new();
+ if mutability.is_mut() {
+ ty_generics.push(RenderType {
+ id: Some(RenderTypeId::Mut),
+ generics: None,
+ bindings: None,
+ });
+ }
+ simplify_fn_type(
+ self_,
+ generics,
+ &type_,
+ tcx,
+ recurse + 1,
+ &mut ty_generics,
+ rgen,
+ is_return,
+ cache,
+ );
+ res.push(get_index_type(arg, ty_generics, rgen));
+ }
+ _ => {
+ // This is not a type parameter. So for example if we have `T, U: Option<T>`, and we're
+ // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't.
+ //
+ // So in here, we can add it directly and look for its own type parameters (so for `Option`,
+ // we will look for them but not for `T`).
+ let mut ty_generics = Vec::new();
+ let mut ty_constraints = Vec::new();
+ if let Some(arg_generics) = arg.generic_args() {
+ for ty in arg_generics.into_iter().filter_map(|param| match param {
+ clean::GenericArg::Type(ty) => Some(ty),
+ _ => None,
+ }) {
+ simplify_fn_type(
+ self_,
+ generics,
+ &ty,
+ tcx,
+ recurse + 1,
+ &mut ty_generics,
+ rgen,
+ is_return,
+ cache,
+ );
+ }
+ for constraint in arg_generics.constraints() {
+ simplify_fn_constraint(
+ self_,
+ generics,
+ &constraint,
+ tcx,
+ recurse + 1,
+ &mut ty_constraints,
+ rgen,
+ is_return,
+ cache,
+ );
}
}
- }
- let id = get_index_type_id(&arg, rgen);
- if id.is_some() || !ty_generics.is_empty() {
- res.push(RenderType {
- id,
- bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
- generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
- });
+ // Every trait associated type on self gets assigned to a type parameter index
+ // this same one is used later for any appearances of these types
+ //
+ // for example, Iterator::next is:
+ //
+ // trait Iterator {
+ // fn next(&mut self) -> Option<Self::Item>
+ // }
+ //
+ // Self is technically just Iterator, but we want to pretend it's more like this:
+ //
+ // fn next<T>(self: Iterator<Item=T>) -> Option<T>
+ if is_self
+ && let Type::Path { path } = arg
+ && let def_id = path.def_id()
+ && let Some(trait_) = cache.traits.get(&def_id)
+ && trait_.items.iter().any(|at| at.is_ty_associated_type())
+ {
+ for assoc_ty in &trait_.items {
+ if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind
+ && let Some(name) = assoc_ty.name
+ {
+ let idx = -isize::try_from(rgen.len() + 1).unwrap();
+ let (idx, stored_bounds) = rgen
+ .entry(SimplifiedParam::AssociatedType(def_id, name))
+ .or_insert_with(|| (idx, Vec::new()));
+ let idx = *idx;
+ if stored_bounds.is_empty() {
+ // Can't just pass stored_bounds to simplify_fn_type,
+ // because it also accepts rgen as a parameter.
+ // Instead, have it fill in this local, then copy it into the map afterward.
+ let mut type_bounds = Vec::new();
+ for bound in bounds {
+ if let Some(path) = bound.get_trait_path() {
+ let ty = Type::Path { path };
+ simplify_fn_type(
+ self_,
+ generics,
+ &ty,
+ tcx,
+ recurse + 1,
+ &mut type_bounds,
+ rgen,
+ is_return,
+ cache,
+ );
+ }
+ }
+ let stored_bounds = &mut rgen
+ .get_mut(&SimplifiedParam::AssociatedType(def_id, name))
+ .unwrap()
+ .1;
+ if stored_bounds.is_empty() {
+ *stored_bounds = type_bounds;
+ }
+ }
+ ty_constraints.push((
+ RenderTypeId::AssociatedType(name),
+ vec![RenderType {
+ id: Some(RenderTypeId::Index(idx)),
+ generics: None,
+ bindings: None,
+ }],
+ ))
+ }
+ }
+ }
+ let id = get_index_type_id(&arg, rgen);
+ if id.is_some() || !ty_generics.is_empty() {
+ res.push(RenderType {
+ id,
+ bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) },
+ generics: if ty_generics.is_empty() { None } else { Some(ty_generics) },
+ });
+ }
}
}
}
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index e5bc2ac..101cc83 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -1,17 +1,18 @@
-use std::{borrow::Cow, rc::Rc};
+use std::borrow::Cow;
+use std::rc::Rc;
use rinja::Template;
use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::{def::CtorKind, def_id::DefIdSet};
+use rustc_hir::def::CtorKind;
+use rustc_hir::def_id::DefIdSet;
use rustc_middle::ty::{self, TyCtxt};
-use crate::{
- clean,
- formats::{item_type::ItemType, Impl},
- html::{format::Buffer, markdown::IdMap},
-};
-
use super::{item_ty_to_section, Context, ItemSection};
+use crate::clean;
+use crate::formats::item_type::ItemType;
+use crate::formats::Impl;
+use crate::html::format::Buffer;
+use crate::html::markdown::IdMap;
#[derive(Template)]
#[template(path = "sidebar.html")]
@@ -76,6 +77,22 @@ pub fn empty() -> Link<'static> {
}
}
+pub(crate) mod filters {
+ use std::fmt::Display;
+
+ use rinja::filters::Safe;
+
+ use crate::html::escape::EscapeBodyTextWithWbr;
+ use crate::html::render::display_fn;
+ pub(crate) fn wrapped<T>(v: T) -> rinja::Result<Safe<impl Display>>
+ where
+ T: Display,
+ {
+ let string = v.to_string();
+ Ok(Safe(display_fn(move |f| EscapeBodyTextWithWbr(&string).fmt(f))))
+ }
+}
+
pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
let blocks: Vec<LinkBlock<'_>> = match *it.kind {
clean::StructItem(ref s) => sidebar_struct(cx, it, s),
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 0535246..5b53277 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -1,5 +1,4 @@
-use crate::clean::{self, rustc_span, PrimitiveType};
-use crate::html::sources;
+use std::path::{Path, PathBuf};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::{DefKind, Res};
@@ -11,7 +10,8 @@
use rustc_span::hygiene::MacroKind;
use rustc_span::{BytePos, ExpnKind, Span};
-use std::path::{Path, PathBuf};
+use crate::clean::{self, rustc_span, PrimitiveType};
+use crate::html::sources;
/// This enum allows us to store two different kinds of information:
///
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index 35a38d5..cd4e597 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -1,14 +1,14 @@
-use rinja::Template;
+use std::fmt;
+use rinja::Template;
use rustc_data_structures::captures::Captures;
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
-use rustc_middle::ty::{self, layout::LayoutError};
+use rustc_middle::ty::layout::LayoutError;
+use rustc_middle::ty::{self};
use rustc_span::symbol::Symbol;
use rustc_target::abi::{Primitive, TagEncoding, Variants};
-use std::fmt;
-
use crate::html::format::display_fn;
use crate::html::render::Context;
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 7b4d1fa..22f115f 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -1,12 +1,9 @@
-use crate::clean;
-use crate::clean::utils::has_doc_flag;
-use crate::docfs::PathError;
-use crate::error::Error;
-use crate::html::format;
-use crate::html::highlight;
-use crate::html::layout;
-use crate::html::render::Context;
-use crate::visit::DocVisitor;
+use std::cell::RefCell;
+use std::ffi::OsStr;
+use std::ops::RangeInclusive;
+use std::path::{Component, Path, PathBuf};
+use std::rc::Rc;
+use std::{fmt, fs};
use rinja::Template;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -15,13 +12,13 @@
use rustc_session::Session;
use rustc_span::{sym, FileName};
-use std::cell::RefCell;
-use std::ffi::OsStr;
-use std::fmt;
-use std::fs;
-use std::ops::RangeInclusive;
-use std::path::{Component, Path, PathBuf};
-use std::rc::Rc;
+use crate::clean;
+use crate::clean::utils::has_doc_flag;
+use crate::docfs::PathError;
+use crate::error::Error;
+use crate::html::render::Context;
+use crate::html::{format, highlight, layout};
+use crate::visit::DocVisitor;
pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> {
info!("emitting source files");
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 6e10cf2..86e8eda 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -104,10 +104,6 @@
--code-highlight-doc-comment-color: #4d4d4c;
--src-line-numbers-span-color: #c67e2d;
--src-line-number-highlighted-background-color: #fdffd3;
- --test-arrow-color: #f5f5f5;
- --test-arrow-background-color: rgba(78, 139, 202, 0.2);
- --test-arrow-hover-color: #f5f5f5;
- --test-arrow-hover-background-color: rgb(78, 139, 202);
--target-background-color: #fdffd3;
--target-border-color: #ad7c37;
--kbd-color: #000;
@@ -210,10 +206,6 @@
--code-highlight-doc-comment-color: #8ca375;
--src-line-numbers-span-color: #3b91e2;
--src-line-number-highlighted-background-color: #0a042f;
- --test-arrow-color: #dedede;
- --test-arrow-background-color: rgba(78, 139, 202, 0.2);
- --test-arrow-hover-color: #dedede;
- --test-arrow-hover-background-color: #4e8bca;
--target-background-color: #494a3d;
--target-border-color: #bb7410;
--kbd-color: #000;
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 41c506f..eb5a5d9 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -16,6 +16,24 @@
--src-sidebar-width: 300px;
--desktop-sidebar-z-index: 100;
--sidebar-elems-left-padding: 24px;
+ /* clipboard <https://github.com/rust-lang/crates.io/commits/main/public/assets/copy.svg> */
+ --clipboard-image: url('data:image/svg+xml,<svg width="19" height="18" viewBox="0 0 24 25" \
+xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\
+<path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 \
+0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 \
+7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 \
+2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/>\
+<path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/>\
+</svg>');
+ --copy-path-height: 34px;
+ --copy-path-width: 33px;
+ /* Checkmark <https://www.svgrepo.com/svg/335033/checkmark> */
+ --checkmark-image: url('data:image/svg+xml,<svg viewBox="-1 -1 23 23" \
+xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
+<g><path d="M9 19.414l-6.707-6.707 1.414-1.414L9 16.586 20.293 5.293l1.414 1.414"></path>\
+</g></svg>');
+ --button-left-margin: 4px;
+ --button-border-radius: 2px;
}
/* See FiraSans-LICENSE.txt for the Fira Sans license. */
@@ -335,7 +353,7 @@
margin-bottom: .6em;
}
-code, pre, a.test-arrow, .code-header {
+code, pre, .code-header {
font-family: "Source Code Pro", monospace;
}
.docblock code, .docblock-short code {
@@ -568,12 +586,15 @@
}
.sidebar h2 {
+ text-wrap: balance;
overflow-wrap: anywhere;
padding: 0;
margin: 0.7rem 0;
}
.sidebar h3 {
+ text-wrap: balance;
+ overflow-wrap: anywhere;
font-size: 1.125rem; /* 18px */
padding: 0;
margin: 0;
@@ -723,6 +744,11 @@
position: relative;
margin-bottom: 10px;
}
+
+.rustdoc .example-wrap > pre {
+ border-radius: 6px;
+}
+
/* For the last child of a div, the margin will be taken care of
by the margin-top of the next item. */
.rustdoc .example-wrap:last-child {
@@ -904,7 +930,7 @@
left: -17px;
/* We add this padding so that when the cursor moves from the heading's text to the anchor,
the anchor doesn't disappear. */
- padding-right: 5px;
+ padding-right: 10px;
/* And this padding is used to make the anchor larger and easier to click on. */
padding-left: 3px;
}
@@ -920,8 +946,8 @@
.main-heading a:hover,
.example-wrap .rust a:hover,
.all-items a:hover,
-.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),
-.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover,
+.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),
+.docblock-short a:not(.scrape-help):not(.tooltip):hover,
.item-info a {
text-decoration: underline;
}
@@ -1427,25 +1453,68 @@
top: 20px;
}
-a.test-arrow {
+.example-wrap > a.test-arrow, .example-wrap .button-holder {
visibility: hidden;
position: absolute;
- padding: 5px 10px 5px 10px;
- border-radius: 5px;
- font-size: 1.375rem;
- top: 5px;
- right: 5px;
+ top: 4px;
+ right: 4px;
z-index: 1;
- color: var(--test-arrow-color);
- background-color: var(--test-arrow-background-color);
}
-a.test-arrow:hover {
- color: var(--test-arrow-hover-color);
- background-color: var(--test-arrow-hover-background-color);
+a.test-arrow {
+ height: var(--copy-path-height);
+ padding: 6px 4px 0 11px;
}
-.example-wrap:hover .test-arrow {
+a.test-arrow::before {
+ content: url('data:image/svg+xml,<svg viewBox="0 0 20 20" width="18" height="20" \
+ xmlns="http://www.w3.org/2000/svg"><path d="M0 0l18 10-18 10z"/></svg>');
+}
+.example-wrap .button-holder {
+ display: flex;
+}
+
+/*
+On iPad, the ":hover" state sticks around, making things work not greatly. Do work around
+it, we move it into this media query. More information can be found at:
+https://css-tricks.com/solving-sticky-hover-states-with-media-hover-hover/
+
+However, using `@media (hover: hover)` makes this rule never to be applied in GUI tests, so
+instead, we check that it's not a "finger" cursor.
+*/
+@media not (pointer: coarse) {
+ .example-wrap:hover > a.test-arrow, .example-wrap:hover > .button-holder {
+ visibility: visible;
+ }
+}
+.example-wrap .button-holder.keep-visible {
visibility: visible;
}
+.example-wrap .button-holder .copy-button, .example-wrap .test-arrow {
+ background: var(--main-background-color);
+ cursor: pointer;
+ border-radius: var(--button-border-radius);
+ height: var(--copy-path-height);
+ width: var(--copy-path-width);
+}
+.example-wrap .button-holder .copy-button {
+ margin-left: var(--button-left-margin);
+ padding: 2px 0 0 4px;
+ border: 0;
+}
+.example-wrap .button-holder .copy-button::before,
+.example-wrap .test-arrow::before {
+ filter: var(--copy-path-img-filter);
+}
+.example-wrap .button-holder .copy-button::before {
+ content: var(--clipboard-image);
+}
+.example-wrap .button-holder .copy-button:hover::before,
+.example-wrap .test-arrow:hover::before {
+ filter: var(--copy-path-img-hover-filter);
+}
+.example-wrap .button-holder .copy-button.clicked::before {
+ content: var(--checkmark-image);
+ padding-right: 5px;
+}
.code-attribute {
font-weight: 300;
@@ -1610,7 +1679,7 @@
}
#settings-menu, #help-button {
- margin-left: 4px;
+ margin-left: var(--button-left-margin);
display: flex;
}
#sidebar-button {
@@ -1641,7 +1710,7 @@
justify-content: center;
background-color: var(--button-background-color);
border: 1px solid var(--border-color);
- border-radius: 2px;
+ border-radius: var(--button-border-radius);
color: var(--settings-button-color);
/* Rare exception to specifying font sizes in rem. Since this is acting
as an icon, it's okay to specify their sizes in pixels. */
@@ -1693,8 +1762,8 @@
#copy-path {
color: var(--copy-path-button-color);
background: var(--main-background-color);
- height: 34px;
- width: 33px;
+ height: var(--copy-path-height);
+ width: var(--copy-path-width);
margin-left: 10px;
padding: 0;
padding-left: 2px;
@@ -1703,27 +1772,13 @@
}
#copy-path::before {
filter: var(--copy-path-img-filter);
- /* clipboard <https://github.com/rust-lang/crates.io/commits/main/public/assets/copy.svg> */
- content: url('data:image/svg+xml,<svg width="19" height="18" viewBox="0 0 24 25" \
-xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\
-<path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 \
-0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 \
-7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 \
-2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/>\
-<path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/>\
-</svg>');
- width: 19px;
- height: 18px;
+ content: var(--clipboard-image);
}
#copy-path:hover::before {
filter: var(--copy-path-img-hover-filter);
}
#copy-path.clicked::before {
- /* Checkmark <https://www.svgrepo.com/svg/335033/checkmark> */
- content: url('data:image/svg+xml,<svg viewBox="-1 -1 23 23" xmlns="http://www.w3.org/2000/svg" \
- fill="black" height="18px">\
- <g><path d="M9 19.414l-6.707-6.707 1.414-1.414L9 16.586 20.293 5.293l1.414 1.414"></path>\
- </g></svg>');
+ content: var(--checkmark-image);
}
@keyframes rotating {
@@ -2183,7 +2238,7 @@
width: 33%;
}
.item-table > li > div {
- word-break: break-all;
+ overflow-wrap: anywhere;
}
}
@@ -2497,10 +2552,6 @@
--code-highlight-doc-comment-color: #4d4d4c;
--src-line-numbers-span-color: #c67e2d;
--src-line-number-highlighted-background-color: #fdffd3;
- --test-arrow-color: #f5f5f5;
- --test-arrow-background-color: rgba(78, 139, 202, 0.2);
- --test-arrow-hover-color: #f5f5f5;
- --test-arrow-hover-background-color: rgb(78, 139, 202);
--target-background-color: #fdffd3;
--target-border-color: #ad7c37;
--kbd-color: #000;
@@ -2603,10 +2654,6 @@
--code-highlight-doc-comment-color: #8ca375;
--src-line-numbers-span-color: #3b91e2;
--src-line-number-highlighted-background-color: #0a042f;
- --test-arrow-color: #dedede;
- --test-arrow-background-color: rgba(78, 139, 202, 0.2);
- --test-arrow-hover-color: #dedede;
- --test-arrow-hover-background-color: #4e8bca;
--target-background-color: #494a3d;
--target-border-color: #bb7410;
--kbd-color: #000;
@@ -2716,10 +2763,6 @@
--code-highlight-doc-comment-color: #a1ac88;
--src-line-numbers-span-color: #5c6773;
--src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06);
- --test-arrow-color: #788797;
- --test-arrow-background-color: rgba(57, 175, 215, 0.09);
- --test-arrow-hover-color: #c5c5c5;
- --test-arrow-hover-background-color: rgba(57, 175, 215, 0.368);
--target-background-color: rgba(255, 236, 164, 0.06);
--target-border-color: rgba(255, 180, 76, 0.85);
--kbd-color: #c5c5c5;
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 9506bc9..75f2a14 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -390,13 +390,18 @@
if (splitAt !== -1) {
const implId = savedHash.slice(0, splitAt);
const assocId = savedHash.slice(splitAt + 1);
- const implElem = document.getElementById(implId);
- if (implElem && implElem.parentElement.tagName === "SUMMARY" &&
- implElem.parentElement.parentElement.tagName === "DETAILS") {
- onEachLazy(implElem.parentElement.parentElement.querySelectorAll(
+ const implElems = document.querySelectorAll(
+ `details > summary > section[id^="${implId}"]`,
+ );
+ onEachLazy(implElems, implElem => {
+ const numbered = /^(.+?)-([0-9]+)$/.exec(implElem.id);
+ if (implElem.id !== implId && (!numbered || numbered[1] !== implId)) {
+ return false;
+ }
+ return onEachLazy(implElem.parentElement.parentElement.querySelectorAll(
`[id^="${assocId}"]`),
item => {
- const numbered = /([^-]+)-([0-9]+)/.exec(item.id);
+ const numbered = /^(.+?)-([0-9]+)$/.exec(item.id);
if (item.id === assocId || (numbered && numbered[1] === assocId)) {
openParentDetails(item);
item.scrollIntoView();
@@ -404,10 +409,11 @@
setTimeout(() => {
window.location.replace("#" + item.id);
}, 0);
+ return true;
}
},
);
- }
+ });
}
}
}
@@ -568,7 +574,6 @@
//block("associatedconstant", "associated-consts", "Associated Constants");
block("foreigntype", "foreign-types", "Foreign Types");
block("keyword", "keywords", "Keywords");
- block("opaque", "opaque-types", "Opaque Types");
block("attr", "attributes", "Attribute Macros");
block("derive", "derives", "Derive Macros");
block("traitalias", "trait-aliases", "Trait Aliases");
@@ -1115,8 +1120,7 @@
wrapper.style.left = 0;
wrapper.style.right = "auto";
wrapper.style.visibility = "hidden";
- const body = document.getElementsByTagName("body")[0];
- body.appendChild(wrapper);
+ document.body.appendChild(wrapper);
const wrapperPos = wrapper.getBoundingClientRect();
// offset so that the arrow points at the center of the "(i)"
const finalPos = pos.left + window.scrollX - wrapperPos.width + 24;
@@ -1235,8 +1239,7 @@
}
window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false;
}
- const body = document.getElementsByTagName("body")[0];
- body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
+ document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);
window.CURRENT_TOOLTIP_ELEMENT = null;
}
@@ -1771,9 +1774,37 @@
}());
// This section handles the copy button that appears next to the path breadcrumbs
+// and the copy buttons on the code examples.
(function() {
- let reset_button_timeout = null;
+ // Common functions to copy buttons.
+ function copyContentToClipboard(content) {
+ const el = document.createElement("textarea");
+ el.value = content;
+ el.setAttribute("readonly", "");
+ // To not make it appear on the screen.
+ el.style.position = "absolute";
+ el.style.left = "-9999px";
+ document.body.appendChild(el);
+ el.select();
+ document.execCommand("copy");
+ document.body.removeChild(el);
+ }
+
+ function copyButtonAnimation(button) {
+ button.classList.add("clicked");
+
+ if (button.reset_button_timeout !== undefined) {
+ window.clearTimeout(button.reset_button_timeout);
+ }
+
+ button.reset_button_timeout = window.setTimeout(() => {
+ button.reset_button_timeout = undefined;
+ button.classList.remove("clicked");
+ }, 1000);
+ }
+
+ // Copy button that appears next to the path breadcrumbs.
const but = document.getElementById("copy-path");
if (!but) {
return;
@@ -1788,29 +1819,74 @@
}
});
- const el = document.createElement("textarea");
- el.value = path.join("::");
- el.setAttribute("readonly", "");
- // To not make it appear on the screen.
- el.style.position = "absolute";
- el.style.left = "-9999px";
-
- document.body.appendChild(el);
- el.select();
- document.execCommand("copy");
- document.body.removeChild(el);
-
- but.classList.add("clicked");
-
- if (reset_button_timeout !== null) {
- window.clearTimeout(reset_button_timeout);
- }
-
- function reset_button() {
- reset_button_timeout = null;
- but.classList.remove("clicked");
- }
-
- reset_button_timeout = window.setTimeout(reset_button, 1000);
+ copyContentToClipboard(path.join("::"));
+ copyButtonAnimation(but);
};
+
+ // Copy buttons on code examples.
+ function copyCode(codeElem) {
+ if (!codeElem) {
+ // Should never happen, but the world is a dark and dangerous place.
+ return;
+ }
+ copyContentToClipboard(codeElem.textContent);
+ }
+
+ function getExampleWrap(event) {
+ let elem = event.target;
+ while (!hasClass(elem, "example-wrap")) {
+ if (elem === document.body ||
+ elem.tagName === "A" ||
+ elem.tagName === "BUTTON" ||
+ hasClass(elem, "docblock")
+ ) {
+ return null;
+ }
+ elem = elem.parentElement;
+ }
+ return elem;
+ }
+
+ function addCopyButton(event) {
+ const elem = getExampleWrap(event);
+ if (elem === null) {
+ return;
+ }
+ // Since the button will be added, no need to keep this listener around.
+ elem.removeEventListener("mouseover", addCopyButton);
+
+ const parent = document.createElement("div");
+ parent.className = "button-holder";
+ const runButton = elem.querySelector(".test-arrow");
+ if (runButton !== null) {
+ // If there is a run button, we move it into the same div.
+ parent.appendChild(runButton);
+ }
+ elem.appendChild(parent);
+ const copyButton = document.createElement("button");
+ copyButton.className = "copy-button";
+ copyButton.title = "Copy code to clipboard";
+ copyButton.addEventListener("click", () => {
+ copyCode(elem.querySelector("pre > code"));
+ copyButtonAnimation(copyButton);
+ });
+ parent.appendChild(copyButton);
+ }
+
+ function showHideCodeExampleButtons(event) {
+ const elem = getExampleWrap(event);
+ if (elem === null) {
+ return;
+ }
+ const buttons = elem.querySelector(".button-holder");
+ if (buttons === null) {
+ return;
+ }
+ buttons.classList.toggle("keep-visible");
+ }
+
+ onEachLazy(document.querySelectorAll(".docblock .example-wrap"), elem => {
+ elem.addEventListener("mouseover", addCopyButton);
+ elem.addEventListener("click", showHideCodeExampleButtons);
+ });
}());
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 035376b..6157598 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -3,11 +3,12 @@
//! All the static files are included here for centralized access in case anything other than the
//! HTML rendering code (say, the theme checker) needs to access one of these files.
-use rustc_data_structures::fx::FxHasher;
use std::hash::Hasher;
use std::path::{Path, PathBuf};
use std::{fmt, str};
+use rustc_data_structures::fx::FxHasher;
+
pub(crate) struct StaticFile {
pub(crate) filename: PathBuf,
pub(crate) bytes: &'static [u8],
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index cdf01fa..65c4304 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -98,7 +98,7 @@
</a> {# #}
{% endif %}
<h2> {# #}
- <a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate}}</a> {# #}
+ <a href="{{page.root_path|safe}}{{display_krate_with_trailing_slash|safe}}index.html">{{display_krate|wrapped|safe}}</a> {# #}
{% if !display_krate_version_number.is_empty() %}
<span class="version">{{+ display_krate_version_number}}</span>
{% endif %}
diff --git a/src/librustdoc/html/templates/sidebar.html b/src/librustdoc/html/templates/sidebar.html
index 3251b4c..0990c27 100644
--- a/src/librustdoc/html/templates/sidebar.html
+++ b/src/librustdoc/html/templates/sidebar.html
@@ -1,6 +1,6 @@
{% if !title.is_empty() %}
<h2 class="location"> {# #}
- <a href="#">{{title_prefix}}{{title}}</a> {# #}
+ <a href="#">{{title_prefix}}{{title|wrapped|safe}}</a> {# #}
</h2>
{% endif %}
<div class="sidebar-elems">
@@ -15,7 +15,9 @@
{% for block in blocks %}
{% if block.should_render() %}
{% if !block.heading.name.is_empty() %}
- <h3><a href="#{{block.heading.href|safe}}">{{block.heading.name}}</a></h3>
+ <h3><a href="#{{block.heading.href|safe}}"> {# #}
+ {{block.heading.name|wrapped|safe}} {# #}
+ </a></h3> {# #}
{% endif %}
{% if !block.links.is_empty() %}
<ul class="block{% if !block.class.is_empty() +%} {{+block.class}}{% endif %}">
@@ -29,6 +31,6 @@
</section>
{% endif %}
{% if !path.is_empty() %}
- <h2><a href="{% if is_mod %}../{% endif %}index.html">In {{+ path}}</a></h2>
+ <h2><a href="{% if is_mod %}../{% endif %}index.html">In {{+ path|wrapped|safe}}</a></h2>
{% endif %}
</div>
diff --git a/src/librustdoc/html/tests.rs b/src/librustdoc/html/tests.rs
index 437d399..059f99c 100644
--- a/src/librustdoc/html/tests.rs
+++ b/src/librustdoc/html/tests.rs
@@ -1,6 +1,7 @@
-use crate::html::format::href_relative_parts;
use rustc_span::{sym, Symbol};
+use crate::html::format::href_relative_parts;
+
fn assert_relative_path(expected: &[Symbol], relative_to_fqp: &[Symbol], fqp: &[Symbol]) {
// No `create_default_session_globals_then` call is needed here because all
// the symbols used are static, and no `Symbol::intern` calls occur.
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 4ab0df3..b97d710 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -8,14 +8,14 @@
use rustc_ast::ast;
use rustc_attr::DeprecatedSince;
-use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId};
+use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def_id::DefId;
use rustc_metadata::rendered_const;
use rustc_middle::bug;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::{Pos, Symbol};
use rustc_target::spec::abi::Abi as RustcAbi;
-
use rustdoc_json_types::*;
use crate::clean::{self, ItemId};
@@ -188,6 +188,16 @@ fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self {
}
}
+impl FromWithTcx<clean::ConstantKind> for Constant {
+ // FIXME(generic_const_items): Add support for generic const items.
+ fn from_tcx(constant: clean::ConstantKind, tcx: TyCtxt<'_>) -> Self {
+ let expr = constant.expr(tcx);
+ let value = constant.value(tcx);
+ let is_literal = constant.is_literal(tcx);
+ Constant { expr, value, is_literal }
+ }
+}
+
impl FromWithTcx<clean::AssocItemConstraint> for TypeBinding {
fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self {
TypeBinding {
@@ -323,10 +333,9 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)),
ForeignTypeItem => ItemEnum::ForeignType,
TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)),
- OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),
// FIXME(generic_const_items): Add support for generic free consts
- ConstantItem(_generics, t, c) => {
- ItemEnum::Constant { type_: (*t).into_tcx(tcx), const_: c.into_tcx(tcx) }
+ ConstantItem(ci) => {
+ ItemEnum::Constant { type_: ci.type_.into_tcx(tcx), const_: ci.kind.into_tcx(tcx) }
}
MacroItem(m) => ItemEnum::Macro(m.source),
ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
@@ -341,8 +350,8 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None }
}
// FIXME(generic_const_items): Add support for generic associated consts.
- AssocConstItem(_generics, ty, default) => {
- ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: Some(default.expr(tcx)) }
+ AssocConstItem(ci) => {
+ ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), default: Some(ci.kind.expr(tcx)) }
}
TyAssocTypeItem(g, b) => ItemEnum::AssocType {
generics: g.into_tcx(tcx),
@@ -569,7 +578,7 @@ impl FromWithTcx<clean::Type> for Type {
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
use clean::Type::{
Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath,
- RawPointer, Slice, Tuple,
+ RawPointer, SelfTy, Slice, Tuple,
};
match ty {
@@ -579,6 +588,8 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
traits: bounds.into_tcx(tcx),
}),
Generic(s) => Type::Generic(s.to_string()),
+ // FIXME: add dedicated variant to json Type?
+ SelfTy => Type::Generic("Self".to_owned()),
Primitive(p) => Type::Primitive(p.as_sym().to_string()),
BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
@@ -820,16 +831,10 @@ fn from_tcx(type_alias: Box<clean::TypeAlias>, tcx: TyCtxt<'_>) -> Self {
}
}
-impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
- fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
- OpaqueTy { bounds: opaque.bounds.into_tcx(tcx), generics: opaque.generics.into_tcx(tcx) }
- }
-}
-
impl FromWithTcx<clean::Static> for Static {
fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
Static {
- type_: stat.type_.into_tcx(tcx),
+ type_: (*stat.type_).into_tcx(tcx),
mutable: stat.mutability == ast::Mutability::Mut,
expr: stat
.expr
@@ -857,7 +862,6 @@ fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
Enum => ItemKind::Enum,
Function | TyMethod | Method => ItemKind::Function,
TypeAlias => ItemKind::TypeAlias,
- OpaqueTy => ItemKind::OpaqueTy,
Static => ItemKind::Static,
Constant => ItemKind::Constant,
Trait => ItemKind::Trait,
diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs
index 982370a..976a7fd 100644
--- a/src/librustdoc/json/import_finder.rs
+++ b/src/librustdoc/json/import_finder.rs
@@ -1,9 +1,7 @@
use rustc_hir::def_id::DefIdSet;
-use crate::{
- clean::{self, Import, ImportSource, Item},
- fold::DocFolder,
-};
+use crate::clean::{self, Import, ImportSource, Item};
+use crate::fold::DocFolder;
/// Get the id's of all items that are `pub use`d in the crate.
///
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 0ef2481..ea191dc 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -18,7 +18,6 @@
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::def_id::LOCAL_CRATE;
-
use rustdoc_json_types as types;
use crate::clean::types::{ExternalCrate, ExternalLocation};
@@ -185,7 +184,6 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
| types::ItemEnum::TraitAlias(_)
| types::ItemEnum::Impl(_)
| types::ItemEnum::TypeAlias(_)
- | types::ItemEnum::OpaqueTy(_)
| types::ItemEnum::Constant { .. }
| types::ItemEnum::Static(_)
| types::ItemEnum::ForeignType
@@ -218,13 +216,7 @@ fn mod_item_in(&mut self, _item: &clean::Item) -> Result<(), Error> {
fn after_krate(&mut self) -> Result<(), Error> {
debug!("Done with crate");
- debug!("Adding Primitive impls");
- for primitive in Rc::clone(&self.cache).primitive_locations.values() {
- self.get_impls(*primitive);
- }
-
let e = ExternalCrate { crate_num: LOCAL_CRATE };
-
let index = (*self.index).clone().into_inner();
debug!("Constructing Output");
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index fb4cd21..e651501 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -75,7 +75,8 @@
use std::env::{self, VarError};
use std::io::{self, IsTerminal};
use std::process;
-use std::sync::{atomic::AtomicBool, Arc};
+use std::sync::atomic::AtomicBool;
+use std::sync::Arc;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
use rustc_interface::interface;
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 5a8fd3e..754ba58 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -1,10 +1,10 @@
+use std::sync::LazyLock as Lazy;
+
use rustc_data_structures::fx::FxHashMap;
use rustc_lint::LintStore;
use rustc_lint_defs::{declare_tool_lint, Lint, LintId};
use rustc_session::{lint, Session};
-use std::sync::LazyLock as Lazy;
-
/// This function is used to setup the lint initialization. By default, in rustdoc, everything
/// is "allowed". Depending if we run in test mode or not, we want some of them to be at their
/// default level. For example, the "INVALID_CODEBLOCK_ATTRIBUTES" lint is activated in both
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 9e57600..d6eef43 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -1,11 +1,8 @@
//! Calculates information used for the --show-coverage flag.
-use crate::clean;
-use crate::core::DocContext;
-use crate::html::markdown::{find_testable_code, ErrorCodes};
-use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests};
-use crate::passes::Pass;
-use crate::visit::DocVisitor;
+use std::collections::BTreeMap;
+use std::ops;
+
use rustc_hir as hir;
use rustc_lint::builtin::MISSING_DOCS;
use rustc_middle::lint::LintLevelSource;
@@ -13,8 +10,12 @@
use rustc_span::FileName;
use serde::Serialize;
-use std::collections::BTreeMap;
-use std::ops;
+use crate::clean;
+use crate::core::DocContext;
+use crate::html::markdown::{find_testable_code, ErrorCodes};
+use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests};
+use crate::passes::Pass;
+use crate::visit::DocVisitor;
pub(crate) const CALCULATE_DOC_COVERAGE: Pass = Pass {
name: "calculate-doc-coverage",
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 0437f5e..d78afdf 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -5,6 +5,10 @@
//! - MISSING_DOC_CODE_EXAMPLES: this lint is **UNSTABLE** and looks for public items missing doctests.
//! - PRIVATE_DOC_TESTS: this lint is **STABLE** and looks for private items with doctests.
+use rustc_hir as hir;
+use rustc_middle::lint::LintLevelSource;
+use rustc_session::lint;
+
use super::Pass;
use crate::clean;
use crate::clean::utils::inherits_doc_hidden;
@@ -12,9 +16,6 @@
use crate::core::DocContext;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString, MdRelLine};
use crate::visit::DocVisitor;
-use rustc_hir as hir;
-use rustc_middle::lint::LintLevelSource;
-use rustc_session::lint;
pub(crate) const CHECK_DOC_TEST_VISIBILITY: Pass = Pass {
name: "check_doc_test_visibility",
@@ -62,7 +63,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
| clean::AssocTypeItem(..)
| clean::TypeAliasItem(_)
| clean::StaticItem(_)
- | clean::ConstantItem(_, _, _)
+ | clean::ConstantItem(..)
| clean::ExternCrateItem { .. }
| clean::ImportItem(_)
| clean::PrimitiveItem(_)
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 37f7e7e..9c7eee4 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -2,12 +2,15 @@
//!
//! [RFC 1946]: https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md
+use std::borrow::Cow;
+use std::fmt::Display;
+use std::mem;
+use std::ops::Range;
+
use pulldown_cmark::LinkType;
use rustc_ast::util::comments::may_have_doc_links;
-use rustc_data_structures::{
- fx::{FxHashMap, FxHashSet},
- intern::Interned,
-};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::intern::Interned;
use rustc_errors::{Applicability, Diag, DiagMessage};
use rustc_hir::def::Namespace::*;
use rustc_hir::def::{DefKind, Namespace, PerNS};
@@ -15,9 +18,9 @@
use rustc_hir::{Mutability, Safety};
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::{bug, span_bug, ty};
-use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution};
use rustc_resolve::rustdoc::{
- source_span_for_markdown_range, strip_generics_from_path, MalformedGenerics,
+ has_primitive_or_keyword_docs, prepare_to_doc_link_resolution, source_span_for_markdown_range,
+ strip_generics_from_path, MalformedGenerics,
};
use rustc_session::lint::Lint;
use rustc_span::hygiene::MacroKind;
@@ -25,13 +28,8 @@
use rustc_span::BytePos;
use smallvec::{smallvec, SmallVec};
-use std::borrow::Cow;
-use std::fmt::Display;
-use std::mem;
-use std::ops::Range;
-
-use crate::clean::{self, utils::find_nearest_parent_module};
-use crate::clean::{Crate, Item, ItemLink, PrimitiveType};
+use crate::clean::utils::find_nearest_parent_module;
+use crate::clean::{self, Crate, Item, ItemLink, PrimitiveType};
use crate::core::DocContext;
use crate::html::markdown::{markdown_links, MarkdownLink, MarkdownLinkRange};
use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 9ac9941..1f00891 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -2,17 +2,17 @@
//! defines a struct that implements a trait, this pass will note that the
//! struct implements that trait.
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
+use rustc_middle::ty;
+use rustc_span::symbol::sym;
+
use super::Pass;
use crate::clean::*;
use crate::core::DocContext;
use crate::formats::cache::Cache;
use crate::visit::DocVisitor;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
-use rustc_middle::ty;
-use rustc_span::symbol::sym;
-
pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
name: "collect-trait-impls",
run: collect_trait_impls,
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index a4ba718..a0a369a 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -1,16 +1,18 @@
//! Detects links that are not linkified, e.g., in Markdown such as `Go to https://example.com/.`
//! Suggests wrapping the link with angle brackets: `Go to <https://example.com/>.` to linkify it.
-use crate::clean::*;
-use crate::core::DocContext;
-use crate::html::markdown::main_body_opts;
use core::ops::Range;
+use std::mem;
+use std::sync::LazyLock;
+
use pulldown_cmark::{Event, Parser, Tag};
use regex::Regex;
use rustc_errors::Applicability;
use rustc_resolve::rustdoc::source_span_for_markdown_range;
-use std::mem;
-use std::sync::LazyLock;
+
+use crate::clean::*;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else {
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index afeb711..ef05bef 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -1,11 +1,9 @@
//! Validates syntax inside Rust code blocks (\`\`\`rust).
use rustc_data_structures::sync::{Lock, Lrc};
-use rustc_errors::{
- emitter::Emitter,
- translation::{to_fluent_args, Translate},
- Applicability, DiagCtxt, DiagInner, LazyFallbackBundle,
-};
+use rustc_errors::emitter::Emitter;
+use rustc_errors::translation::{to_fluent_args, Translate};
+use rustc_errors::{Applicability, DiagCtxt, DiagInner, LazyFallbackBundle};
use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal};
use rustc_resolve::rustdoc::source_span_for_markdown_range;
use rustc_session::parse::ParseSess;
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 87dfa5d..6f9e9d3 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -1,15 +1,15 @@
//! Detects invalid HTML (like an unclosed `<span>`) in doc comments.
-use crate::clean::*;
-use crate::core::DocContext;
-use crate::html::markdown::main_body_opts;
+use std::iter::Peekable;
+use std::ops::Range;
+use std::str::CharIndices;
use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag, TagEnd};
use rustc_resolve::rustdoc::source_span_for_markdown_range;
-use std::iter::Peekable;
-use std::ops::Range;
-use std::str::CharIndices;
+use crate::clean::*;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
let tcx = cx.tcx;
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index b36b41c..0a90c03 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -12,8 +12,7 @@
use rustc_span::def_id::DefId;
use rustc_span::Symbol;
-use crate::clean::utils::find_nearest_parent_module;
-use crate::clean::utils::inherits_doc_hidden;
+use crate::clean::utils::{find_nearest_parent_module, inherits_doc_hidden};
use crate::clean::Item;
use crate::core::DocContext;
use crate::html::markdown::main_body_opts;
diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs
index be96700..a6c8db1 100644
--- a/src/librustdoc/passes/lint/unescaped_backticks.rs
+++ b/src/librustdoc/passes/lint/unescaped_backticks.rs
@@ -1,13 +1,15 @@
//! Detects unescaped backticks (\`) in doc comments.
-use crate::clean::Item;
-use crate::core::DocContext;
-use crate::html::markdown::main_body_opts;
+use std::ops::Range;
+
use pulldown_cmark::{BrokenLink, Event, Parser};
use rustc_errors::Diag;
use rustc_lint_defs::Applicability;
use rustc_resolve::rustdoc::source_span_for_markdown_range;
-use std::ops::Range;
+
+use crate::clean::Item;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
let tcx = cx.tcx;
diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs
index 5f18537..87fe005 100644
--- a/src/librustdoc/passes/lint/unportable_markdown.rs
+++ b/src/librustdoc/passes/lint/unportable_markdown.rs
@@ -10,13 +10,14 @@
//!
//! <https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html#add-the-lint-to-the-list-of-removed-lists>
-use crate::clean::Item;
-use crate::core::DocContext;
-use pulldown_cmark as cmarkn;
-use pulldown_cmark_old as cmarko;
+use std::collections::{BTreeMap, BTreeSet};
+
use rustc_lint_defs::Applicability;
use rustc_resolve::rustdoc::source_span_for_markdown_range;
-use std::collections::{BTreeMap, BTreeSet};
+use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko};
+
+use crate::clean::Item;
+use crate::core::DocContext;
pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
let tcx = cx.tcx;
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 8de7f23..5aa6a5e 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -2,6 +2,8 @@
use std::sync::Arc;
+use rustc_hir::def_id::LocalDefId;
+
use crate::clean::cfg::Cfg;
use crate::clean::inline::{load_attrs, merge_attrs};
use crate::clean::{Crate, Item, ItemKind};
@@ -9,8 +11,6 @@
use crate::fold::DocFolder;
use crate::passes::Pass;
-use rustc_hir::def_id::LocalDefId;
-
pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass {
name: "propagate-doc-cfg",
run: propagate_doc_cfg,
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
index ac7d422..e1dd2d3 100644
--- a/src/librustdoc/passes/strip_aliased_non_local.rs
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -1,5 +1,4 @@
-use rustc_middle::ty::TyCtxt;
-use rustc_middle::ty::Visibility;
+use rustc_middle::ty::{TyCtxt, Visibility};
use crate::clean;
use crate::clean::Item;
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 81a90ed..faf42b3 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -1,9 +1,10 @@
//! Strip all doc(hidden) items from the output.
+use std::mem;
+
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
-use std::mem;
use crate::clean;
use crate::clean::utils::inherits_doc_hidden;
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index 1cf80a0..f807c33 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -1,8 +1,9 @@
//! A collection of utility functions for the `strip_*` passes.
+use std::mem;
+
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{TyCtxt, Visibility};
-use std::mem;
use crate::clean::utils::inherits_doc_hidden;
use crate::clean::{self, Item, ItemId, ItemIdSet};
@@ -49,8 +50,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
return Some(ret);
}
// These items can all get re-exported
- clean::OpaqueTyItem(..)
- | clean::TypeAliasItem(..)
+ clean::TypeAliasItem(..)
| clean::StaticItem(..)
| clean::StructItem(..)
| clean::EnumItem(..)
@@ -95,7 +95,14 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
}
clean::ModuleItem(..) => {
- if i.item_id.is_local() && i.visibility(self.tcx) != Some(Visibility::Public) {
+ if i.item_id.is_local()
+ && !is_item_reachable(
+ self.tcx,
+ self.is_json_output,
+ self.effective_visibilities,
+ i.item_id,
+ )
+ {
debug!("Stripper: stripping module {:?}", i.name);
let old = mem::replace(&mut self.update_retained, false);
let ret = strip_item(self.fold_item_recur(i));
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 5a595e0..f001fb2 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -1,35 +1,27 @@
//! This module analyzes crates to find call sites that can serve as examples in the documentation.
-use crate::clean;
-use crate::config;
-use crate::formats;
-use crate::formats::renderer::FormatRenderer;
-use crate::html::render::Context;
+use std::fs;
+use std::path::PathBuf;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::DiagCtxtHandle;
-use rustc_hir::{
- self as hir,
- intravisit::{self, Visitor},
-};
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{self as hir};
use rustc_interface::interface;
use rustc_macros::{Decodable, Encodable};
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_serialize::{
- opaque::{FileEncoder, MemDecoder},
- Decodable, Encodable,
-};
+use rustc_serialize::opaque::{FileEncoder, MemDecoder};
+use rustc_serialize::{Decodable, Encodable};
use rustc_session::getopts;
-use rustc_span::{
- def_id::{CrateNum, DefPathHash, LOCAL_CRATE},
- edition::Edition,
- BytePos, FileName, SourceFile,
-};
+use rustc_span::def_id::{CrateNum, DefPathHash, LOCAL_CRATE};
+use rustc_span::edition::Edition;
+use rustc_span::{BytePos, FileName, SourceFile};
-use std::fs;
-use std::path::PathBuf;
+use crate::formats::renderer::FormatRenderer;
+use crate::html::render::Context;
+use crate::{clean, config, formats};
#[derive(Debug, Clone)]
pub(crate) struct ScrapeExamplesOptions {
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index 2fa54a9..409728a 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -1,10 +1,10 @@
-use rustc_data_structures::fx::FxHashMap;
use std::collections::hash_map::Entry;
use std::fs;
use std::iter::Peekable;
use std::path::Path;
use std::str::Chars;
+use rustc_data_structures::fx::FxHashMap;
use rustc_errors::DiagCtxtHandle;
#[cfg(test)]
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index b335dc5..430bbe9 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -26,9 +26,8 @@ fn visit_inner_recur(&mut self, kind: &ItemKind) {
| ImportItem(_)
| FunctionItem(_)
| TypeAliasItem(_)
- | OpaqueTyItem(_)
| StaticItem(_)
- | ConstantItem(_, _, _)
+ | ConstantItem(..)
| TraitAliasItem(_)
| TyMethodItem(_)
| MethodItem(_, _)
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 886df82..d7a4a0d 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -1,6 +1,8 @@
//! The Rust AST Visitor. Extracts useful information and massages it into a form
//! usable for `clean`.
+use std::mem;
+
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
@@ -14,10 +16,9 @@
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use std::mem;
-
+use crate::clean::cfg::Cfg;
use crate::clean::utils::{inherits_doc_hidden, should_ignore_res};
-use crate::clean::{cfg::Cfg, reexport_chain, AttributesExt, NestedAttributesExt};
+use crate::clean::{reexport_chain, AttributesExt, NestedAttributesExt};
use crate::core;
/// This module is used to store stuff from Rust's AST in a more convenient
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 82c9746..3e66ed9 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -1,8 +1,9 @@
-use crate::core::DocContext;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_middle::ty::TyCtxt;
+use crate::core::DocContext;
+
// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
#[derive(Default)]
diff --git a/src/llvm-project b/src/llvm-project
index c54cff0..57ae1a3 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit c54cff0e6e4d1a0d0a2df7c1ce3d96cdd554763e
+Subproject commit 57ae1a3474057fead2c438928ed368b3740bf0ec
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 6fd23b6..999134a 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -3,14 +3,21 @@
//! These types are the public API exposed through the `--output-format json` flag. The [`Crate`]
//! struct is the root of the JSON blob and all other items are contained within.
-use rustc_hash::FxHashMap;
-use serde::{Deserialize, Serialize};
use std::path::PathBuf;
-/// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 32;
+use rustc_hash::FxHashMap;
+use serde::{Deserialize, Serialize};
-/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
+/// The version of JSON output that this crate represents.
+///
+/// This integer is incremented with every breaking change to the API,
+/// and is returned along with the JSON blob as [`Crate::format_version`].
+/// Consuming code should assert that this value matches the format version(s) that it supports.
+pub const FORMAT_VERSION: u32 = 33;
+
+/// The root of the emitted JSON blob.
+///
+/// It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
/// tools to find or link to them.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -33,13 +40,18 @@ pub struct Crate {
pub format_version: u32,
}
+/// Metadata of a crate, either the same crate on which `rustdoc` was invoked, or its dependency.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ExternalCrate {
+ /// The name of the crate.
pub name: String,
+ /// The root URL at which the crate's documentation lives.
pub html_root_url: Option<String>,
}
-/// For external (not defined in the local crate) items, you don't get the same level of
+/// Information about an external (not defined in the local crate) [`Item`].
+///
+/// For external items, you don't get the same level of
/// information. This struct should contain enough to generate a link/reference to the item in
/// question, or can be used by a tool that takes the json output of multiple crates to find
/// the actual item definition with all the relevant info.
@@ -60,6 +72,10 @@ pub struct ItemSummary {
pub kind: ItemKind,
}
+/// Anything that can hold documentation - modules, structs, enums, functions, traits, etc.
+///
+/// The `Item` data type holds fields that can apply to any of these,
+/// and leaves kind-specific details (like function args or enum variants) to the `inner` field.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Item {
/// The unique identifier of this item. Can be used to find this item in various mappings.
@@ -82,10 +98,13 @@ pub struct Item {
pub links: FxHashMap<String, Id>,
/// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
pub attrs: Vec<String>,
+ /// Information about the item’s deprecation, if present.
pub deprecation: Option<Deprecation>,
+ /// The type-specific fields describing this item.
pub inner: ItemEnum,
}
+/// A range of source code.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Span {
/// The path to the source file for this span relative to the path `rustdoc` was invoked with.
@@ -96,28 +115,39 @@ pub struct Span {
pub end: (usize, usize),
}
+/// Information about the deprecation of an [`Item`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Deprecation {
+ /// Usually a version number when this [`Item`] first became deprecated.
pub since: Option<String>,
+ /// The reason for deprecation and/or what alternatives to use.
pub note: Option<String>,
}
+/// Visibility of an [`Item`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Visibility {
+ /// Explicitly public visibility set with `pub`.
Public,
/// For the most part items are private by default. The exceptions are associated items of
/// public traits and variants of public enums.
Default,
+ /// Explicitly crate-wide visibility set with `pub(crate)`
Crate,
- /// For `pub(in path)` visibility. `parent` is the module it's restricted to and `path` is how
- /// that module was referenced (like `"super::super"` or `"crate::foo::bar"`).
+ /// For `pub(in path)` visibility.
Restricted {
+ /// ID of the module to which this visibility restricts items.
parent: Id,
+ /// The path with which [`parent`] was referenced
+ /// (like `super::super` or `crate::foo::bar`).
+ ///
+ /// [`parent`]: Visibility::Restricted::parent
path: String,
},
}
+/// Dynamic trait object type (`dyn Trait`).
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct DynTrait {
/// All the traits implemented. One of them is the vtable, and the rest must be auto traits.
@@ -132,64 +162,133 @@ pub struct DynTrait {
pub lifetime: Option<String>,
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
/// A trait and potential HRTBs
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct PolyTrait {
+ /// The path to the trait.
#[serde(rename = "trait")]
pub trait_: Path,
/// Used for Higher-Rank Trait Bounds (HRTBs)
/// ```text
/// dyn for<'a> Fn() -> &'a i32"
/// ^^^^^^^
- /// |
- /// this part
/// ```
pub generic_params: Vec<GenericParamDef>,
}
+/// A set of generic arguments provided to a path segment, e.g.
+///
+/// ```text
+/// std::option::Option::<u32>::None
+/// ^^^^^
+/// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GenericArgs {
- /// <'a, 32, B: Copy, C = u32>
- AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
- /// Fn(A, B) -> C
- Parenthesized { inputs: Vec<Type>, output: Option<Type> },
+ /// `<'a, 32, B: Copy, C = u32>`
+ AngleBracketed {
+ /// The list of each argument on this type.
+ /// ```text
+ /// <'a, 32, B: Copy, C = u32>
+ /// ^^^^^^
+ /// ```
+ args: Vec<GenericArg>,
+ /// Associated type or constant bindings (e.g. `Item=i32` or `Item: Clone`) for this type.
+ bindings: Vec<TypeBinding>,
+ },
+ /// `Fn(A, B) -> C`
+ Parenthesized {
+ /// The input types, enclosed in parentheses.
+ inputs: Vec<Type>,
+ /// The output type provided after the `->`, if present.
+ output: Option<Type>,
+ },
}
+/// One argument in a list of generic arguments to a path segment.
+///
+/// Part of [`GenericArgs`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GenericArg {
+ /// A lifetime argument.
+ /// ```text
+ /// std::borrow::Cow<'static, str>
+ /// ^^^^^^^
+ /// ```
Lifetime(String),
+ /// A type argument.
+ /// ```text
+ /// std::borrow::Cow<'static, str>
+ /// ^^^
+ /// ```
Type(Type),
+ /// A constant as a generic argument.
+ /// ```text
+ /// core::array::IntoIter<u32, { 640 * 1024 }>
+ /// ^^^^^^^^^^^^^^
+ /// ```
Const(Constant),
+ /// A generic argument that's explicitly set to be inferred.
+ /// ```text
+ /// std::vec::Vec::<_>::new()
+ /// ^
+ /// ```
Infer,
}
+/// A constant.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Constant {
+ /// The stringified expression of this constant. Note that its mapping to the original
+ /// source code is unstable and it's not guaranteed that it'll match the source code.
pub expr: String,
+ /// The value of the evaluated expression for this constant, which is only computed for numeric
+ /// types.
pub value: Option<String>,
+ /// Whether this constant is a bool, numeric, string, or char literal.
pub is_literal: bool,
}
+/// Describes a bound applied to an associated type/constant.
+///
+/// Example:
+/// ```text
+/// IntoIterator<Item = u32, IntoIter: Clone>
+/// ^^^^^^^^^^ ^^^^^^^^^^^^^^^
+/// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TypeBinding {
+ /// The name of the associated type/constant.
pub name: String,
+ /// Arguments provided to the associated type/constant.
pub args: GenericArgs,
+ /// The kind of bound applied to the associated type/constant.
pub binding: TypeBindingKind,
}
+/// The way in which an associate type/constant is bound.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TypeBindingKind {
+ /// The required value/type is specified exactly. e.g.
+ /// ```text
+ /// Iterator<Item = u32, IntoIter: DoubleEndedIterator>
+ /// ^^^^^^^^^^
+ /// ```
Equality(Term),
+ /// The type is required to satisfy a set of bounds.
+ /// ```text
+ /// Iterator<Item = u32, IntoIter: DoubleEndedIterator>
+ /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// ```
Constraint(Vec<GenericBound>),
}
/// An opaque identifier for an item.
///
-/// It can be used to lookup in [Crate::index] or [Crate::paths] to resolve it
-/// to an [Item].
+/// It can be used to lookup in [`Crate::index`] or [`Crate::paths`] to resolve it
+/// to an [`Item`].
///
/// Id's are only valid within a single JSON blob. They cannot be used to
/// resolve references between the JSON output's for different crates.
@@ -201,115 +300,228 @@ pub enum TypeBindingKind {
// FIXME(aDotInTheVoid): Consider making this non-public in rustdoc-types.
pub struct Id(pub String);
+/// The fundamental kind of an item. Unlike [`ItemEnum`], this does not carry any aditional info.
+///
+/// Part of [`ItemSummary`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ItemKind {
+ /// A module declaration, e.g. `mod foo;` or `mod foo {}`
Module,
+ /// A crate imported via the `extern crate` syntax.
ExternCrate,
+ /// An import of 1 or more items into scope, using the `use` keyword.
Import,
+ /// A `struct` declaration.
Struct,
+ /// A field of a struct.
StructField,
+ /// A `union` declaration.
Union,
+ /// An `enum` declaration.
Enum,
+ /// A variant of a enum.
Variant,
+ /// A function declaration, e.g. `fn f() {}`
Function,
+ /// A type alias declaration, e.g. `type Pig = std::borrow::Cow<'static, str>;`
TypeAlias,
- OpaqueTy,
+ /// The declaration of a constant, e.g. `const GREETING: &str = "Hi :3";`
Constant,
+ /// A `trait` declaration.
Trait,
+ /// A trait alias declaration, e.g. `trait Int = Add + Sub + Mul + Div;`
+ ///
+ /// See [the tracking issue](https://github.com/rust-lang/rust/issues/41517)
TraitAlias,
+ /// An `impl` block.
Impl,
+ /// A `static` declaration.
Static,
+ /// `type`s from an `extern` block.
+ ///
+ /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467)
ForeignType,
+ /// A macro declaration.
+ ///
+ /// Corresponds to either `ItemEnum::Macro(_)`
+ /// or `ItemEnum::ProcMacro(ProcMacro { kind: MacroKind::Bang })`
Macro,
+ /// A procedural macro attribute.
+ ///
+ /// Corresponds to `ItemEnum::ProcMacro(ProcMacro { kind: MacroKind::Attr })`
ProcAttribute,
+ /// A procedural macro usable in the `#[derive()]` attribute.
+ ///
+ /// Corresponds to `ItemEnum::ProcMacro(ProcMacro { kind: MacroKind::Derive })`
ProcDerive,
+ /// An associated constant of a trait or a type.
AssocConst,
+ /// An associated type of a trait or a type.
AssocType,
+ /// A primitive type, e.g. `u32`.
+ ///
+ /// [`Item`]s of this kind only come from the core library.
Primitive,
+ /// A keyword declaration.
+ ///
+ /// [`Item`]s of this kind only come from the come library and exist solely
+ /// to carry documentation for the respective keywords.
Keyword,
}
+/// Specific fields of an item.
+///
+/// Part of [`Item`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ItemEnum {
+ /// A module declaration, e.g. `mod foo;` or `mod foo {}`
Module(Module),
+ /// A crate imported via the `extern crate` syntax.
ExternCrate {
+ /// The name of the imported crate.
name: String,
+ /// If the crate is renamed, this is its name in the crate.
rename: Option<String>,
},
+ /// An import of 1 or more items into scope, using the `use` keyword.
Import(Import),
+ /// A `union` declaration.
Union(Union),
+ /// A `struct` declaration.
Struct(Struct),
+ /// A field of a struct.
StructField(Type),
+ /// An `enum` declaration.
Enum(Enum),
+ /// A variant of a enum.
Variant(Variant),
+ /// A function declaration (including methods and other associated functions)
Function(Function),
+ /// A `trait` declaration.
Trait(Trait),
+ /// A trait alias declaration, e.g. `trait Int = Add + Sub + Mul + Div;`
+ ///
+ /// See [the tracking issue](https://github.com/rust-lang/rust/issues/41517)
TraitAlias(TraitAlias),
+ /// An `impl` block.
Impl(Impl),
+ /// A type alias declaration, e.g. `type Pig = std::borrow::Cow<'static, str>;`
TypeAlias(TypeAlias),
- OpaqueTy(OpaqueTy),
+ /// The declaration of a constant, e.g. `const GREETING: &str = "Hi :3";`
Constant {
+ /// The type of the constant.
#[serde(rename = "type")]
type_: Type,
+ /// The declared constant itself.
#[serde(rename = "const")]
const_: Constant,
},
+ /// A declaration of a `static`.
Static(Static),
- /// `type`s from an extern block
+ /// `type`s from an `extern` block.
+ ///
+ /// See [the tracking issue](https://github.com/rust-lang/rust/issues/43467)
ForeignType,
- /// Declarative macro_rules! macro
+ /// A macro_rules! declarative macro. Contains a single string with the source
+ /// representation of the macro with the patterns stripped.
Macro(String),
+ /// A procedural macro.
ProcMacro(ProcMacro),
+ /// A primitive type, e.g. `u32`.
+ ///
+ /// [`Item`]s of this kind only come from the core library.
Primitive(Primitive),
+ /// An associated constant of a trait or a type.
AssocConst {
+ /// The type of the constant.
#[serde(rename = "type")]
type_: Type,
- /// e.g. `const X: usize = 5;`
+ /// The stringified expression for the default value, if provided, e.g.
+ /// ```rust
+ /// const X: usize = 640 * 1024;
+ /// // ^^^^^^^^^^
+ /// ```
default: Option<String>,
},
+ /// An associated type of a trait or a type.
AssocType {
+ /// The generic parameters and where clauses on ahis associated type.
generics: Generics,
+ /// The bounds for this associated type. e.g.
+ /// ```rust
+ /// trait IntoIterator {
+ /// type Item;
+ /// type IntoIter: Iterator<Item = Self::Item>;
+ /// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// }
+ /// ```
bounds: Vec<GenericBound>,
- /// e.g. `type X = usize;`
+ /// The default for this type, if provided, e.g.
+ /// ```rust
+ /// type X = usize;
+ /// // ^^^^^
+ /// ```
default: Option<Type>,
},
}
+/// A module declaration, e.g. `mod foo;` or `mod foo {}`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Module {
+ /// Whether this is the root item of a crate.
+ ///
+ /// This item doesn't correspond to any construction in the source code and is generated by the
+ /// compiler.
pub is_crate: bool,
+ /// [`Item`]s declared inside this module.
pub items: Vec<Id>,
/// If `true`, this module is not part of the public API, but it contains
/// items that are re-exported as public API.
pub is_stripped: bool,
}
+/// A `union`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Union {
+ /// The generic parameters and where clauses on this union.
pub generics: Generics,
+ /// Whether any fields have been removed from the result, due to being private or hidden.
pub fields_stripped: bool,
+ /// The list of fields in the union.
+ ///
+ /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`].
pub fields: Vec<Id>,
+ /// All impls (both of traits and inherent) for this union.
+ ///
+ /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Impl`].
pub impls: Vec<Id>,
}
+/// A `struct`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Struct {
+ /// The kind of the struct (e.g. unit, tuple-like or struct-like) and the data specific to it,
+ /// i.e. fields.
pub kind: StructKind,
+ /// The generic parameters and where clauses on this struct.
pub generics: Generics,
+ /// All impls (both of traits and inherent) for this struct.
+ /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Impl`].
pub impls: Vec<Id>,
}
+/// The kind of a [`Struct`] and the data specific to it, i.e. fields.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StructKind {
@@ -321,13 +533,14 @@ pub enum StructKind {
Unit,
/// A struct with unnamed fields.
///
+ /// All [`Id`]'s will point to [`ItemEnum::StructField`].
+ /// Unlike most of JSON, private and `#[doc(hidden)]` fields will be given as `None`
+ /// instead of being omitted, because order matters.
+ ///
/// ```rust
/// pub struct TupleStruct(i32);
/// pub struct EmptyTupleStruct();
/// ```
- ///
- /// All [`Id`]'s will point to [`ItemEnum::StructField`]. Private and
- /// `#[doc(hidden)]` fields will be given as `None`
Tuple(Vec<Option<Id>>),
/// A struct with named fields.
///
@@ -335,17 +548,32 @@ pub enum StructKind {
/// pub struct PlainStruct { x: i32 }
/// pub struct EmptyPlainStruct {}
/// ```
- Plain { fields: Vec<Id>, fields_stripped: bool },
+ Plain {
+ /// The list of fields in the struct.
+ ///
+ /// All of the corresponding [`Item`]s are of kind [`ItemEnum::StructField`].
+ fields: Vec<Id>,
+ /// Whether any fields have been removed from the result, due to being private or hidden.
+ fields_stripped: bool,
+ },
}
+/// An `enum`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Enum {
+ /// Information about the type parameters and `where` clauses of the enum.
pub generics: Generics,
+ /// Whether any variants have been removed from the result, due to being private or hidden.
pub variants_stripped: bool,
+ /// The list of variants in the enum.
+ ///
+ /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`]
pub variants: Vec<Id>,
+ /// `impl`s for the enum.
pub impls: Vec<Id>,
}
+/// A variant of an enum.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Variant {
/// Whether the variant is plain, a tuple-like, or struct-like. Contains the fields.
@@ -354,6 +582,7 @@ pub struct Variant {
pub discriminant: Option<Discriminant>,
}
+/// The kind of an [`Enum`] [`Variant`] and the data specific to it, i.e. fields.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum VariantKind {
@@ -368,7 +597,8 @@ pub enum VariantKind {
Plain,
/// A variant with unnamed fields.
///
- /// Unlike most of json, `#[doc(hidden)]` fields will be given as `None`
+ /// All [`Id`]'s will point to [`ItemEnum::StructField`].
+ /// Unlike most of JSON, `#[doc(hidden)]` fields will be given as `None`
/// instead of being omitted, because order matters.
///
/// ```rust
@@ -386,9 +616,16 @@ pub enum VariantKind {
/// EmptyStructVariant {},
/// }
/// ```
- Struct { fields: Vec<Id>, fields_stripped: bool },
+ Struct {
+ /// The list of variants in the enum.
+ /// All of the corresponding [`Item`]s are of kind [`ItemEnum::Variant`].
+ fields: Vec<Id>,
+ /// Whether any variants have been removed from the result, due to being private or hidden.
+ fields_stripped: bool,
+ },
}
+/// The value that distinguishes a variant in an [`Enum`] from other variants.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Discriminant {
/// The expression that produced the discriminant.
@@ -397,7 +634,7 @@ pub struct Discriminant {
/// hexadecimal, and underscores), making it unsuitable to be machine
/// interpreted.
///
- /// In some cases, when the value is to complex, this may be `"{ _ }"`.
+ /// In some cases, when the value is too complex, this may be `"{ _ }"`.
/// When this occurs is unstable, and may change without notice.
pub expr: String,
/// The numerical value of the discriminant. Stored as a string due to
@@ -406,62 +643,123 @@ pub struct Discriminant {
pub value: String,
}
+/// A set of fundamental properties of a function.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Header {
+ /// Is this function marked as `const`?
#[serde(rename = "const")]
pub const_: bool,
+ /// Is this function unsafe?
#[serde(rename = "unsafe")]
pub unsafe_: bool,
+ /// Is this function async?
#[serde(rename = "async")]
pub async_: bool,
+ /// The ABI used by the function.
pub abi: Abi,
}
+/// The ABI (Application Binary Interface) used by a function.
+///
+/// If a variant has an `unwind` field, this means the ABI that it represents can be specified in 2
+/// ways: `extern "_"` and `extern "_-unwind"`, and a value of `true` for that field signifies the
+/// latter variant.
+///
+/// See the [Rustonomicon section](https://doc.rust-lang.org/nightly/nomicon/ffi.html#ffi-and-unwinding)
+/// on unwinding for more info.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Abi {
// We only have a concrete listing here for stable ABI's because their are so many
// See rustc_ast_passes::feature_gate::PostExpansionVisitor::check_abi for the list
+ /// The default ABI, but that can also be written explicitly with `extern "Rust"`.
Rust,
+ /// Can be specified as `extern "C"` or, as a shorthand, just `extern`.
C { unwind: bool },
+ /// Can be specified as `extern "cdecl"`.
Cdecl { unwind: bool },
+ /// Can be specified as `extern "stdcall"`.
Stdcall { unwind: bool },
+ /// Can be specified as `extern "fastcall"`.
Fastcall { unwind: bool },
+ /// Can be specified as `extern "aapcs"`.
Aapcs { unwind: bool },
+ /// Can be specified as `extern "win64"`.
Win64 { unwind: bool },
+ /// Can be specifed as `extern "sysv64"`.
SysV64 { unwind: bool },
+ /// Can be specified as `extern "system"`.
System { unwind: bool },
+ /// Any other ABI, including unstable ones.
Other(String),
}
-/// Represents a function (including methods and other associated functions)
+/// A function declaration (including methods and other associated functions).
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Function {
+ /// Information about the function signature, or declaration.
pub decl: FnDecl,
+ /// Information about the function’s type parameters and `where` clauses.
pub generics: Generics,
+ /// Information about core properties of the function, e.g. whether it's `const`, its ABI, etc.
pub header: Header,
+ /// Whether the function has a body, i.e. an implementation.
pub has_body: bool,
}
+/// Generic parameters accepted by an item and `where` clauses imposed on it and the parameters.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Generics {
+ /// A list of generic parameter definitions (e.g. `<T: Clone + Hash, U: Copy>`).
pub params: Vec<GenericParamDef>,
+ /// A list of where predicates (e.g. `where T: Iterator, T::Item: Copy`).
pub where_predicates: Vec<WherePredicate>,
}
+/// One generic parameter accepted by an item.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct GenericParamDef {
+ /// Name of the parameter.
+ /// ```rust
+ /// fn f<'resource, Resource>(x: &'resource Resource) {}
+ /// // ^^^^^^^^ ^^^^^^^^
+ /// ```
pub name: String,
+ /// The kind of the parameter and data specific to a particular parameter kind, e.g. type
+ /// bounds.
pub kind: GenericParamDefKind,
}
+/// The kind of a [`GenericParamDef`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GenericParamDefKind {
+ /// Denotes a lifetime parameter.
Lifetime {
+ /// Lifetimes that this lifetime parameter is required to outlive.
+ ///
+ /// ```rust
+ /// fn f<'a, 'b, 'resource: 'a + 'b>(a: &'a str, b: &'b str, res: &'resource str) {}
+ /// // ^^^^^^^
+ /// ```
outlives: Vec<String>,
},
+
+ /// Denotes a type parameter.
Type {
+ /// Bounds applied directly to the type. Note that the bounds from `where` clauses
+ /// that constrain this parameter won't appear here.
+ ///
+ /// ```rust
+ /// fn default2<T: Default>() -> [T; 2] where T: Clone { todo!() }
+ /// // ^^^^^^^
+ /// ```
bounds: Vec<GenericBound>,
+ /// The default type for this parameter, if provided, e.g.
+ ///
+ /// ```rust
+ /// trait PartialEq<Rhs = Self> {}
+ /// // ^^^^
+ /// ```
default: Option<Type>,
/// This is normally `false`, which means that this generic parameter is
/// declared in the Rust source text.
@@ -488,43 +786,75 @@ pub enum GenericParamDefKind {
/// the Rust source text.
synthetic: bool,
},
+
+ /// Denotes a constant parameter.
Const {
+ /// The type of the constant as declared.
#[serde(rename = "type")]
type_: Type,
+ /// The stringified expression for the default value, if provided. It's not guaranteed that
+ /// it'll match the actual source code for the default value.
default: Option<String>,
},
}
+/// One `where` clause.
+/// ```rust
+/// fn default<T>() -> T where T: Default { T::default() }
+/// // ^^^^^^^^^^
+/// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum WherePredicate {
+ /// A type is expected to comply with a set of bounds
BoundPredicate {
+ /// The type that's being constrained.
+ ///
+ /// ```rust
+ /// fn f<T>(x: T) where for<'a> &'a T: Iterator {}
+ /// // ^
+ /// ```
#[serde(rename = "type")]
type_: Type,
+ /// The set of bounds that constrain the type.
+ ///
+ /// ```rust
+ /// fn f<T>(x: T) where for<'a> &'a T: Iterator {}
+ /// // ^^^^^^^^
+ /// ```
bounds: Vec<GenericBound>,
/// Used for Higher-Rank Trait Bounds (HRTBs)
- /// ```text
- /// where for<'a> &'a T: Iterator,"
- /// ^^^^^^^
- /// |
- /// this part
+ /// ```rust
+ /// fn f<T>(x: T) where for<'a> &'a T: Iterator {}
+ /// // ^^^^^^^
/// ```
generic_params: Vec<GenericParamDef>,
},
+
+ /// A lifetime is expected to outlive other lifetimes.
LifetimePredicate {
+ /// The name of the lifetime.
lifetime: String,
+ /// The lifetimes that must be encompassed by the lifetime.
outlives: Vec<String>,
},
+
+ /// A type must exactly equal another type.
EqPredicate {
+ /// The left side of the equation.
lhs: Type,
+ /// The right side of the equation.
rhs: Term,
},
}
+/// Either a trait bound or a lifetime bound.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum GenericBound {
+ /// A trait bound.
TraitBound {
+ /// The full path to the trait.
#[serde(rename = "trait")]
trait_: Path,
/// Used for Higher-Rank Trait Bounds (HRTBs)
@@ -535,79 +865,142 @@ pub enum GenericBound {
/// this part
/// ```
generic_params: Vec<GenericParamDef>,
+ /// The context for which a trait is supposed to be used, e.g. `const
modifier: TraitBoundModifier,
},
+ /// A lifetime bound, e.g.
+ /// ```rust
+ /// fn f<'a, T>(x: &'a str, y: &T) where T: 'a {}
+ /// // ^^^
+ /// ```
Outlives(String),
/// `use<'a, T>` precise-capturing bound syntax
Use(Vec<String>),
}
+/// A set of modifiers applied to a trait.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TraitBoundModifier {
+ /// Marks the absence of a modifier.
None,
+ /// Indicates that the trait bound relaxes a trait bound applied to a parameter by default,
+ /// e.g. `T: Sized?`, the `Sized` trait is required for all generic type parameters by default
+ /// unless specified otherwise with this modifier.
Maybe,
+ /// Indicates that the trait bound must be applicable in both a run-time and a compile-time
+ /// context.
MaybeConst,
}
+/// Either a type or a constant, usually stored as the right-hand side of an equation in places like
+/// [`TypeBinding`]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Term {
+ /// A type.
+ ///
+ /// ```rust
+ /// fn f(x: impl IntoIterator<Item = u32>) {}
+ /// // ^^^
+ /// ```
Type(Type),
+ /// A constant.
+ ///
+ /// ```ignore (incomplete feature in the snippet)
+ /// trait Foo {
+ /// const BAR: usize;
+ /// }
+ ///
+ /// fn f(x: impl Foo<BAR = 42>) {}
+ /// // ^^
+ /// ```
Constant(Constant),
}
+/// A type.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
- /// Structs, enums, and unions
+ /// Structs, enums, unions and type aliases, e.g. `std::option::Option<u32>`
ResolvedPath(Path),
+ /// Dynamic trait object type (`dyn Trait`).
DynTrait(DynTrait),
- /// Parameterized types
+ /// Parameterized types. The contained string is the name of the parameter.
Generic(String),
- /// Built in numeric (i*, u*, f*) types, bool, and char
+ /// Built-in numeric types (e.g. `u32`, `f32`), `bool`, `char`.
Primitive(String),
- /// `extern "ABI" fn`
+ /// A function pointer type, e.g. `fn(u32) -> u32`, `extern "C" fn() -> *const u8`
FunctionPointer(Box<FunctionPointer>),
- /// `(String, u32, Box<usize>)`
+ /// A tuple type, e.g. `(String, u32, Box<usize>)`
Tuple(Vec<Type>),
- /// `[u32]`
+ /// An unsized slice type, e.g. `[u32]`.
Slice(Box<Type>),
- /// [u32; 15]
+ /// An array type, e.g. `[u32; 15]`
Array {
+ /// The type of the contained element.
#[serde(rename = "type")]
type_: Box<Type>,
+ /// The stringified expression that is the length of the array.
+ ///
+ /// Keep in mind that it's not guaranteed to match the actual source code of the expression.
len: String,
},
- /// `u32 is 1..`
+ /// A pattern type, e.g. `u32 is 1..`
+ ///
+ /// See [the tracking issue](https://github.com/rust-lang/rust/issues/123646)
Pat {
+ /// The base type, e.g. the `u32` in `u32 is 1..`
#[serde(rename = "type")]
type_: Box<Type>,
#[doc(hidden)]
__pat_unstable_do_not_use: String,
},
- /// `impl TraitA + TraitB + ...`
+ /// An opaque type that satisfies a set of bounds, `impl TraitA + TraitB + ...`
ImplTrait(Vec<GenericBound>),
- /// `_`
+ /// A type that's left to be inferred, `_`
Infer,
- /// `*mut u32`, `*u8`, etc.
+ /// A raw pointer type, e.g. `*mut u32`, `*const u8`, etc.
RawPointer {
+ /// This is `true` for `*mut _` and `false` for `*const _`.
mutable: bool,
+ /// The type of the pointee.
#[serde(rename = "type")]
type_: Box<Type>,
},
/// `&'a mut String`, `&str`, etc.
BorrowedRef {
+ /// The name of the lifetime of the reference, if provided.
lifetime: Option<String>,
+ /// This is `true` for `&mut i32` and `false` for `&i32`
mutable: bool,
+ /// The type of the pointee, e.g. the `i32` in `&'a mut i32`
#[serde(rename = "type")]
type_: Box<Type>,
},
/// Associated types like `<Type as Trait>::Name` and `T::Item` where
/// `T: Iterator` or inherent associated types like `Struct::Name`.
QualifiedPath {
+ /// The name of the associated type in the parent type.
+ ///
+ /// ```ignore (incomplete expresssion)
+ /// <core::array::IntoIter<u32, 42> as Iterator>::Item
+ /// // ^^^^
+ /// ```
name: String,
+ /// The generic arguments provided to the associated type.
+ ///
+ /// ```ignore (incomplete expression)
+ /// <core::slice::IterMut<'static, u32> as BetterIterator>::Item<'static>
+ /// // ^^^^^^^^^
+ /// ```
args: Box<GenericArgs>,
+ /// The type with which this type is associated.
+ ///
+ /// ```ignore (incomplete expression)
+ /// <core::array::IntoIter<u32, 42> as Iterator>::Item
+ /// // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ /// ```
self_type: Box<Type>,
/// `None` iff this is an *inherent* associated type.
#[serde(rename = "trait")]
@@ -615,34 +1008,47 @@ pub enum Type {
},
}
+/// A type that has a simple path to it. This is the kind of type of structs, unions, enums, etc.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Path {
+ /// The name of the type as declared, e.g. in
+ ///
+ /// ```rust
+ /// mod foo {
+ /// struct Bar;
+ /// }
+ /// ```
+ ///
+ /// for `foo::Bar`, this field will be `Bar`.
pub name: String,
+ /// The ID of the type.
pub id: Id,
- /// Generic arguments to the type
- /// ```test
+ /// Generic arguments to the type.
+ ///
+ /// ```ignore (incomplete expression)
/// std::borrow::Cow<'static, str>
- /// ^^^^^^^^^^^^^^
- /// |
- /// this part
+ /// // ^^^^^^^^^^^^^^
/// ```
pub args: Option<Box<GenericArgs>>,
}
+/// A type that is a function pointer.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FunctionPointer {
+ /// The signature of the function.
pub decl: FnDecl,
/// Used for Higher-Rank Trait Bounds (HRTBs)
- /// ```text
- /// for<'c> fn(val: &'c i32) -> i32
- /// ^^^^^^^
- /// |
- /// this part
+ ///
+ /// ```ignore (incomplete expression)
+ /// for<'c> fn(val: &'c i32) -> i32
+ /// // ^^^^^^^
/// ```
pub generic_params: Vec<GenericParamDef>,
+ /// The core properties of the function, such as the ABI it conforms to, whether it's unsafe, etc.
pub header: Header,
}
+/// The signature of a function.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FnDecl {
/// List of argument names and their type.
@@ -650,42 +1056,86 @@ pub struct FnDecl {
/// Note that not all names will be valid identifiers, as some of
/// them may be patterns.
pub inputs: Vec<(String, Type)>,
+ /// The output type, if specified.
pub output: Option<Type>,
+ /// Whether the function accepts an arbitrary amount of trailing arguments the C way.
+ ///
+ /// ```ignore (incomplete code)
+ /// fn printf(fmt: &str, ...);
+ /// ```
pub c_variadic: bool,
}
+/// A `trait` declaration.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Trait {
+ /// Whether the trait is marked `auto` and is thus implemented automatically
+ /// for all aplicable types.
pub is_auto: bool,
+ /// Whether the trait is marked as `unsafe`.
pub is_unsafe: bool,
+ /// Whether the trait is [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety).
pub is_object_safe: bool,
+ /// Associated [`Item`]s that can/must be implemented by the `impl` blocks.
pub items: Vec<Id>,
+ /// Information about the type parameters and `where` clauses of the trait.
pub generics: Generics,
+ /// Constraints that must be met by the implementor of the trait.
pub bounds: Vec<GenericBound>,
+ /// The implementations of the trait.
pub implementations: Vec<Id>,
}
+/// A trait alias declaration, e.g. `trait Int = Add + Sub + Mul + Div;`
+///
+/// See [the tracking issue](https://github.com/rust-lang/rust/issues/41517)
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TraitAlias {
+ /// Information about the type parameters and `where` clauses of the alias.
pub generics: Generics,
+ /// The bounds that are associated with the alias.
pub params: Vec<GenericBound>,
}
+/// An `impl` block.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Impl {
+ /// Whether this impl is for an unsafe trait.
pub is_unsafe: bool,
+ /// Information about the impl’s type parameters and `where` clauses.
pub generics: Generics,
+ /// The list of the names of all the trait methods that weren't mentioned in this impl but
+ /// were provided by the trait itself.
+ ///
+ /// For example, for this impl of the [`PartialEq`] trait:
+ /// ```rust
+ /// struct Foo;
+ ///
+ /// impl PartialEq for Foo {
+ /// fn eq(&self, other: &Self) -> bool { todo!() }
+ /// }
+ /// ```
+ /// This field will be `["ne"]`, as it has a default implementation defined for it.
pub provided_trait_methods: Vec<String>,
+ /// The trait being implemented or `None` if the impl is inherent, which means
+ /// `impl Struct {}` as opposed to `impl Trait for Struct {}`.
#[serde(rename = "trait")]
pub trait_: Option<Path>,
+ /// The type that the impl block is for.
#[serde(rename = "for")]
pub for_: Type,
+ /// The list of associated items contained in this impl block.
pub items: Vec<Id>,
+ /// Whether this is a negative impl (e.g. `!Sized` or `!Send`).
pub negative: bool,
+ /// Whether this is an impl that’s implied by the compiler
+ /// (for autotraits, e.g. `Send` or `Sync`).
pub synthetic: bool,
+ // FIXME: document this
pub blanket_impl: Option<Type>,
}
+/// A `use` statement.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Import {
@@ -699,16 +1149,34 @@ pub struct Import {
/// pub use i32 as my_i32;
/// ```
pub id: Option<Id>,
- /// Whether this import uses a glob: `use source::*;`
+ /// Whether this statement is a wildcard `use`, e.g. `use source::*;`
pub glob: bool,
}
+/// A procedural macro.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ProcMacro {
+ /// How this macro is supposed to be called: `foo!()`, `#[foo]` or `#[derive(foo)]`
pub kind: MacroKind,
+ /// Helper attributes defined by a macro to be used inside it.
+ ///
+ /// Defined only for attribute & derive macros.
+ ///
+ /// E.g. the [`Default`] derive macro defines a `#[default]` helper attribute so that one can
+ /// do:
+ ///
+ /// ```rust
+ /// #[derive(Default)]
+ /// enum Option<T> {
+ /// #[default]
+ /// None,
+ /// Some(T),
+ /// }
+ /// ```
pub helpers: Vec<String>,
}
+/// The way a [`ProcMacro`] is declared to be used.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MacroKind {
@@ -720,30 +1188,36 @@ pub enum MacroKind {
Derive,
}
+/// A type alias declaration, e.g. `type Pig = std::borrow::Cow<'static, str>;`
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct TypeAlias {
+ /// The type referred to by this alias.
#[serde(rename = "type")]
pub type_: Type,
+ /// Information about the type parameters and `where` clauses of the alias.
pub generics: Generics,
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-pub struct OpaqueTy {
- pub bounds: Vec<GenericBound>,
- pub generics: Generics,
-}
-
+/// A `static` declaration.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Static {
+ /// The type of the static.
#[serde(rename = "type")]
pub type_: Type,
+ /// This is `true` for mutable statics, declared as `static mut X: T = f();`
pub mutable: bool,
+ /// The stringified expression for the initial value.
+ ///
+ /// It's not guaranteed that it'll match the actual source code for the initial value.
pub expr: String,
}
+/// A primitive type declaration. Declarations of this kind can only come from the core library.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Primitive {
+ /// The name of the type.
pub name: String,
+ /// The implementations, inherent and of traits, on the primitive type.
pub impls: Vec<Id>,
}
diff --git a/src/stage0 b/src/stage0
index f36010f..dcc2267 100644
--- a/src/stage0
+++ b/src/stage0
@@ -14,434 +14,448 @@
# All changes below this comment will be overridden the next time the
# tool is executed.
-compiler_date=2024-06-11
+compiler_date=2024-07-26
compiler_version=beta
-rustfmt_date=2024-06-11
+rustfmt_date=2024-07-30
rustfmt_version=nightly
-dist/2024-06-11/rustc-beta-x86_64-unknown-freebsd.tar.gz=4bf5a3ae2656a992beedec2f41dc98c791426a1a6a88f3503b003b4d6f0ddc1f
-dist/2024-06-11/rustc-beta-x86_64-unknown-freebsd.tar.xz=feaa1484586e78d77225734328d460277dde14baaf1299a30b30ef91e9a26a82
-dist/2024-06-11/rustc-beta-x86_64-unknown-illumos.tar.gz=9c692a71916f7ca9d41a97416f51d463b0495311491ba92b4d3cdb0f6c4e7c87
-dist/2024-06-11/rustc-beta-x86_64-unknown-illumos.tar.xz=97dece0cc2e4856a49f9ae17f09171fb55f140987acd0f988bbd0aa1e8971936
-dist/2024-06-11/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=6ad2e87e637302e8458d47dc1af923e38bffd7332775cfa5520c29110594d9b9
-dist/2024-06-11/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=84f6755c1377ced8ed2700b5ca9a2d38dd2e26a03e1fd636841ad46d3cf63895
-dist/2024-06-11/rustc-beta-i686-unknown-linux-gnu.tar.gz=11b439045379be2722cb42409b8bc342ff4b5f7df85e42566006cd72bb1a4e8a
-dist/2024-06-11/rustc-beta-i686-unknown-linux-gnu.tar.xz=4e5103702b4e43ea71914e9c508aeb0db6382ea331c31981142163b2a89e19e1
-dist/2024-06-11/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=396a3aaefca9511086f7e5442209b70622082d133b96783b4237c3f01f42bf87
-dist/2024-06-11/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=66e46ed344af9f165b7c4fde2c576340fa81ecade61c45ecc1562de70a9203da
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=831420b262c5a2f44459e0daceebe271f298179c37aa5b7a1704a15bbbb1fb97
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=691a6c4d0276add72cfab40968520ff48f683d4e660a50d1626ba9564dbf4914
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-musl.tar.gz=ebe1efe3c5d74e37d1c40dbd585ada7a7e256ce76911746f54994dfa15f9907f
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3bb37fcab069713fe8aa5ca72291a439eba5af4a3cc0be9d152e5f29ccaef864
-dist/2024-06-11/rustc-beta-s390x-unknown-linux-gnu.tar.gz=c00c2ecb5aae552069395d03f4135f051da073efc68ed645348f026c1884799b
-dist/2024-06-11/rustc-beta-s390x-unknown-linux-gnu.tar.xz=2c72347688058091a4bcb0c2fbcff49020df2b2c1733bc19d93b6e5149d5b13a
-dist/2024-06-11/rustc-beta-aarch64-pc-windows-msvc.tar.gz=517977edaa51470d460aa9ec09309eea2082cffa6adb13571a8f36efa9351dff
-dist/2024-06-11/rustc-beta-aarch64-pc-windows-msvc.tar.xz=0cc0b740cb267fde814b4971591b5797faa528b1e6250ef7b2d5220f0916208d
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-gnu.tar.gz=9fe7d85fdbca12fbfdb776789c336f726303c8845a6f6c93b2dc6ea8487585d4
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-gnu.tar.xz=38130e3d9779ad54bd890c4001b34b7c58368ed1940e7e676947e9c05a8f6649
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=acca3e045de3c0d908caec4249e3905d207d96b4a1722644457b3cbe5707422c
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e4e92fc4b672f72b1f03db62ae712d9f944b982db89cf0d8dcb94adb1d560b3e
-dist/2024-06-11/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=63274e707bd0d2b2f08c49f170f26773f802db833347d2aa694d345d11c841f5
-dist/2024-06-11/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=13702b24228d983710d5678e0a1003e4f77e2244fbdf599015f52adbbb77bfcc
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-msvc.tar.gz=ca877491bf7bf50989b9ac21c12e335fd0ff002ccf4a2c07316ae1df1a3d7e6b
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-msvc.tar.xz=d757a328595887039d8017e9e3faf79448850c3dd9bd3c26d309a313ccc09a38
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-musl.tar.gz=155497f2abe036f09f6aa014969d58132a9e2e4e148fea485b483e0dc3705a39
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-musl.tar.xz=6204d1fa08beeadcf1564e334cbb65a7317c571557cbc5517eb6bf08f5b0ce75
-dist/2024-06-11/rustc-beta-aarch64-apple-darwin.tar.gz=3bd7db536344c6a3d0d0bdf95986136d5db8996228802444b561783f2e7c3c9c
-dist/2024-06-11/rustc-beta-aarch64-apple-darwin.tar.xz=b425561b3e7d9130fae94e78522bb262c634304ced32030828743fb332b11ecb
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=e2f78198d33f98aa34bedd4f5920868a8f68620e29eca2917833f6a8f23f787c
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=22f3b45678081fe52a9c8e89234a9939aad5623eb43ec54921effc28c0bdcd80
-dist/2024-06-11/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=beb5ec95069cbac4e53c51ea3e785ab5f25122132c8b78b196372bb2a31ed46f
-dist/2024-06-11/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=17242f74c96cf581f2e40a82f6d7fbd585af2c2990cc73ad4ba7a3503dd279a3
-dist/2024-06-11/rustc-beta-x86_64-apple-darwin.tar.gz=d952d90397c70c5b53caa98b2e5d48e35780e1e5b342775c10fcbf504717d2ec
-dist/2024-06-11/rustc-beta-x86_64-apple-darwin.tar.xz=14bd4336eb396a133ddbb2acd01ae799f2f68a7ac723a00a9db8c3e06bfa8027
-dist/2024-06-11/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=a2118f80091d62ebb762df0bdd159d19befb440d754034da7348aae50d63628f
-dist/2024-06-11/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=a4b9d1a04d8f9cfd4daaf57fbeed3615d000c5107c6fa1b2992dad6ca552e35a
-dist/2024-06-11/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=d5c16c5621e43cd3007ba4d2bc0f6e8a3a2376bc2a911e42bd2f2670ff94c12c
-dist/2024-06-11/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=202662492afd863b6b6428a3bc5ed822c62ac2aeb8a0264df1d69cc5a3728d8f
-dist/2024-06-11/rustc-beta-i686-pc-windows-msvc.tar.gz=a9fb64cac53595444bdbe8f152e52214812498e0c6e2b664db10f1f693a92dca
-dist/2024-06-11/rustc-beta-i686-pc-windows-msvc.tar.xz=fe78c5ac51d96c3c3e222828dca3d105a2d4d7f8acd6e0d86ecd4b27ea70a4c3
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=8c584010c964ef1b02e1014ca1c6ed9584c1ff781f8af115ee001e3a13213954
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=4a407fb59db284ddf6fc0ccd487116fafbcd7c227f3dfd4e0b7b64dd560dc113
-dist/2024-06-11/rustc-beta-x86_64-unknown-netbsd.tar.gz=2f07a283bb0e57ad50366b67d216503a423867eae205e4354b74b748e9d3ce85
-dist/2024-06-11/rustc-beta-x86_64-unknown-netbsd.tar.xz=8008331b32e9d0daeb275327082e38671dcc91864a3ac95be67bd15ecaa852ad
-dist/2024-06-11/rustc-beta-i686-pc-windows-gnu.tar.gz=c42637a8aa8666d746a45c9f47b437a9720d355b5bc6db42c2a90fb03d2c4a26
-dist/2024-06-11/rustc-beta-i686-pc-windows-gnu.tar.xz=eabe3a7e72829e0e5904ef381157cc3da169d9f5942e0367b2d1b1781c387560
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=f4010eea815cbab895c96311a456c4e3aa24c5f0d55f09052bcde59de7f286e6
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=a8f555c713cbe4a1860ee5bc812eb624f2775e034da54bd0e37c325453d70448
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=c89619ed4ec28d4f48ef2f7e51155716483a7f4bb51fe38235e69d4694cfcbe5
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=89aa3d1add14298bd40e3bcbc6b41df91312258ac6f203fff9eca4422f0c5e9f
-dist/2024-06-11/rust-std-beta-x86_64-apple-darwin.tar.gz=2303e7926bcc4fa2c67c7063fcac3a7b581fdd91fb89123cb6cdf514ff38afed
-dist/2024-06-11/rust-std-beta-x86_64-apple-darwin.tar.xz=9ddf392d8c696e902c2924ff938a4bd099b9a54834dc62710e42527e464e776f
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6016b465a0cfc628f2c978ed18bc19a4a27e20a5ac11a170c40d01a857a5f50a
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=8e3d6f7ef6efead7d08b1c889bcc6e520d0a6d29226ade1b150aeb625fdb9abd
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=5f53b7630fa7703fc6752c3fb8c8eba8e25b9f77a3b91e14982510a0091d9e44
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=8ed3c2f0b0f81d197d0dbd01aa777eb17ebc7303176601be2b2b05ebe1bcc971
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=dbc1a1bb8cfb4472739d7f3a52bcd571357d2d2761f3723aa4c7d69abe9a5dfc
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=58f46f20d58669d497ff683d6ea85e18ff68d51a442f6e21bc20ddee779e1c4f
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=d71947b5ddcfe538162b14d6b785c365c34f2b6ac2f1abdc90b020c4a446a313
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=ca0a665e566b3ff74c5f552e7e4e030d3cae9080dbb6055dce3aa41206b5b111
-dist/2024-06-11/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=e927c0890d2c5135d86b1960b6b182d5c47853b53eeb196b4748e7b8ec9362e4
-dist/2024-06-11/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=df33672f826ce8681d6c18ec2129ef47623b7cbaf6515cd921d39dfc05cb7a06
-dist/2024-06-11/rust-std-beta-i686-linux-android.tar.gz=2559fdcf250e7e0a1b5589e8f2bc69340f5610b7e6ddf08185936fa2e6f10534
-dist/2024-06-11/rust-std-beta-i686-linux-android.tar.xz=442f0aa53f343eec2b6984934bbf0651ff45f314d1f46dad2aa11a2f5c5a5a5b
-dist/2024-06-11/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=cb657852d05766e1c18b11d99a94f3570b6c6147dbf9b2113b80236566d2d4ac
-dist/2024-06-11/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=943de72c556821b67d59afd9dd128bfb01b3ba743dd3e7561c50559afd3768f4
-dist/2024-06-11/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a7c6d3f54d925be073007e3737173b0def7d781b6bfd5345971a69300aeee9c3
-dist/2024-06-11/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=cb9115328bf6f5ae661ce5bc9cc9165c6c9e6f759f3cc5038154531b314e6013
-dist/2024-06-11/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=2a2dac9fba84958818f6b31f30f91fcfef521111827937c88aa696b646f5b075
-dist/2024-06-11/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d16b28da0196a815f028d432dfa0957d0bfb512b259129969548bd050afac872
-dist/2024-06-11/rust-std-beta-armv7a-none-eabi.tar.gz=d78f96102490f9025598b11cb72e31e96d3f5fd566e8f7b2b2c503a37b0dc6c3
-dist/2024-06-11/rust-std-beta-armv7a-none-eabi.tar.xz=a439af58e90970b4dadaa04d8f94ea53c6c7a159117926c46b7da0eaa0d0ca5b
-dist/2024-06-11/rust-std-beta-i686-pc-windows-msvc.tar.gz=d7847f3d9b1a2f50541ef3d2c25eeda469b28412817cadca52756aeb4f2c57b1
-dist/2024-06-11/rust-std-beta-i686-pc-windows-msvc.tar.xz=622cafc347ec1d3f0ef70354a0713cd255029730b17ad1f1ee951d9b0cb515e5
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=5fee2542ee8ee8d155edc0ac36ec8822896e6f93f9f573b9284d70aeb186a05d
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=dfe9ca3e3f217922b65db0d65826c0962369fefd3d5d72d6f03039acd710f122
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=b0937c5dcd458f313aabe07668ea338f2629bfc9c45d6139211b6923a7c7eb0e
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=65973a26c69f8ca7d3022180e2729161f7a618706cd9974fc54b14cf48f1af79
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none.tar.gz=def2fc3aca20a74d023156606067f88ea8f1c8b602fb628b8f27ee43e3b62cfd
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none.tar.xz=43cdb54af35a6c00ee10759a3f6ff6ca5c9080ba817aaf2eab7df8f239d77196
-dist/2024-06-11/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=ae2cbe53d304442e112585dd968f72454cc33bb75d3b4d7854a04575ff7b5301
-dist/2024-06-11/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=b3192290a45ff978126f4f08e7ddaf6de8720a2f6abbc5b41536fad6f994d7ae
-dist/2024-06-11/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=0e2dc167dbb66366252100fc87b94a67cca3360343302697c2989beb2eb14704
-dist/2024-06-11/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=6144604269f533eed11471b4c5d2f31a9f8340d9edf0f398a42e6e970c95b991
-dist/2024-06-11/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b57e11248924ac54500d80525b8fe823e7dc74bc579c2b7f3f076c0a4c85ee2a
-dist/2024-06-11/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=9e473a5de0d02e6d8278a9e2430af135e3d6d4ecf5ce59827b384c8f20af39c2
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=1a62b5af52767e68146a45a47384b33c93b32a4579e51d41f66746e38dfa6eba
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=81bcf448ec54470edf60c2079ad9ef03f34052aef5fe9d8f5af933c565fdfd29
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=88eb49f86265a7fdb49b455cf5a9a373ac1e0f7cbcac08ef2194eaefbb039b22
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=bf9a278615765e199786d16f154006007ddfca0d5a5869c55a05e513a7b06580
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabihf.tar.gz=13f16402dea66facba6e10a9556e0afdbd6b004e8aa5d08e106cf76ea59b8288
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabihf.tar.xz=7ecd66dc65758cdf32cdebc38f6f399392788a7085d69ec7e8fbd63be7b3e904
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=96ccb2252defcd5bcd9eca19380b9d4e4115ffb135efebe6717b1527ee440bf8
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=c31f4ef95857a445bc480b73babb886e259443b3137efd694c4b67f913838212
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabi.tar.gz=0637fe1ab1284334ed4f9aec87a4b51b6983418997844e10ffe20326078f6d18
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabi.tar.xz=ac7f13ba1a107d03c1b7bb0d2e6753b926a26554c82de38263113e2d5dfeca21
-dist/2024-06-11/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0e8a21970d4ea6331968b10e990cb6dbe3d38af393e4dc8d603efec1b59aa0bd
-dist/2024-06-11/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=04b9663cef2d3507c96b77b18aff7c9beee0f6bd0e0cb9ef37b8c9cacadbb198
-dist/2024-06-11/rust-std-beta-wasm32-unknown-emscripten.tar.gz=01d4da0efebf4615da7c92c6cfdaedaf283d3f5e66c58a1b1e2e17488d86b3d3
-dist/2024-06-11/rust-std-beta-wasm32-unknown-emscripten.tar.xz=c203ec9216407f90d0bcc451e40a29e50279dae8ee161f05d9245e3cc8e1b30a
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=3621e0a16f7e6d9f292894a343941399a54b5d76a858fe5a69b83c95f15ada07
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=5944208b88c6924f8586304abea6827cdf756066158dc64200e207027143e843
-dist/2024-06-11/rust-std-beta-aarch64-unknown-uefi.tar.gz=1887e342d5c6453a63336023e51c124838762f89e9289d1abd8226a717bb96d3
-dist/2024-06-11/rust-std-beta-aarch64-unknown-uefi.tar.xz=ba0ca831ed66a72a14c8c9dd591e97d7d6cbc55762c961283088e897de4a8669
-dist/2024-06-11/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=59790fb6982ebfefc40d352d411604840b7540a6ddfb26ad14d70e139df3ab99
-dist/2024-06-11/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=c022c80da2debecdbea32ce34ef040bdebc8566a78e2867512815532746e1c95
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabihf.tar.gz=4d4a380bed233e86ea957c173412b819fce00d66d369657a0778da5e4f244034
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabihf.tar.xz=577763a4758c42bcf0c875d606a6dd538c07866e9a65c2b73271f0e9d0762830
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-gnu.tar.gz=29f8e4dc5d88bfd66f600402022267ad85d4afcffd7142107d0fd28d0cae4cd8
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-gnu.tar.xz=d030db59dd1788fa8438c52b9a8cbc6754eaf529de60fa4fa9693a687e644dfb
-dist/2024-06-11/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=df978c1519ea4b50fcec2ec18d2cd9a6b813982dc50f6442af9ce340b98a8c46
-dist/2024-06-11/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=13585b56ce162922dbf03d0b6432a6af9b9059a664063a6adca957301c23b905
-dist/2024-06-11/rust-std-beta-wasm32-unknown-unknown.tar.gz=6365c96d363a345c4882ad47a3e9242f37c930a10bdc89d137e5e05b1b599351
-dist/2024-06-11/rust-std-beta-wasm32-unknown-unknown.tar.xz=480e07d3f110ff9f201315f5a01bf674ead911773241d80d9005772cfe4a3d88
-dist/2024-06-11/rust-std-beta-armv7r-none-eabi.tar.gz=0514e7022540078895be3000fa0405157bf1165762e77672f78230e62ef2c8ec
-dist/2024-06-11/rust-std-beta-armv7r-none-eabi.tar.xz=659cec4d3e3f0783bf9a8b42a245b995e00b36a8ff04a9b6b458ace016d825d1
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnu.tar.gz=2c6b17e0fa22a9d528217fdb8231aefd21839e29babad0fd975fd3654a9706f2
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnu.tar.xz=c2c98b0c6b21618d5c49283f19ccdd3ba76159afd904c9683251d36317582615
-dist/2024-06-11/rust-std-beta-x86_64-pc-solaris.tar.gz=9433aed1f5f87157cf02d13e7ad375e9a2e9a260afb8419a05eeb1856069ab26
-dist/2024-06-11/rust-std-beta-x86_64-pc-solaris.tar.xz=2a39a792676fd60f47db90979fd56f3fee709d05d91b5c8bf4e0a01f39fed14e
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=29e4553e9889c3e202f550042555b5c24cf52ce68979870fe33d9e9eaad37db0
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=7d56ef2eb64550f95b2ec1e1cfb9f153e9c6b412dcceef35f76db44eccd4d8a1
-dist/2024-06-11/rust-std-beta-i586-pc-windows-msvc.tar.gz=da7c08348c6834793263e136747e0e3dfcd5cd805c0c6ca25323fab8a30de427
-dist/2024-06-11/rust-std-beta-i586-pc-windows-msvc.tar.xz=3d60ea1671800cb8f271f1869186ed099f35ee8171d23df7c6ef0c79b4567540
-dist/2024-06-11/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f3cfa8625f3586ddf48c301b7016d49d216324daaa3b76168a97f15506346c3a
-dist/2024-06-11/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=2e5388097f10a3640514d1a4040f6fec090e1c4aba0259cbdd900ead7fcdfd94
-dist/2024-06-11/rust-std-beta-i686-unknown-freebsd.tar.gz=cf38eeced5efe6139043e123b217a5c3f43bef3d86001a9a51fa21b012c9b468
-dist/2024-06-11/rust-std-beta-i686-unknown-freebsd.tar.xz=e078625da24308d78603400e96454e60606bed23f1132b64efbbbc815791d58c
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios.tar.gz=2f1dcaa67df6adacbb850bf17ed5df8258fd2087668d028814874fc8292bf420
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios.tar.xz=2a11e0abb8b162a12f72825cac59cc0df993b5582d911bdf6b97252078887651
-dist/2024-06-11/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d7f4366df7f3599f031b9654d3c0bebd9c21ec530330283e6560cceccc17365b
-dist/2024-06-11/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=cb9e8470fd9934870cbb881f7611a0bd614416faa42cfa6096a1ed19abdf9cac
-dist/2024-06-11/rust-std-beta-wasm32-wasi.tar.gz=5e7d7b535a7c1449a4dcac4022de279c7676852a7da3e63dc063595dd3fa1b54
-dist/2024-06-11/rust-std-beta-wasm32-wasi.tar.xz=c4db5ad4aa261a01ba3fd8a191c7ac6323e6134b2e17522b3fe0891a642d4c87
-dist/2024-06-11/rust-std-beta-x86_64-apple-ios.tar.gz=a27f3ff22b233c72673e32bf257f766ad8e11abfaf9f83fc7c3e756f785ee83e
-dist/2024-06-11/rust-std-beta-x86_64-apple-ios.tar.xz=8592a2f8b1d6c3cab199cabe8b6e9a668b90bd77bf6a5e0869e2b4f3cc6d1170
-dist/2024-06-11/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=ffd9d5acd9a2a33e6a699b850d1776521da443b52504ba77fc71d6dd7353e18d
-dist/2024-06-11/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=e92eec9cd55b37f135237c98cfe00c4ee23d2ef400cc3470deb8f1a0010e94c3
-dist/2024-06-11/rust-std-beta-x86_64-unknown-illumos.tar.gz=b1d2e427120295375eecc3d8fc647fe57e1195210d7d0243b20d156f173c3155
-dist/2024-06-11/rust-std-beta-x86_64-unknown-illumos.tar.xz=b97fe83bb5050460465c57c37456868368d0ce18e5134fedad07ae00df8b7432
-dist/2024-06-11/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=25ad2d1a91456394427a5db691ebd903e56e60daa89d73598155655caf6592b6
-dist/2024-06-11/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=88b0a7fb002922f78af0f8e9580acdfeb4c341c9fad35e53daf4d6073c73ab8f
-dist/2024-06-11/rust-std-beta-x86_64-unknown-netbsd.tar.gz=b5e129c655bdc051eaa5aca8c8a577914100137a5bca753df619edd22889a1c2
-dist/2024-06-11/rust-std-beta-x86_64-unknown-netbsd.tar.xz=5fc42453c00c3498af2fd60fa4345c2047f302113666bf4a1d044539e3c1e66d
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=afb1e9e37af72ba42b71f2a8a78ef7ba8593dbf8e35501e20a81e2aae204722e
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=3b7f63b544a5e8aad8a18097b915e01c1fb880d48514bd1fefe3a5d4872eae28
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=bc151debda651b76573e77c489c3b9c2be4af0f632e0061e067889f21ab254fb
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=f2f9225460e2e7fa7d28cee2dfdab483698c6f51b0eeafe49e2d8e44381a727c
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=5418a327d270c603ddc903ae6061fcb6bc9bca14593f13fe10ab3fe0f4a656ca
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=423e7f6fd6555c6d850e7317a8677d4778bc1270d3cfefc05614ef1acc61fd96
-dist/2024-06-11/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=d30d36a72c1e874a7f9df7f805f5cea3617f912b5ad5e7163616b07022e0f7ae
-dist/2024-06-11/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=4afd0b4ab3787dcbb2b2f686d56844c6aa3af69fbd72d04bd57901fdd58b6333
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=0a9b8bd1d39d346a20803ede808815dbf0cd55d9167561c8aabe7db3300a3dda
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=e36372611dd3cdabd1f32fb942c79bd31b5fc13946448cbf9a178ad5005dc7b5
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=2fe6221704614b167d837f52cfd439d9586e27ae82a34577659f86382c3192fe
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=55ffdc97b8b6d309b1aa8443b49a5fd6133f5d7653069eb7f32625c1c0bf86ea
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=87386371b64d4d922dc2fd01a0db28191748002b74a59437ddbab572b0d6fce5
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=6c1f9a6683a9d3ad8203b9d08ed829e4990675cb07fdc2214fc1f7970dee7e60
-dist/2024-06-11/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=525a64f28aa0d757e82558737db3150ff90ecb885c3da8e0215370e47fb2ff23
-dist/2024-06-11/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=af49d1730949036a48c05a147a3c67885326df5bea314fef2828e04433f33ef0
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabi.tar.gz=eba00bc621ee0235444698e5bc67780bc93765e70bed11634a8555d8d645635b
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabi.tar.xz=236fe5262d76fd8ab7c12ab6c231608c7e704e5fc0d95210b47e0c86201d8a8d
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=ac98cc34543e6faa0429cb9756d1b0d30dc13d8d8a44380b5feecc0e7d083e40
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ed8fffbe7899a7c35e5985adae1b35b7eabd076970a8eac280e834b7877f272c
-dist/2024-06-11/rust-std-beta-x86_64-linux-android.tar.gz=fa53ef5ea66f93f9fa46ac84d3cf6a16743b46a941910b092c9c71208a15defd
-dist/2024-06-11/rust-std-beta-x86_64-linux-android.tar.xz=66b394876549c4faaf872d4103ee49ef59cfba5c78777c01ad1df00dc6babd14
-dist/2024-06-11/rust-std-beta-sparcv9-sun-solaris.tar.gz=63794d1cc16a541cc07b56870d86db2212c2c8e3f06e11fd9bdca90fd93aa56f
-dist/2024-06-11/rust-std-beta-sparcv9-sun-solaris.tar.xz=4d419a3c4402c303b9437c7564e2bea79575623eaa0b300c2fe688d9d8f9db95
-dist/2024-06-11/rust-std-beta-aarch64-linux-android.tar.gz=b82186abf1bb250753a2640def13aa477b606e0601c5c1fdb25af0e37ea638b0
-dist/2024-06-11/rust-std-beta-aarch64-linux-android.tar.xz=57065c7b4f1f5d51d1366164b62b4114ab95f1a68cf551d12db8e9a2dad044dd
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=bef7ed6391f906226a20f8d2d842fbc335891d7fb92f91b1c5873ce778d70675
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=d80843f5f25923605681541b285ebf6868c0368841efacd376aac4dc9f01d0ce
-dist/2024-06-11/rust-std-beta-armv7r-none-eabihf.tar.gz=5b7d75f5f9294327ffb3c441b2e99fbc8402d1dfe0afaa20b2981a987e96801b
-dist/2024-06-11/rust-std-beta-armv7r-none-eabihf.tar.xz=ab56542b3be354d6c4f19fefe90af2daf59507e969a4144b6553a900e37e2a4e
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=7365d0ccde4cd000b44992c80cf0e48ead99c2a00e18cde4446d9401792606a3
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=69124687ee3ff876f557b7b21c8f78f7015c5f3b6537b65480613469772e00ec
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=d1307c1b3fab3dcb6b1e5cfd5c30e1ef1c7b7e1e831ccecb00ce35bc2c1d8b9c
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=8685907906feb9e16e34d4ea72e3ad338df9d6407dca6da81739b100926efcd2
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=d8c1c3d800eaedcf23c25f436e30892df1938a618200f0f041fc1921a5b517ac
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=53493d039721d5a2f54eb49ba7e16a205dd846bee559519182ca0af30111d182
-dist/2024-06-11/rust-std-beta-x86_64-unknown-redox.tar.gz=3f9842f81f45cbf35fd923ea69f1c88696070edfec0dcecac286519820741078
-dist/2024-06-11/rust-std-beta-x86_64-unknown-redox.tar.xz=73bc6b9b72bf6a9ba7dabe63b7a7d426eb47716466000d05802ef78ccb9128e4
-dist/2024-06-11/rust-std-beta-i686-unknown-uefi.tar.gz=c9954b477c329c3706891f77e9163d98aeadd96b1aa8a71f1eac20f316a9269f
-dist/2024-06-11/rust-std-beta-i686-unknown-uefi.tar.xz=88876cb6cf03707065fe172540e82faaf5dd55332c939891253476d4da3f8a00
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=e731faa24568e97821c5960229dd9a489ea7ead964a5aa052a6db322bcc55c18
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=47b529a6e19c9d609c41809fd62906c34f23a5c515bf62d91e88a87cf7cc0c85
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none.tar.gz=c6150b3b7481f2396b305188a16c4ce2206c440e9d7639446c76566d00dc5159
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none.tar.xz=e641747ef4ae46e4d0a8a3050d00b1b8c21c0f25da53a54de8e540a9953468db
-dist/2024-06-11/rust-std-beta-wasm32-wasip1-threads.tar.gz=37d141ba5beeaefd08834154f66219df734c379c9315c094433aebb75b82bca7
-dist/2024-06-11/rust-std-beta-wasm32-wasip1-threads.tar.xz=2045a0b765de96eb17e18d8028ed2e553cc998fb71a4811e3d848db320f6b9a3
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=82de12e6a2b01c0b98c83b4264a4e00ceefc424f673c97826bb28729c3f31382
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c97b8a57ed8eefd60bbfe2df54121c548d9e271d9691def843185bac9d82b703
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=6903175fa7cc3fdda5545ce11f4cc504e4183e56c626e25ff2b0d20a4f5190c4
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=df06eee91ba57ff2c0a779da5d746db02f682514b8c03de875f03c96d05188e5
-dist/2024-06-11/rust-std-beta-thumbv7m-none-eabi.tar.gz=d7023edb8c723803e114e5b8ed316a6839e0c37d92cf6a2a09b767ee5ea2b7b9
-dist/2024-06-11/rust-std-beta-thumbv7m-none-eabi.tar.xz=41e19659bc0e0445ebafc49740579f0ac23a9af8e233c529ba2132f3d111faa9
-dist/2024-06-11/rust-std-beta-arm-linux-androideabi.tar.gz=42c0a6bfed8ca53b8833dbee78f2eab92bee061c42a4d629e870c8e655bc3728
-dist/2024-06-11/rust-std-beta-arm-linux-androideabi.tar.xz=5f85c99315a18bfc7fcc3f0caa7218ddc3b6548eb04be0ded835b5c45ec2ae89
-dist/2024-06-11/rust-std-beta-wasm32-wasip1.tar.gz=97abd2b9a68973263da0116eb5a0b9ead2145c1550f3190d02b35606bb9dcf58
-dist/2024-06-11/rust-std-beta-wasm32-wasip1.tar.xz=4ba0ef9b136761e739ab8ef125ffd993ccf71161d69e7640d94de6d5df601dff
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=886562504ee3e73ceedce6cfcc8d128f22a80f0a33c84b9c29920d7760a8a208
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a8f28e60aa1938cdc7b7d46a1fa770d587be9534a291f5367a80a52772a0b458
-dist/2024-06-11/rust-std-beta-x86_64-unknown-none.tar.gz=642e7fbeaa76403ccfaf6c3c1bfaa8b94ded7311abfece44c863df231c282406
-dist/2024-06-11/rust-std-beta-x86_64-unknown-none.tar.xz=b1441ef88a1a97ecb6d7b674b571beeefab9f59fc8799d9e63b8a01078042f15
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-gnu.tar.gz=fba54c97da35d0f11af99dca7cb0f43784da2104c461518149974da1f2248301
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-gnu.tar.xz=e7acfab1f7bb8b2c2a0f7558b813f627a3f6b6dadcd05f62c5895f753c2f3ffa
-dist/2024-06-11/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=e4d5ec39520d069609f32c4dc7dd4114623bcd112a729529a096c992fc19f61e
-dist/2024-06-11/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=94d508cc6c86516ae5e3bba9366cb466635a1e3f41fd00ba6b1a44a87175fea5
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=76e17967c09311f9e0c684531f21588d5bfbbdd4c707e454068df240fcfa56ab
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=e627a81855b3d93497b071138917dcf6382b60793a4a76073769537531d01789
-dist/2024-06-11/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=aa5a1b430e31bd5f912d378eab8447ecd920a5840c03b01799a410d86a7c4850
-dist/2024-06-11/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=20f6fc50caaff58aa2883696c61031e9cec5cc24aea94026cf9b84a7642c4d31
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-musl.tar.gz=62d2daf4c1a0a6b4630559c64bc22ceccd658ea0e9e74ebf58a9b791226964fd
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-musl.tar.xz=34681e4cac9a6e18f1952f51d6192c8b71b970a0edaf0a06766e1a576a7898d9
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=da45a5c9a7c7c1db32d6664358699ceeb27f59247862190a93ac203e5f49f116
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=f881c61a8ed04f02576374a82f28505be2ad4b694254503d30c1ab415b6b5a74
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-musl.tar.gz=2056b8d9d54baeab1fcf7dcf65916645f8404413bff60851fd97108b7822a54b
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-musl.tar.xz=d06fd5dcb976c5331185d308e2ac0e53597275a57603aa171a753b3d005f0667
-dist/2024-06-11/rust-std-beta-armv7-linux-androideabi.tar.gz=27fb1ba34b2331810174f88d0e75075d6af26ef3fb7cd3ec820408e819f36cc8
-dist/2024-06-11/rust-std-beta-armv7-linux-androideabi.tar.xz=f44ff932cecc16cb292a6149ac42fb440b5e4a8a6b56f55634d9031002eb56f7
-dist/2024-06-11/rust-std-beta-aarch64-apple-darwin.tar.gz=3ab3178d3c1d4b9908dc2d0b6236c147e8f787f323c0c02fb924e2d692ec839e
-dist/2024-06-11/rust-std-beta-aarch64-apple-darwin.tar.xz=4b67844f0413cd1b0fde9702542eb2ce297020c29531230c37d3e2f65d56b0e3
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios-sim.tar.gz=317035259b48845882a4561bd1c61108331ce68231b3362fa6e9b0a323ea3fc5
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios-sim.tar.xz=04585ea6b3e53cdf62372dc64f00237d26991a2f7ca6ce06f921065957c2ffc8
-dist/2024-06-11/rust-std-beta-x86_64-unknown-freebsd.tar.gz=048684f3b437110dee704d8ef58f166806d69504a0fbf661ad71d19575cc8436
-dist/2024-06-11/rust-std-beta-x86_64-unknown-freebsd.tar.xz=43762fd9d2cf4dda5e8b64dccbabf5637dde37685530eceba060faeba8212b62
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=40b3feff4834beb31125cffff479288adb2cc8a2d9b8963943907ba2b5478589
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=f088ad7f9697570c251655adbf6921341f74bb8deaa445cdb0d15e5ab556699c
-dist/2024-06-11/rust-std-beta-thumbv6m-none-eabi.tar.gz=94b65456fa327c6d8acd59f1fd004feea8572374e8eadc022338de75c45a6c03
-dist/2024-06-11/rust-std-beta-thumbv6m-none-eabi.tar.xz=9ca368829aaab88a93abb580a0ecc1195ce5fa3877bd556c856ab52af51095ec
-dist/2024-06-11/rust-std-beta-x86_64-unknown-uefi.tar.gz=1a9892b1efce5e6aaa361675e008c623c47056a64deb73246c4211f5194f31a9
-dist/2024-06-11/rust-std-beta-x86_64-unknown-uefi.tar.xz=e9a2df6f754ff4c1ced354250de51939efb1e003843f1d0d8962c2a25e7c0f46
-dist/2024-06-11/cargo-beta-x86_64-unknown-illumos.tar.gz=d6f794f092c47e97e822dd6526ac2622f8a7b3a3cfa8b8462b3378eb16dc4801
-dist/2024-06-11/cargo-beta-x86_64-unknown-illumos.tar.xz=bcf8204f4750c6ea9ff5667ae07de7d06e5b68e78176adb79fc1bc433f7d90c0
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=27ba1abe717de9e96b802c8026a17a6b5f5dc728ba4813c705a03d54c234be3f
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=55cbb9abf863c05f13049bc59e99ea3e64523f0193ba1dd155b21cb732db50c2
-dist/2024-06-11/cargo-beta-i686-pc-windows-msvc.tar.gz=ceb0b610395fb2519bc6207b7916f402a17fac9685cf8b5c2ee354b350b396ff
-dist/2024-06-11/cargo-beta-i686-pc-windows-msvc.tar.xz=73f1cca9028510331477a0299e214d50a3b9ad02ac035d056acce110f52a1463
-dist/2024-06-11/cargo-beta-s390x-unknown-linux-gnu.tar.gz=eb0dbf227a1ad39436af2334ddb6e90831881c75c24855e9c040bcbb6ce8d876
-dist/2024-06-11/cargo-beta-s390x-unknown-linux-gnu.tar.xz=1b95d58699e8f534b5d93ad02c4281d8e791e8c266f10820de887fe13b1d88c6
-dist/2024-06-11/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=b078cbb4e2e18b6da3618a1048b038c52bf37a398618179b1c03f25d5e154ce0
-dist/2024-06-11/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=80bd1e79864e21ed914a6a2b8ee5d66867734252002789c6d76c3f7e82133eab
-dist/2024-06-11/cargo-beta-x86_64-unknown-netbsd.tar.gz=e2fb5140e90588e6ab158352e3f198ea71107a1aa01785f692d5ef64925af58d
-dist/2024-06-11/cargo-beta-x86_64-unknown-netbsd.tar.xz=6bf7fc08f593ef8847b3b14a33783fb3c54c542fe61a8a92c0e462a1bbf34b9c
-dist/2024-06-11/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=6cc72fe175632e68fefaea683c0569e9fe8f036488154e4f1ccd6a3135479cfa
-dist/2024-06-11/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b27004517d35019ead69bcd1a09c81aa20d2b00b57ad42655f1f434f8d66eed3
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-msvc.tar.gz=e5d5945884554970344d16e90f9eed0dd60f61ed57e48b40fac2ee1d7c035475
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-msvc.tar.xz=421ee0fca436d4d4d3bcd03c242f9312fa620da854b906618a1d8ab27979d609
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-musl.tar.gz=7406ba1c14e53da0a9ca696dc6c90fb816c072734f569c01f49c6b8f7d542d81
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-musl.tar.xz=917a2e63fcf03be81375143692306afb54fc2addef9f5508dd58fc1729119752
-dist/2024-06-11/cargo-beta-i686-unknown-linux-gnu.tar.gz=bdbd9c4e2808d9dd0acd219c3ba9972634d73fc4f177468bc196c66be620df65
-dist/2024-06-11/cargo-beta-i686-unknown-linux-gnu.tar.xz=e64d3405f99f8ad74984b81238a088b250be4e079e2c05aa68be1cf84f04154c
-dist/2024-06-11/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=bf7c374c02676f9e5a50f4964e6deb4d3aab19ecd66c4d246de0c9a06ebd23bd
-dist/2024-06-11/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=52e7907ca99467c71429d03012a3f6cdd95711b9cf002d3aa06ba25b3e53d2b1
-dist/2024-06-11/cargo-beta-x86_64-unknown-freebsd.tar.gz=bd9aace135befd19104b193e09bf982c79c8cb9cce301ff709cde2ee2dc82821
-dist/2024-06-11/cargo-beta-x86_64-unknown-freebsd.tar.xz=c0d2c3a2e56a1f43f62fb73e41b07def93baa278172d822a2a33f571d54f0463
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-musl.tar.gz=61526c6e4f0ce1a57d4831ac67252cf5a6cef3c106c6953b329bc0aa9c685e6c
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-musl.tar.xz=82bcddea6b3d976e7dee07afe7f805f5a6ff66f0721d281d2c896f352f395c89
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=70c5bd18c756123f033a7cec027631f71d7400cb4d0c85d7602a8a6309379070
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=f8a6c7dd8ba408a5fe623a0ca1d2f8bfe287b13bc09b1d8ea636ebbdec06c557
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-gnu.tar.gz=fe26e842e6e4186437ea679cc75cd37d70a98b1ed0f17ed9ac876aa0501ebd5d
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-gnu.tar.xz=f3fcb2b698736b3df87c06ba829a1f09c218e37b51ff1c59f165aaf8078c619f
-dist/2024-06-11/cargo-beta-i686-pc-windows-gnu.tar.gz=607f623f30e25541d9e6c8412bffcb9c16f7180250a244dfe1e2606edd45db42
-dist/2024-06-11/cargo-beta-i686-pc-windows-gnu.tar.xz=604369c997e05719d0fae92f7904e6b66f662bb75add1d836cb100e0032526a3
-dist/2024-06-11/cargo-beta-aarch64-pc-windows-msvc.tar.gz=de283125b79d17f4cf24bb608819177ac1637525b8c7e67a66e798f0c0b1024a
-dist/2024-06-11/cargo-beta-aarch64-pc-windows-msvc.tar.xz=8228a47ce003faf1edb4a10cf800d3316ba421a97176c97f6952743f7eddf734
-dist/2024-06-11/cargo-beta-aarch64-apple-darwin.tar.gz=8525a4015fa8078921f8bc5f67012c0d5747b7e7111079bffce79f2b696fbd4a
-dist/2024-06-11/cargo-beta-aarch64-apple-darwin.tar.xz=038c700f1b0ab543bb765a4b86638fc7eb1e44257a19d5a5457fcff4fc08f280
-dist/2024-06-11/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=16c75d17531e10f1bb9e95c79d8c3aa05549db3029663c69d2f56b2d2f3214d8
-dist/2024-06-11/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=113d97f781bf8d54f457e07fbe3de1d3a0ce0a1f8054a652083b67b81f4cb642
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=7856fc9731c3dd7b360eacf422ce358acb2d33a7fd8b16fa190dc77cd9bdb3de
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=85c930785fe9857458c9256c5a2849ae223c5dd162bd20ccc8021b2d2ff0a6ba
-dist/2024-06-11/cargo-beta-x86_64-apple-darwin.tar.gz=aa4aec2cf417a7446c2990d03cfb3dcaab9d99f5ac249cbb955a59a64b5b7b0f
-dist/2024-06-11/cargo-beta-x86_64-apple-darwin.tar.xz=01d4bd8dd8a58f16ee31df775d0d7046ce671dc86f8907514e3713a62aadbb12
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6e5c68d0665add368a6574528184dc1d182e7d72b8da0827b69eb9f9aecbc4ac
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=180a6148f5c5be222d4e2626eed9cd7de2e0f62d0b456e520d1ab7c4931e1f4e
-dist/2024-06-11/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=6af892aa858f35708bf9db322abf35967b1e92725e05f6974e1d9ee3cb4c7b84
-dist/2024-06-11/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=40ffc9713504366978bb6f2eea12741400164318945df22290c7b669d3b77878
-dist/2024-06-11/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=9989b0189f7a4c5aa39c39c78be04e7291cc1358ebed597636f404f56980c199
-dist/2024-06-11/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=8c7d7dc2530f25cc771c75d454fd11f3e94c7954bb869e43736860be1f253d2b
-dist/2024-06-11/clippy-beta-i686-unknown-linux-gnu.tar.gz=94505902c45770c45a89ea12759bf46cd97efed657b43322d5dd09c13ed26331
-dist/2024-06-11/clippy-beta-i686-unknown-linux-gnu.tar.xz=14830f6fa92b0d814527a9aa5575d0cd529e76dbe2481533b819c735470ad684
-dist/2024-06-11/clippy-beta-x86_64-unknown-netbsd.tar.gz=5cc5f4202003b940a6a62c2384c749b741a9f6d62461ba13a6179464f6c3e6ea
-dist/2024-06-11/clippy-beta-x86_64-unknown-netbsd.tar.xz=01f4f0ef78f17e4991ddf3d974ef7b1dc9d56702ee2d65ede4918e9db99ec222
-dist/2024-06-11/clippy-beta-aarch64-pc-windows-msvc.tar.gz=ee6b64a7a0fc8d8482c38d2a263f9a9ed0b9462e6bd748a72e33c5cd7dac015b
-dist/2024-06-11/clippy-beta-aarch64-pc-windows-msvc.tar.xz=f91457f5dccfc81a601b075da340bf521e3cc17ba05d12f90c31c7f5b215a7bf
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=7da546ff13b3e340f2ba22e6995566cb26e487271e3f1b68b3b7dc0bd5122623
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=01807b62c65fe33acd05d10191cb16ee1bdeb1bd7b410a9c0cfd8f53006624da
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=64f41430de84569a7b933db7f0c573fecf99f5d0c6900e35598c94a433c0296c
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=b30a73278552ddf511ae82620f14ec7324f281582fa4fa9df3fe984510835aa3
-dist/2024-06-11/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=e6b0ac4bcec2871d2a50e644733399e684d7fa86798131243c4022cbe2ee5222
-dist/2024-06-11/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=edc629f04503ce88443ca6cce0b74b5833ce50f428e00a02b544f422577abb1e
-dist/2024-06-11/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ac52f8b4a1b6332aca1ad2363195daf571f7f1870ffa6237441dc7928a408167
-dist/2024-06-11/clippy-beta-s390x-unknown-linux-gnu.tar.xz=96b366fa989d2f739a92ee03bcd141b666b942e0b26922acd620e0fea6d44d8d
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-musl.tar.gz=8ab584ad05a7836bebb20be8d84b0dd3a29d1823dcee3897abde3a47a10e582b
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-musl.tar.xz=e7b669a2936a22ed6d2a36b70a6593657488e5ed8d00a911bf33ce51c4c0cc51
-dist/2024-06-11/clippy-beta-x86_64-unknown-illumos.tar.gz=419ef233cfdbe9011d74796e8413a8b6c1f8e6281248969eaf7c9157542c1b70
-dist/2024-06-11/clippy-beta-x86_64-unknown-illumos.tar.xz=673a2f16268fba4d9bf7dca2c0758f3ee60f9754cdcefa36032b8140e6fcddbf
-dist/2024-06-11/clippy-beta-i686-pc-windows-msvc.tar.gz=a3c3bd3b90c951ce404a26a59421f00a03e0dc3351d9dd2876346ff096b7361a
-dist/2024-06-11/clippy-beta-i686-pc-windows-msvc.tar.xz=c3e7c1cc91f48003e1b68fdf753011711ee516bc2ff8c7227d427dd8ee98a72e
-dist/2024-06-11/clippy-beta-aarch64-apple-darwin.tar.gz=ad7b4ac9cfacd860e03f8a41da51b4d279d76b7f3f2f8ac8a048a45f89a7ed04
-dist/2024-06-11/clippy-beta-aarch64-apple-darwin.tar.xz=ca5d2d63b8d7cae00c86383d9075b2292a28d1a85864877a6c8282f5596631f6
-dist/2024-06-11/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=12820c3e8b952dfa931783b550f882dd96c48d3b776fa9cdb29b02d66ad14d96
-dist/2024-06-11/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=394873c6b2499ebc385a11b512c7378b95478a0b6f530c5b313fe86b65a18eaa
-dist/2024-06-11/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=8d9353baa4388d02d89b42403e07d6a61f314fc975b8fcd737d8f4edb0ab027e
-dist/2024-06-11/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=3cf0511bc5b14619dd6ca1cfeed003effa7fbfecb42fc096a45a211d1ccf419a
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-msvc.tar.gz=cfae39e5d5cbc817aa3ba892822fe2ff122df8a648106aaf0ec18b1ce1a02632
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1f1f0596bef154eb3fb4e73993794850f8ad903f4dd0ef9697aa8d5b4d6ec2b7
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-gnu.tar.gz=0909caa93377b2aaf2a05a345e8cfea2c69dc27bd7f7d7a9515576e90cd0aad3
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-gnu.tar.xz=9125bfbaae2103f176b1e1b444fd38c7e74d3414536370037ffc6a85d8567551
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=3721470fcc17f8d37c66281bb66c65a66181c80775571520fcc2dfdb583dc640
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=79ec48af2925aaad12be405fb72dc9bd9e2ca89fd3a6017111020570ddeb6585
-dist/2024-06-11/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d957f503dd4d9d228b6a445eab1183dbc6509a49ccbd475d25143cf1dd28f03d
-dist/2024-06-11/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=da7ec767b4a85fa327c957888b228671b2311286043165926942504239008d3b
-dist/2024-06-11/clippy-beta-i686-pc-windows-gnu.tar.gz=51ff631084254be43d79d7791000a14ad9f11239e42be73f48383f774109c2cb
-dist/2024-06-11/clippy-beta-i686-pc-windows-gnu.tar.xz=52079acb4f908150d207a838cc7d3c15a725c1d61be35d0d0b2ed85b3386f3fc
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-musl.tar.gz=99a534de9e5fb552a4e7a10eca2645ad260a723f42e15df3b4e2bacf82e90348
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-musl.tar.xz=7f9e6da187bb71c384f5040298c43bd303fcbc5e3034dd7fdc7b251c5d7b3a34
-dist/2024-06-11/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=acf05b62fc219ddc2fc4e4bca2bc4c2cca24398d6276bd7e7d9f8504627094c4
-dist/2024-06-11/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=c737aaf9c4bc3a743752b13159902fc5a8ce746f44221799bbcbcb1f9d04dc4c
-dist/2024-06-11/clippy-beta-x86_64-apple-darwin.tar.gz=422e97d9081e66a46ec3f4c2a7ccbf9b6443c7b343e0a2e90845f233536f545c
-dist/2024-06-11/clippy-beta-x86_64-apple-darwin.tar.xz=c9d02836c9d0e48684f0a343d6935848ec75e1faaf7007a6a3e0718b71e77f7b
-dist/2024-06-11/clippy-beta-x86_64-unknown-freebsd.tar.gz=f207fbfca76eb22f7097eb98ccda1da513fed417371a391e43e8d19fad9b76b4
-dist/2024-06-11/clippy-beta-x86_64-unknown-freebsd.tar.xz=61e39b0aa88a1d8e131a461cb3cebd05154c261058b735f29dc6ed603464b5a1
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=c68d27b08f9699c7c2cff9e9bdb7485991d8445074e8b84c2e2222fbff209f83
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d5961f82b9688b9c1ccdcaf578b8325e8ac1e0cc2ffa02131fcc3281cc88dcfd
-dist/2024-06-11/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=12ccb5b1d82ad22292b337c49d1c5b0c0d584cfb4e649faf6c53471915df2473
-dist/2024-06-11/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=80fa7cb902135006046c10db64d9060103dfb1452e8e0ef256f8344fe0a9c8c5
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=c08499ebec188f67477d0c4eac2e172b59f6d66ad4becb36330b5066af6547d8
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=b3f29c79fc8bd64a2e62101468bbaa28338f444839659d4f99df34ccccad5eee
-dist/2024-06-11/rustfmt-nightly-aarch64-apple-darwin.tar.gz=4866e6d478424fb1c01b2b98678107b9c89e67a2cce3db49833bf34007f868b3
-dist/2024-06-11/rustfmt-nightly-aarch64-apple-darwin.tar.xz=e8e6fd846f70a99e6fad735ce4f4c8bca5f6b5f2d63364c2f8a7df85c13b63f4
-dist/2024-06-11/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=f14077408a763f0fa6218ed97d7697499c2bded289a5953336c727e2de93bd92
-dist/2024-06-11/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=27324f62ecfdeeb4a66ce3c62219c491f04ac3822305ea771df0381a5f4e5418
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1147008dfa30891e264bf5f469c9528fe47bdfc729a12215e5a985179513cc66
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=95fd945a6c9bcbc9549913906a8f2de20adf54b84b82fe8d981dbb5b767f0cfe
-dist/2024-06-11/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=4f423c5ce278204dce918ece2af84bdb55429b7a11f630de95a1516e7b113f53
-dist/2024-06-11/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=c86fe94c9b6cbc56285478ffa715877d234af19f1b58b3fd4b2af23a0267b657
-dist/2024-06-11/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=f1200f077402474049f6b817688435db0ebef7fb52ef645d5b5d2f7ceea52a08
-dist/2024-06-11/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=a0d801ec3aa93389d5c6ae2a95be25ba3a50f53182c0a84a00c38a2f708447e4
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=d4e28ad9b054cdd19fce6bbc37dc86210b0536aee5c23bca53a6bf1340fdb5bf
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=b0958ab975026e09ba921234353f5a81b3227d23c10ded4be4fe37831e6abd12
-dist/2024-06-11/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=f1caa15f16aa1c93ee783bf273d0ae6a7abd0b38c93c717f2d49af5444cd4e09
-dist/2024-06-11/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=130687b9de22fb1d0c4c845cff5475e5959278718e3b6a1af7f1b9e8869b527f
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=32e3881c61abfff7f9c006083045ffa5765c0b3a5a6ec46607e5428423ab76da
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=c1859b8a44306b5b3ca27b9226bbf351cd3ff3cacb4faf61200d7baa76009367
-dist/2024-06-11/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=4f5c23ba3426719c39a7c767be8db83382c84ff7798c5194aefbeda821462269
-dist/2024-06-11/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=18d9a2084cd5e55792f3841fc7d6602bd4a973726662b516289385b7908ffa4c
-dist/2024-06-11/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=df5478f63a49c55ffe9cf62a1882feeca019290c0cc9a9ed5a4122b8aa1325cd
-dist/2024-06-11/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=f54c3b8febfa4023a0334dfeee59d75a44f5c1d3a02d2d57959473d6ad51205a
-dist/2024-06-11/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=dd2d83a7bcd45a0d5de312a2a4a28b2471a9597d318135214b45a69e1e449f91
-dist/2024-06-11/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=02a8ada9d737e115033d26b0691f2ef22428ba2f67b7fbab7c4205df8162a96b
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=20bde0cb3ddca790c0d126d5d590b9a35a1c8631b42fbc2d4e85cfe5aa880d04
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=dd29e278f79ce1be14ad44d61039e5a6a63e0e597c4736ab153beb758ad37fb9
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=09d98f5c61def16b62b980a6cef3b1b3704cde5c0ad2fdd7d23521db410b6b8d
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ef43e61c2d3d90b09494a8dcbb5d2375223fcba6078f2bfb02ea43750b1a76a3
-dist/2024-06-11/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=80318fdf7d55c71beb8ff1434b79776c59008f5d62c63530da9f19a67cc18484
-dist/2024-06-11/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=05ae6d4f8ed07cc75b333e606af14f239978abe197b70409a5f2aadc7de43a4d
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a079a478e9a89c3a24864b44670bdffcebc139bbec9c54e7aab6394c08bcaab4
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=243c2d7c23e8aeddf9729e1f7f9add6f88f50d012efa02644030110cba111713
-dist/2024-06-11/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=76b69b4b25e8c0d47b80491bcbb724a25c02d95e7f9cfe7a9c3c3570c24363c1
-dist/2024-06-11/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=027e075c94f53403f03a4fb29d4575928e1cba141fc0713c93edaa4ea5917e42
-dist/2024-06-11/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b34d3f33e7ae81a5a95927997658d738a3d39db01408dad2d9fa72efb539c73f
-dist/2024-06-11/rustfmt-nightly-x86_64-apple-darwin.tar.xz=7efe129502b732219d1d24d59584b5ad002e7dc5288e047b06bbc81fab36e054
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=231f11ec1c6e4f57556aa32226d22328656d2ceab075cff67c8ab0a1ec32a823
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=b1cd7aa45a516df3a68814ce52753eeead4134943d610449456a30c682079ad0
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=3fb86c9281ae8203e1119bc00e8001afe7e894360adc791a9a0ca1d50e6a9032
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=6380fcfb015a40c4605ff18f8ba54c3be9a8e6a0115ede378565d9cc9943c627
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=f3ff749dedcfb259a4b2d66ae30245caeb79fdec3b41a3bb4f65d50b1cf18120
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=1ca50ca8ff36df7433a4ab4c8a63c3c91e214f6c7889843edfb9120c1f4f68d4
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=a7f5f171dfef5b67498c93354d9dc5a7443d69f3f9bc0bc56b660d1450e9b7a5
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=dff02f7a7e9ae58c41faf4c5731862d11fee06d17099c1ed18863219a4a82815
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=71dc189c1d29d3fec849b47f64deb831569515e56821511b1221983eb9ed99a9
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=17736f80644c8cdf8239940812962e6f55c1924896f79bd2581d20582a9c752a
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=b77e4a1e42c7169d91e268972a9195f7c8494e5cffa5fc71720df799a4eaf74a
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=8cf89f982aaa5559f2cd1721edfdc25f5e99518c418e1a6818c566d668c8f842
-dist/2024-06-11/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=7703c27800aa2d871624563380596a18deb90081e38cdf6c05cab8e794e5805c
-dist/2024-06-11/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=ca9dcda51c8945db32e004424eaf26d4f541a51a78be87be0063e5a0b06fdd4f
-dist/2024-06-11/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=59a2173462baaea0cef3e0f088b4e6ef64e2fe469d1833798d92e844f0126902
-dist/2024-06-11/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=0cab2fde15bbfab741eead0b084886f8b640aeb181251368464bd833fd08df73
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=8473ef60ff1d5c7aee90b8e0a984c9be7e095446d87e0f13ebcf10f245c0ef0f
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=657a55f27794460bad174c4f9412e771c679c6b608cc3dbe32903efb075418da
-dist/2024-06-11/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=bea7aff88f7d7622a23e91c437d9616a9f1adfbd56ddcb42ee33589d064d5161
-dist/2024-06-11/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=a5ab0850c71e322b1042815c443c79505f1daab2b4a69f8cce05e3761a24f10c
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=8c00db9c85fa8053f78285c8a546afb32d6b864795388f1ee7a6a49d12643625
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=c137f5f943d1c3f14a4a8b5eca2b541c43c82738452646df524e57a6ef0cbd3c
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a4087ded3076e4d487efcd4a957554255ea1fad5052a01529ea1847559f7b40f
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=ed2b01ad985668564ba2c3f87dcac4f5c4bcf7ea0b5ecca6a30c1f1c4b63a4ef
-dist/2024-06-11/rustc-nightly-i686-pc-windows-msvc.tar.gz=41db0331bc8f9d164d4198c93234dae41c1b9d2f53d466ee8cdfba4f9704c45b
-dist/2024-06-11/rustc-nightly-i686-pc-windows-msvc.tar.xz=49766cd2ad581f253f3fc0ba4f755a4aeaae954c75d41fa29a9302568e78aa75
-dist/2024-06-11/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=b57be1a1dc9e70c47564253877bc0cbbdde8a8064a6a4bcf68f8adc6b4c5d4df
-dist/2024-06-11/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=cf2c4651297993671f033eb9bb9877b157638bc41cb40ccac3294c3fd13786ef
-dist/2024-06-11/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=619c2eb3ed3f153d2c0ba6cbeb7f0e72c67fbb1e40c025752f94b46c9b740426
-dist/2024-06-11/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=105560769c3672133ecb063ac0a8ef541229490401470180af75151403287d3a
-dist/2024-06-11/rustc-nightly-i686-unknown-linux-gnu.tar.gz=211498f7eb884908c8110ce922183bbd6cc05d96d9c8b5c9068dcfc4d29010cd
-dist/2024-06-11/rustc-nightly-i686-unknown-linux-gnu.tar.xz=61beb47b917ce644defed991afa6d82028cb8f1e6a191cf5c84e8be883ad3870
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=06036f5bfc00950e03a66e8dcab0eb7420fd055aadb85bd42e11845eef122122
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=39d3dc95b1e0cfcc381d27540d100b8325728ef9a6a8b72a0e4ad85e2e957a63
-dist/2024-06-11/rustc-nightly-x86_64-unknown-freebsd.tar.gz=9b7badc1c8443571aec7b403e890d14846c3972b02159c8aacf3157ede69af9a
-dist/2024-06-11/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a1fdcbe1ca277b22c2dc8aced8ac0f34f841e7a7512fe421c2b045608c4ce07d
-dist/2024-06-11/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5e6105bc6304ea630a8170c785df11cd435521a2ac90348284898c4aab6ed5f2
-dist/2024-06-11/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=97dc7091b1ffa6a23a4b609a680c1f2f63debab80b5c01bc90fe271d6599bf89
-dist/2024-06-11/rustc-nightly-x86_64-apple-darwin.tar.gz=64769377c3714749acf6404d75f46b00ede0107840e736432d759dbfff15b6f9
-dist/2024-06-11/rustc-nightly-x86_64-apple-darwin.tar.xz=8ce829c39fdf21467307ee540c6b06b510d45c76c395947afdc2e5592d775977
-dist/2024-06-11/rustc-nightly-i686-pc-windows-gnu.tar.gz=4c9425ef2d5fdf9badec75783fe61ce0a251fde672c993c5b0069182449e2d7c
-dist/2024-06-11/rustc-nightly-i686-pc-windows-gnu.tar.xz=442467ab4199e2fb62c69a96cc1c9f03478a415877996f0fef20c54760b2e8b9
-dist/2024-06-11/rustc-nightly-x86_64-unknown-illumos.tar.gz=0b4c3520ff6e5b053a6b37f7d3708fb115fbb99981f337a1786d675e70034acc
-dist/2024-06-11/rustc-nightly-x86_64-unknown-illumos.tar.xz=d192e69dd328e6f930ad5b578065ebab12913762845f68ee55b43ddc9ba074a1
-dist/2024-06-11/rustc-nightly-x86_64-unknown-netbsd.tar.gz=0828f2d9395cdac8e9db6ad5c6b3cab3587fc82bccdec9962cd096e43e4f7793
-dist/2024-06-11/rustc-nightly-x86_64-unknown-netbsd.tar.xz=542f61a4c5a719f2583b0ba820207dc9d09cb9a2bb802da7cfbee5273bbfddfc
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=289b1bee22b8d9d84e92461694c6558476f944ac07caf2d22f0c4ccf3d29dbcf
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=23c86fc06ed9e7bcf8da72085ff88ec224ccddeca78ddc31032b314cb254ad64
-dist/2024-06-11/rustc-nightly-aarch64-apple-darwin.tar.gz=cf045620e63a5e623047490af956e0daf0bb321ed6a215ae355b8829c047e58e
-dist/2024-06-11/rustc-nightly-aarch64-apple-darwin.tar.xz=0abec976185b9573dbc91868ab4fb84ba2837d25f3fa1d74b3a193609387f3fa
-dist/2024-06-11/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=0b1146e24e4e59e4577b1e40d3ca45096864e87bcf9f258a34b9d9cf5abc3eef
-dist/2024-06-11/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=289e97314fd22da08c8943d1240fa94b1cfd2cdf061dea15bfb582a9d482d6a6
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=8957493cf92d57381b35d6ce5bbdb408a05c2a6becc8e2cd37b0502e3ef35ffb
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=9015e492f773b91054c53aca92ac704336504959779e4b916d42fc966e6058ea
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=aea2dc3831864dc5ea2c389c8208fc82baf1566f4e5688511495db25525e6020
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=9b6f1c3b1656ee2037afe170d6909aa037d484897a83679e2115392a35559062
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=3a962a42e427675df5d8fbc4e638949ec0669a95ecabcdddf5103a9c19f291ac
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=6fe48c92425b41ad7c3e812abe2e5decb117be178a16f6910bd60000fe8f355b
-dist/2024-06-11/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0a3147dd45cbf54e66b92baec479a5550c63327185baef3df9638c5a740e0921
-dist/2024-06-11/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=d35948d49fa1e526434ca89c2f7542fcfeb86b4ec35bb92f87f387ec37f4ccda
\ No newline at end of file
+dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e
+dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17
+dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96
+dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=02bcdc3eed81ba17e485556f1c4d5a00e851afb75a20f860ce7b6d22cb8f9e99
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=52b72cc7270fe75e023ca9c40d095a84cb0ce31657357cd7676d6570ca59bc1c
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=b47ba6f2214f238cf8df3c386765e7816bc86e1166f27ddb6c0ce678ec716939
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=95537778025708922b4bf27f34f0634a61a1d963a8424f8a06c82564c74e849a
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=5e0d51532c4bb0c29fd01ef5d931c229f711c9326df0bdcb2b88c75aa72dc210
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5fe623cab0afd5f7bdd664a593ac02791915e30cfc9ca76a02ffd70e1e865ede
+dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=1df1e1a44170d6c9ab4988e9841ab56ee00248ca5cbf7e38b69677bd5b2de585
+dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=70791fcd1aef6686e012740017a0e5bb4441eb4018f875e8e50d5597c183291d
+dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6
+dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47
+dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e
+dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1
+dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224
+dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a
+dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7
+dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014
+dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=e8f09f56c43ae6e99a42a8c430492157415fa6baee2c3f8f86f94ab4279634cd
+dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=599fcd5c57687e29eec085f7cc2733965a8e8fe5eac6499abd92ffda64f6e500
+dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef
+dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b
+dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=4d374e60b8ac2f3fddd5ba9b46ab80555bc5b19f080b86604dde994087b00ed9
+dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=c905a880b98d1eaabfb306d5b6dda018e5025b42028cbb12bad408f4d469f3ae
+dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=69f0228799685960f36f31eb4c139cbd7925f5180468e2d4a435ecbad63e9535
+dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=1da1caf5b2ad149ef82af58278dea6c381c372366c48cda8ca7f520cc8752b2c
+dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944
+dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998
+dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=dcc93e7b76ca7a469544597885a7b5f4b5f822e05a89b2d7a093e06dede9f52b
+dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=3efb7d4d97dc9b13a0178464e79bbf96bb71763a588b48c587746acd456ceb8d
+dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed
+dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=a9b352f61f8124c1fba0c76ecc8c1c972e61e97f5299f3b86bc17f035351ced5
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a8fced9a5de02bb660491b440f6596e4baf6eb9114b8dd8d93ac7ada6266d274
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539
+dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a
+dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18
+dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc
+dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.gz=8c129310921ed45d3cdfc30e60d93403adf8158a6661de96ee5d4a63119cf3e5
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.xz=e1fcee4b062f25b0350e5e74064615c354ee8b399adf792d46319ee782857398
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6
+dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779
+dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9dce2956e4b01d867ef6c229dbff9319a779a80e43a29fe1f8b10a333049264d
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=b64e7b87027dceba21283ba71430a8053a918bfaf6c071cc70d5f5da00155944
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0d103e0c4ec8039dd42be09bb9c74f269a9567fe7dfacfc54106912cd2aeb35b
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=4b3627e9e363e9b2fd85222c677a7250b12a5d32919f38a31ed7375637a79a81
+dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c
+dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c47cab4bb196e749f07d03f6f6c8f2fe538c84a055a298f0b505ab98dadf4a1c
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=b36aa3f0bab63ac21fb69610d379a87fbd1ee87041153eb1e6886a237d22b171
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b
+dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb
+dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc
+dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.gz=baad78bda532ed77dbf3e4265595b9dac82f6fdc27dc6deaf7386a60b981b927
+dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.xz=cf4283b1224d4dac3c55da905608c5bba7639b6511977f3de344a999ae39e571
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2325e8bc225a24a0a8c16da6dded16d4befb671b913051a7cce12ee3e183eac7
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=ab9ad0ec7057deda5c29e5d7de317eb32512fb95b62ba628b91b5246dde9c90d
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=be6d9a01609152eb815cef9462023f0ca2f2950ed03d914629d8e6e3a96af8ab
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=75ec6023cf9a43ec7ed0f52a1633b56154d9505c5d5d769153b48b9991ce99a8
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb
+dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=949a18d9d8b4c7cb3442ec4e387c91feddf0cc26f1fe602ec6c2c484312c9845
+dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=7adb9a93d35002d0335b3449b8d9af35a80a35524fe98bd86c3896481f020597
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a
+dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec
+dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159
+dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4
+dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020
+dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212
+dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181
+dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f
+dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da
+dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2
+dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a
+dist/2024-07-26/rust-std-beta-i686-linux-android.tar.gz=d36c3baba2df9d69e197a773f752bc36e107c2411d78037a357039a856e35aa5
+dist/2024-07-26/rust-std-beta-i686-linux-android.tar.xz=14b9bedd1bb95e1bac2bb028670b1d9dbe6998bb6ad0cfab1db0be0cd9e3d4cf
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746
+dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e
+dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869
+dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685
+dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=96afb9b33c86a6007f9c02f1f418d28f13014ec5154b648ceb7f725449dcbddf
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=7ed52c039fdd13a7477ed211ad8432cfd2fab98832174c8a534e5ac280f28572
+dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b
+dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=ff2eb11f284da7883dbf6ae465af86e50a9cd98c9b7d22b1e710626716e07db5
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=953fedb9dac336cb796290f619919f4ff9b2a6fcce09e23072f93a40b5498bdd
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7
+dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b
+dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1
+dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a
+dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b
+dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5
+dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310
+dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b
+dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166
+dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05
+dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82
+dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767
+dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8
+dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1
+dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a
+dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854
+dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074
+dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa
+dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2
+dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465
+dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927
+dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f877200e388345c10d3b0f5b8c484dd42905e769dcc1e21692e1cf7f2d59317e
+dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1052e8e5681c95ed3c004adee2492ff19d109965e9441a3362df876719899486
+dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300
+dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d
+dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd
+dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8
+dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=2aa967414bd03764774338e377c4714b8d169b1bbc651624a20158441b8111c3
+dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=d1a3b6ccbc55d1d9555674d1596a0c9f489304f9cb211e0c4645c17256ada4d1
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8
+dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d
+dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244
+dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f
+dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5
+dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b
+dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4
+dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae
+dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4
+dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7
+dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465
+dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=5144fe563c42205ba777678291950bd1b8c2b010b9aae28e2fe96e14e93e28cb
+dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=6e55e79f65a02abf37e1533c2590f53dfe56b474b58a3220d88f3d1458b6dcdc
+dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549
+dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7
+dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74
+dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519
+dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded
+dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602
+dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1
+dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4
+dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938
+dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474
+dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9
+dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b
+dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939
+dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd
+dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9
+dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497
+dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4
+dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897
+dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187
+dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af
+dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21
+dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85
+dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4
+dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf
+dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9
+dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496
+dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d
+dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90
+dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e
+dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.gz=62f687da4c02bef3e114b92c75b62fc6f7fdfcd210fb66329f6d4780f7dbcd70
+dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.xz=f9346e9ed4e5638f58dc237b22aef9e1b25b23bb588c736dceaa25b7b935f2bb
+dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9
+dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=01ba37e80e18e673c275538fc0db63b667ef52a72000dcbe76ac68018bd585e8
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=004f5119454fa53c2a7a58f6d176f65903b3c5bfc8eb1f894f6ca4e9bc32b7a1
+dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde
+dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707
+dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97
+dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542
+dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3
+dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b
+dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=cbfc580db37b135a20f42f9da02517ec8cf0a286b7274252c23c6a4947ba6755
+dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=dc2198fabb6fe6f68353c268698dece4ca3d6901b424a7cc2c68850f81f75f20
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=46ea726328e1700cf2b7d0ddeb16e25ebb648267c76268ba2f4aecb75ba47661
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=520ee25c1f18d80b4e4ce25e8fd961a19c0dd2ee0274e9d9cd3201f7c57c6f77
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904
+dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27
+dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab
+dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48
+dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576
+dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=74e57cbc139d548202d94262170ee45e33ae01331358ac2eaa9fa67c968ea1ea
+dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6cf99b689e32ff0caa56e9704dd185f6c268b484ccb657eff212e66fe64d1c10
+dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ed13a39d74e9d814d585ce7fb1aafd093f94317d6ead76e4b43c03b01e210086
+dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b5379d677d6596ffcbd7f3ebef2fd6d968096228101104a45565b170fb050042
+dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=1a29502881e6512a8bea566a90781870181f5727359668fa3bed2b3210a21b8d
+dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=95970245a7f304c6b83b8dad58b4c877ad2c9b0ca6bfc0090151561ce53a217b
+dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366
+dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=7b7ef80aa6131ddcb8bfec0f9493417e9a1e617a8f599a27de52ee914d022f95
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=647a6d0ff8f38dd4404c0006e5ed7b3a981dc89bbc334b1bd53225cc4f5511c8
+dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53
+dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60
+dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5
+dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851
+dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123
+dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb
+dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.gz=4c8991c692f200c6a5f25957e6648e07b7271681cbd9c61749bc990216dbbe6f
+dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.xz=51b5b85d46af2a3faeb53b81472c285eccc01f0c83575f62f37739cd48397fe2
+dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7
+dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=267b8dd0b5024152e36bcfb15af0b8ae3c68a71f559b8ecea1a3c9a8982e315b
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6aaae715599da14ca8cc405e51deed3bc160661ec56e929ae347ef1ead7ccf00
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3dcd9775b46a100a50fbb00188dffdc6f07fca9843994c8406a2d053e41c1672
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=e069b852ace430b2f75486a291d3d7849439c67c3381f5eedc0d6a9e6cde56db
+dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82
+dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40
+dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f
+dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557
+dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.gz=ffa017562648e98c7229e43a7422602c265441228485f0e14e52ebaf48a13e91
+dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292ab3d318a34e67463728752dc175f65cf5530f9368344dccaa79bad4df3b85
+dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763
+dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f6ed6391c8997f942d180cd32e81aca654450fb050cd865a8a1b13f77a892245
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=16e736f65b0ff029fe9fbafceec938123dff1b5a133f6c48b25edab379a20685
+dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd
+dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f
+dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99
+dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881
+dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837
+dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560
+dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=01ba50dae501edf3afa60aab59d8d81ccfd91126ded4cf7d45f7c4b13fb8c4aa
+dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a7e749bc581f9c64137a00dd891c4abff0d7f5684d2d501aad20ed1b01d9a312
+dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=f19081755c37e3dc43091b06bcdc59c82b28c6fa0a78ff02d800a25d6d9f22f2
+dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=d5f222e23f4f0ed4929e11684bc7b861c29fa183fffba0dbbfd5739b921f5234
+dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310
+dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=d4759993b9659ad8354d3fdf858cf99efebdf8202442505e11b55d24a54b31a0
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=e29eaea7b7f2e54b9285a2216f5b85440313650090c268048ce9e830e007fa92
+dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1
+dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef
+dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.gz=a88fd4b3e30faaecf270936422e254a25ff5dba93b08ca4003a9978ee80d0838
+dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.xz=f391b26009b7089f3d49d2f3409bb4e02e3de0700284727d2d26e7062bb18011
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7
+dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701
+dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4
+dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz=d3bb2f1fa20555373189caa7e58a8e3071c7ea6e7059bab15d6dd52dfef56c4f
+dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ba0019eb0766dd438069988156994270959c875b010afce0f455540a0bb2ee2f
+dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=24bbbe80a998b78f04c15d82fcef9498315b1b8d0ddabeeb5b6729b14bafbf70
+dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=cc396d3639c7213ab6442dc79ab6a1a42bb17910aa6d27046cc89ebeb6973231
+dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e6dc772727a20920607923ff5a99526054e6244c40cc6c97fe68db58896de6fc
+dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=eec95e09ec7bd64ab8a47e7311103f5bc58aa3499edcba052699686315f8441a
+dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=fef3eb7d5dee7458daacfba9b97d579868864267fcdc85334f02384683ce0c17
+dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=44f376f4d9e84645373b4cbfe17678c288a71b92622ab4091ca7b82ed6a21b57
+dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=5c17927f12149fa605e3f671d25ac456d1d2bdac796b5ca466bfa7fb8688d224
+dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=04783b1a2efc10696b0d32fde7c63437e17548d38b2272f928f28915107f4f18
+dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=1365d93efc4391f189726e69c7a968c8debb50411f29404da42d19bc9e053937
+dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=db344c9f6d31ac5a2efc839cbb886c312534e9b1fe4b116629eaca74f79c316d
+dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=049a2b666956a56365661d944a0fc030673bec5578062ddaad104363f4ff1031
+dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=32d3bc08316c0cfc3c1ea689ccdc80978f744864c048863b9d51ae59b6e2f0c2
+dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bc33833cd41bf5ac36730fc9d3ef9c87643d42b8e711de286138962fb5fac4a5
+dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=feffb4527ad627a0239d788272edac9a0fbec704de3a67aabbd8a9cbb95d4fe3
+dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=0ffb98b839f6640ac75e094cbb469a06f2e45f51ced01efbeb51a3fba866a048
+dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=d229ea866bf4d6c2d8d748630146c7bccedb4ba5a17056fbdc4558baf976f067
+dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=431de55efb797c75d8e440ba3da9ac70a04cccfc56b4e22b80b6488360915f90
+dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=e9e4eac4205014b6b61c759a8326f7a5e44e8ff05726510a8bbefd656f78e97c
+dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=99381507f8fc42d9bd00c545dd7ef4734e364a4e994d02bae148f78b94f50ab5
+dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6e2cd283d9370beb9c208bd823ac2433df500adf7e70d8acfe5a261e62be2b4a
+dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=761a9733f53ecba343139bd1c028a66242824ef8f7c54ae63e0aaf0e77cabcf9
+dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=c2973a99220588ea78b7a052861c345f01254073d6bb77e96982b12382907e2b
+dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=4288ee8fc5f650b3d5c24be2ea114e133d3bad8ddf7e2211cdb72151410c755a
+dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=2a31e1f211a26f6798acd4c779827bfa4e1ac4d77103a48be74617e5af1661a1
+dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=9598edeb1ff5eff934f1e4783b3ed263babb53d3513564ccccf453dada872ba1
+dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=eb5392fce8ee4a016406efba546366ff91d4db8cda94dd131dbda70c553b6c06
+dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=0e9c55ee790eed653eda7b913e64d344ccbbe1681321377186d1e4882dc93bfc
+dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c9a0b3eddac707c4e0c1cdc754d2821845e5f4bdcbd001b71d7287fe851cc44b
+dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=99c264f806d4a6a1288a9cc7f28e178102520ebe4728fb0da3f8142c1d6720e0
+dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3f1835460dbf17a3dbf47f2772e182ebf6337fd6a946a033f9700fb38140eda6
+dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=385224b95c56de8598dd5b4eeb48d7d7a8eb920825c55bb4d7be54142d7e2857
+dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=535220608ee858d46746c8de4c1e58f4f675061517b6b06c8af47004d5291f85
+dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz=aa19f1856befff101bcb433049e923486d7bc1a056638e478651936572e7e3bf
+dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz=2ed04cf9fddeafbb83d82988e00d3b7f5ae9382468ce1093cbb110bf46b04711
+dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=962dea60de3ac68a573f088f9c1b003816ce93f9088df15fe8cf7771a3abdc73
+dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=72f7b787644bd9008b13018512c0b09a425c15a337821dc9bded9ab7211c61de
+dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=1096ba25a23461eed84804584eb9ffdff780e2c737cc9dce1e8929419dfd645b
+dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=854b9e410e65b953ab71f356bd5b618679aa7c1f5a3de7f81ec388720ed04f60
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=03b4ab410c70fee3daa7a577c311b29344158a7d35ea87627233cb6165191338
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d755700cc17416c4488db2d582250b5ec329fc0c2b94e9db0e6688ca30a7316c
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b7448089c61c2f0a427416cd7521130c31a98c52e435bd0d04d6aad72d765ba6
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=cb3f479897032ff9ec5e06913e8e4374ce46af7f8a9030299c7b0cab2dab2005
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=0c7dbff79d04218a7ba3f5992f67d25043bc5f348038f37ab7385cbc4d0df00d
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4f62cbc75a81d57748111a915ebb20f561f403c1b695141780d50c398b186fa6
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=e5e8b07ae7ba0e1f526828a10f2515a68b0ed6023eed25e3bb10b80e21e8db76
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=424ec90c59fca7e21b302efd7c6c7f7dbc5dcadd1afbb15e90efea38ea8a19cf
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=f22576893113958f6caabcf3ab3e38287fea010c1809a8bb1197220d6660ea4e
+dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5e85141abe2a3c537cb4171c60cff5bdb11f075aa79212e0a958081d4648aec6
+dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.gz=f793e4645be9461fae09e82710bcfdfc6d749735be202f2e2cd6c2c643bb8925
+dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.xz=e42f52cc5a865ab92321b97aaeff4d39cbaad1a5b60a9a77de9f42e3b3231d21
+dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0258ba5bf957d190ef3a384c5451ebbe8406c195a29b3a7ee2a4c48e0514f203
+dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=788b7e9239562f43c0d96cfd66f543604eef1c9b40d22898c456fade608e9c31
+dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=94187df22d7b96a5c39c5c9a078f566b80d392abfd2a5d7059b836cfa0c446e1
+dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=ca1381c6de1a96f32a30736c28aa196f7e653b4f57f01ffe2db52fe238a9f202
+dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=1c72596862a133003f68590a8ae09bf6ab25a5f9667a6d245eafede1ebd8f450
+dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de0c216f229301bc88690b10b8f063b8e389915503980973b91bfe17b1fb6eda
+dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e00283a7ee9a702446456feb0156f1d1fc738fd013983f15c456fcafb8294309
+dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=03fab128bc3756676c645f637edc5051f8096b00780d8ef4de7a85b3f248933a
+dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=105e06c0ca69b4a700980f2a588f831c23a9a9253268bd652110328b99918cb1
+dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=0da27ffe5504a03923ae5858b69cdd6eb276e6bd2bfb504bcf13ebdda654316b
+dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=edb1bec402f3799e05fd3e31f30763e7266d2e062e410af8eab7636440da272c
+dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=638a09ecfe0b66391ce6802e3e15bf15462aca1c8cfb2a49b948ec69eda0575c
+dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.gz=456683fa10703ba8249f8b1735293c79edac0c32aec60c1a91315fb41c8e5ecc
+dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.xz=fd5d9a7bf543d3c61ca85340961d5e17b42b37c35fe45c666c2a0e125548f42e
+dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.gz=2b75a4e15d1f98f123ef74aecab3570296aeb7e35f18548a2b3d1735e01b06e0
+dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.xz=1163178e95180725bd31b7dabf1e9a9788a8e7cc576dd53148cfec32443e64a1
+dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz=0aad8dd79beca26278e1c1847dde17ee22ae64b78f2b02be65e12bc126de699b
+dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz=a548e90fbce90c26b6700cff7964d72c7e959a6f317e891db4f91ce7cd187c41
+dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=654ec9040afb20d660603adcd31824efeacef0ae2d48d342bb9504bd2f723453
+dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=998407bc1303eecb1ef4c6b14862ffdf31fb0cf991f5d169a822a23627b29352
+dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=5b4febf9a1802c2c756ef8a7693a9cfd83bf95284d79d9f9b9dd265234d6aebc
+dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=dbc2a6417fabcfb37f4fa42d50391c1cb29f18d1771321088c08afdf0a0e4809
+dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=2befcab4aa3e31064b87e4696aa2f1e76bd9c24067eb1921feb7f6497d58338c
+dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=508a3c1241507a53a0d6b27df2171eaf0a4df903773b5592f005ee4d39d91287
+dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c4e8da248306be350f7a89b2522e976a12ab89d5ae2e19157ed3b148e3948c50
+dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5858e1cf6371f25ba3c381e07ba6f4551c2a13516011fc10dbdafc4caf1bff93
+dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3639bbb7aac353772171dcfaecd589352de3fd8cc7395e7628d7590830034af4
+dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3cad5f0b74fc3f5be70cf496c93054c50e8a3f92cfc894a2febfbecc382dcb55
+dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=437fc8b815c09a3c5159735d9fec0e5d8dd64416149cb77c13a16863e6636412
+dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7bc2917e7816f7df1bc7faeda28010d247c923aba412b5ec1cc9c6757eec37d9
+dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=603e391a14c26a51f4f02020b5abbd307d29476fdc0689e5bf9570f2e6ac69a8
+dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=d04ea4e522cf1ecaa6b2f3edcb32155142378bc648aa159a574838ed2d58b794
+dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.gz=0ed639da01e58645eb33a75e020d57c58c92651d817e89574cb67bae5b298d35
+dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.xz=b4010f38396e7b8acd67cf2234c94ede11cf78a226a134c809d504e594037311
+dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=7ec8aba7a7581d59c7ceaffdd374852d08b17bc7e02674c5bfd4f47f4a0aee39
+dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=41c3ba0543220e11bc53282dd7d2a37acd6450a59683e1c83d2150dc798cfba7
+dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=67e5d75dda47c587a4be517db547354d1da0228110b7d5488d8822a7ef7cda20
+dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4b5f0c4101a783dd313c0cd1435d7eccfeac97452afaeaf42ba975805541dc74
+dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz=09e12b5003969b768b5c06b3e3b41a64429e28c32790ff28c12b8c5814f350c0
+dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a4b3b402cf4beb3e7c7b9b6620f34d045ef42261514ae7d8483d3790d1dfd88a
+dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.gz=c344d0c95aadac0e5e0100743b80768c9d0cd76b123ab07e6387ad1ea3e3efba
+dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.xz=ac0a79660227fe163c796e6b816596299f6d8b32ba008ce30cde492709efb7c0
+dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4090ff8086317662d3def1bc92d51e6f2decd2c64f4b6ede38604fd5029d3d02
+dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e665bd4e3763b456576eaa45bcf188648cc6e6443ecdff8ef91a5c7649cbfd25
+dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=4fa994e08274599ae3bceb9310c584be89d11f231aad3e8fc1e2d6a6ddbb77bf
+dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=bd8d53403bf6337782bffc3050a46887fbe2568c850809c5b32c8d84492d2ee9
+dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz=606a430036fdda0b92dd4a4cb99830881389693e6ed02a01ddd51eaecdfdf463
+dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz=fa34273b20336b8b373f686c88ee297033f635895ad225a2ca5271b6da3d7dea
\ No newline at end of file
diff --git a/src/tools/build-manifest/src/checksum.rs b/src/tools/build-manifest/src/checksum.rs
index c019c7a..c69b4180 100644
--- a/src/tools/build-manifest/src/checksum.rs
+++ b/src/tools/build-manifest/src/checksum.rs
@@ -1,6 +1,3 @@
-use crate::manifest::{FileHash, Manifest};
-use rayon::prelude::*;
-use sha2::{Digest, Sha256};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::fs::File;
@@ -9,6 +6,11 @@
use std::sync::Mutex;
use std::time::Instant;
+use rayon::prelude::*;
+use sha2::{Digest, Sha256};
+
+use crate::manifest::{FileHash, Manifest};
+
pub(crate) struct Checksums {
cache_path: Option<PathBuf>,
collected: Mutex<HashMap<PathBuf, String>>,
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index e0bea5f..2b263f8 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -4,13 +4,13 @@
mod manifest;
mod versions;
+use std::collections::{BTreeMap, HashSet};
+use std::path::{Path, PathBuf};
+use std::{env, fs};
+
use crate::checksum::Checksums;
use crate::manifest::{Component, Manifest, Package, Rename, Target};
use crate::versions::{PkgType, Versions};
-use std::collections::{BTreeMap, HashSet};
-use std::env;
-use std::fs;
-use std::path::{Path, PathBuf};
static HOSTS: &[&str] = &[
"aarch64-apple-darwin",
@@ -141,6 +141,7 @@
"riscv64gc-unknown-hermit",
"riscv64gc-unknown-none-elf",
"riscv64gc-unknown-linux-gnu",
+ "riscv64gc-unknown-linux-musl",
"s390x-unknown-linux-gnu",
"sparc64-unknown-linux-gnu",
"sparcv9-sun-solaris",
diff --git a/src/tools/build-manifest/src/manifest.rs b/src/tools/build-manifest/src/manifest.rs
index 6fa4f83..695a8f5 100644
--- a/src/tools/build-manifest/src/manifest.rs
+++ b/src/tools/build-manifest/src/manifest.rs
@@ -1,9 +1,11 @@
-use crate::versions::PkgType;
-use crate::Builder;
-use serde::{Serialize, Serializer};
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
+use serde::{Serialize, Serializer};
+
+use crate::versions::PkgType;
+use crate::Builder;
+
#[derive(Serialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) struct Manifest {
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index 233a267..495cab5 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -1,9 +1,10 @@
-use anyhow::Error;
-use flate2::read::GzDecoder;
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
+
+use anyhow::Error;
+use flate2::read::GzDecoder;
use tar::Archive;
use xz2::read::XzDecoder;
@@ -100,9 +101,10 @@ fn should_use_rust_version(&self) -> bool {
}
pub(crate) fn targets(&self) -> &[&str] {
- use crate::{HOSTS, MINGW, TARGETS};
use PkgType::*;
+ use crate::{HOSTS, MINGW, TARGETS};
+
match self {
Rust => HOSTS, // doesn't matter in practice, but return something to avoid panicking
Rustc => HOSTS,
diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs
index 8be38dc..da84569 100644
--- a/src/tools/build_helper/src/git.rs
+++ b/src/tools/build_helper/src/git.rs
@@ -1,5 +1,5 @@
-use std::process::Stdio;
-use std::{path::Path, process::Command};
+use std::path::Path;
+use std::process::{Command, Stdio};
pub struct GitConfig<'a> {
pub git_repository: &'a str,
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
index bb06e11..f8c75ca 100644
--- a/src/tools/bump-stage0/src/main.rs
+++ b/src/tools/bump-stage0/src/main.rs
@@ -4,7 +4,6 @@
use build_helper::stage0_parser::{parse_stage0_file, Stage0Config, VersionMetadata};
use curl::easy::Easy;
use indexmap::IndexMap;
-use std::collections::HashMap;
const PATH: &str = "src/stage0";
const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo", "clippy-preview"];
@@ -216,13 +215,13 @@ enum Channel {
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Manifest {
date: String,
- pkg: HashMap<String, ManifestPackage>,
+ pkg: IndexMap<String, ManifestPackage>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct ManifestPackage {
version: String,
- target: HashMap<String, ManifestTargetPackage>,
+ target: IndexMap<String, ManifestTargetPackage>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
diff --git a/src/tools/cargo b/src/tools/cargo
index b5d44db..0d8d22f 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit b5d44db1daf0469b227a6211b987162a39a54730
+Subproject commit 0d8d22f83b066503f6b2b755925197e959e58b4f
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index a5d2ffb..4c57683 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -1,7 +1,6 @@
-use std::env;
-use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
+use std::{env, fs};
struct Test {
repo: &'static str,
diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml
index 7afdd06..ce07290 100644
--- a/src/tools/clippy/.cargo/config.toml
+++ b/src/tools/clippy/.cargo/config.toml
@@ -13,6 +13,13 @@
[unstable]
binary-dep-depinfo = true
+profile-rustflags = true
[profile.dev]
split-debuginfo = "unpacked"
+
+# Add back the containing directory of the packages we have to refer to using --manifest-path
+[profile.dev.package.clippy_dev]
+rustflags = ["--remap-path-prefix", "=clippy_dev"]
+[profile.dev.package.lintcheck]
+rustflags = ["--remap-path-prefix", "=lintcheck"]
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 06bf3b6..0a05384 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -25,6 +25,7 @@
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
NO_FMT_TEST: 1
CARGO_INCREMENTAL: 0
+ RUSTFLAGS: -D warnings
concurrency:
# For a given workflow, if we push to the same PR, cancel all previous builds on that PR.
@@ -47,25 +48,25 @@
# Run
- name: Build
- run: cargo build --tests --features deny-warnings,internal
+ run: cargo build --tests --features internal
- name: Test
- run: cargo test --features deny-warnings,internal
+ run: cargo test --features internal
- name: Test clippy_lints
- run: cargo test --features deny-warnings,internal
+ run: cargo test --features internal
working-directory: clippy_lints
- name: Test clippy_utils
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: clippy_utils
- name: Test rustc_tools_util
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: rustc_tools_util
- name: Test clippy_dev
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: clippy_dev
- name: Test clippy-driver
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 1f4bec9..10e18e8 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -11,6 +11,7 @@
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
NO_FMT_TEST: 1
CARGO_INCREMENTAL: 0
+ RUSTFLAGS: -D warnings
concurrency:
# For a given workflow, if we push to the same branch, cancel all previous builds on that branch.
@@ -85,34 +86,34 @@
# Run
- name: Build
- run: cargo build --tests --features deny-warnings,internal
+ run: cargo build --tests --features internal
- name: Test
if: matrix.host == 'x86_64-unknown-linux-gnu'
- run: cargo test --features deny-warnings,internal
+ run: cargo test --features internal
- name: Test
if: matrix.host != 'x86_64-unknown-linux-gnu'
- run: cargo test --features deny-warnings,internal -- --skip dogfood
+ run: cargo test --features internal -- --skip dogfood
- name: Test clippy_lints
- run: cargo test --features deny-warnings,internal
+ run: cargo test --features internal
working-directory: clippy_lints
- name: Test clippy_utils
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: clippy_utils
- name: Test clippy_config
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: clippy_config
- name: Test rustc_tools_util
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: rustc_tools_util
- name: Test clippy_dev
- run: cargo test --features deny-warnings
+ run: cargo test
working-directory: clippy_dev
- name: Test clippy-driver
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 37f18a4..cf0a8bd 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -16,6 +16,7 @@
env:
RUST_BACKTRACE: 1
CARGO_INCREMENTAL: 0
+ RUSTFLAGS: -D warnings
jobs:
clippy_dev:
@@ -28,7 +29,7 @@
# Run
- name: Build
- run: cargo build --features deny-warnings
+ run: cargo build
working-directory: clippy_dev
- name: Test update_lints
@@ -38,6 +39,8 @@
run: cargo dev fmt --check
- name: Test cargo dev new lint
+ env:
+ RUSTFLAGS: -A unused-imports
run: |
cargo dev new_lint --name new_early_pass --pass early
cargo dev new_lint --name new_late_pass --pass late
diff --git a/src/tools/clippy/.github/workflows/lintcheck.yml b/src/tools/clippy/.github/workflows/lintcheck.yml
index 6a5139b..3cbda0b 100644
--- a/src/tools/clippy/.github/workflows/lintcheck.yml
+++ b/src/tools/clippy/.github/workflows/lintcheck.yml
@@ -58,7 +58,7 @@
- name: Run lintcheck
if: steps.cache-json.outputs.cache-hit != 'true'
- run: ./target/debug/lintcheck --format json --warn-all --crates-toml ./lintcheck/ci_crates.toml
+ run: ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml
- name: Upload base JSON
uses: actions/upload-artifact@v4
@@ -86,7 +86,7 @@
run: cargo build --manifest-path=lintcheck/Cargo.toml
- name: Run lintcheck
- run: ./target/debug/lintcheck --format json --warn-all --crates-toml ./lintcheck/ci_crates.toml
+ run: ./target/debug/lintcheck --format json --all-lints --crates-toml ./lintcheck/ci_crates.toml
- name: Upload head JSON
uses: actions/upload-artifact@v4
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 60c03b0..fddc2fd 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5830,6 +5830,7 @@
[`result_unit_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unit_err
[`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used
[`return_self_not_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#return_self_not_must_use
+[`reverse_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#reverse_range_loop
[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges
[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition
[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
@@ -5998,6 +5999,7 @@
[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
[`unused_peekable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_peekable
+[`unused_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_result_ok
[`unused_rounding`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_rounding
[`unused_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_self
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index bb4dc97..78409c7 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -30,7 +30,7 @@
anstream = "0.6.0"
[dev-dependencies]
-ui_test = "0.24"
+ui_test = "0.25"
regex = "1.5.5"
toml = "0.7.3"
walkdir = "2.3"
@@ -51,7 +51,6 @@
rustc_tools_util = "0.3.0"
[features]
-deny-warnings = ["clippy_lints/deny-warnings"]
integration = ["tempfile"]
internal = ["clippy_lints/internal", "tempfile"]
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index fb717a2..e3d550b 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -364,7 +364,7 @@
## `await-holding-invalid-types`
-
+The list of types which may not be held across an await point.
**Default Value:** `[]`
@@ -668,6 +668,8 @@
## `msrv`
The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
+**Default Value:** `current version`
+
---
**Affected lints:**
* [`allow_attributes`](https://rust-lang.github.io/rust-clippy/master/index.html#allow_attributes)
@@ -862,6 +864,8 @@
The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
reference. By default there is no limit
+**Default Value:** `target_pointer_width * 2`
+
---
**Affected lints:**
* [`trivially_copy_pass_by_ref`](https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref)
diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml
index e1b2edc..d5b28e2 100644
--- a/src/tools/clippy/clippy_config/Cargo.toml
+++ b/src/tools/clippy/clippy_config/Cargo.toml
@@ -6,6 +6,7 @@
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+itertools = "0.12"
rustc-semver = "1.1"
serde = { version = "1.0", features = ["derive"] }
toml = "0.7.3"
@@ -13,9 +14,6 @@
[dev-dependencies]
walkdir = "2.3"
-[features]
-deny-warnings = []
-
[package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)]
rustc_private = true
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 63140a3..4c2a825 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -123,7 +123,8 @@ macro_rules! define_Conf {
$(#[doc = $doc:literal])+
$(#[conf_deprecated($dep:literal, $new_conf:ident)])?
$(#[default_text = $default_text:expr])?
- ($name:ident: $ty:ty = $default:expr),
+ $(#[lints($($for_lints:ident),* $(,)?)])?
+ $name:ident: $ty:ty = $default:expr,
)*) => {
/// Clippy lint configuration
pub struct Conf {
@@ -201,411 +202,91 @@ fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> where V: MapA
}
pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
- let mut sorted = vec![
- $(
- {
- let deprecation_reason = wrap_option!($($dep)?);
-
- ClippyConfiguration::new(
- stringify!($name),
- default_text!(defaults::$name() $(, $default_text)?),
- concat!($($doc, '\n',)*),
- deprecation_reason,
- )
- },
- )+
- ];
- sorted.sort_by(|a, b| a.name.cmp(&b.name));
- sorted
+ vec![$(
+ ClippyConfiguration {
+ name: stringify!($name).replace('_', "-"),
+ default: default_text!(defaults::$name() $(, $default_text)?),
+ lints: &[$($(stringify!($for_lints)),*)?],
+ doc: concat!($($doc, '\n',)*),
+ deprecation_reason: wrap_option!($($dep)?)
+ },
+ )*]
}
};
}
define_Conf! {
- /// Lint: ARITHMETIC_SIDE_EFFECTS.
- ///
- /// Suppress checking of the passed type names in all types of operations.
- ///
- /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
+ /// Which crates to allow absolute paths from
+ #[lints(absolute_paths)]
+ absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default(),
+ /// The maximum number of segments a path can have before being linted, anything above this will
+ /// be linted.
+ #[lints(absolute_paths)]
+ absolute_paths_max_segments: u64 = 2,
+ /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
+ #[lints(undocumented_unsafe_blocks)]
+ accept_comment_above_attributes: bool = true,
+ /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
+ #[lints(undocumented_unsafe_blocks)]
+ accept_comment_above_statement: bool = true,
+ /// Don't lint when comparing the result of a modulo operation to zero.
+ #[lints(modulo_arithmetic)]
+ allow_comparison_to_zero: bool = true,
+ /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
+ #[lints(dbg_macro)]
+ allow_dbg_in_tests: bool = false,
+ /// Whether `expect` should be allowed in test functions or `#[cfg(test)]`
+ #[lints(expect_used)]
+ allow_expect_in_tests: bool = false,
+ /// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
+ #[lints(uninlined_format_args)]
+ allow_mixed_uninlined_format_args: bool = true,
+ /// Whether to allow `r#""#` when `r""` can be used
+ #[lints(unnecessary_raw_string_hashes)]
+ allow_one_hash_in_raw_strings: bool = false,
+ /// Whether `panic` should be allowed in test functions or `#[cfg(test)]`
+ #[lints(panic)]
+ allow_panic_in_tests: bool = false,
+ /// Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
+ #[lints(print_stderr, print_stdout)]
+ allow_print_in_tests: bool = false,
+ /// Whether to allow module inception if it's not public.
+ #[lints(module_inception)]
+ allow_private_module_inception: bool = false,
+ /// List of trait paths to ignore when checking renamed function parameters.
///
/// #### Example
///
/// ```toml
- /// arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
+ /// allow-renamed-params-for = [ "std::convert::From" ]
/// ```
///
/// #### Noteworthy
///
- /// A type, say `SomeType`, listed in this configuration has the same behavior of
- /// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
- (arithmetic_side_effects_allowed: Vec<String> = <_>::default()),
- /// Lint: ARITHMETIC_SIDE_EFFECTS.
- ///
- /// Suppress checking of the passed type pair names in binary operations like addition or
- /// multiplication.
- ///
- /// Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
- /// of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
- ///
- /// Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
- /// `["AnotherType", "SomeType"]`.
- ///
- /// #### Example
- ///
- /// ```toml
- /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
- /// ```
- (arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default()),
- /// Lint: ARITHMETIC_SIDE_EFFECTS.
- ///
- /// Suppress checking of the passed type names in unary operations like "negation" (`-`).
- ///
- /// #### Example
- ///
- /// ```toml
- /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
- /// ```
- (arithmetic_side_effects_allowed_unary: Vec<String> = <_>::default()),
- /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS, SINGLE_CALL_FN, NEEDLESS_PASS_BY_REF_MUT.
- ///
- /// Suppress lints whenever the suggested change would cause breakage for other crates.
- (avoid_breaking_exported_api: bool = true),
- /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS, ASSIGNING_CLONES, LEGACY_NUMERIC_CONSTANTS, MANUAL_PATTERN_CHAR_COMPARISON, ALLOW_ATTRIBUTES, ALLOW_ATTRIBUTES_WITHOUT_REASON, COLLAPSIBLE_MATCH.
- ///
- /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
- #[default_text = ""]
- (msrv: Msrv = Msrv::empty()),
- /// DEPRECATED LINT: BLACKLISTED_NAME.
- ///
- /// Use the Disallowed Names lint instead
- #[conf_deprecated("Please use `disallowed-names` instead", disallowed_names)]
- (blacklisted_names: Vec<String> = Vec::new()),
- /// Lint: COGNITIVE_COMPLEXITY.
- ///
- /// The maximum cognitive complexity a function can have
- (cognitive_complexity_threshold: u64 = 25),
- /// Lint: EXCESSIVE_NESTING.
- ///
- /// The maximum amount of nesting a block can reside in
- (excessive_nesting_threshold: u64 = 0),
- /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
- ///
- /// Use the Cognitive Complexity lint instead.
- #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)]
- (cyclomatic_complexity_threshold: u64 = 25),
- /// Lint: DISALLOWED_NAMES.
- ///
- /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
- /// `".."` can be used as part of the list to indicate that the configured values should be appended to the
+ /// - By default, the following traits are ignored: `From`, `TryFrom`, `FromStr`
+ /// - `".."` can be used as part of the list to indicate that the configured values should be appended to the
/// default configuration of Clippy. By default, any configuration will replace the default value.
- (disallowed_names: Vec<String> = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
- /// Lint: SEMICOLON_INSIDE_BLOCK.
- ///
- /// Whether to lint only if it's multiline.
- (semicolon_inside_block_ignore_singleline: bool = false),
- /// Lint: SEMICOLON_OUTSIDE_BLOCK.
- ///
- /// Whether to lint only if it's singleline.
- (semicolon_outside_block_ignore_multiline: bool = false),
- /// Lint: DOC_MARKDOWN.
- ///
- /// The list of words this lint should not consider as identifiers needing ticks. The value
- /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
- /// default configuration of Clippy. By default, any configuration will replace the default value. For example:
- /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
- /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
- (doc_valid_idents: FxHashSet<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect()),
- /// Lint: TOO_MANY_ARGUMENTS.
- ///
- /// The maximum number of argument a function or method can have
- (too_many_arguments_threshold: u64 = 7),
- /// Lint: TYPE_COMPLEXITY.
- ///
- /// The maximum complexity a type can have
- (type_complexity_threshold: u64 = 250),
- /// Lint: MANY_SINGLE_CHAR_NAMES.
- ///
- /// The maximum number of single char bindings a scope may have
- (single_char_binding_names_threshold: u64 = 4),
- /// Lint: BOXED_LOCAL, USELESS_VEC.
- ///
- /// The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
- (too_large_for_stack: u64 = 200),
- /// Lint: ENUM_VARIANT_NAMES.
- ///
- /// The minimum number of enum variants for the lints about variant names to trigger
- (enum_variant_name_threshold: u64 = 3),
- /// Lint: STRUCT_FIELD_NAMES.
- ///
- /// The minimum number of struct fields for the lints about field names to trigger
- (struct_field_name_threshold: u64 = 3),
- /// Lint: LARGE_ENUM_VARIANT.
- ///
- /// The maximum size of an enum's variant to avoid box suggestion
- (enum_variant_size_threshold: u64 = 200),
- /// Lint: VERBOSE_BIT_MASK.
- ///
- /// The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
- (verbose_bit_mask_threshold: u64 = 1),
- /// Lint: DECIMAL_LITERAL_REPRESENTATION.
- ///
- /// The lower bound for linting decimal literals
- (literal_representation_threshold: u64 = 16384),
- /// Lint: TRIVIALLY_COPY_PASS_BY_REF.
- ///
- /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
- /// reference. By default there is no limit
- #[default_text = ""]
- (trivial_copy_size_limit: Option<u64> = None),
- /// Lint: LARGE_TYPES_PASSED_BY_VALUE.
- ///
- /// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
- (pass_by_value_size_limit: u64 = 256),
- /// Lint: TOO_MANY_LINES.
- ///
- /// The maximum number of lines a function or method can have
- (too_many_lines_threshold: u64 = 100),
- /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS.
- ///
- /// The maximum allowed size for arrays on the stack
- (array_size_threshold: u64 = 512_000),
- /// Lint: LARGE_STACK_FRAMES.
- ///
- /// The maximum allowed stack size for functions in bytes
- (stack_size_threshold: u64 = 512_000),
- /// Lint: VEC_BOX.
- ///
- /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
- (vec_box_size_threshold: u64 = 4096),
- /// Lint: TYPE_REPETITION_IN_BOUNDS.
- ///
- /// The maximum number of bounds a trait can have to be linted
- (max_trait_bounds: u64 = 3),
- /// Lint: STRUCT_EXCESSIVE_BOOLS.
- ///
- /// The maximum number of bool fields a struct can have
- (max_struct_bools: u64 = 3),
- /// Lint: FN_PARAMS_EXCESSIVE_BOOLS.
- ///
- /// The maximum number of bool parameters a function can have
- (max_fn_params_bools: u64 = 3),
- /// Lint: WILDCARD_IMPORTS.
- ///
- /// Whether to allow certain wildcard imports (prelude, super in tests).
- (warn_on_all_wildcard_imports: bool = false),
- /// Lint: DISALLOWED_MACROS.
- ///
- /// The list of disallowed macros, written as fully qualified paths.
- (disallowed_macros: Vec<DisallowedPath> = Vec::new()),
- /// Lint: DISALLOWED_METHODS.
- ///
- /// The list of disallowed methods, written as fully qualified paths.
- (disallowed_methods: Vec<DisallowedPath> = Vec::new()),
- /// Lint: DISALLOWED_TYPES.
- ///
- /// The list of disallowed types, written as fully qualified paths.
- (disallowed_types: Vec<DisallowedPath> = Vec::new()),
- /// Lint: UNREADABLE_LITERAL.
- ///
- /// Should the fraction of a decimal be linted to include separators.
- (unreadable_literal_lint_fractions: bool = true),
- /// Lint: UPPER_CASE_ACRONYMS.
- ///
- /// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
- (upper_case_acronyms_aggressive: bool = false),
- /// Lint: MANUAL_LET_ELSE.
- ///
- /// Whether the matches should be considered by the lint, and whether there should
- /// be filtering for common types.
- (matches_for_let_else: MatchLintBehaviour = MatchLintBehaviour::WellKnownTypes),
- /// Lint: CARGO_COMMON_METADATA.
- ///
- /// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
- (cargo_ignore_publish: bool = false),
- /// Lint: NONSTANDARD_MACRO_BRACES.
- ///
- /// Enforce the named macros always use the braces specified.
- ///
- /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
- /// could be used with a full path two `MacroMatcher`s have to be added one with the full path
- /// `crate_name::macro_name` and one with just the macro name.
- (standard_macro_braces: Vec<MacroMatcher> = Vec::new()),
- /// Lint: MISSING_ENFORCED_IMPORT_RENAMES.
- ///
- /// The list of imports to always rename, a fully qualified path followed by the rename.
- (enforced_import_renames: Vec<Rename> = Vec::new()),
- /// Lint: DISALLOWED_SCRIPT_IDENTS.
- ///
- /// The list of unicode scripts allowed to be used in the scope.
- (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
- /// Lint: NON_SEND_FIELDS_IN_SEND_TY.
- ///
- /// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
- (enable_raw_pointer_heuristic_for_send: bool = true),
- /// Lint: INDEX_REFUTABLE_SLICE.
- ///
- /// When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
- /// the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
- /// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
- (max_suggested_slice_pattern_length: u64 = 3),
- /// Lint: AWAIT_HOLDING_INVALID_TYPE.
- (await_holding_invalid_types: Vec<DisallowedPath> = Vec::new()),
- /// Lint: LARGE_INCLUDE_FILE.
- ///
- /// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
- (max_include_file_size: u64 = 1_000_000),
- /// Lint: EXPECT_USED.
- ///
- /// Whether `expect` should be allowed in test functions or `#[cfg(test)]`
- (allow_expect_in_tests: bool = false),
- /// Lint: UNWRAP_USED.
- ///
+ #[lints(renamed_function_params)]
+ allow_renamed_params_for: Vec<String> =
+ DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS.iter().map(ToString::to_string).collect(),
/// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
- (allow_unwrap_in_tests: bool = false),
- /// Lint: PANIC.
- ///
- /// Whether `panic` should be allowed in test functions or `#[cfg(test)]`
- (allow_panic_in_tests: bool = false),
- /// Lint: DBG_MACRO.
- ///
- /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
- (allow_dbg_in_tests: bool = false),
- /// Lint: PRINT_STDOUT, PRINT_STDERR.
- ///
- /// Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
- (allow_print_in_tests: bool = false),
- /// Lint: USELESS_VEC.
- ///
+ #[lints(unwrap_used)]
+ allow_unwrap_in_tests: bool = false,
/// Whether `useless_vec` should ignore test functions or `#[cfg(test)]`
- (allow_useless_vec_in_tests: bool = false),
- /// Lint: RESULT_LARGE_ERR.
- ///
- /// The maximum size of the `Err`-variant in a `Result` returned from a function
- (large_error_threshold: u64 = 128),
- /// Lint: MUTABLE_KEY_TYPE, IFS_SAME_COND, BORROW_INTERIOR_MUTABLE_CONST, DECLARE_INTERIOR_MUTABLE_CONST.
- ///
- /// A list of paths to types that should be treated as if they do not contain interior mutability
- (ignore_interior_mutability: Vec<String> = Vec::from(["bytes::Bytes".into()])),
- /// Lint: UNINLINED_FORMAT_ARGS.
- ///
- /// Whether to allow mixed uninlined format args, e.g. `format!("{} {}", a, foo.bar)`
- (allow_mixed_uninlined_format_args: bool = true),
- /// Lint: INDEXING_SLICING.
- ///
- /// Whether to suppress a restriction lint in constant code. In same
- /// cases the restructured operation might not be unavoidable, as the
- /// suggested counterparts are unavailable in constant code. This
- /// configuration will cause restriction lints to trigger even
- /// if no suggestion can be made.
- (suppress_restriction_lint_in_const: bool = false),
- /// Lint: MISSING_DOCS_IN_PRIVATE_ITEMS.
- ///
- /// Whether to **only** check for missing documentation in items visible within the current
- /// crate. For example, `pub(crate)` items.
- (missing_docs_in_crate_items: bool = false),
- /// Lint: LARGE_FUTURES.
- ///
- /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
- (future_size_threshold: u64 = 16 * 1024),
- /// Lint: UNNECESSARY_BOX_RETURNS.
- ///
- /// The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
- (unnecessary_box_size: u64 = 128),
- /// Lint: MODULE_INCEPTION.
- ///
- /// Whether to allow module inception if it's not public.
- (allow_private_module_inception: bool = false),
- /// Lint: MIN_IDENT_CHARS.
- ///
+ #[lints(useless_vec)]
+ allow_useless_vec_in_tests: bool = false,
+ /// Additional dotfiles (files or directories starting with a dot) to allow
+ #[lints(path_ends_with_ext)]
+ allowed_dotfiles: Vec<String> = Vec::default(),
+ /// A list of crate names to allow duplicates of
+ #[lints(multiple_crate_versions)]
+ allowed_duplicate_crates: FxHashSet<String> = FxHashSet::default(),
/// Allowed names below the minimum allowed characters. The value `".."` can be used as part of
/// the list to indicate, that the configured values should be appended to the default
/// configuration of Clippy. By default, any configuration will replace the default value.
- (allowed_idents_below_min_chars: FxHashSet<String> =
- DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect()),
- /// Lint: MIN_IDENT_CHARS.
- ///
- /// Minimum chars an ident can have, anything below or equal to this will be linted.
- (min_ident_chars_threshold: u64 = 1),
- /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
- ///
- /// Whether to accept a safety comment to be placed above the statement containing the `unsafe` block
- (accept_comment_above_statement: bool = true),
- /// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
- ///
- /// Whether to accept a safety comment to be placed above the attributes for the `unsafe` block
- (accept_comment_above_attributes: bool = true),
- /// Lint: UNNECESSARY_RAW_STRING_HASHES.
- ///
- /// Whether to allow `r#""#` when `r""` can be used
- (allow_one_hash_in_raw_strings: bool = false),
- /// Lint: ABSOLUTE_PATHS.
- ///
- /// The maximum number of segments a path can have before being linted, anything above this will
- /// be linted.
- (absolute_paths_max_segments: u64 = 2),
- /// Lint: ABSOLUTE_PATHS.
- ///
- /// Which crates to allow absolute paths from
- (absolute_paths_allowed_crates: FxHashSet<String> = FxHashSet::default()),
- /// Lint: PATH_ENDS_WITH_EXT.
- ///
- /// Additional dotfiles (files or directories starting with a dot) to allow
- (allowed_dotfiles: Vec<String> = Vec::default()),
- /// Lint: MULTIPLE_CRATE_VERSIONS.
- ///
- /// A list of crate names to allow duplicates of
- (allowed_duplicate_crates: FxHashSet<String> = FxHashSet::default()),
- /// Lint: EXPLICIT_ITER_LOOP.
- ///
- /// Whether to recommend using implicit into iter for reborrowed values.
- ///
- /// #### Example
- /// ```no_run
- /// let mut vec = vec![1, 2, 3];
- /// let rmvec = &mut vec;
- /// for _ in rmvec.iter() {}
- /// for _ in rmvec.iter_mut() {}
- /// ```
- ///
- /// Use instead:
- /// ```no_run
- /// let mut vec = vec![1, 2, 3];
- /// let rmvec = &mut vec;
- /// for _ in &*rmvec {}
- /// for _ in &mut *rmvec {}
- /// ```
- (enforce_iter_loop_reborrow: bool = false),
- /// Lint: MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC, MISSING_PANICS_DOC, MISSING_ERRORS_DOC.
- ///
- /// Whether to also run the listed lints on private items.
- (check_private_items: bool = false),
- /// Lint: PUB_UNDERSCORE_FIELDS.
- ///
- /// Lint "public" fields in a struct that are prefixed with an underscore based on their
- /// exported visibility, or whether they are marked as "pub".
- (pub_underscore_fields_behavior: PubUnderscoreFieldsBehaviour = PubUnderscoreFieldsBehaviour::PubliclyExported),
- /// Lint: MODULO_ARITHMETIC.
- ///
- /// Don't lint when comparing the result of a modulo operation to zero.
- (allow_comparison_to_zero: bool = true),
- /// Lint: WILDCARD_IMPORTS.
- ///
- /// List of path segments allowed to have wildcard imports.
- ///
- /// #### Example
- ///
- /// ```toml
- /// allowed-wildcard-imports = [ "utils", "common" ]
- /// ```
- ///
- /// #### Noteworthy
- ///
- /// 1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`.
- /// 2. Paths with any segment that containing the word 'prelude'
- /// are already allowed by default.
- (allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default()),
- /// Lint: MODULE_NAME_REPETITIONS.
- ///
+ #[lints(min_ident_chars)]
+ allowed_idents_below_min_chars: FxHashSet<String> =
+ DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS.iter().map(ToString::to_string).collect(),
/// List of prefixes to allow when determining whether an item's name ends with the module's name.
/// If the rest of an item's name is an allowed prefix (e.g. item `ToFoo` or `to_foo` in module `foo`),
/// then don't emit a warning.
@@ -623,28 +304,343 @@ pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
/// `TryInto` will also be included)
/// - Use `".."` as part of the list to indicate that the configured values should be appended to the
/// default configuration of Clippy. By default, any configuration will replace the default value
- (allowed_prefixes: Vec<String> = DEFAULT_ALLOWED_PREFIXES.iter().map(ToString::to_string).collect()),
- /// Lint: RENAMED_FUNCTION_PARAMS.
- ///
- /// List of trait paths to ignore when checking renamed function parameters.
+ #[lints(module_name_repetitions)]
+ allowed_prefixes: Vec<String> = DEFAULT_ALLOWED_PREFIXES.iter().map(ToString::to_string).collect(),
+ /// The list of unicode scripts allowed to be used in the scope.
+ #[lints(disallowed_script_idents)]
+ allowed_scripts: Vec<String> = vec!["Latin".to_string()],
+ /// List of path segments allowed to have wildcard imports.
///
/// #### Example
///
/// ```toml
- /// allow-renamed-params-for = [ "std::convert::From" ]
+ /// allowed-wildcard-imports = [ "utils", "common" ]
/// ```
///
/// #### Noteworthy
///
- /// - By default, the following traits are ignored: `From`, `TryFrom`, `FromStr`
- /// - `".."` can be used as part of the list to indicate that the configured values should be appended to the
- /// default configuration of Clippy. By default, any configuration will replace the default value.
- (allow_renamed_params_for: Vec<String> =
- DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS.iter().map(ToString::to_string).collect()),
- /// Lint: MACRO_METAVARS_IN_UNSAFE.
+ /// 1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`.
+ /// 2. Paths with any segment that containing the word 'prelude'
+ /// are already allowed by default.
+ #[lints(wildcard_imports)]
+ allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default(),
+ /// Suppress checking of the passed type names in all types of operations.
///
+ /// If a specific operation is desired, consider using `arithmetic_side_effects_allowed_binary` or `arithmetic_side_effects_allowed_unary` instead.
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed = ["SomeType", "AnotherType"]
+ /// ```
+ ///
+ /// #### Noteworthy
+ ///
+ /// A type, say `SomeType`, listed in this configuration has the same behavior of
+ /// `["SomeType" , "*"], ["*", "SomeType"]` in `arithmetic_side_effects_allowed_binary`.
+ #[lints(arithmetic_side_effects)]
+ arithmetic_side_effects_allowed: Vec<String> = <_>::default(),
+ /// Suppress checking of the passed type pair names in binary operations like addition or
+ /// multiplication.
+ ///
+ /// Supports the "*" wildcard to indicate that a certain type won't trigger the lint regardless
+ /// of the involved counterpart. For example, `["SomeType", "*"]` or `["*", "AnotherType"]`.
+ ///
+ /// Pairs are asymmetric, which means that `["SomeType", "AnotherType"]` is not the same as
+ /// `["AnotherType", "SomeType"]`.
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed-binary = [["SomeType" , "f32"], ["AnotherType", "*"]]
+ /// ```
+ #[lints(arithmetic_side_effects)]
+ arithmetic_side_effects_allowed_binary: Vec<[String; 2]> = <_>::default(),
+ /// Suppress checking of the passed type names in unary operations like "negation" (`-`).
+ ///
+ /// #### Example
+ ///
+ /// ```toml
+ /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
+ /// ```
+ #[lints(arithmetic_side_effects)]
+ arithmetic_side_effects_allowed_unary: Vec<String> = <_>::default(),
+ /// The maximum allowed size for arrays on the stack
+ #[lints(large_const_arrays, large_stack_arrays)]
+ array_size_threshold: u64 = 512_000,
+ /// Suppress lints whenever the suggested change would cause breakage for other crates.
+ #[lints(
+ box_collection,
+ enum_variant_names,
+ large_types_passed_by_value,
+ linkedlist,
+ needless_pass_by_ref_mut,
+ option_option,
+ rc_buffer,
+ rc_mutex,
+ redundant_allocation,
+ single_call_fn,
+ trivially_copy_pass_by_ref,
+ unnecessary_box_returns,
+ unnecessary_wraps,
+ unused_self,
+ upper_case_acronyms,
+ vec_box,
+ wrong_self_convention,
+ )]
+ avoid_breaking_exported_api: bool = true,
+ /// The list of types which may not be held across an await point.
+ #[lints(await_holding_invalid_type)]
+ await_holding_invalid_types: Vec<DisallowedPath> = Vec::new(),
+ /// DEPRECATED LINT: BLACKLISTED_NAME.
+ ///
+ /// Use the Disallowed Names lint instead
+ #[conf_deprecated("Please use `disallowed-names` instead", disallowed_names)]
+ blacklisted_names: Vec<String> = Vec::new(),
+ /// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
+ #[lints(cargo_common_metadata)]
+ cargo_ignore_publish: bool = false,
+ /// Whether to also run the listed lints on private items.
+ #[lints(missing_errors_doc, missing_panics_doc, missing_safety_doc, unnecessary_safety_doc)]
+ check_private_items: bool = false,
+ /// The maximum cognitive complexity a function can have
+ #[lints(cognitive_complexity)]
+ cognitive_complexity_threshold: u64 = 25,
+ /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
+ ///
+ /// Use the Cognitive Complexity lint instead.
+ #[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)]
+ cyclomatic_complexity_threshold: u64 = 25,
+ /// The list of disallowed macros, written as fully qualified paths.
+ #[lints(disallowed_macros)]
+ disallowed_macros: Vec<DisallowedPath> = Vec::new(),
+ /// The list of disallowed methods, written as fully qualified paths.
+ #[lints(disallowed_methods)]
+ disallowed_methods: Vec<DisallowedPath> = Vec::new(),
+ /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
+ /// `".."` can be used as part of the list to indicate that the configured values should be appended to the
+ /// default configuration of Clippy. By default, any configuration will replace the default value.
+ #[lints(disallowed_names)]
+ disallowed_names: Vec<String> = DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect(),
+ /// The list of disallowed types, written as fully qualified paths.
+ #[lints(disallowed_types)]
+ disallowed_types: Vec<DisallowedPath> = Vec::new(),
+ /// The list of words this lint should not consider as identifiers needing ticks. The value
+ /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
+ /// default configuration of Clippy. By default, any configuration will replace the default value. For example:
+ /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
+ /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
+ #[lints(doc_markdown)]
+ doc_valid_idents: FxHashSet<String> = DEFAULT_DOC_VALID_IDENTS.iter().map(ToString::to_string).collect(),
+ /// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
+ #[lints(non_send_fields_in_send_ty)]
+ enable_raw_pointer_heuristic_for_send: bool = true,
+ /// Whether to recommend using implicit into iter for reborrowed values.
+ ///
+ /// #### Example
+ /// ```no_run
+ /// let mut vec = vec![1, 2, 3];
+ /// let rmvec = &mut vec;
+ /// for _ in rmvec.iter() {}
+ /// for _ in rmvec.iter_mut() {}
+ /// ```
+ ///
+ /// Use instead:
+ /// ```no_run
+ /// let mut vec = vec![1, 2, 3];
+ /// let rmvec = &mut vec;
+ /// for _ in &*rmvec {}
+ /// for _ in &mut *rmvec {}
+ /// ```
+ #[lints(explicit_iter_loop)]
+ enforce_iter_loop_reborrow: bool = false,
+ /// The list of imports to always rename, a fully qualified path followed by the rename.
+ #[lints(missing_enforced_import_renames)]
+ enforced_import_renames: Vec<Rename> = Vec::new(),
+ /// The minimum number of enum variants for the lints about variant names to trigger
+ #[lints(enum_variant_names)]
+ enum_variant_name_threshold: u64 = 3,
+ /// The maximum size of an enum's variant to avoid box suggestion
+ #[lints(large_enum_variant)]
+ enum_variant_size_threshold: u64 = 200,
+ /// The maximum amount of nesting a block can reside in
+ #[lints(excessive_nesting)]
+ excessive_nesting_threshold: u64 = 0,
+ /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
+ #[lints(large_futures)]
+ future_size_threshold: u64 = 16 * 1024,
+ /// A list of paths to types that should be treated as if they do not contain interior mutability
+ #[lints(borrow_interior_mutable_const, declare_interior_mutable_const, ifs_same_cond, mutable_key_type)]
+ ignore_interior_mutability: Vec<String> = Vec::from(["bytes::Bytes".into()]),
+ /// The maximum size of the `Err`-variant in a `Result` returned from a function
+ #[lints(result_large_err)]
+ large_error_threshold: u64 = 128,
+ /// The lower bound for linting decimal literals
+ #[lints(decimal_literal_representation)]
+ literal_representation_threshold: u64 = 16384,
+ /// Whether the matches should be considered by the lint, and whether there should
+ /// be filtering for common types.
+ #[lints(manual_let_else)]
+ matches_for_let_else: MatchLintBehaviour = MatchLintBehaviour::WellKnownTypes,
+ /// The maximum number of bool parameters a function can have
+ #[lints(fn_params_excessive_bools)]
+ max_fn_params_bools: u64 = 3,
+ /// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
+ #[lints(large_include_file)]
+ max_include_file_size: u64 = 1_000_000,
+ /// The maximum number of bool fields a struct can have
+ #[lints(struct_excessive_bools)]
+ max_struct_bools: u64 = 3,
+ /// When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
+ /// the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
+ /// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
+ #[lints(index_refutable_slice)]
+ max_suggested_slice_pattern_length: u64 = 3,
+ /// The maximum number of bounds a trait can have to be linted
+ #[lints(type_repetition_in_bounds)]
+ max_trait_bounds: u64 = 3,
+ /// Minimum chars an ident can have, anything below or equal to this will be linted.
+ #[lints(min_ident_chars)]
+ min_ident_chars_threshold: u64 = 1,
+ /// Whether to **only** check for missing documentation in items visible within the current
+ /// crate. For example, `pub(crate)` items.
+ #[lints(missing_docs_in_private_items)]
+ missing_docs_in_crate_items: bool = false,
+ /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
+ #[default_text = "current version"]
+ #[lints(
+ allow_attributes,
+ allow_attributes_without_reason,
+ almost_complete_range,
+ approx_constant,
+ assigning_clones,
+ borrow_as_ptr,
+ cast_abs_to_unsigned,
+ checked_conversions,
+ cloned_instead_of_copied,
+ collapsible_match,
+ collapsible_str_replace,
+ deprecated_cfg_attr,
+ derivable_impls,
+ err_expect,
+ filter_map_next,
+ from_over_into,
+ if_then_some_else_none,
+ index_refutable_slice,
+ iter_kv_map,
+ legacy_numeric_constants,
+ manual_bits,
+ manual_c_str_literals,
+ manual_clamp,
+ manual_hash_one,
+ manual_is_ascii_check,
+ manual_let_else,
+ manual_non_exhaustive,
+ manual_pattern_char_comparison,
+ manual_range_contains,
+ manual_rem_euclid,
+ manual_retain,
+ manual_split_once,
+ manual_str_repeat,
+ manual_strip,
+ manual_try_fold,
+ map_clone,
+ map_unwrap_or,
+ match_like_matches_macro,
+ mem_replace_with_default,
+ missing_const_for_fn,
+ needless_borrow,
+ option_as_ref_deref,
+ option_map_unwrap_or,
+ ptr_as_ptr,
+ redundant_field_names,
+ redundant_static_lifetimes,
+ seek_from_current,
+ seek_rewind,
+ transmute_ptr_to_ref,
+ tuple_array_conversions,
+ type_repetition_in_bounds,
+ unchecked_duration_subtraction,
+ uninlined_format_args,
+ unnecessary_lazy_evaluations,
+ unnested_or_patterns,
+ use_self,
+ )]
+ msrv: Msrv = Msrv::empty(),
+ /// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
+ #[lints(large_types_passed_by_value)]
+ pass_by_value_size_limit: u64 = 256,
+ /// Lint "public" fields in a struct that are prefixed with an underscore based on their
+ /// exported visibility, or whether they are marked as "pub".
+ #[lints(pub_underscore_fields)]
+ pub_underscore_fields_behavior: PubUnderscoreFieldsBehaviour = PubUnderscoreFieldsBehaviour::PubliclyExported,
+ /// Whether to lint only if it's multiline.
+ #[lints(semicolon_inside_block)]
+ semicolon_inside_block_ignore_singleline: bool = false,
+ /// Whether to lint only if it's singleline.
+ #[lints(semicolon_outside_block)]
+ semicolon_outside_block_ignore_multiline: bool = false,
+ /// The maximum number of single char bindings a scope may have
+ #[lints(many_single_char_names)]
+ single_char_binding_names_threshold: u64 = 4,
+ /// The maximum allowed stack size for functions in bytes
+ #[lints(large_stack_frames)]
+ stack_size_threshold: u64 = 512_000,
+ /// Enforce the named macros always use the braces specified.
+ ///
+ /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
+ /// could be used with a full path two `MacroMatcher`s have to be added one with the full path
+ /// `crate_name::macro_name` and one with just the macro name.
+ #[lints(nonstandard_macro_braces)]
+ standard_macro_braces: Vec<MacroMatcher> = Vec::new(),
+ /// The minimum number of struct fields for the lints about field names to trigger
+ #[lints(struct_field_names)]
+ struct_field_name_threshold: u64 = 3,
+ /// Whether to suppress a restriction lint in constant code. In same
+ /// cases the restructured operation might not be unavoidable, as the
+ /// suggested counterparts are unavailable in constant code. This
+ /// configuration will cause restriction lints to trigger even
+ /// if no suggestion can be made.
+ #[lints(indexing_slicing)]
+ suppress_restriction_lint_in_const: bool = false,
+ /// The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
+ #[lints(boxed_local, useless_vec)]
+ too_large_for_stack: u64 = 200,
+ /// The maximum number of argument a function or method can have
+ #[lints(too_many_arguments)]
+ too_many_arguments_threshold: u64 = 7,
+ /// The maximum number of lines a function or method can have
+ #[lints(too_many_lines)]
+ too_many_lines_threshold: u64 = 100,
+ /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
+ /// reference. By default there is no limit
+ #[default_text = "target_pointer_width * 2"]
+ #[lints(trivially_copy_pass_by_ref)]
+ trivial_copy_size_limit: Option<u64> = None,
+ /// The maximum complexity a type can have
+ #[lints(type_complexity)]
+ type_complexity_threshold: u64 = 250,
+ /// The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
+ #[lints(unnecessary_box_returns)]
+ unnecessary_box_size: u64 = 128,
+ /// Should the fraction of a decimal be linted to include separators.
+ #[lints(unreadable_literal)]
+ unreadable_literal_lint_fractions: bool = true,
+ /// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
+ #[lints(upper_case_acronyms)]
+ upper_case_acronyms_aggressive: bool = false,
+ /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
+ #[lints(vec_box)]
+ vec_box_size_threshold: u64 = 4096,
+ /// The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
+ #[lints(verbose_bit_mask)]
+ verbose_bit_mask_threshold: u64 = 1,
+ /// Whether to allow certain wildcard imports (prelude, super in tests).
+ #[lints(wildcard_imports)]
+ warn_on_all_wildcard_imports: bool = false,
/// Whether to also emit warnings for unsafe blocks with metavariable expansions in **private** macros.
- (warn_unsafe_macro_metavars_in_private_macros: bool = false),
+ #[lints(macro_metavars_in_unsafe)]
+ warn_unsafe_macro_metavars_in_private_macros: bool = false,
}
/// Search for the configuration file.
diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs
index ff7fa72..d2246f1 100644
--- a/src/tools/clippy/clippy_config/src/lib.rs
+++ b/src/tools/clippy/clippy_config/src/lib.rs
@@ -1,5 +1,4 @@
-#![feature(rustc_private, let_chains)]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![feature(rustc_private, array_windows, let_chains)]
#![warn(
trivial_casts,
trivial_numeric_casts,
diff --git a/src/tools/clippy/clippy_config/src/metadata.rs b/src/tools/clippy/clippy_config/src/metadata.rs
index 4008871..7cbd92a 100644
--- a/src/tools/clippy/clippy_config/src/metadata.rs
+++ b/src/tools/clippy/clippy_config/src/metadata.rs
@@ -1,11 +1,12 @@
-use std::fmt::{self, Write};
+use itertools::Itertools;
+use std::fmt;
#[derive(Debug, Clone, Default)]
pub struct ClippyConfiguration {
pub name: String,
pub default: String,
- pub lints: Vec<String>,
- pub doc: String,
+ pub lints: &'static [&'static str],
+ pub doc: &'static str,
pub deprecation_reason: Option<&'static str>,
}
@@ -13,61 +14,23 @@ impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "- `{}`: {}", self.name, self.doc)?;
if !self.default.is_empty() {
- write!(f, " (default: `{}`)", self.default)?;
+ write!(f, "\n\n (default: `{}`)", self.default)?;
}
Ok(())
}
}
impl ClippyConfiguration {
- pub fn new(
- name: &'static str,
- default: String,
- doc_comment: &'static str,
- deprecation_reason: Option<&'static str>,
- ) -> Self {
- let (mut lints, doc) = parse_config_field_doc(doc_comment)
- .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
-
- lints.sort();
-
- Self {
- name: to_kebab(name),
- lints,
- doc,
- default,
- deprecation_reason,
- }
- }
-
pub fn to_markdown_paragraph(&self) -> String {
- let mut out = format!(
- "## `{}`\n{}\n\n",
+ format!(
+ "## `{}`\n{}\n\n**Default Value:** `{}`\n\n---\n**Affected lints:**\n{}\n\n",
self.name,
- self.doc
- .lines()
- .map(|line| line.strip_prefix(" ").unwrap_or(line))
- .collect::<Vec<_>>()
- .join("\n"),
- );
-
- if !self.default.is_empty() {
- write!(out, "**Default Value:** `{}`\n\n", self.default).unwrap();
- }
-
- write!(
- out,
- "---\n**Affected lints:**\n{}\n\n",
- self.lints
- .iter()
- .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
- .map(|name| format!("* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
- .collect::<Vec<_>>()
- .join("\n"),
+ self.doc.lines().map(|x| x.strip_prefix(' ').unwrap_or(x)).join("\n"),
+ self.default,
+ self.lints.iter().format_with("\n", |name, f| f(&format_args!(
+ "* [`{name}`](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"
+ ))),
)
- .unwrap();
-
- out
}
pub fn to_markdown_link(&self) -> String {
@@ -75,47 +38,3 @@ pub fn to_markdown_link(&self) -> String {
format!("[`{}`]: {BOOK_CONFIGS_PATH}#{}", self.name, self.name)
}
}
-
-/// This parses the field documentation of the config struct.
-///
-/// ```rust, ignore
-/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
-/// ```
-///
-/// Would yield:
-/// ```rust, ignore
-/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
-/// ```
-fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
- const DOC_START: &str = " Lint: ";
- if doc_comment.starts_with(DOC_START)
- && let Some(split_pos) = doc_comment.find('.')
- {
- let mut doc_comment = doc_comment.to_string();
- let mut documentation = doc_comment.split_off(split_pos);
-
- // Extract lints
- doc_comment.make_ascii_lowercase();
- let lints: Vec<String> = doc_comment
- .split_off(DOC_START.len())
- .lines()
- .next()
- .unwrap()
- .split(", ")
- .map(str::to_string)
- .collect();
-
- // Format documentation correctly
- // split off leading `.` from lint name list and indent for correct formatting
- documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
-
- Some((lints, documentation))
- } else {
- None
- }
-}
-
-/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
-fn to_kebab(config_name: &str) -> String {
- config_name.replace('_', "-")
-}
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index 4104e7d..a5d72c3 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -13,9 +13,6 @@
shell-escape = "0.1"
walkdir = "2.3"
-[features]
-deny-warnings = []
-
[package.metadata.rust-analyzer]
# This package uses #[feature(rustc_private)]
rustc_private = true
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 2562314..5fc4365 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -1,30 +1,65 @@
use crate::clippy_project_root;
use itertools::Itertools;
+use rustc_lexer::{tokenize, TokenKind};
use shell_escape::escape;
use std::ffi::{OsStr, OsString};
-use std::path::Path;
+use std::ops::ControlFlow;
+use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};
use std::{fs, io};
use walkdir::WalkDir;
-#[derive(Debug)]
-pub enum CliError {
+pub enum Error {
CommandFailed(String, String),
- IoError(io::Error),
+ Io(io::Error),
RustfmtNotInstalled,
- WalkDirError(walkdir::Error),
+ WalkDir(walkdir::Error),
IntellijSetupActive,
+ Parse(PathBuf, usize, String),
+ CheckFailed,
}
-impl From<io::Error> for CliError {
+impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
- Self::IoError(error)
+ Self::Io(error)
}
}
-impl From<walkdir::Error> for CliError {
+impl From<walkdir::Error> for Error {
fn from(error: walkdir::Error) -> Self {
- Self::WalkDirError(error)
+ Self::WalkDir(error)
+ }
+}
+
+impl Error {
+ fn display(&self) {
+ match self {
+ Self::CheckFailed => {
+ eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update.");
+ },
+ Self::CommandFailed(command, stderr) => {
+ eprintln!("error: command `{command}` failed!\nstderr: {stderr}");
+ },
+ Self::Io(err) => {
+ eprintln!("error: {err}");
+ },
+ Self::RustfmtNotInstalled => {
+ eprintln!("error: rustfmt nightly is not installed.");
+ },
+ Self::WalkDir(err) => {
+ eprintln!("error: {err}");
+ },
+ Self::IntellijSetupActive => {
+ eprintln!(
+ "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.\n\
+ Not formatting because that would format the local repo as well!\n\
+ Please revert the changes to `Cargo.toml`s with `cargo dev remove intellij`."
+ );
+ },
+ Self::Parse(path, line, msg) => {
+ eprintln!("error parsing `{}:{line}`: {msg}", path.display());
+ },
+ }
}
}
@@ -34,75 +69,244 @@ struct FmtContext {
rustfmt_path: String,
}
+struct ClippyConf<'a> {
+ name: &'a str,
+ attrs: &'a str,
+ lints: Vec<&'a str>,
+ field: &'a str,
+}
+
+fn offset_to_line(text: &str, offset: usize) -> usize {
+ match text.split('\n').try_fold((1usize, 0usize), |(line, pos), s| {
+ let pos = pos + s.len() + 1;
+ if pos > offset {
+ ControlFlow::Break(line)
+ } else {
+ ControlFlow::Continue((line + 1, pos))
+ }
+ }) {
+ ControlFlow::Break(x) | ControlFlow::Continue((x, _)) => x,
+ }
+}
+
+/// Formats the configuration list in `clippy_config/src/conf.rs`
+#[expect(clippy::too_many_lines)]
+fn fmt_conf(check: bool) -> Result<(), Error> {
+ #[derive(Clone, Copy)]
+ enum State {
+ Start,
+ Docs,
+ Pound,
+ OpenBracket,
+ Attr(u32),
+ Lints,
+ EndLints,
+ Field,
+ }
+
+ let path: PathBuf = [
+ clippy_project_root().as_path(),
+ "clippy_config".as_ref(),
+ "src".as_ref(),
+ "conf.rs".as_ref(),
+ ]
+ .into_iter()
+ .collect();
+ let text = fs::read_to_string(&path)?;
+
+ let (pre, conf) = text
+ .split_once("define_Conf! {\n")
+ .expect("can't find config definition");
+ let (conf, post) = conf.split_once("\n}\n").expect("can't find config definition");
+ let conf_offset = pre.len() + 15;
+
+ let mut pos = 0u32;
+ let mut attrs_start = 0;
+ let mut attrs_end = 0;
+ let mut field_start = 0;
+ let mut lints = Vec::new();
+ let mut name = "";
+ let mut fields = Vec::new();
+ let mut state = State::Start;
+
+ for (i, t) in tokenize(conf)
+ .map(|x| {
+ let start = pos;
+ pos += x.len;
+ (start as usize, x)
+ })
+ .filter(|(_, t)| !matches!(t.kind, TokenKind::Whitespace))
+ {
+ match (state, t.kind) {
+ (State::Start, TokenKind::LineComment { doc_style: Some(_) }) => {
+ attrs_start = i;
+ attrs_end = i + t.len as usize;
+ state = State::Docs;
+ },
+ (State::Start, TokenKind::Pound) => {
+ attrs_start = i;
+ attrs_end = i;
+ state = State::Pound;
+ },
+ (State::Docs, TokenKind::LineComment { doc_style: Some(_) }) => attrs_end = i + t.len as usize,
+ (State::Docs, TokenKind::Pound) => state = State::Pound,
+ (State::Pound, TokenKind::OpenBracket) => state = State::OpenBracket,
+ (State::OpenBracket, TokenKind::Ident) => {
+ state = if conf[i..i + t.len as usize] == *"lints" {
+ State::Lints
+ } else {
+ State::Attr(0)
+ };
+ },
+ (State::Attr(0), TokenKind::CloseBracket) => {
+ attrs_end = i + 1;
+ state = State::Docs;
+ },
+ (State::Attr(x), TokenKind::OpenParen | TokenKind::OpenBracket | TokenKind::OpenBrace) => {
+ state = State::Attr(x + 1);
+ },
+ (State::Attr(x), TokenKind::CloseParen | TokenKind::CloseBracket | TokenKind::CloseBrace) => {
+ state = State::Attr(x - 1);
+ },
+ (State::Lints, TokenKind::Ident) => lints.push(&conf[i..i + t.len as usize]),
+ (State::Lints, TokenKind::CloseBracket) => state = State::EndLints,
+ (State::EndLints | State::Docs, TokenKind::Ident) => {
+ field_start = i;
+ name = &conf[i..i + t.len as usize];
+ state = State::Field;
+ },
+ (State::Field, TokenKind::LineComment { doc_style: Some(_) }) => {
+ #[expect(clippy::drain_collect)]
+ fields.push(ClippyConf {
+ name,
+ lints: lints.drain(..).collect(),
+ attrs: &conf[attrs_start..attrs_end],
+ field: conf[field_start..i].trim_end(),
+ });
+ attrs_start = i;
+ attrs_end = i + t.len as usize;
+ state = State::Docs;
+ },
+ (State::Field, TokenKind::Pound) => {
+ #[expect(clippy::drain_collect)]
+ fields.push(ClippyConf {
+ name,
+ lints: lints.drain(..).collect(),
+ attrs: &conf[attrs_start..attrs_end],
+ field: conf[field_start..i].trim_end(),
+ });
+ attrs_start = i;
+ attrs_end = i;
+ state = State::Pound;
+ },
+ (State::Field | State::Attr(_), _)
+ | (State::Lints, TokenKind::Comma | TokenKind::OpenParen | TokenKind::CloseParen) => {},
+ _ => {
+ return Err(Error::Parse(
+ path,
+ offset_to_line(&text, conf_offset + i),
+ format!("unexpected token `{}`", &conf[i..i + t.len as usize]),
+ ));
+ },
+ }
+ }
+
+ if !matches!(state, State::Field) {
+ return Err(Error::Parse(
+ path,
+ offset_to_line(&text, conf_offset + conf.len()),
+ "incomplete field".into(),
+ ));
+ }
+ fields.push(ClippyConf {
+ name,
+ lints,
+ attrs: &conf[attrs_start..attrs_end],
+ field: conf[field_start..].trim_end(),
+ });
+
+ for field in &mut fields {
+ field.lints.sort_unstable();
+ }
+ fields.sort_by_key(|x| x.name);
+
+ let new_text = format!(
+ "{pre}define_Conf! {{\n{}}}\n{post}",
+ fields.iter().format_with("", |field, f| {
+ if field.lints.is_empty() {
+ f(&format_args!(" {}\n {}\n", field.attrs, field.field))
+ } else if field.lints.iter().map(|x| x.len() + 2).sum::<usize>() < 120 - 14 {
+ f(&format_args!(
+ " {}\n #[lints({})]\n {}\n",
+ field.attrs,
+ field.lints.iter().join(", "),
+ field.field,
+ ))
+ } else {
+ f(&format_args!(
+ " {}\n #[lints({}\n )]\n {}\n",
+ field.attrs,
+ field
+ .lints
+ .iter()
+ .format_with("", |x, f| f(&format_args!("\n {x},"))),
+ field.field,
+ ))
+ }
+ })
+ );
+
+ if text != new_text {
+ if check {
+ return Err(Error::CheckFailed);
+ }
+ fs::write(&path, new_text.as_bytes())?;
+ }
+ Ok(())
+}
+
+fn run_rustfmt(context: &FmtContext) -> Result<(), Error> {
+ let project_root = clippy_project_root();
+
+ // if we added a local rustc repo as path dependency to clippy for rust analyzer, we do NOT want to
+ // format because rustfmt would also format the entire rustc repo as it is a local
+ // dependency
+ if fs::read_to_string(project_root.join("Cargo.toml"))
+ .expect("Failed to read clippy Cargo.toml")
+ .contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]")
+ {
+ return Err(Error::IntellijSetupActive);
+ }
+
+ check_for_rustfmt(context)?;
+
+ cargo_fmt(context, project_root.as_path())?;
+ cargo_fmt(context, &project_root.join("clippy_dev"))?;
+ cargo_fmt(context, &project_root.join("rustc_tools_util"))?;
+ cargo_fmt(context, &project_root.join("lintcheck"))?;
+
+ let chunks = WalkDir::new(project_root.join("tests"))
+ .into_iter()
+ .filter_map(|entry| {
+ let entry = entry.expect("failed to find tests");
+ let path = entry.path();
+
+ if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" {
+ None
+ } else {
+ Some(entry.into_path().into_os_string())
+ }
+ })
+ .chunks(250);
+
+ for chunk in &chunks {
+ rustfmt(context, chunk)?;
+ }
+ Ok(())
+}
+
// the "main" function of cargo dev fmt
pub fn run(check: bool, verbose: bool) {
- fn try_run(context: &FmtContext) -> Result<bool, CliError> {
- let mut success = true;
-
- let project_root = clippy_project_root();
-
- // if we added a local rustc repo as path dependency to clippy for rust analyzer, we do NOT want to
- // format because rustfmt would also format the entire rustc repo as it is a local
- // dependency
- if fs::read_to_string(project_root.join("Cargo.toml"))
- .expect("Failed to read clippy Cargo.toml")
- .contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]")
- {
- return Err(CliError::IntellijSetupActive);
- }
-
- rustfmt_test(context)?;
-
- success &= cargo_fmt(context, project_root.as_path())?;
- success &= cargo_fmt(context, &project_root.join("clippy_dev"))?;
- success &= cargo_fmt(context, &project_root.join("rustc_tools_util"))?;
- success &= cargo_fmt(context, &project_root.join("lintcheck"))?;
-
- let chunks = WalkDir::new(project_root.join("tests"))
- .into_iter()
- .filter_map(|entry| {
- let entry = entry.expect("failed to find tests");
- let path = entry.path();
-
- if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" {
- None
- } else {
- Some(entry.into_path().into_os_string())
- }
- })
- .chunks(250);
-
- for chunk in &chunks {
- success &= rustfmt(context, chunk)?;
- }
-
- Ok(success)
- }
-
- fn output_err(err: CliError) {
- match err {
- CliError::CommandFailed(command, stderr) => {
- eprintln!("error: A command failed! `{command}`\nstderr: {stderr}");
- },
- CliError::IoError(err) => {
- eprintln!("error: {err}");
- },
- CliError::RustfmtNotInstalled => {
- eprintln!("error: rustfmt nightly is not installed.");
- },
- CliError::WalkDirError(err) => {
- eprintln!("error: {err}");
- },
- CliError::IntellijSetupActive => {
- eprintln!(
- "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.
-Not formatting because that would format the local repo as well!
-Please revert the changes to Cargo.tomls with `cargo dev remove intellij`."
- );
- },
- }
- }
-
let output = Command::new("rustup")
.args(["which", "rustfmt"])
.stderr(Stdio::inherit())
@@ -120,21 +324,10 @@ fn output_err(err: CliError) {
verbose,
rustfmt_path,
};
- let result = try_run(&context);
- let code = match result {
- Ok(true) => 0,
- Ok(false) => {
- eprintln!();
- eprintln!("Formatting check failed.");
- eprintln!("Run `cargo dev fmt` to update formatting.");
- 1
- },
- Err(err) => {
- output_err(err);
- 1
- },
- };
- process::exit(code);
+ if let Err(e) = run_rustfmt(&context).and_then(|()| fmt_conf(check)) {
+ e.display();
+ process::exit(1);
+ }
}
fn format_command(program: impl AsRef<OsStr>, dir: impl AsRef<Path>, args: &[impl AsRef<OsStr>]) -> String {
@@ -148,12 +341,12 @@ fn format_command(program: impl AsRef<OsStr>, dir: impl AsRef<Path>, args: &[imp
)
}
-fn exec(
+fn exec_fmt_command(
context: &FmtContext,
program: impl AsRef<OsStr>,
dir: impl AsRef<Path>,
args: &[impl AsRef<OsStr>],
-) -> Result<bool, CliError> {
+) -> Result<(), Error> {
if context.verbose {
println!("{}", format_command(&program, &dir, args));
}
@@ -166,28 +359,28 @@ fn exec(
.unwrap();
let success = output.status.success();
- if !context.check && !success {
- let stderr = std::str::from_utf8(&output.stderr).unwrap_or("");
- return Err(CliError::CommandFailed(
- format_command(&program, &dir, args),
- String::from(stderr),
- ));
+ match (context.check, success) {
+ (_, true) => Ok(()),
+ (true, false) => Err(Error::CheckFailed),
+ (false, false) => {
+ let stderr = std::str::from_utf8(&output.stderr).unwrap_or("");
+ Err(Error::CommandFailed(
+ format_command(&program, &dir, args),
+ String::from(stderr),
+ ))
+ },
}
-
- Ok(success)
}
-fn cargo_fmt(context: &FmtContext, path: &Path) -> Result<bool, CliError> {
+fn cargo_fmt(context: &FmtContext, path: &Path) -> Result<(), Error> {
let mut args = vec!["fmt", "--all"];
if context.check {
args.push("--check");
}
- let success = exec(context, "cargo", path, &args)?;
-
- Ok(success)
+ exec_fmt_command(context, "cargo", path, &args)
}
-fn rustfmt_test(context: &FmtContext) -> Result<(), CliError> {
+fn check_for_rustfmt(context: &FmtContext) -> Result<(), Error> {
let program = "rustfmt";
let dir = std::env::current_dir()?;
let args = &["--version"];
@@ -204,23 +397,20 @@ fn rustfmt_test(context: &FmtContext) -> Result<(), CliError> {
.unwrap_or("")
.starts_with("error: 'rustfmt' is not installed")
{
- Err(CliError::RustfmtNotInstalled)
+ Err(Error::RustfmtNotInstalled)
} else {
- Err(CliError::CommandFailed(
+ Err(Error::CommandFailed(
format_command(program, &dir, args),
std::str::from_utf8(&output.stderr).unwrap_or("").to_string(),
))
}
}
-fn rustfmt(context: &FmtContext, paths: impl Iterator<Item = OsString>) -> Result<bool, CliError> {
+fn rustfmt(context: &FmtContext, paths: impl Iterator<Item = OsString>) -> Result<(), Error> {
let mut args = Vec::new();
if context.check {
args.push(OsString::from("--check"));
}
args.extend(paths);
-
- let success = exec(context, &context.rustfmt_path, std::env::current_dir()?, &args)?;
-
- Ok(success)
+ exec_fmt_command(context, &context.rustfmt_path, std::env::current_dir()?, &args)
}
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 3aa43db..ad385d5 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,6 +1,5 @@
#![feature(let_chains)]
#![feature(rustc_private)]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(
trivial_casts,
trivial_numeric_casts,
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index 366b52b..755b04b 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
@@ -74,7 +73,7 @@ fn main() {
new_name,
uplift,
} => update_lints::rename(&old_name, new_name.as_ref().unwrap_or(&old_name), uplift),
- DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, reason.as_deref()),
+ DevCommand::Deprecate { name, reason } => update_lints::deprecate(&name, &reason),
}
}
@@ -223,7 +222,7 @@ enum DevCommand {
name: String,
#[arg(long, short)]
/// The reason for deprecation
- reason: Option<String>,
+ reason: String,
},
}
diff --git a/src/tools/clippy/clippy_dev/src/serve.rs b/src/tools/clippy/clippy_dev/src/serve.rs
index 4a4261d..19560b3 100644
--- a/src/tools/clippy/clippy_dev/src/serve.rs
+++ b/src/tools/clippy/clippy_dev/src/serve.rs
@@ -1,10 +1,14 @@
-use std::ffi::OsStr;
-use std::num::ParseIntError;
use std::path::Path;
use std::process::Command;
use std::time::{Duration, SystemTime};
use std::{env, thread};
+#[cfg(windows)]
+const PYTHON: &str = "python";
+
+#[cfg(not(windows))]
+const PYTHON: &str = "python3";
+
/// # Panics
///
/// Panics if the python commands could not be spawned
@@ -25,7 +29,7 @@ pub fn run(port: u16, lint: Option<String>) -> ! {
}
if let Some(url) = url.take() {
thread::spawn(move || {
- Command::new("python3")
+ Command::new(PYTHON)
.arg("-m")
.arg("http.server")
.arg(port.to_string())
@@ -58,8 +62,3 @@ fn mtime(path: impl AsRef<Path>) -> SystemTime {
.unwrap_or(SystemTime::UNIX_EPOCH)
}
}
-
-#[allow(clippy::missing_errors_doc)]
-pub fn validate_port(arg: &OsStr) -> Result<(), ParseIntError> {
- arg.to_string_lossy().parse::<u16>().map(|_| ())
-}
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 4535390..15578d6 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -1,13 +1,12 @@
use crate::clippy_project_root;
use aho_corasick::AhoCorasickBuilder;
-use indoc::writedoc;
use itertools::Itertools;
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::fmt::{self, Write};
use std::fs::{self, OpenOptions};
-use std::io::{self, Read, Seek, SeekFrom, Write as _};
+use std::io::{self, Read, Seek, Write as _};
use std::ops::Range;
use std::path::{Path, PathBuf};
use walkdir::{DirEntry, WalkDir};
@@ -77,12 +76,8 @@ fn generate_lint_files(
for lint in usable_lints
.iter()
.map(|l| &*l.name)
- .chain(deprecated_lints.iter().map(|l| &*l.name))
- .chain(
- renamed_lints
- .iter()
- .map(|l| l.old_name.strip_prefix("clippy::").unwrap_or(&l.old_name)),
- )
+ .chain(deprecated_lints.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
+ .chain(renamed_lints.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
.sorted()
{
writeln!(res, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
@@ -108,11 +103,6 @@ fn generate_lint_files(
update_mode,
&gen_declared_lints(internal_lints.iter(), usable_lints.iter()),
);
- process_file(
- "clippy_lints/src/lib.deprecated.rs",
- update_mode,
- &gen_deprecated(deprecated_lints),
- );
let content = gen_deprecated_lints_test(deprecated_lints);
process_file("tests/ui/deprecated.rs", update_mode, &content);
@@ -205,7 +195,7 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
let ext = f.path().extension();
(ext == Some(OsStr::new("rs")) || ext == Some(OsStr::new("fixed")))
&& name != Some(OsStr::new("rename.rs"))
- && name != Some(OsStr::new("renamed_lints.rs"))
+ && name != Some(OsStr::new("deprecated_lints.rs"))
})
{
rewrite_file(file.path(), |s| {
@@ -213,6 +203,19 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
});
}
+ let version = crate::new_lint::get_stabilization_version();
+ rewrite_file(Path::new("clippy_lints/src/deprecated_lints.rs"), |s| {
+ insert_at_marker(
+ s,
+ "// end renamed lints. used by `cargo dev rename_lint`",
+ &format!(
+ "#[clippy::version = \"{version}\"]\n \
+ (\"{}\", \"{}\"),\n ",
+ lint.old_name, lint.new_name,
+ ),
+ )
+ });
+
renamed_lints.push(lint);
renamed_lints.sort_by(|lhs, rhs| {
lhs.new_name
@@ -222,11 +225,6 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
.then_with(|| lhs.old_name.cmp(&rhs.old_name))
});
- write_file(
- Path::new("clippy_lints/src/renamed_lints.rs"),
- &gen_renamed_lints_list(&renamed_lints),
- );
-
if uplift {
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
println!(
@@ -293,7 +291,8 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
// Don't change `clippy_utils/src/renamed_lints.rs` here as it would try to edit the lint being
// renamed.
- for (_, file) in clippy_lints_src_files().filter(|(rel_path, _)| rel_path != OsStr::new("renamed_lints.rs")) {
+ for (_, file) in clippy_lints_src_files().filter(|(rel_path, _)| rel_path != OsStr::new("deprecated_lints.rs"))
+ {
rewrite_file(file.path(), |s| replace_ident_like(s, replacements));
}
@@ -304,7 +303,6 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
println!("note: `cargo uitest` still needs to be run to update the test results");
}
-const DEFAULT_DEPRECATION_REASON: &str = "default deprecation note";
/// Runs the `deprecate` command
///
/// This does the following:
@@ -314,33 +312,16 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
/// # Panics
///
/// If a file path could not read from or written to
-pub fn deprecate(name: &str, reason: Option<&str>) {
- fn finish(
- (lints, mut deprecated_lints, renamed_lints): (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>),
- name: &str,
- reason: &str,
- ) {
- deprecated_lints.push(DeprecatedLint {
- name: name.to_string(),
- reason: reason.to_string(),
- declaration_range: Range::default(),
- });
+pub fn deprecate(name: &str, reason: &str) {
+ let prefixed_name = if name.starts_with("clippy::") {
+ name.to_owned()
+ } else {
+ format!("clippy::{name}")
+ };
+ let stripped_name = &prefixed_name[8..];
- generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
- println!("info: `{name}` has successfully been deprecated");
-
- if reason == DEFAULT_DEPRECATION_REASON {
- println!("note: the deprecation reason must be updated in `clippy_lints/src/deprecated_lints.rs`");
- }
- println!("note: you must run `cargo uitest` to update the test results");
- }
-
- let reason = reason.unwrap_or(DEFAULT_DEPRECATION_REASON);
- let name_lower = name.to_lowercase();
- let name_upper = name.to_uppercase();
-
- let (mut lints, deprecated_lints, renamed_lints) = gather_all();
- let Some(lint) = lints.iter().find(|l| l.name == name_lower) else {
+ let (mut lints, mut deprecated_lints, renamed_lints) = gather_all();
+ let Some(lint) = lints.iter().find(|l| l.name == stripped_name) else {
eprintln!("error: failed to find lint `{name}`");
return;
};
@@ -357,13 +338,27 @@ fn finish(
let deprecated_lints_path = &*clippy_project_root().join("clippy_lints/src/deprecated_lints.rs");
- if remove_lint_declaration(&name_lower, &mod_path, &mut lints).unwrap_or(false) {
- declare_deprecated(&name_upper, deprecated_lints_path, reason).unwrap();
- finish((lints, deprecated_lints, renamed_lints), name, reason);
- return;
- }
+ if remove_lint_declaration(stripped_name, &mod_path, &mut lints).unwrap_or(false) {
+ let version = crate::new_lint::get_stabilization_version();
+ rewrite_file(deprecated_lints_path, |s| {
+ insert_at_marker(
+ s,
+ "// end deprecated lints. used by `cargo dev deprecate_lint`",
+ &format!("#[clippy::version = \"{version}\"]\n (\"{prefixed_name}\", \"{reason}\"),\n ",),
+ )
+ });
- eprintln!("error: lint not found");
+ deprecated_lints.push(DeprecatedLint {
+ name: prefixed_name,
+ reason: reason.into(),
+ });
+
+ generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
+ println!("info: `{name}` has successfully been deprecated");
+ println!("note: you must run `cargo uitest` to update the test results");
+ } else {
+ eprintln!("error: lint not found");
+ }
}
fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io::Result<bool> {
@@ -377,14 +372,14 @@ fn remove_test_assets(name: &str) {
// Some lints have their own directories, delete them
if path.is_dir() {
- fs::remove_dir_all(path).ok();
+ let _ = fs::remove_dir_all(path);
return;
}
// Remove all related test files
- fs::remove_file(path.with_extension("rs")).ok();
- fs::remove_file(path.with_extension("stderr")).ok();
- fs::remove_file(path.with_extension("fixed")).ok();
+ let _ = fs::remove_file(path.with_extension("rs"));
+ let _ = fs::remove_file(path.with_extension("stderr"));
+ let _ = fs::remove_file(path.with_extension("fixed"));
}
fn remove_impl_lint_pass(lint_name_upper: &str, content: &mut String) {
@@ -427,7 +422,7 @@ fn remove_impl_lint_pass(lint_name_upper: &str, content: &mut String) {
lint_mod_path.set_file_name(name);
lint_mod_path.set_extension("rs");
- fs::remove_file(lint_mod_path).ok();
+ let _ = fs::remove_file(lint_mod_path);
}
let mut content =
@@ -465,37 +460,6 @@ fn remove_impl_lint_pass(lint_name_upper: &str, content: &mut String) {
Ok(false)
}
-fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> {
- let mut file = OpenOptions::new().write(true).open(path)?;
-
- file.seek(SeekFrom::End(0))?;
-
- let version = crate::new_lint::get_stabilization_version();
- let deprecation_reason = if reason == DEFAULT_DEPRECATION_REASON {
- "TODO"
- } else {
- reason
- };
-
- writedoc!(
- file,
- "
-
- declare_deprecated_lint! {{
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// {deprecation_reason}
- #[clippy::version = \"{version}\"]
- pub {name},
- \"{reason}\"
- }}
-
- "
- )
-}
-
/// Replace substrings if they aren't bordered by identifier characters. Returns `None` if there
/// were no replacements.
fn replace_ident_like(contents: &str, replacements: &[(&str, &str)]) -> Option<String> {
@@ -604,14 +568,12 @@ fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>
struct DeprecatedLint {
name: String,
reason: String,
- declaration_range: Range<usize>,
}
impl DeprecatedLint {
- fn new(name: &str, reason: &str, declaration_range: Range<usize>) -> Self {
+ fn new(name: &str, reason: &str) -> Self {
Self {
- name: name.to_lowercase(),
+ name: remove_line_splices(name),
reason: remove_line_splices(reason),
- declaration_range,
}
}
}
@@ -629,28 +591,6 @@ fn new(old_name: &str, new_name: &str) -> Self {
}
}
-/// Generates the `register_removed` code
-#[must_use]
-fn gen_deprecated(lints: &[DeprecatedLint]) -> String {
- let mut output = GENERATED_FILE_COMMENT.to_string();
- output.push_str("{\n");
- for lint in lints {
- let _: fmt::Result = write!(
- output,
- concat!(
- " store.register_removed(\n",
- " \"clippy::{}\",\n",
- " \"{}\",\n",
- " );\n"
- ),
- lint.name, lint.reason,
- );
- }
- output.push_str("}\n");
-
- output
-}
-
/// Generates the code for registering lints
#[must_use]
fn gen_declared_lints<'a>(
@@ -680,7 +620,7 @@ fn gen_declared_lints<'a>(
fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String {
let mut res: String = GENERATED_FILE_COMMENT.into();
for lint in lints {
- writeln!(res, "#![warn(clippy::{})]", lint.name).unwrap();
+ writeln!(res, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
}
res.push_str("\nfn main() {}\n");
res
@@ -699,27 +639,13 @@ fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
seen_lints.clear();
for lint in lints {
if seen_lints.insert(&lint.old_name) {
- writeln!(res, "#![warn({})]", lint.old_name).unwrap();
+ writeln!(res, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
}
}
res.push_str("\nfn main() {}\n");
res
}
-fn gen_renamed_lints_list(lints: &[RenamedLint]) -> String {
- const HEADER: &str = "\
- // This file is managed by `cargo dev rename_lint`. Prefer using that when possible.\n\n\
- #[rustfmt::skip]\n\
- pub static RENAMED_LINTS: &[(&str, &str)] = &[\n";
-
- let mut res = String::from(HEADER);
- for lint in lints {
- writeln!(res, " (\"{}\", \"{}\"),", lint.old_name, lint.new_name).unwrap();
- }
- res.push_str("];\n");
- res
-}
-
/// Gathers all lints defined in `clippy_lints/src`
fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
let mut lints = Vec::with_capacity(1000);
@@ -744,10 +670,10 @@ fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
module.strip_suffix(".rs").unwrap_or(&module)
};
- match module {
- "deprecated_lints" => parse_deprecated_contents(&contents, &mut deprecated_lints),
- "renamed_lints" => parse_renamed_contents(&contents, &mut renamed_lints),
- _ => parse_contents(&contents, module, &mut lints),
+ if module == "deprecated_lints" {
+ parse_deprecated_contents(&contents, &mut deprecated_lints, &mut renamed_lints);
+ } else {
+ parse_contents(&contents, module, &mut lints);
}
}
(lints, deprecated_lints, renamed_lints)
@@ -848,54 +774,37 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec<Lint>) {
}
/// Parse a source file looking for `declare_deprecated_lint` macro invocations.
-fn parse_deprecated_contents(contents: &str, lints: &mut Vec<DeprecatedLint>) {
- let mut offset = 0usize;
- let mut iter = tokenize(contents).map(|t| {
- let range = offset..offset + t.len as usize;
- offset = range.end;
+fn parse_deprecated_contents(contents: &str, deprecated: &mut Vec<DeprecatedLint>, renamed: &mut Vec<RenamedLint>) {
+ let Some((_, contents)) = contents.split_once("\ndeclare_with_version! { DEPRECATED") else {
+ return;
+ };
+ let Some((deprecated_src, renamed_src)) = contents.split_once("\ndeclare_with_version! { RENAMED") else {
+ return;
+ };
- LintDeclSearchResult {
- token_kind: t.kind,
- content: &contents[range.clone()],
- range,
- }
- });
+ for line in deprecated_src.lines() {
+ let mut offset = 0usize;
+ let mut iter = tokenize(line).map(|t| {
+ let range = offset..offset + t.len as usize;
+ offset = range.end;
- while let Some(LintDeclSearchResult { range, .. }) = iter.find(
- |LintDeclSearchResult {
- token_kind, content, ..
- }| token_kind == &TokenKind::Ident && *content == "declare_deprecated_lint",
- ) {
- let start = range.start;
-
- let mut iter = iter.by_ref().filter(|LintDeclSearchResult { ref token_kind, .. }| {
- !matches!(token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. })
+ LintDeclSearchResult {
+ token_kind: t.kind,
+ content: &line[range.clone()],
+ range,
+ }
});
+
let (name, reason) = match_tokens!(
iter,
- // !{
- Bang OpenBrace
- // #[clippy::version = "version"]
- Pound OpenBracket Ident Colon Colon Ident Eq Literal{..} CloseBracket
- // pub LINT_NAME,
- Ident Ident(name) Comma
- // "description"
- Literal{kind: LiteralKind::Str{..},..}(reason)
+ // ("old_name",
+ Whitespace OpenParen Literal{kind: LiteralKind::Str{..},..}(name) Comma
+ // "new_name"),
+ Whitespace Literal{kind: LiteralKind::Str{..},..}(reason) CloseParen Comma
);
-
- if let Some(LintDeclSearchResult {
- token_kind: TokenKind::CloseBrace,
- range,
- ..
- }) = iter.next()
- {
- lints.push(DeprecatedLint::new(name, reason, start..range.end));
- }
+ deprecated.push(DeprecatedLint::new(name, reason));
}
-}
-
-fn parse_renamed_contents(contents: &str, lints: &mut Vec<RenamedLint>) {
- for line in contents.lines() {
+ for line in renamed_src.lines() {
let mut offset = 0usize;
let mut iter = tokenize(line).map(|t| {
let range = offset..offset + t.len as usize;
@@ -915,7 +824,7 @@ fn parse_renamed_contents(contents: &str, lints: &mut Vec<RenamedLint>) {
// "new_name"),
Whitespace Literal{kind: LiteralKind::Str{..},..}(new_name) CloseParen Comma
);
- lints.push(RenamedLint::new(old_name, new_name));
+ renamed.push(RenamedLint::new(old_name, new_name));
}
}
@@ -1015,6 +924,12 @@ fn panic_file(error: io::Error, name: &Path, action: &str) -> ! {
panic!("failed to {action} file `{}`: {error}", name.display())
}
+fn insert_at_marker(text: &str, marker: &str, new_text: &str) -> Option<String> {
+ let i = text.find(marker)?;
+ let (pre, post) = text.split_at(i);
+ Some([pre, new_text, post].into_iter().collect())
+}
+
fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option<String>) {
let mut file = OpenOptions::new()
.write(true)
@@ -1085,31 +1000,6 @@ fn test_parse_contents() {
}
#[test]
- fn test_parse_deprecated_contents() {
- static DEPRECATED_CONTENTS: &str = r#"
- /// some doc comment
- declare_deprecated_lint! {
- #[clippy::version = "I'm a version"]
- pub SHOULD_ASSERT_EQ,
- "`assert!()` will be more flexible with RFC 2011"
- }
- "#;
-
- let mut result = Vec::new();
- parse_deprecated_contents(DEPRECATED_CONTENTS, &mut result);
- for r in &mut result {
- r.declaration_range = Range::default();
- }
-
- let expected = vec![DeprecatedLint::new(
- "should_assert_eq",
- "\"`assert!()` will be more flexible with RFC 2011\"",
- Range::default(),
- )];
- assert_eq!(expected, result);
- }
-
- #[test]
fn test_usable_lints() {
let lints = vec![
Lint::new(
@@ -1177,34 +1067,4 @@ fn test_by_lint_group() {
);
assert_eq!(expected, Lint::by_lint_group(lints.into_iter()));
}
-
- #[test]
- fn test_gen_deprecated() {
- let lints = vec![
- DeprecatedLint::new(
- "should_assert_eq",
- "\"has been superseded by should_assert_eq2\"",
- Range::default(),
- ),
- DeprecatedLint::new("another_deprecated", "\"will be removed\"", Range::default()),
- ];
-
- let expected = GENERATED_FILE_COMMENT.to_string()
- + &[
- "{",
- " store.register_removed(",
- " \"clippy::should_assert_eq\",",
- " \"has been superseded by should_assert_eq2\",",
- " );",
- " store.register_removed(",
- " \"clippy::another_deprecated\",",
- " \"will be removed\",",
- " );",
- "}",
- ]
- .join("\n")
- + "\n";
-
- assert_eq!(expected, gen_deprecated(&lints));
- }
}
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index eb04c00..99ed934 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -32,7 +32,6 @@
walkdir = "2.3"
[features]
-deny-warnings = ["clippy_config/deny-warnings", "clippy_utils/deny-warnings"]
# build clippy with internal lints enabled, off by default
internal = ["serde_json", "tempfile", "regex"]
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index e6d52bc..3b4cc11 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -97,7 +97,7 @@ fn check_known_consts(&self, cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symb
cx,
APPROX_CONSTANT,
e.span,
- format!("approximate value of `{module}::consts::{}` found", &name),
+ format!("approximate value of `{module}::consts::{name}` found"),
None,
"consider using the constant directly",
);
diff --git a/src/tools/clippy/clippy_lints/src/as_conversions.rs b/src/tools/clippy/clippy_lints/src/as_conversions.rs
index cfa2500..fefd819 100644
--- a/src/tools/clippy/clippy_lints/src/as_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/as_conversions.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -52,13 +52,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
&& !in_external_macro(cx.sess(), expr.span)
&& !is_from_proc_macro(cx, expr)
{
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
AS_CONVERSIONS,
expr.span,
"using a potentially dangerous silent `as` conversion",
- None,
- "consider using a safe wrapper for this conversion",
+ |diag| {
+ diag.help("consider using a safe wrapper for this conversion");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
index 0db1456..69a8eb7 100644
--- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs
+++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
@@ -1,6 +1,6 @@
use std::fmt;
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
use rustc_ast::{InlineAsm, Item, ItemKind};
use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
@@ -49,14 +49,10 @@ fn check_asm_syntax(
};
if style == check_for {
- span_lint_and_help(
- cx,
- lint,
- span,
- format!("{style} x86 assembly syntax used"),
- None,
- format!("use {} x86 assembly syntax", !style),
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, lint, span, format!("{style} x86 assembly syntax used"), |diag| {
+ diag.help(format!("use {} x86 assembly syntax", !style));
+ });
}
}
}
@@ -98,13 +94,13 @@ fn check_asm_syntax(
impl EarlyLintPass for InlineAsmX86IntelSyntax {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if let ExprKind::InlineAsm(inline_asm) = &expr.kind {
- check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Intel);
+ check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, expr.span, AsmStyle::Intel);
}
}
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if let ItemKind::GlobalAsm(inline_asm) = &item.kind {
- check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Intel);
+ check_asm_syntax(INLINE_ASM_X86_INTEL_SYNTAX, cx, inline_asm, item.span, AsmStyle::Intel);
}
}
}
@@ -146,13 +142,13 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
impl EarlyLintPass for InlineAsmX86AttSyntax {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if let ExprKind::InlineAsm(inline_asm) = &expr.kind {
- check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Att);
+ check_asm_syntax(INLINE_ASM_X86_ATT_SYNTAX, cx, inline_asm, expr.span, AsmStyle::Att);
}
}
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if let ItemKind::GlobalAsm(inline_asm) = &item.kind {
- check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Att);
+ check_asm_syntax(INLINE_ASM_X86_ATT_SYNTAX, cx, inline_asm, item.span, AsmStyle::Att);
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index ed4cdce..7eaac80 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_inside_always_const_context;
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
@@ -43,7 +43,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else {
return;
};
- let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else {
+ let Some(Constant::Bool(val)) = ConstEvalCtxt::new(cx).eval(condition) else {
return;
};
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
index 7217686..f1cb4a0 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
@@ -68,39 +68,28 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
return;
}
}
- let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
- let mut app = Applicability::MachineApplicable;
- match method_segment.ident.as_str() {
+ let (message, replacement) = match method_segment.ident.as_str() {
"is_ok" if type_suitable_to_unwrap(cx, args.type_at(1)) => {
- span_lint_and_sugg(
- cx,
- ASSERTIONS_ON_RESULT_STATES,
- macro_call.span,
- "called `assert!` with `Result::is_ok`",
- "replace with",
- format!(
- "{}.unwrap(){semicolon}",
- snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
- ),
- app,
- );
+ ("called `assert!` with `Result::is_ok`", "unwrap")
},
"is_err" if type_suitable_to_unwrap(cx, args.type_at(0)) => {
- span_lint_and_sugg(
- cx,
- ASSERTIONS_ON_RESULT_STATES,
- macro_call.span,
- "called `assert!` with `Result::is_err`",
- "replace with",
- format!(
- "{}.unwrap_err(){semicolon}",
- snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
- ),
- app,
- );
+ ("called `assert!` with `Result::is_err`", "unwrap_err")
},
- _ => (),
+ _ => return,
};
+ span_lint_and_then(cx, ASSERTIONS_ON_RESULT_STATES, macro_call.span, message, |diag| {
+ let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
+ let mut app = Applicability::MachineApplicable;
+ diag.span_suggestion(
+ macro_call.span,
+ "replace with",
+ format!(
+ "{}.{replacement}(){semicolon}",
+ snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
+ ),
+ app,
+ );
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
index 03f7776..6e336ef 100644
--- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs
+++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs
@@ -227,9 +227,22 @@ fn build_sugg<'tcx>(
match call_kind {
CallKind::Method => {
let receiver_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind {
- // `*lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)`
- Sugg::hir_with_applicability(cx, ref_expr, "_", app)
+ // If `ref_expr` is a reference, we can remove the dereference operator (`*`) to make
+ // the generated code a bit simpler. In other cases, we don't do this special case, to avoid
+ // having to deal with Deref (https://github.com/rust-lang/rust-clippy/issues/12437).
+
+ let ty = cx.typeck_results().expr_ty(ref_expr);
+ if ty.is_ref() {
+ // Apply special case, remove `*`
+ // `*lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)`
+ Sugg::hir_with_applicability(cx, ref_expr, "_", app)
+ } else {
+ // Keep the original lhs
+ // `*lhs = self_expr.clone();` -> `(*lhs).clone_from(self_expr)`
+ Sugg::hir_with_applicability(cx, lhs, "_", app)
+ }
} else {
+ // Keep the original lhs
// `lhs = self_expr.clone();` -> `lhs.clone_from(self_expr)`
Sugg::hir_with_applicability(cx, lhs, "_", app)
}
@@ -249,8 +262,16 @@ fn build_sugg<'tcx>(
},
CallKind::Ufcs => {
let self_sugg = if let ExprKind::Unary(hir::UnOp::Deref, ref_expr) = lhs.kind {
- // `*lhs = Clone::clone(self_expr);` -> `Clone::clone_from(lhs, self_expr)`
- Sugg::hir_with_applicability(cx, ref_expr, "_", app)
+ // See special case of removing `*` in method handling above
+ let ty = cx.typeck_results().expr_ty(ref_expr);
+ if ty.is_ref() {
+ // `*lhs = Clone::clone(self_expr);` -> `Clone::clone_from(lhs, self_expr)`
+ Sugg::hir_with_applicability(cx, ref_expr, "_", app)
+ } else {
+ // `*lhs = Clone::clone(self_expr);` -> `Clone::clone_from(&mut *lhs, self_expr)`
+ // mut_addr_deref is used to avoid unnecessary parentheses around `*lhs`
+ Sugg::hir_with_applicability(cx, ref_expr, "_", app).mut_addr_deref()
+ }
} else {
// `lhs = Clone::clone(self_expr);` -> `Clone::clone_from(&mut lhs, self_expr)`
Sugg::hir_with_applicability(cx, lhs, "_", app).mut_addr()
diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs
index df99940..a5a7b9f 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs
@@ -1,5 +1,5 @@
use super::ALLOW_ATTRIBUTES;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_ast::{AttrStyle, Attribute};
use rustc_errors::Applicability;
@@ -13,14 +13,14 @@ pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
&& let Some(ident) = attr.ident()
&& !is_from_proc_macro(cx, attr)
{
- span_lint_and_sugg(
- cx,
- ALLOW_ATTRIBUTES,
- ident.span,
- "#[allow] attribute found",
- "replace it with",
- "expect".into(),
- Applicability::MachineApplicable,
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, ALLOW_ATTRIBUTES, ident.span, "#[allow] attribute found", |diag| {
+ diag.span_suggestion(
+ ident.span,
+ "replace it with",
+ "expect",
+ Applicability::MachineApplicable,
+ );
+ });
}
}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
index 4b42616..4ab9711 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -1,5 +1,5 @@
use super::{Attribute, ALLOW_ATTRIBUTES_WITHOUT_REASON};
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_ast::{MetaItemKind, NestedMetaItem};
use rustc_lint::{LateContext, LintContext};
@@ -21,12 +21,14 @@ pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMet
return;
}
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
ALLOW_ATTRIBUTES_WITHOUT_REASON,
attr.span,
format!("`{}` attribute without specifying a reason", name.as_str()),
- None,
- "try adding a reason at the end with `, reason = \"..\"`",
+ |diag| {
+ diag.help("try adding a reason at the end with `, reason = \"..\"`");
+ },
);
}
diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
index 561ca9b..612712d 100644
--- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::sugg::Sugg;
-use clippy_utils::{in_constant, is_else_clause};
+use clippy_utils::{is_else_clause, is_in_const_context};
use rustc_ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
@@ -52,7 +52,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
&& let Some(else_lit) = as_int_bool_lit(else_)
&& then_lit != else_lit
&& !expr.span.from_expansion()
- && !in_constant(cx, expr.hir_id)
+ && !is_in_const_context(cx)
{
let ty = cx.typeck_results().expr_ty(then);
let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index a1c6c0b..a2f48c18 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -477,14 +477,12 @@ fn bool_expr(&self, e: &'tcx Expr<'_>) {
cx: self.cx,
};
if let Ok(expr) = h2q.run(e) {
- if h2q.terminals.len() > 8 {
- // QMC has exponentially slow behavior as the number of terminals increases
- // 8 is reasonable, it takes approximately 0.2 seconds.
- // See #825
+ let stats = terminal_stats(&expr);
+ if stats.ops > 7 {
+ // QMC has exponentially slow behavior as the number of ops increases.
+ // See #825, #13206
return;
}
-
- let stats = terminal_stats(&expr);
let mut simplified = expr.simplify();
for simple in Bool::Not(Box::new(expr)).simplify() {
match simple {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index ff460a3..bd3acc0 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::in_constant;
+use clippy_utils::is_in_const_context;
use clippy_utils::source::snippet_opt;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_isize_or_usize;
@@ -21,7 +21,7 @@ pub(super) fn check(
cast_to_hir: &rustc_hir::Ty<'_>,
msrv: &Msrv,
) {
- if !should_lint(cx, expr, cast_from, cast_to, msrv) {
+ if !should_lint(cx, cast_from, cast_to, msrv) {
return;
}
@@ -70,9 +70,9 @@ pub(super) fn check(
);
}
-fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool {
+fn should_lint(cx: &LateContext<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool {
// Do not suggest using From in consts/statics until it is valid to do so (see #2267).
- if in_constant(cx, expr.hir_id) {
+ if is_in_const_context(cx) {
return false;
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
index 5bc8692..464eabe 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -1,6 +1,6 @@
use super::CAST_NAN_TO_INT;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_note;
use rustc_hir::Expr;
use rustc_lint::LateContext;
@@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
}
fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
- match constant(cx, cx.typeck_results(), e) {
+ match ConstEvalCtxt::new(cx).eval(e) {
// FIXME(f16_f128): add these types when nan checks are available on all platforms
Some(Constant::F64(n)) => n.is_nan(),
Some(Constant::F32(n)) => n.is_nan(),
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 7c5acd1..102fe25 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::expr_or_init;
use clippy_utils::source::snippet;
@@ -15,7 +15,7 @@
use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
- if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) {
+ if let Some(Constant::Int(c)) = ConstEvalCtxt::new(cx).eval(expr) {
Some(c)
} else {
None
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 8bbd41b..9daf237 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -1,7 +1,7 @@
use std::convert::Infallible;
use std::ops::ControlFlow;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::visitors::{for_each_expr_without_closures, Descend};
use clippy_utils::{method_chain_args, sext};
@@ -88,7 +88,7 @@ fn get_const_signed_int_eval<'cx>(
) -> Option<i128> {
let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr));
- if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)?
+ if let Constant::Int(n) = ConstEvalCtxt::new(cx).eval(expr)?
&& let ty::Int(ity) = *ty.kind()
{
return Some(sext(cx.tcx, n, ity));
@@ -103,7 +103,7 @@ fn get_const_unsigned_int_eval<'cx>(
) -> Option<u128> {
let ty = ty.into().unwrap_or_else(|| cx.typeck_results().expr_ty(expr));
- if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)?
+ if let Constant::Int(n) = ConstEvalCtxt::new(cx).eval(expr)?
&& let ty::Uint(_ity) = *ty.kind()
{
return Some(n);
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
index 826589b..75de53f 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
@@ -1,6 +1,6 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
@@ -14,21 +14,24 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
_ => { /* continue to checks */ },
}
- match cast_from.kind() {
- ty::FnDef(..) | ty::FnPtr(_) => {
- let mut applicability = Applicability::MaybeIncorrect;
- let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability);
+ if let ty::FnDef(..) | ty::FnPtr(_) = cast_from.kind() {
+ let mut applicability = Applicability::MaybeIncorrect;
+ let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability);
- span_lint_and_sugg(
- cx,
- FN_TO_NUMERIC_CAST_ANY,
- expr.span,
- format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
- "did you mean to invoke the function?",
- format!("{from_snippet}() as {cast_to}"),
- applicability,
- );
- },
- _ => {},
+ span_lint_and_then(
+ cx,
+ FN_TO_NUMERIC_CAST_ANY,
+ expr.span,
+ format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
+ |diag| {
+ diag.span_suggestion_with_style(
+ expr.span,
+ "did you mean to invoke the function?",
+ format!("{from_snippet}() as {cast_to}"),
+ applicability,
+ SuggestionStyle::ShowAlways,
+ );
+ },
+ );
}
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs
index 5071af5..3c1c7d2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
-use clippy_utils::{in_constant, is_integer_literal, std_or_core};
+use clippy_utils::{is_in_const_context, is_integer_literal, std_or_core};
use rustc_errors::Applicability;
use rustc_hir::{Expr, Mutability, Ty, TyKind};
use rustc_lint::LateContext;
@@ -10,7 +10,7 @@
pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) {
if let TyKind::Ptr(ref mut_ty) = to.kind
&& is_integer_literal(from, 0)
- && !in_constant(cx, from.hir_id)
+ && !is_in_const_context(cx)
&& let Some(std_or_core) = std_or_core(cx)
{
let (msg, sugg_fn) = match mut_ty.mutbl {
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index 0b1ab54..1711565 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -4,7 +4,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
+use clippy_utils::{is_in_const_context, is_integer_literal, SpanlessEq};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -67,7 +67,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
_ => return,
}
&& !in_external_macro(cx.sess(), item.span)
- && !in_constant(cx, item.hir_id)
+ && !is_in_const_context(cx)
&& self.msrv.meets(msrvs::TRY_FROM)
&& let Some(cv) = match op2 {
// todo: check for case signed -> larger unsigned == only x >= 0
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index 2c23c0b..5d78744 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{if_sequence, in_constant, is_else_clause, SpanlessEq};
+use clippy_utils::{if_sequence, is_else_clause, is_in_const_context, SpanlessEq};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@@ -68,7 +68,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
return;
}
- if in_constant(cx, expr.hir_id) {
+ if is_in_const_context(cx) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/create_dir.rs b/src/tools/clippy/clippy_lints/src/create_dir.rs
index 27c0094..b49a977 100644
--- a/src/tools/clippy/clippy_lints/src/create_dir.rs
+++ b/src/tools/clippy/clippy_lints/src/create_dir.rs
@@ -1,6 +1,6 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::snippet;
-use rustc_errors::Applicability;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet_with_applicability;
+use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@@ -39,14 +39,24 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
&& let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
&& cx.tcx.is_diagnostic_item(sym::fs_create_dir, def_id)
{
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
CREATE_DIR,
expr.span,
"calling `std::fs::create_dir` where there may be a better way",
- "consider calling `std::fs::create_dir_all` instead",
- format!("create_dir_all({})", snippet(cx, arg.span, "..")),
- Applicability::MaybeIncorrect,
+ |diag| {
+ let mut app = Applicability::MaybeIncorrect;
+ diag.span_suggestion_with_style(
+ expr.span,
+ "consider calling `std::fs::create_dir_all` instead",
+ format!(
+ "create_dir_all({})",
+ snippet_with_applicability(cx, arg.span, "..", &mut app)
+ ),
+ app,
+ SuggestionStyle::ShowAlways,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 788c6f3..93c8fff 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -1,5 +1,5 @@
use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_test;
use clippy_utils::macros::{macro_backtrace, MacroCall};
use clippy_utils::source::snippet_with_applicability;
@@ -65,61 +65,67 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
// allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
!(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
{
- let mut applicability = Applicability::MachineApplicable;
-
- let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
- // dbg!()
- ExprKind::Block(..) => {
- // If the `dbg!` macro is a "free" statement and not contained within other expressions,
- // remove the whole statement.
- if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
- && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
- {
- (macro_call.span.to(semi_span), String::new())
- } else {
- (macro_call.span, String::from("()"))
- }
- },
- // dbg!(1)
- ExprKind::Match(val, ..) => (
- macro_call.span,
- snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
- ),
- // dbg!(2, 3)
- ExprKind::Tup(
- [
- Expr {
- kind: ExprKind::Match(first, ..),
- ..
- },
- ..,
- Expr {
- kind: ExprKind::Match(last, ..),
- ..
- },
- ],
- ) => {
- let snippet = snippet_with_applicability(
- cx,
- first.span.source_callsite().to(last.span.source_callsite()),
- "..",
- &mut applicability,
- );
- (macro_call.span, format!("({snippet})"))
- },
- _ => return,
- };
-
self.prev_ctxt = cur_syntax_ctxt;
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
DBG_MACRO,
- sugg_span,
+ macro_call.span,
"the `dbg!` macro is intended as a debugging tool",
- "remove the invocation before committing it to a version control system",
- suggestion,
- applicability,
+ |diag| {
+ let mut applicability = Applicability::MachineApplicable;
+
+ let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
+ // dbg!()
+ ExprKind::Block(..) => {
+ // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+ // remove the whole statement.
+ if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
+ && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
+ {
+ (macro_call.span.to(semi_span), String::new())
+ } else {
+ (macro_call.span, String::from("()"))
+ }
+ },
+ // dbg!(1)
+ ExprKind::Match(val, ..) => (
+ macro_call.span,
+ snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
+ .to_string(),
+ ),
+ // dbg!(2, 3)
+ ExprKind::Tup(
+ [
+ Expr {
+ kind: ExprKind::Match(first, ..),
+ ..
+ },
+ ..,
+ Expr {
+ kind: ExprKind::Match(last, ..),
+ ..
+ },
+ ],
+ ) => {
+ let snippet = snippet_with_applicability(
+ cx,
+ first.span.source_callsite().to(last.span.source_callsite()),
+ "..",
+ &mut applicability,
+ );
+ (macro_call.span, format!("({snippet})"))
+ },
+ _ => unreachable!(),
+ };
+
+ diag.span_suggestion(
+ sugg_span,
+ "remove the invocation before committing it to a version control system",
+ suggestion,
+ applicability,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 69f9eb6..3fb083d 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -14,8 +14,6 @@
#[cfg(feature = "internal")]
crate::utils::internal_lints::invalid_paths::INVALID_PATHS_INFO,
#[cfg(feature = "internal")]
- crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON_INFO,
- #[cfg(feature = "internal")]
crate::utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE_INFO,
@@ -741,6 +739,7 @@
crate::unused_async::UNUSED_ASYNC_INFO,
crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO,
crate::unused_peekable::UNUSED_PEEKABLE_INFO,
+ crate::unused_result_ok::UNUSED_RESULT_OK_INFO,
crate::unused_rounding::UNUSED_ROUNDING_INFO,
crate::unused_self::UNUSED_SELF_INFO,
crate::unused_unit::UNUSED_UNIT_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 72fa05b..0b7279f 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -221,7 +221,7 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ");
- format!("{adt_def_ty_name}::<{}>", &tys_str)
+ format!("{adt_def_ty_name}::<{tys_str}>")
} else {
binding_type.to_string()
};
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 9af73db..a74b3a8 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -92,20 +92,8 @@ fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
let (suffix, is_float) = match lit_ty.kind() {
ty::Int(IntTy::I32) => ("i32", false),
ty::Float(FloatTy::F64) => ("f64", true),
- // Default numeric fallback never results in other types.
_ => return,
};
-
- let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
- src
- } else {
- match lit.node {
- LitKind::Int(src, _) => format!("{src}"),
- LitKind::Float(src, _) => format!("{src}"),
- _ => return,
- }
- };
- let sugg = numeric_literal::format(&src, Some(suffix), is_float);
span_lint_hir_and_then(
self.cx,
DEFAULT_NUMERIC_FALLBACK,
@@ -113,6 +101,17 @@ fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
lit.span,
"default numeric fallback might occur",
|diag| {
+ let src = if let Some(src) = snippet_opt(self.cx, lit.span) {
+ src
+ } else {
+ match lit.node {
+ LitKind::Int(src, _) => format!("{src}"),
+ LitKind::Float(src, _) => format!("{src}"),
+ _ => unreachable!("Default numeric fallback never results in other types"),
+ }
+ };
+
+ let sugg = numeric_literal::format(&src, Some(suffix), is_float);
diag.span_suggestion(lit.span, "consider adding suffix", sugg, Applicability::MaybeIncorrect);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index 3fa9bad..9f020d3 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir::{HirId, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
@@ -56,16 +56,18 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
&& is_union_with_two_non_zst_fields(cx, item)
&& !has_c_repr_attr(cx, item.hir_id())
{
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
DEFAULT_UNION_REPRESENTATION,
item.span,
"this union has the default representation",
- None,
- format!(
- "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
- cx.tcx.def_path_str(item.owner_id)
- ),
+ |diag| {
+ diag.help(format!(
+ "consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
+ cx.tcx.def_path_str(item.owner_id)
+ ));
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index a0900f4..0066ed6 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -1,243 +1,181 @@
-// NOTE: Entries should be created with `cargo dev deprecate`
+// This file is managed by `cargo dev rename_lint` and `cargo dev deprecate_lint`.
+// Prefer to use those when possible.
-/// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This
-/// enables the simple extraction of the metadata without changing the current deprecation
-/// declaration.
-pub struct ClippyDeprecatedLint {
- #[allow(dead_code)]
- pub desc: &'static str,
+macro_rules! declare_with_version {
+ ($name:ident($name_version:ident): &[$ty:ty] = &[$(
+ #[clippy::version = $version:literal]
+ $e:expr,
+ )*]) => {
+ pub static $name: &[$ty] = &[$($e),*];
+ #[allow(unused)]
+ pub static $name_version: &[&str] = &[$($version),*];
+ };
}
-#[macro_export]
-macro_rules! declare_deprecated_lint {
- { $(#[$attr:meta])* pub $name: ident, $reason: literal} => {
- $(#[$attr])*
- #[allow(dead_code)]
- pub static $name: ClippyDeprecatedLint = ClippyDeprecatedLint {
- desc: $reason
- };
- }
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This used to check for `assert!(a == b)` and recommend
- /// replacement with `assert_eq!(a, b)`, but this is no longer needed after RFC 2011.
+#[rustfmt::skip]
+declare_with_version! { DEPRECATED(DEPRECATED_VERSION): &[(&str, &str)] = &[
#[clippy::version = "pre 1.29.0"]
- pub SHOULD_ASSERT_EQ,
- "`assert!()` will be more flexible with RFC 2011"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This used to check for `Vec::extend`, which was slower than
- /// `Vec::extend_from_slice`. Thanks to specialization, this is no longer true.
+ ("clippy::should_assert_eq", "`assert!(a == b)` can now print the values the same way `assert_eq!(a, b) can"),
#[clippy::version = "pre 1.29.0"]
- pub EXTEND_FROM_SLICE,
- "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// `Range::step_by(0)` used to be linted since it's
- /// an infinite iterator, which is better expressed by `iter::repeat`,
- /// but the method has been removed for `Iterator::step_by` which panics
- /// if given a zero
+ ("clippy::extend_from_slice", "`Vec::extend_from_slice` is no longer faster than `Vec::extend` due to specialization"),
#[clippy::version = "pre 1.29.0"]
- pub RANGE_STEP_BY_ZERO,
- "`iterator.step_by(0)` panics nowadays"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This used to check for `Vec::as_slice`, which was unstable with good
- /// stable alternatives. `Vec::as_slice` has now been stabilized.
+ ("clippy::range_step_by_zero", "`Iterator::step_by(0)` now panics and is no longer an infinite iterator"),
#[clippy::version = "pre 1.29.0"]
- pub UNSTABLE_AS_SLICE,
- "`Vec::as_slice` has been stabilized in 1.7"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This used to check for `Vec::as_mut_slice`, which was unstable with good
- /// stable alternatives. `Vec::as_mut_slice` has now been stabilized.
+ ("clippy::unstable_as_slice", "`Vec::as_slice` is now stable"),
#[clippy::version = "pre 1.29.0"]
- pub UNSTABLE_AS_MUT_SLICE,
- "`Vec::as_mut_slice` has been stabilized in 1.7"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint should never have applied to non-pointer types, as transmuting
- /// between non-pointer types of differing alignment is well-defined behavior (it's semantically
- /// equivalent to a memcpy). This lint has thus been refactored into two separate lints:
- /// cast_ptr_alignment and transmute_ptr_to_ptr.
+ ("clippy::unstable_as_mut_slice", "`Vec::as_mut_slice` is now stable"),
#[clippy::version = "pre 1.29.0"]
- pub MISALIGNED_TRANSMUTE,
- "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint is too subjective, not having a good reason for being in clippy.
- /// Additionally, compound assignment operators may be overloaded separately from their non-assigning
- /// counterparts, so this lint may suggest a change in behavior or the code may not compile.
+ ("clippy::misaligned_transmute", "split into `clippy::cast_ptr_alignment` and `clippy::transmute_ptr_to_ptr`"),
#[clippy::version = "1.30.0"]
- pub ASSIGN_OPS,
- "using compound assignment operators (e.g., `+=`) is harmless"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// The original rule will only lint for `if let`. After
- /// making it support to lint `match`, naming as `if let` is not suitable for it.
- /// So, this lint is deprecated.
+ ("clippy::assign_ops", "compound operators are harmless and linting on them is not in scope for clippy"),
#[clippy::version = "pre 1.29.0"]
- pub IF_LET_REDUNDANT_PATTERN_MATCHING,
- "this lint has been changed to redundant_pattern_matching"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint used to suggest replacing `let mut vec =
- /// Vec::with_capacity(n); vec.set_len(n);` with `let vec = vec![0; n];`. The
- /// replacement has very different performance characteristics so the lint is
- /// deprecated.
- #[clippy::version = "pre 1.29.0"]
- pub UNSAFE_VECTOR_INITIALIZATION,
- "the replacement suggested by this lint had substantially different behavior"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint has been superseded by #[must_use] in rustc.
+ ("clippy::unsafe_vector_initialization", "the suggested alternative could be substantially slower"),
#[clippy::version = "1.39.0"]
- pub UNUSED_COLLECT,
- "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// Associated-constants are now preferred.
+ ("clippy::unused_collect", "`Iterator::collect` is now marked as `#[must_use]`"),
#[clippy::version = "1.44.0"]
- pub REPLACE_CONSTS,
- "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// The regex! macro does not exist anymore.
+ ("clippy::replace_consts", "`min_value` and `max_value` are now deprecated"),
#[clippy::version = "1.47.0"]
- pub REGEX_MACRO,
- "the regex! macro has been removed from the regex crate in 2018"
-}
+ ("clippy::regex_macro", "the `regex!` macro was removed from the regex crate in 2018"),
+ #[clippy::version = "1.54.0"]
+ ("clippy::pub_enum_variant_names", "`clippy::enum_variant_names` now covers this case via the `avoid-breaking-exported-api` config"),
+ #[clippy::version = "1.54.0"]
+ ("clippy::wrong_pub_self_convention", "`clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config"),
+ // end deprecated lints. used by `cargo dev deprecate_lint`
+]}
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint has been replaced by `manual_find_map`, a
- /// more specific lint.
+#[rustfmt::skip]
+declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
+ #[clippy::version = ""]
+ ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"),
+ #[clippy::version = ""]
+ ("clippy::blacklisted_name", "clippy::disallowed_names"),
+ #[clippy::version = ""]
+ ("clippy::block_in_if_condition_expr", "clippy::blocks_in_conditions"),
+ #[clippy::version = ""]
+ ("clippy::block_in_if_condition_stmt", "clippy::blocks_in_conditions"),
+ #[clippy::version = ""]
+ ("clippy::blocks_in_if_conditions", "clippy::blocks_in_conditions"),
+ #[clippy::version = ""]
+ ("clippy::box_vec", "clippy::box_collection"),
+ #[clippy::version = ""]
+ ("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
+ #[clippy::version = ""]
+ ("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
+ #[clippy::version = ""]
+ ("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"),
+ #[clippy::version = ""]
+ ("clippy::disallowed_method", "clippy::disallowed_methods"),
+ #[clippy::version = ""]
+ ("clippy::disallowed_type", "clippy::disallowed_types"),
+ #[clippy::version = ""]
+ ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
#[clippy::version = "1.51.0"]
- pub FIND_MAP,
- "this lint has been replaced by `manual_find_map`, a more specific lint"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint has been replaced by `manual_filter_map`, a
- /// more specific lint.
+ ("clippy::find_map", "clippy::manual_find_map"),
#[clippy::version = "1.53.0"]
- pub FILTER_MAP,
- "this lint has been replaced by `manual_filter_map`, a more specific lint"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// The `avoid_breaking_exported_api` config option was added, which
- /// enables the `enum_variant_names` lint for public items.
- #[clippy::version = "1.54.0"]
- pub PUB_ENUM_VARIANT_NAMES,
- "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// The `avoid_breaking_exported_api` config option was added, which
- /// enables the `wrong_self_conversion` lint for public items.
- #[clippy::version = "1.54.0"]
- pub WRONG_PUB_SELF_CONVENTION,
- "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint has been superseded by rustc's own [`unexpected_cfgs`] lint that is able to detect the `#[cfg(features)]` and `#[cfg(tests)]` typos.
- ///
- /// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs
+ ("clippy::filter_map", "clippy::manual_filter_map"),
+ #[clippy::version = ""]
+ ("clippy::identity_conversion", "clippy::useless_conversion"),
+ #[clippy::version = "pre 1.29.0"]
+ ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"),
+ #[clippy::version = ""]
+ ("clippy::if_let_some_result", "clippy::match_result_ok"),
+ #[clippy::version = ""]
+ ("clippy::incorrect_clone_impl_on_copy_type", "clippy::non_canonical_clone_impl"),
+ #[clippy::version = ""]
+ ("clippy::incorrect_partial_ord_impl_on_ord_type", "clippy::non_canonical_partial_ord_impl"),
+ #[clippy::version = ""]
+ ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
+ #[clippy::version = ""]
+ ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
+ #[clippy::version = ""]
+ ("clippy::new_without_default_derive", "clippy::new_without_default"),
+ #[clippy::version = ""]
+ ("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
+ #[clippy::version = ""]
+ ("clippy::option_expect_used", "clippy::expect_used"),
+ #[clippy::version = ""]
+ ("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"),
+ #[clippy::version = ""]
+ ("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"),
+ #[clippy::version = ""]
+ ("clippy::option_unwrap_used", "clippy::unwrap_used"),
+ #[clippy::version = ""]
+ ("clippy::overflow_check_conditional", "clippy::panicking_overflow_checks"),
+ #[clippy::version = ""]
+ ("clippy::ref_in_deref", "clippy::needless_borrow"),
+ #[clippy::version = ""]
+ ("clippy::result_expect_used", "clippy::expect_used"),
+ #[clippy::version = ""]
+ ("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"),
+ #[clippy::version = ""]
+ ("clippy::result_unwrap_used", "clippy::unwrap_used"),
+ #[clippy::version = ""]
+ ("clippy::single_char_push_str", "clippy::single_char_add_str"),
+ #[clippy::version = ""]
+ ("clippy::stutter", "clippy::module_name_repetitions"),
+ #[clippy::version = ""]
+ ("clippy::thread_local_initializer_can_be_made_const", "clippy::missing_const_for_thread_local"),
+ #[clippy::version = ""]
+ ("clippy::to_string_in_display", "clippy::recursive_format_impl"),
+ #[clippy::version = ""]
+ ("clippy::unwrap_or_else_default", "clippy::unwrap_or_default"),
+ #[clippy::version = ""]
+ ("clippy::zero_width_space", "clippy::invisible_characters"),
+ #[clippy::version = ""]
+ ("clippy::cast_ref_to_mut", "invalid_reference_casting"),
+ #[clippy::version = ""]
+ ("clippy::clone_double_ref", "suspicious_double_ref_op"),
+ #[clippy::version = ""]
+ ("clippy::cmp_nan", "invalid_nan_comparisons"),
+ #[clippy::version = ""]
+ ("clippy::drop_bounds", "drop_bounds"),
+ #[clippy::version = ""]
+ ("clippy::drop_copy", "dropping_copy_types"),
+ #[clippy::version = ""]
+ ("clippy::drop_ref", "dropping_references"),
+ #[clippy::version = ""]
+ ("clippy::fn_null_check", "useless_ptr_null_checks"),
+ #[clippy::version = ""]
+ ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
+ #[clippy::version = ""]
+ ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
+ #[clippy::version = ""]
+ ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
+ #[clippy::version = ""]
+ ("clippy::forget_copy", "forgetting_copy_types"),
+ #[clippy::version = ""]
+ ("clippy::forget_ref", "forgetting_references"),
+ #[clippy::version = ""]
+ ("clippy::into_iter_on_array", "array_into_iter"),
+ #[clippy::version = ""]
+ ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
+ #[clippy::version = ""]
+ ("clippy::invalid_ref", "invalid_value"),
+ #[clippy::version = ""]
+ ("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"),
+ #[clippy::version = ""]
+ ("clippy::let_underscore_drop", "let_underscore_drop"),
#[clippy::version = "1.80.0"]
- pub MAYBE_MISUSED_CFG,
- "this lint has been replaced by `unexpected_cfgs`"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint has been superseded by rustc's own [`unexpected_cfgs`] lint that is able to detect invalid `#[cfg(linux)]` attributes.
- ///
- /// [`unexpected_cfgs`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unexpected-cfgs
+ ("clippy::maybe_misused_cfg", "unexpected_cfgs"),
+ #[clippy::version = ""]
+ ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
#[clippy::version = "1.80.0"]
- pub MISMATCHED_TARGET_OS,
- "this lint has been replaced by `unexpected_cfgs`"
-}
+ ("clippy::mismatched_target_os", "unexpected_cfgs"),
+ #[clippy::version = ""]
+ ("clippy::panic_params", "non_fmt_panics"),
+ #[clippy::version = ""]
+ ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
+ #[clippy::version = ""]
+ ("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
+ #[clippy::version = ""]
+ ("clippy::undropped_manually_drops", "undropped_manually_drops"),
+ #[clippy::version = ""]
+ ("clippy::unknown_clippy_lints", "unknown_lints"),
+ #[clippy::version = ""]
+ ("clippy::unused_label", "unused_labels"),
+ #[clippy::version = ""]
+ ("clippy::vtable_address_comparisons", "ambiguous_wide_pointer_comparisons"),
+ #[clippy::version = ""]
+ ("clippy::reverse_range_loop", "clippy::reversed_empty_ranges"),
+ // end renamed lints. used by `cargo dev rename_lint`
+]}
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 253f995..d0cb248 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs};
+use clippy_utils::ty::{implements_trait, is_manually_drop};
use clippy_utils::{
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, peel_middle_ty_refs, DefinedTy,
ExprUseNode,
@@ -947,7 +947,7 @@ fn report<'tcx>(
let (expr_str, _expr_is_macro_call) =
snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app);
let ty = typeck.expr_ty(expr);
- let (_, ref_count) = peel_mid_ty_refs(ty);
+ let (_, ref_count) = peel_middle_ty_refs(ty);
let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
// a deref call changing &T -> &U requires two deref operators the first time
// this occurs. One to remove the reference, a second to call the deref impl.
diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs
index 5b6a5b0..d7b3a7c 100644
--- a/src/tools/clippy/clippy_lints/src/doc/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs
@@ -5,7 +5,7 @@
use clippy_utils::macros::{is_panic, root_macro_call_first_node};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::Visitable;
-use clippy_utils::{in_constant, is_entrypoint_fn, is_trait_impl_item, method_chain_args};
+use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args};
use pulldown_cmark::Event::{
Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start,
TaskListMarker, Text,
@@ -768,7 +768,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
);
}
},
- FootnoteReference(text) | Text(text) => {
+ Text(text) => {
paragraph_range.end = range.end;
let range_ = range.clone();
ticks_unbalanced |= text.contains('`')
@@ -812,7 +812,8 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
}
text_to_check.push((text, range, code_level));
}
- },
+ }
+ FootnoteReference(_) => {}
}
}
headers
@@ -857,7 +858,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
"assert" | "assert_eq" | "assert_ne"
)
{
- self.is_const = in_constant(self.cx, expr.hir_id);
+ self.is_const = self.cx.tcx.hir().is_inside_const_context(expr.hir_id);
self.panic_span = Some(macro_call.span);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index 4a6ffcd..c7dd729 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_must_use_func_call;
use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item};
use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node};
@@ -126,14 +126,14 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
},
_ => return,
};
- span_lint_and_note(
- cx,
- lint,
- expr.span,
- msg,
- note_span,
- format!("argument has type `{arg_ty}`"),
- );
+ span_lint_and_then(cx, lint, expr.span, msg, |diag| {
+ let note = format!("argument has type `{arg_ty}`");
+ if let Some(span) = note_span {
+ diag.span_note(span, note);
+ } else {
+ diag.note(note);
+ }
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
index 7a6dc46..02f9c2c 100644
--- a/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
+++ b/src/tools/clippy/clippy_lints/src/else_if_without_else.rs
@@ -1,6 +1,6 @@
//! Lint on if expressions with an else if, but without a final else branch.
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Expr, ExprKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -54,13 +54,15 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
&& let ExprKind::If(_, _, None) = els.kind
&& !in_external_macro(cx.sess(), item.span)
{
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
ELSE_IF_WITHOUT_ELSE,
els.span,
"`if` expression with an `else if`, but without a final `else`",
- None,
- "add an `else` block here",
+ |diag| {
+ diag.help("add an `else` block here");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs
index c5fc72b..b66dd21 100644
--- a/src/tools/clippy/clippy_lints/src/empty_drop.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::peel_blocks;
use rustc_errors::Applicability;
use rustc_hir::{Body, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node};
@@ -50,15 +50,14 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
&& block.stmts.is_empty()
&& block.expr.is_none()
{
- span_lint_and_sugg(
- cx,
- EMPTY_DROP,
- item.span,
- "empty drop implementation",
- "try removing this impl",
- String::new(),
- Applicability::MaybeIncorrect,
- );
+ span_lint_and_then(cx, EMPTY_DROP, item.span, "empty drop implementation", |diag| {
+ diag.span_suggestion_hidden(
+ item.span,
+ "try removing this impl",
+ String::new(),
+ Applicability::MaybeIncorrect,
+ );
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/endian_bytes.rs b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
index 5bba9c5..209104c 100644
--- a/src/tools/clippy/clippy_lints/src/endian_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/endian_bytes.rs
@@ -7,7 +7,6 @@
use rustc_middle::ty::Ty;
use rustc_session::declare_lint_pass;
use rustc_span::Symbol;
-use std::borrow::Cow;
declare_clippy_lint! {
/// ### What it does
@@ -141,52 +140,6 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
_ => return,
};
- let mut help = None;
-
- 'build_help: {
- // all lints disallowed, don't give help here
- if [&[lint], other_lints.as_slice()]
- .concat()
- .iter()
- .all(|lint| !lint.allowed(cx, expr))
- {
- break 'build_help;
- }
-
- // ne_bytes and all other lints allowed
- if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) {
- help = Some(Cow::Borrowed("specify the desired endianness explicitly"));
- break 'build_help;
- }
-
- // le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but
- // le_bytes is not
- if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) {
- help = Some(Cow::Borrowed("use the native endianness instead"));
- break 'build_help;
- }
-
- let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr));
- let len = allowed_lints.clone().count();
-
- let mut help_str = "use ".to_owned();
-
- for (i, lint) in allowed_lints.enumerate() {
- let only_one = len == 1;
- if !only_one {
- help_str.push_str("either of ");
- }
-
- help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));
-
- if i != len && !only_one {
- help_str.push_str("or ");
- }
- }
-
- help = Some(Cow::Owned(help_str + "instead"));
- }
-
span_lint_and_then(
cx,
lint.as_lint(),
@@ -198,9 +151,47 @@ fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix
if prefix == Prefix::To { " method" } else { "" },
),
move |diag| {
- if let Some(help) = help {
- diag.help(help);
+ // all lints disallowed, don't give help here
+ if [&[lint], other_lints.as_slice()]
+ .concat()
+ .iter()
+ .all(|lint| !lint.allowed(cx, expr))
+ {
+ return;
}
+
+ // ne_bytes and all other lints allowed
+ if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) {
+ diag.help("specify the desired endianness explicitly");
+ return;
+ }
+
+ // le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but
+ // le_bytes is not
+ if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) {
+ diag.help("use the native endianness instead");
+ return;
+ }
+
+ let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr));
+ let len = allowed_lints.clone().count();
+
+ let mut help_str = "use ".to_owned();
+
+ for (i, lint) in allowed_lints.enumerate() {
+ let only_one = len == 1;
+ if !only_one {
+ help_str.push_str("either of ");
+ }
+
+ help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));
+
+ if i != len && !only_one {
+ help_str.push_str("or ");
+ }
+ }
+ help_str.push_str("instead");
+ diag.help(help_str);
},
);
}
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index 30eb643..e54cd24 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -51,7 +51,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
.const_eval_poly(def_id.to_def_id())
.ok()
.map(|val| rustc_middle::mir::Const::from_value(val, ty));
- if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx, c)) {
+ if let Some(Constant::Int(val)) = constant.and_then(|c| mir_to_const(cx.tcx, c)) {
if let ty::Adt(adt, _) = ty.kind() {
if adt.is_enum() {
ty = adt.repr().discr_type().to_ty(cx.tcx);
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 0ed7859..5a7226d 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -9,8 +9,7 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{
- self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, RegionKind, Ty, TyCtxt,
- TypeVisitableExt, TypeckResults,
+ self, Binder, ClosureKind, FnSig, GenericArg, GenericArgKind, List, Region, Ty, TypeVisitableExt, TypeckResults,
};
use rustc_session::declare_lint_pass;
use rustc_span::symbol::sym;
@@ -74,159 +73,184 @@
declare_lint_pass!(EtaReduction => [REDUNDANT_CLOSURE, REDUNDANT_CLOSURE_FOR_METHOD_CALLS]);
impl<'tcx> LateLintPass<'tcx> for EtaReduction {
- #[allow(clippy::too_many_lines)]
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- let body = if let ExprKind::Closure(c) = expr.kind
- && c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer))
- && matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_))
- && !expr.span.from_expansion()
- {
- cx.tcx.hir().body(c.body)
- } else {
- return;
- };
-
- if body.value.span.from_expansion() {
- if body.params.is_empty() {
- if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) {
- // replace `|| vec![]` with `Vec::new`
- span_lint_and_sugg(
- cx,
- REDUNDANT_CLOSURE,
- expr.span,
- "redundant closure",
- "replace the closure with `Vec::new`",
- "std::vec::Vec::new".into(),
- Applicability::MachineApplicable,
- );
- }
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+ if let ExprKind::MethodCall(_method, receiver, args, _) = expr.kind {
+ for arg in args {
+ check_clousure(cx, Some(receiver), arg);
}
- // skip `foo(|| macro!())`
- return;
}
-
- let typeck = cx.typeck_results();
- let closure = if let ty::Closure(_, closure_subs) = typeck.expr_ty(expr).kind() {
- closure_subs.as_closure()
- } else {
- return;
- };
-
- if is_adjusted(cx, body.value) {
- return;
+ if let ExprKind::Call(func, args) = expr.kind {
+ check_clousure(cx, None, func);
+ for arg in args {
+ check_clousure(cx, None, arg);
+ }
}
+ }
+}
- match body.value.kind {
- ExprKind::Call(callee, args)
- if matches!(
- callee.kind,
- ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))
- ) =>
+#[allow(clippy::too_many_lines)]
+fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx>>, expr: &Expr<'tcx>) {
+ let body = if let ExprKind::Closure(c) = expr.kind
+ && c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer))
+ && matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_))
+ && !expr.span.from_expansion()
+ {
+ cx.tcx.hir().body(c.body)
+ } else {
+ return;
+ };
+
+ if body.value.span.from_expansion() {
+ if body.params.is_empty() {
+ if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) {
+ // replace `|| vec![]` with `Vec::new`
+ span_lint_and_sugg(
+ cx,
+ REDUNDANT_CLOSURE,
+ expr.span,
+ "redundant closure",
+ "replace the closure with `Vec::new`",
+ "std::vec::Vec::new".into(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ // skip `foo(|| macro!())`
+ return;
+ }
+
+ if is_adjusted(cx, body.value) {
+ return;
+ }
+
+ let typeck = cx.typeck_results();
+ let closure = if let ty::Closure(_, closure_subs) = typeck.expr_ty(expr).kind() {
+ closure_subs.as_closure()
+ } else {
+ return;
+ };
+ let closure_sig = cx.tcx.signature_unclosure(closure.sig(), Safety::Safe).skip_binder();
+ match body.value.kind {
+ ExprKind::Call(callee, args)
+ if matches!(
+ callee.kind,
+ ExprKind::Path(QPath::Resolved(..) | QPath::TypeRelative(..))
+ ) =>
+ {
+ let callee_ty_raw = typeck.expr_ty(callee);
+ let callee_ty = callee_ty_raw.peel_refs();
+ if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
+ || !check_inputs(typeck, body.params, None, args)
{
- let callee_ty_raw = typeck.expr_ty(callee);
- let callee_ty = callee_ty_raw.peel_refs();
- if matches!(type_diagnostic_name(cx, callee_ty), Some(sym::Arc | sym::Rc))
- || !check_inputs(typeck, body.params, None, args)
- {
- return;
- }
- let callee_ty_adjusted = typeck
- .expr_adjustments(callee)
- .last()
- .map_or(callee_ty, |a| a.target.peel_refs());
+ return;
+ }
+ let callee_ty_adjusted = typeck
+ .expr_adjustments(callee)
+ .last()
+ .map_or(callee_ty, |a| a.target.peel_refs());
- let sig = match callee_ty_adjusted.kind() {
- ty::FnDef(def, _) => {
- // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location`
- if cx.tcx.has_attr(*def, sym::track_caller) {
- return;
- }
+ let sig = match callee_ty_adjusted.kind() {
+ ty::FnDef(def, _) => {
+ // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location`
+ if cx.tcx.has_attr(*def, sym::track_caller) {
+ return;
+ }
- cx.tcx.fn_sig(def).skip_binder().skip_binder()
- },
- ty::FnPtr(sig) => sig.skip_binder(),
- ty::Closure(_, subs) => cx
- .tcx
- .signature_unclosure(subs.as_closure().sig(), Safety::Safe)
- .skip_binder(),
- _ => {
- if typeck.type_dependent_def_id(body.value.hir_id).is_some()
- && let subs = typeck.node_args(body.value.hir_id)
- && let output = typeck.expr_ty(body.value)
- && let ty::Tuple(tys) = *subs.type_at(1).kind()
- {
- cx.tcx.mk_fn_sig(tys, output, false, Safety::Safe, Abi::Rust)
- } else {
- return;
- }
- },
- };
- if check_sig(cx, closure, sig)
- && let generic_args = typeck.node_args(callee.hir_id)
- // Given some trait fn `fn f() -> ()` and some type `T: Trait`, `T::f` is not
- // `'static` unless `T: 'static`. The cast `T::f as fn()` will, however, result
- // in a type which is `'static`.
- // For now ignore all callee types which reference a type parameter.
- && !generic_args.types().any(|t| matches!(t.kind(), ty::Param(_)))
- {
- span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
- if let Some(mut snippet) = snippet_opt(cx, callee.span) {
- if path_to_local(callee).map_or(false, |l| {
- // FIXME: Do we really need this `local_used_in` check?
- // Isn't it checking something like... `callee(callee)`?
- // If somehow this check is needed, add some test for it,
- // 'cuz currently nothing changes after deleting this check.
- local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
- }) {
- match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
- cx.param_env,
- Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
- ty::PredicatePolarity::Positive,
- ) {
- // Mutable closure is used after current expr; we cannot consume it.
- Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
- Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
- snippet = format!("&{snippet}");
- },
- _ => (),
- }
+ cx.tcx.fn_sig(def).skip_binder().skip_binder()
+ },
+ ty::FnPtr(sig) => sig.skip_binder(),
+ ty::Closure(_, subs) => cx
+ .tcx
+ .signature_unclosure(subs.as_closure().sig(), Safety::Safe)
+ .skip_binder(),
+ _ => {
+ if typeck.type_dependent_def_id(body.value.hir_id).is_some()
+ && let subs = typeck.node_args(body.value.hir_id)
+ && let output = typeck.expr_ty(body.value)
+ && let ty::Tuple(tys) = *subs.type_at(1).kind()
+ {
+ cx.tcx.mk_fn_sig(tys, output, false, Safety::Safe, Abi::Rust)
+ } else {
+ return;
+ }
+ },
+ };
+ if let Some(outer) = outer_receiver
+ && ty_has_static(sig.output())
+ && let generic_args = typeck.node_args(outer.hir_id)
+ // HACK: Given a closure in `T.method(|| f())`, where `fn f() -> U where U: 'static`, `T.method(f)`
+ // will succeed iff `T: 'static`. But the region of `T` is always erased by `typeck.expr_ty()` when
+ // T is a generic type. For example, return type of `Option<String>::as_deref()` is a generic.
+ // So we have a hack like this.
+ && generic_args.len() > 0
+ {
+ return;
+ }
+ if check_sig(closure_sig, sig)
+ && let generic_args = typeck.node_args(callee.hir_id)
+ // Given some trait fn `fn f() -> ()` and some type `T: Trait`, `T::f` is not
+ // `'static` unless `T: 'static`. The cast `T::f as fn()` will, however, result
+ // in a type which is `'static`.
+ // For now ignore all callee types which reference a type parameter.
+ && !generic_args.types().any(|t| matches!(t.kind(), ty::Param(_)))
+ {
+ span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
+ if let Some(mut snippet) = snippet_opt(cx, callee.span) {
+ if path_to_local(callee).map_or(false, |l| {
+ // FIXME: Do we really need this `local_used_in` check?
+ // Isn't it checking something like... `callee(callee)`?
+ // If somehow this check is needed, add some test for it,
+ // 'cuz currently nothing changes after deleting this check.
+ local_used_in(cx, l, args) || local_used_after_expr(cx, l, expr)
+ }) {
+ match cx.tcx.infer_ctxt().build().err_ctxt().type_implements_fn_trait(
+ cx.param_env,
+ Binder::bind_with_vars(callee_ty_adjusted, List::empty()),
+ ty::PredicatePolarity::Positive,
+ ) {
+ // Mutable closure is used after current expr; we cannot consume it.
+ Ok((ClosureKind::FnMut, _)) => snippet = format!("&mut {snippet}"),
+ Ok((ClosureKind::Fn, _)) if !callee_ty_raw.is_ref() => {
+ snippet = format!("&{snippet}");
+ },
+ _ => (),
}
- diag.span_suggestion(
- expr.span,
- "replace the closure with the function itself",
- snippet,
- Applicability::MachineApplicable,
- );
}
- });
- }
- },
- ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => {
- if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id)
- && !cx.tcx.has_attr(method_def_id, sym::track_caller)
- && check_sig(cx, closure, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder())
- {
- span_lint_and_then(
- cx,
- REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
- expr.span,
- "redundant closure",
- |diag| {
- let args = typeck.node_args(body.value.hir_id);
- let caller = self_.hir_id.owner.def_id;
- let type_name = get_path_from_caller_to_method_type(cx.tcx, caller, method_def_id, args);
- diag.span_suggestion(
- expr.span,
- "replace the closure with the method itself",
- format!("{}::{}", type_name, path.ident.name),
- Applicability::MachineApplicable,
- );
- },
- );
- }
- },
- _ => (),
- }
+ diag.span_suggestion(
+ expr.span,
+ "replace the closure with the function itself",
+ snippet,
+ Applicability::MachineApplicable,
+ );
+ }
+ });
+ }
+ },
+ ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => {
+ if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id)
+ && !cx.tcx.has_attr(method_def_id, sym::track_caller)
+ && check_sig(closure_sig, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder())
+ {
+ span_lint_and_then(
+ cx,
+ REDUNDANT_CLOSURE_FOR_METHOD_CALLS,
+ expr.span,
+ "redundant closure",
+ |diag| {
+ let args = typeck.node_args(body.value.hir_id);
+ let caller = self_.hir_id.owner.def_id;
+ let type_name = get_path_from_caller_to_method_type(cx.tcx, caller, method_def_id, args);
+ diag.span_suggestion(
+ expr.span,
+ "replace the closure with the method itself",
+ format!("{}::{}", type_name, path.ident.name),
+ Applicability::MachineApplicable,
+ );
+ },
+ );
+ }
+ },
+ _ => (),
}
}
@@ -251,12 +275,8 @@ fn check_inputs(
})
}
-fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<TyCtxt<'tcx>>, call_sig: FnSig<'_>) -> bool {
- call_sig.safety == Safety::Safe
- && !has_late_bound_to_non_late_bound_regions(
- cx.tcx.signature_unclosure(closure.sig(), Safety::Safe).skip_binder(),
- call_sig,
- )
+fn check_sig<'tcx>(closure_sig: FnSig<'tcx>, call_sig: FnSig<'tcx>) -> bool {
+ call_sig.safety == Safety::Safe && !has_late_bound_to_non_late_bound_regions(closure_sig, call_sig)
}
/// This walks through both signatures and checks for any time a late-bound region is expected by an
@@ -265,7 +285,7 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure: ClosureArgs<TyCtxt<'tcx>>, c
/// This is needed because rustc is unable to late bind early-bound regions in a function signature.
fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<'_>) -> bool {
fn check_region(from_region: Region<'_>, to_region: Region<'_>) -> bool {
- matches!(from_region.kind(), RegionKind::ReBound(..)) && !matches!(to_region.kind(), RegionKind::ReBound(..))
+ from_region.is_bound() && !to_region.is_bound()
}
fn check_subs(from_subs: &[GenericArg<'_>], to_subs: &[GenericArg<'_>]) -> bool {
@@ -318,3 +338,8 @@ fn check_ty(from_ty: Ty<'_>, to_ty: Ty<'_>) -> bool {
.zip(to_sig.inputs_and_output)
.any(|(from_ty, to_ty)| check_ty(from_ty, to_ty))
}
+
+fn ty_has_static(ty: Ty<'_>) -> bool {
+ ty.walk()
+ .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(re) if re.is_static()))
+}
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 0f4176e..9bf3bab 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -88,11 +88,11 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
{
- let suggestion_span = item.span.shrink_to_lo();
- let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
span_lint_and_then(cx, lint, item.span, msg, |diag| {
+ let suggestion_span = item.span.shrink_to_lo();
+ let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
let sugg = format!("#[non_exhaustive]\n{indent}");
- diag.span_suggestion(
+ diag.span_suggestion_verbose(
suggestion_span,
"try adding #[non_exhaustive]",
sugg,
diff --git a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
index bb74e34..95b8e88 100644
--- a/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
+++ b/src/tools/clippy/clippy_lints/src/field_scoped_visibility_modifiers.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Item, ItemKind, VisibilityKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -62,13 +62,15 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
// pub(self) is equivalent to not using pub at all, so we ignore it
continue;
}
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
FIELD_SCOPED_VISIBILITY_MODIFIERS,
field.vis.span,
"scoped visibility modifier on a field",
- None,
- "consider making the field private and adding a scoped visibility method for it",
+ |diag| {
+ diag.help("consider making the field private and adding a scoped visibility method for it");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index 6adcd22..f095c1a 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -1,7 +1,7 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::numeric_literal;
use rustc_ast::ast::{self, LitFloatType, LitKind};
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, FloatTy};
@@ -105,32 +105,43 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if is_whole && !sym_str.contains(['e', 'E']) {
// Normalize the literal by stripping the fractional portion
if sym_str.split('.').next().unwrap() != float_str {
- // If the type suffix is missing the suggestion would be
- // incorrectly interpreted as an integer so adding a `.0`
- // suffix to prevent that.
- if type_suffix.is_none() {
- float_str.push_str(".0");
- }
-
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
LOSSY_FLOAT_LITERAL,
expr.span,
"literal cannot be represented as the underlying type without loss of precision",
- "consider changing the type or replacing it with",
- numeric_literal::format(&float_str, type_suffix, true),
- Applicability::MachineApplicable,
+ |diag| {
+ // If the type suffix is missing the suggestion would be
+ // incorrectly interpreted as an integer so adding a `.0`
+ // suffix to prevent that.
+ if type_suffix.is_none() {
+ float_str.push_str(".0");
+ }
+ diag.span_suggestion_with_style(
+ expr.span,
+ "consider changing the type or replacing it with",
+ numeric_literal::format(&float_str, type_suffix, true),
+ Applicability::MachineApplicable,
+ SuggestionStyle::ShowAlways,
+ );
+ },
);
}
} else if digits > max as usize && float_str.len() < sym_str.len() {
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
EXCESSIVE_PRECISION,
expr.span,
"float has excessive precision",
- "consider changing the type or truncating it to",
- numeric_literal::format(&float_str, type_suffix, true),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion_with_style(
+ expr.span,
+ "consider changing the type or truncating it to",
+ numeric_literal::format(&float_str, type_suffix, true),
+ Applicability::MachineApplicable,
+ SuggestionStyle::ShowAlways,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 68bdf88..bf4bcab 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -1,9 +1,9 @@
use clippy_utils::consts::Constant::{Int, F32, F64};
-use clippy_utils::consts::{constant, constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{
- eq_expr_value, get_parent_expr, higher, in_constant, is_inherent_method_call, is_no_std_crate, numeric_literal,
- peel_blocks, sugg,
+ eq_expr_value, get_parent_expr, higher, is_in_const_context, is_inherent_method_call, is_no_std_crate,
+ numeric_literal, peel_blocks, sugg,
};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
@@ -112,7 +112,7 @@
// Returns the specialized log method for a given base if base is constant
// and is one of 2, 10 and e
fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> {
- if let Some(value) = constant(cx, cx.typeck_results(), base) {
+ if let Some(value) = ConstEvalCtxt::new(cx).eval(base) {
if F32(2.0) == value || F64(2.0) == value {
return Some("log2");
} else if F32(10.0) == value || F64(10.0) == value {
@@ -182,10 +182,8 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
rhs,
) = receiver.kind
{
- let recv = match (
- constant(cx, cx.typeck_results(), lhs),
- constant(cx, cx.typeck_results(), rhs),
- ) {
+ let ecx = ConstEvalCtxt::new(cx);
+ let recv = match (ecx.eval(lhs), ecx.eval(rhs)) {
(Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
(_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
_ => return,
@@ -230,7 +228,7 @@ fn get_integer_from_float_constant(value: &Constant<'_>) -> Option<i32> {
fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
// Check receiver
- if let Some(value) = constant(cx, cx.typeck_results(), receiver) {
+ if let Some(value) = ConstEvalCtxt::new(cx).eval(receiver) {
if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
Some("exp")
} else if F32(2.0) == value || F64(2.0) == value {
@@ -251,7 +249,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
}
// Check argument
- if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
+ if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) {
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
(
SUBOPTIMAL_FLOPS,
@@ -291,7 +289,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
}
fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
- if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
+ if let Some(value) = ConstEvalCtxt::new(cx).eval(&args[0]) {
if value == Int(2) {
if let Some(parent) = get_parent_expr(cx, expr) {
if let Some(grandparent) = get_parent_expr(cx, parent) {
@@ -397,8 +395,9 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
) = &add_rhs.kind
&& lmethod_name.as_str() == "powi"
&& rmethod_name.as_str() == "powi"
- && let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1)
- && let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1)
+ && let ecx = ConstEvalCtxt::new(cx)
+ && let Some(lvalue) = ecx.eval(largs_1)
+ && let Some(rvalue) = ecx.eval(rargs_1)
&& Int(2) == lvalue
&& Int(2) == rvalue
{
@@ -438,7 +437,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
rhs,
) = expr.kind
&& cx.typeck_results().expr_ty(lhs).is_floating_point()
- && let Some(value) = constant(cx, cx.typeck_results(), rhs)
+ && let Some(value) = ConstEvalCtxt::new(cx).eval(rhs)
&& (F32(1.0) == value || F64(1.0) == value)
&& let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind
&& cx.typeck_results().expr_ty(self_arg).is_floating_point()
@@ -552,7 +551,7 @@ fn is_testing_negative(cx: &LateContext<'_>, expr: &Expr<'_>, test: &Expr<'_>) -
/// Returns true iff expr is some zero literal
fn is_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
- match constant_simple(cx, cx.typeck_results(), expr) {
+ match ConstEvalCtxt::new(cx).eval_simple(expr) {
Some(Int(i)) => i == 0,
Some(F32(f)) => f == 0.0,
Some(F64(f)) => f == 0.0,
@@ -696,8 +695,9 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
mul_lhs,
mul_rhs,
) = &div_lhs.kind
- && let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs)
- && let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs)
+ && let ecx = ConstEvalCtxt::new(cx)
+ && let Some(rvalue) = ecx.eval(div_rhs)
+ && let Some(lvalue) = ecx.eval(mul_rhs)
{
// TODO: also check for constant values near PI/180 or 180/PI
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue)
@@ -753,7 +753,7 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// All of these operations are currently not const and are in std.
- if in_constant(cx, expr.hir_id) {
+ if is_in_const_context(cx) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs
index a75538d..d05c5a0 100644
--- a/src/tools/clippy/clippy_lints/src/format_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{higher, match_def_path, paths};
use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
@@ -81,13 +81,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
_ => return,
};
if is_format(cx, arg) {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
FORMAT_PUSH_STRING,
expr.span,
"`format!(..)` appended to existing `String`",
- None,
- "consider using `write!` to avoid the extra allocation",
+ |diag| {
+ diag.help("consider using `write!` to avoid the extra allocation");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
index 9acb72b..6ab7bbc 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
-use clippy_utils::{in_constant, is_integer_literal};
+use clippy_utils::{is_in_const_context, is_integer_literal};
use rustc_errors::Applicability;
use rustc_hir::{def, Expr, ExprKind, LangItem, PrimTy, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass};
@@ -62,8 +62,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) {
&& matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_))
// do not lint in constant context, because the suggestion won't work.
- // NB: keep this check until a new `const_trait_impl` is available and stablized.
- && !in_constant(cx, exp.hir_id)
+ // NB: keep this check until a new `const_trait_impl` is available and stabilized.
+ && !is_in_const_context(cx)
{
let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
let ty = cx.typeck_results().expr_ty(expr);
diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
index b38cc7b..1c52514 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::for_each_expr_without_closures;
-use clippy_utils::{higher, SpanlessEq};
+use clippy_utils::{eq_expr_value, higher};
use core::ops::ControlFlow;
use rustc_errors::Diag;
use rustc_hir::{Expr, ExprKind};
@@ -51,53 +51,45 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if_else: Some(if_else),
..
}) = higher::IfLet::hir(cx, expr)
+ && let Some(op_mutex) = for_each_expr_without_closures(let_expr, |e| mutex_lock_call(cx, e, None))
+ && let Some(arm_mutex) =
+ for_each_expr_without_closures((if_then, if_else), |e| mutex_lock_call(cx, e, Some(op_mutex)))
{
- let is_mutex_lock = |e: &'tcx Expr<'tcx>| {
- if let Some(mutex) = is_mutex_lock_call(cx, e) {
- ControlFlow::Break(mutex)
- } else {
- ControlFlow::Continue(())
- }
+ let diag = |diag: &mut Diag<'_, ()>| {
+ diag.span_label(
+ op_mutex.span,
+ "this Mutex will remain locked for the entire `if let`-block...",
+ );
+ diag.span_label(
+ arm_mutex.span,
+ "... and is tried to lock again here, which will always deadlock.",
+ );
+ diag.help("move the lock call outside of the `if let ...` expression");
};
-
- let op_mutex = for_each_expr_without_closures(let_expr, is_mutex_lock);
- if let Some(op_mutex) = op_mutex {
- let arm_mutex = for_each_expr_without_closures((if_then, if_else), is_mutex_lock);
- if let Some(arm_mutex) = arm_mutex
- && SpanlessEq::new(cx).eq_expr(op_mutex, arm_mutex)
- {
- let diag = |diag: &mut Diag<'_, ()>| {
- diag.span_label(
- op_mutex.span,
- "this Mutex will remain locked for the entire `if let`-block...",
- );
- diag.span_label(
- arm_mutex.span,
- "... and is tried to lock again here, which will always deadlock.",
- );
- diag.help("move the lock call outside of the `if let ...` expression");
- };
- span_lint_and_then(
- cx,
- IF_LET_MUTEX,
- expr.span,
- "calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock",
- diag,
- );
- }
- }
+ span_lint_and_then(
+ cx,
+ IF_LET_MUTEX,
+ expr.span,
+ "calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock",
+ diag,
+ );
}
}
}
-fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+fn mutex_lock_call<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ op_mutex: Option<&'tcx Expr<'_>>,
+) -> ControlFlow<&'tcx Expr<'tcx>> {
if let ExprKind::MethodCall(path, self_arg, ..) = &expr.kind
&& path.ident.as_str() == "lock"
&& let ty = cx.typeck_results().expr_ty(self_arg).peel_refs()
&& is_type_diagnostic_item(cx, ty, sym::Mutex)
+ && op_mutex.map_or(true, |op| eq_expr_value(cx, self_arg, op))
{
- Some(self_arg)
+ ControlFlow::Break(self_arg)
} else {
- None
+ ControlFlow::Continue(())
}
}
diff --git a/src/tools/clippy/clippy_lints/src/if_not_else.rs b/src/tools/clippy/clippy_lints/src/if_not_else.rs
index 2f6daee..0ebd8d0 100644
--- a/src/tools/clippy/clippy_lints/src/if_not_else.rs
+++ b/src/tools/clippy/clippy_lints/src/if_not_else.rs
@@ -1,7 +1,7 @@
//! lint on if branches that could be swapped so no `!` operation is necessary
//! on the condition
-use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_else_clause;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@@ -49,7 +49,7 @@
declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
fn is_zero_const(expr: &Expr<'_>, cx: &LateContext<'_>) -> bool {
- if let Some(value) = constant_simple(cx, cx.typeck_results(), expr) {
+ if let Some(value) = ConstEvalCtxt::new(cx).eval_simple(expr) {
return Constant::Int(0) == value;
}
false
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index 39ea16b..0bca53c 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -1,10 +1,12 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::source::snippet_with_context;
use clippy_utils::sugg::Sugg;
-use clippy_utils::{contains_return, higher, in_constant, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
+use clippy_utils::{
+ contains_return, higher, is_else_clause, is_in_const_context, is_res_lang_ctor, path_res, peel_blocks,
+};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind};
@@ -76,37 +78,44 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
&& is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
&& is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
&& !is_else_clause(cx.tcx, expr)
- && !in_constant(cx, expr.hir_id)
+ && !is_in_const_context(cx)
&& !in_external_macro(cx.sess(), expr.span)
&& self.msrv.meets(msrvs::BOOL_THEN)
&& !contains_return(then_block.stmts)
{
- let mut app = Applicability::Unspecified;
- let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
- .maybe_par()
- .to_string();
- let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
- let mut method_body = if then_block.stmts.is_empty() {
- arg_snip.into_owned()
- } else {
- format!("{{ /* snippet */ {arg_snip} }}")
- };
let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(msrvs::BOOL_THEN_SOME) {
"then_some"
} else {
- method_body.insert_str(0, "|| ");
"then"
};
- let help =
- format!("consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",);
- span_lint_and_help(
+ span_lint_and_then(
cx,
IF_THEN_SOME_ELSE_NONE,
expr.span,
format!("this could be simplified with `bool::{method_name}`"),
- None,
- help,
+ |diag| {
+ let mut app = Applicability::Unspecified;
+ let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
+ .maybe_par()
+ .to_string();
+ let arg_snip = snippet_with_context(cx, then_arg.span, ctxt, "[body]", &mut app).0;
+ let method_body = if let Some(first_stmt) = then_block.stmts.first() {
+ let (block_snippet, _) =
+ snippet_with_context(cx, first_stmt.span.until(then_arg.span), ctxt, "..", &mut app);
+ let closure = if method_name == "then" { "|| " } else { "" };
+ format!("{closure} {{ {block_snippet}; {arg_snip} }}")
+ } else {
+ arg_snip.into_owned()
+ };
+
+ diag.span_suggestion(
+ expr.span,
+ "try",
+ format!("{cond_snip}.{method_name}({method_body})"),
+ app,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 344a04e..e56f33f 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -1,7 +1,7 @@
use std::borrow::Cow;
use std::collections::BTreeMap;
-use rustc_errors::Diag;
+use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
@@ -13,7 +13,7 @@
use rustc_span::symbol::sym;
use rustc_span::Span;
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet, IntoSpan, SpanRangeExt};
use clippy_utils::ty::is_type_diagnostic_item;
@@ -77,33 +77,32 @@ fn suggestion(
&generics_snip[1..generics_snip.len() - 1]
};
- multispan_sugg(
- diag,
- "consider adding a type parameter",
- vec![
- (
- generics_suggestion_span,
- format!(
- "<{generics_snip}{}S: ::std::hash::BuildHasher{}>",
- if generics_snip.is_empty() { "" } else { ", " },
- if vis.suggestions.is_empty() {
- ""
- } else {
- // request users to add `Default` bound so that generic constructors can be used
- " + Default"
- },
- ),
+ let mut suggestions = vec![
+ (
+ generics_suggestion_span,
+ format!(
+ "<{generics_snip}{}S: ::std::hash::BuildHasher{}>",
+ if generics_snip.is_empty() { "" } else { ", " },
+ if vis.suggestions.is_empty() {
+ ""
+ } else {
+ // request users to add `Default` bound so that generic constructors can be used
+ " + Default"
+ },
),
- (
- target.span(),
- format!("{}<{}, S>", target.type_name(), target.type_arguments(),),
- ),
- ],
- );
+ ),
+ (
+ target.span(),
+ format!("{}<{}, S>", target.type_name(), target.type_arguments(),),
+ ),
+ ];
+ suggestions.extend(vis.suggestions);
- if !vis.suggestions.is_empty() {
- multispan_sugg(diag, "...and use generic constructor", vis.suggestions);
- }
+ diag.multipart_suggestion(
+ "add a type parameter for `BuildHasher`",
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
}
if !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index a102b43..b926e1e 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -3,7 +3,7 @@
use clippy_utils::visitors::for_each_expr_without_closures;
use clippy_utils::{get_async_fn_body, is_async_fn, is_from_proc_macro};
use core::ops::ControlFlow;
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -45,8 +45,6 @@
declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]);
fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
- let mut app = Applicability::MachineApplicable;
- let snip = snippet_with_applicability(cx, span, "..", &mut app);
span_lint_hir_and_then(
cx,
IMPLICIT_RETURN,
@@ -54,14 +52,20 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
span,
"missing `return` statement",
|diag| {
- diag.span_suggestion(span, "add `return` as shown", format!("return {snip}"), app);
+ let mut app = Applicability::MachineApplicable;
+ let snip = snippet_with_applicability(cx, span, "..", &mut app);
+ diag.span_suggestion_with_style(
+ span,
+ "add `return` as shown",
+ format!("return {snip}"),
+ app,
+ SuggestionStyle::ShowAlways,
+ );
},
);
}
fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, expr_span: Span) {
- let mut app = Applicability::MachineApplicable;
- let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
span_lint_hir_and_then(
cx,
IMPLICIT_RETURN,
@@ -69,11 +73,14 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp
break_span,
"missing `return` statement",
|diag| {
- diag.span_suggestion(
+ let mut app = Applicability::MachineApplicable;
+ let snip = snippet_with_context(cx, expr_span, break_span.ctxt(), "..", &mut app).0;
+ diag.span_suggestion_with_style(
break_span,
"change `break` to `return` as shown",
format!("return {snip}"),
app,
+ SuggestionStyle::ShowAlways,
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index f225c6e..dd59085 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_context;
@@ -117,11 +117,11 @@ fn get_int_max(ty: Ty<'_>) -> Option<u128> {
fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
if let ExprKind::Binary(op, l, r) = expr.kind {
- let tr = cx.typeck_results();
- if let Some(Constant::Int(c)) = constant(cx, tr, r) {
+ let ecx = ConstEvalCtxt::new(cx);
+ if let Some(Constant::Int(c)) = ecx.eval(r) {
return Some((c, op.node, l));
};
- if let Some(Constant::Int(c)) = constant(cx, tr, l) {
+ if let Some(Constant::Int(c)) = ecx.eval(l) {
return Some((c, invert_op(op.node)?, r));
}
}
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index 12ca6d4..0ef5b80 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -55,7 +55,6 @@ pub fn new(conf: &'static Conf) -> Self {
}
}
- #[allow(clippy::cast_lossless)]
fn get_def_id_version(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> RustcVersion {
if let Some(version) = self.is_above_msrv.get(&def_id) {
return *version;
@@ -67,9 +66,9 @@ fn get_def_id_version(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> RustcVersion
since: StableSince::Version(version),
..
} => Some(RustcVersion::new(
- version.major as _,
- version.minor as _,
- version.patch as _,
+ version.major.into(),
+ version.minor.into(),
+ version.patch.into(),
)),
_ => None,
}) {
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 526b4e1..2f9661c 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -1,6 +1,6 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
use clippy_utils::ty::is_copy;
@@ -246,7 +246,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
&& let parent_id = cx.tcx.parent_hir_id(expr.hir_id)
&& let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id)
&& let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind
- && let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr)
+ && let Some(Constant::Int(index_value)) = ConstEvalCtxt::new(cx).eval(index_expr)
&& let Ok(index_value) = index_value.try_into()
&& index_value < max_suggested_slice
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 6729c7c..3ac50b8 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -1,7 +1,7 @@
//! lint on indexing and slicing operations
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::ty::{deref_chain, get_adt_inherent_method};
use clippy_utils::{higher, is_from_proc_macro};
@@ -70,8 +70,6 @@
///
/// Use instead:
/// ```no_run
- /// # #![allow(unused)]
- ///
/// # let x = vec![0; 5];
/// # let y = [0, 1, 2, 3];
/// x.get(2);
@@ -179,7 +177,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
return;
}
// Index is a constant uint.
- if let Some(constant) = constant(cx, cx.typeck_results(), index) {
+ if let Some(constant) = ConstEvalCtxt::new(cx).eval(index) {
// only `usize` index is legal in rust array index
// leave other type to rustc
if let Constant::Int(off) = constant
@@ -217,14 +215,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
/// Returns a tuple of options with the start and end (exclusive) values of
/// the range. If the start or end is not constant, None is returned.
fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option<u128>, Option<u128>) {
- let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr));
+ let ecx = ConstEvalCtxt::new(cx);
+ let s = range.start.map(|expr| ecx.eval(expr));
let start = match s {
Some(Some(Constant::Int(x))) => Some(x),
Some(_) => None,
None => Some(0),
};
- let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr));
+ let e = range.end.map(|expr| ecx.eval(expr));
let end = match e {
Some(Some(Constant::Int(x))) => {
if range.limits == RangeLimits::Closed {
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index fa7e7f6..676d50c 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -41,7 +41,6 @@
/// ### Example
/// ```no_run
/// let infinite_iter = 0..;
- /// # #[allow(unused)]
/// [0..].iter().zip(infinite_iter.take_while(|x| *x > 5));
/// ```
#[clippy::version = "pre 1.29.0"]
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index 0d3786d..9eed7aa 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -1,6 +1,6 @@
//! lint on inherent implementations
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::LocalDefId;
@@ -105,13 +105,14 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
// `TyCtxt::crate_inherent_impls` doesn't have a defined order. Sort the lint output first.
lint_spans.sort_by_key(|x| x.0.lo());
for (span, first_span) in lint_spans {
- span_lint_and_note(
+ span_lint_and_then(
cx,
MULTIPLE_INHERENT_IMPL,
span,
"multiple implementations of this structure",
- Some(first_span),
- "first implementation here",
+ |diag| {
+ diag.span_note(first_span, "first implementation here");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
index 30f2285..1929fbd 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -7,7 +7,7 @@
use clippy_utils::comparisons;
use clippy_utils::comparisons::Rel;
-use clippy_utils::consts::{constant_full_int, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, FullInt};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet;
@@ -95,7 +95,7 @@ fn upcast_comparison_bounds_err<'tcx>(
invert: bool,
) {
if let Some((lb, ub)) = lhs_bounds {
- if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) {
+ if let Some(norm_rhs_val) = ConstEvalCtxt::new(cx).eval_full_int(rhs) {
if rel == Rel::Eq || rel == Rel::Ne {
if norm_rhs_val < lb || norm_rhs_val > ub {
err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
diff --git a/src/tools/clippy/clippy_lints/src/large_include_file.rs b/src/tools/clippy/clippy_lints/src/large_include_file.rs
index c67da68..f2f841d 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -1,5 +1,5 @@
use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::root_macro_call_first_node;
use rustc_ast::LitKind;
use rustc_hir::{Expr, ExprKind};
@@ -66,16 +66,18 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
&& (cx.tcx.is_diagnostic_item(sym::include_bytes_macro, macro_call.def_id)
|| cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id))
{
- span_lint_and_note(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
LARGE_INCLUDE_FILE,
expr.span.source_callsite(),
"attempted to include a large file",
- None,
- format!(
- "the configuration allows a maximum size of {} bytes",
- self.max_file_size
- ),
+ |diag| {
+ diag.note(format!(
+ "the configuration allows a maximum size of {} bytes",
+ self.max_file_size
+ ));
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 8fa63f3..b522c22 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths};
use rustc_hir::{LetStmt, LocalSource, PatKind};
@@ -149,43 +149,53 @@ fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) {
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
});
if contains_sync_guard {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
LET_UNDERSCORE_LOCK,
local.span,
"non-binding `let` on a synchronization lock",
- None,
- "consider using an underscore-prefixed named \
- binding or dropping explicitly with `std::mem::drop`",
+ |diag| {
+ diag.help(
+ "consider using an underscore-prefixed named \
+ binding or dropping explicitly with `std::mem::drop`",
+ );
+ },
);
} else if let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
&& implements_trait(cx, cx.typeck_results().expr_ty(init), future_trait_def_id, &[])
{
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
LET_UNDERSCORE_FUTURE,
local.span,
"non-binding `let` on a future",
- None,
- "consider awaiting the future or dropping explicitly with `std::mem::drop`",
+ |diag| {
+ diag.help("consider awaiting the future or dropping explicitly with `std::mem::drop`");
+ },
);
} else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
LET_UNDERSCORE_MUST_USE,
local.span,
"non-binding `let` on an expression with `#[must_use]` type",
- None,
- "consider explicitly using expression value",
+ |diag| {
+ diag.help("consider explicitly using expression value");
+ },
);
} else if is_must_use_func_call(cx, init) {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
LET_UNDERSCORE_MUST_USE,
local.span,
"non-binding `let` on a result of a `#[must_use]` function",
- None,
- "consider explicitly using function result",
+ |diag| {
+ diag.help("consider explicitly using function result");
+ },
);
}
@@ -204,18 +214,22 @@ fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) {
return;
}
- span_lint_and_help(
+ span_lint_and_then(
cx,
LET_UNDERSCORE_UNTYPED,
local.span,
"non-binding `let` without a type annotation",
- Some(Span::new(
- local.pat.span.hi(),
- local.pat.span.hi() + BytePos(1),
- local.pat.span.ctxt(),
- local.pat.span.parent(),
- )),
- "consider adding a type annotation",
+ |diag| {
+ diag.span_help(
+ Span::new(
+ local.pat.span.hi(),
+ local.pat.span.hi() + BytePos(1),
+ local.pat.span.ctxt(),
+ local.pat.span.parent(),
+ ),
+ "consider adding a type annotation",
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/lib.deprecated.rs b/src/tools/clippy/clippy_lints/src/lib.deprecated.rs
deleted file mode 100644
index 0d21261..0000000
--- a/src/tools/clippy/clippy_lints/src/lib.deprecated.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-// This file was generated by `cargo dev update_lints`.
-// Use that command to update this file and do not edit by hand.
-// Manual edits will be overwritten.
-
-{
- store.register_removed(
- "clippy::should_assert_eq",
- "`assert!()` will be more flexible with RFC 2011",
- );
- store.register_removed(
- "clippy::extend_from_slice",
- "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice",
- );
- store.register_removed(
- "clippy::range_step_by_zero",
- "`iterator.step_by(0)` panics nowadays",
- );
- store.register_removed(
- "clippy::unstable_as_slice",
- "`Vec::as_slice` has been stabilized in 1.7",
- );
- store.register_removed(
- "clippy::unstable_as_mut_slice",
- "`Vec::as_mut_slice` has been stabilized in 1.7",
- );
- store.register_removed(
- "clippy::misaligned_transmute",
- "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
- );
- store.register_removed(
- "clippy::assign_ops",
- "using compound assignment operators (e.g., `+=`) is harmless",
- );
- store.register_removed(
- "clippy::if_let_redundant_pattern_matching",
- "this lint has been changed to redundant_pattern_matching",
- );
- store.register_removed(
- "clippy::unsafe_vector_initialization",
- "the replacement suggested by this lint had substantially different behavior",
- );
- store.register_removed(
- "clippy::unused_collect",
- "`collect` has been marked as #[must_use] in rustc and that covers all cases of this lint",
- );
- store.register_removed(
- "clippy::replace_consts",
- "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants",
- );
- store.register_removed(
- "clippy::regex_macro",
- "the regex! macro has been removed from the regex crate in 2018",
- );
- store.register_removed(
- "clippy::find_map",
- "this lint has been replaced by `manual_find_map`, a more specific lint",
- );
- store.register_removed(
- "clippy::filter_map",
- "this lint has been replaced by `manual_filter_map`, a more specific lint",
- );
- store.register_removed(
- "clippy::pub_enum_variant_names",
- "set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items",
- );
- store.register_removed(
- "clippy::wrong_pub_self_convention",
- "set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items",
- );
- store.register_removed(
- "clippy::maybe_misused_cfg",
- "this lint has been replaced by `unexpected_cfgs`",
- );
- store.register_removed(
- "clippy::mismatched_target_os",
- "this lint has been replaced by `unexpected_cfgs`",
- );
-}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 22d23a1..ce13a9a 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -8,13 +8,11 @@
#![feature(iter_intersperse)]
#![feature(iter_partition_in_place)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
#![feature(never_type)]
#![feature(rustc_private)]
#![feature(stmt_expr_attributes)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![allow(
clippy::missing_docs_in_private_items,
clippy::must_use_candidate,
@@ -65,13 +63,11 @@
#[macro_use]
extern crate declare_clippy_lint;
-#[cfg(feature = "internal")]
-pub mod deprecated_lints;
#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
mod utils;
mod declared_lints;
-mod renamed_lints;
+mod deprecated_lints;
// begin lints modules, do not remove this comment, it’s used in `update_lints`
mod absolute_paths;
@@ -373,6 +369,7 @@
mod unused_async;
mod unused_io_amount;
mod unused_peekable;
+mod unused_result_ok;
mod unused_rounding;
mod unused_self;
mod unused_unit;
@@ -496,7 +493,7 @@ pub fn explain(name: &str) -> i32 {
// Check if the lint has configuration
let mut mdconf = get_configuration_metadata();
let name = name.to_ascii_lowercase();
- mdconf.retain(|cconf| cconf.lints.contains(&name));
+ mdconf.retain(|cconf| cconf.lints.contains(&&*name));
if !mdconf.is_empty() {
println!("### Configuration for {}:\n", info.lint.name_lower());
for conf in mdconf {
@@ -532,10 +529,14 @@ fn register_categories(store: &mut rustc_lint::LintStore) {
/// Used in `./src/driver.rs`.
#[expect(clippy::too_many_lines)]
pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
- register_removed_non_tool_lints(store);
register_categories(store);
- include!("lib.deprecated.rs");
+ for (old_name, new_name) in deprecated_lints::RENAMED {
+ store.register_renamed(old_name, new_name);
+ }
+ for (name, reason) in deprecated_lints::DEPRECATED {
+ store.register_removed(name, reason);
+ }
#[cfg(feature = "internal")]
{
@@ -670,6 +671,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(conf)));
store.register_late_pass(|_| Box::new(missing_inline::MissingInline));
store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems));
+ store.register_late_pass(|_| Box::new(unused_result_ok::UnusedResultOk));
store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk));
store.register_late_pass(|_| Box::new(partialeq_ne_impl::PartialEqNeImpl));
store.register_late_pass(|_| Box::new(unused_io_amount::UnusedIoAmount));
@@ -819,7 +821,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(conf)));
store.register_late_pass(move |_| Box::new(manual_rotate::ManualRotate));
store.register_late_pass(move |_| Box::new(operators::Operators::new(conf)));
- store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
+ store.register_late_pass(move |_| Box::new(std_instead_of_core::StdReexports::new(conf)));
store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(conf)));
store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(conf)));
@@ -908,68 +910,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(move |_| Box::new(macro_metavars_in_unsafe::ExprMetavarsInUnsafe::new(conf)));
store.register_late_pass(move |_| Box::new(string_patterns::StringPatterns::new(conf)));
store.register_early_pass(|| Box::new(field_scoped_visibility_modifiers::FieldScopedVisibilityModifiers));
- store.register_late_pass(|_| Box::new(set_contains_or_insert::HashsetInsertAfterContains));
+ store.register_late_pass(|_| Box::new(set_contains_or_insert::SetContainsOrInsert));
store.register_early_pass(|| Box::new(byte_char_slices::ByteCharSlice));
store.register_early_pass(|| Box::new(cfg_not_test::CfgNotTest));
// add lints here, do not remove this comment, it's used in `new_lint`
}
-
-#[rustfmt::skip]
-fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
- store.register_removed(
- "should_assert_eq",
- "`assert!()` will be more flexible with RFC 2011",
- );
- store.register_removed(
- "extend_from_slice",
- "`.extend_from_slice(_)` is a faster way to extend a Vec by a slice",
- );
- store.register_removed(
- "range_step_by_zero",
- "`iterator.step_by(0)` panics nowadays",
- );
- store.register_removed(
- "unstable_as_slice",
- "`Vec::as_slice` has been stabilized in 1.7",
- );
- store.register_removed(
- "unstable_as_mut_slice",
- "`Vec::as_mut_slice` has been stabilized in 1.7",
- );
- store.register_removed(
- "misaligned_transmute",
- "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
- );
- store.register_removed(
- "assign_ops",
- "using compound assignment operators (e.g., `+=`) is harmless",
- );
- store.register_removed(
- "if_let_redundant_pattern_matching",
- "this lint has been changed to redundant_pattern_matching",
- );
- store.register_removed(
- "unsafe_vector_initialization",
- "the replacement suggested by this lint had substantially different behavior",
- );
- store.register_removed(
- "reverse_range_loop",
- "this lint is now included in reversed_empty_ranges",
- );
-}
-
-/// Register renamed lints.
-///
-/// Used in `./src/driver.rs`.
-pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
- for (old_name, new_name) in renamed_lints::RENAMED_LINTS {
- ls.register_renamed(old_name, new_name);
- }
-}
-
-// only exists to let the dogfood integration test works.
-// Don't run clippy as an executable directly
-#[allow(dead_code)]
-fn main() {
- panic!("Please use the cargo-clippy executable");
-}
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index b685d1d..259e4d6 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -2,13 +2,13 @@
//! floating-point literal expressions.
use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Expr, ExprKind, LitKind};
use rustc_ast::token;
use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::impl_lint_pass;
use rustc_span::Span;
@@ -159,63 +159,39 @@ enum WarningType {
}
impl WarningType {
- fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: Span) {
+ fn lint_and_text(&self) -> (&'static Lint, &'static str, &'static str) {
match self {
- Self::MistypedLiteralSuffix => span_lint_and_sugg(
- cx,
+ Self::MistypedLiteralSuffix => (
MISTYPED_LITERAL_SUFFIXES,
- span,
"mistyped literal suffix",
"did you mean to write",
- suggested_format,
- Applicability::MaybeIncorrect,
),
- Self::UnreadableLiteral => span_lint_and_sugg(
- cx,
- UNREADABLE_LITERAL,
- span,
- "long literal lacking separators",
- "consider",
- suggested_format,
- Applicability::MachineApplicable,
- ),
- Self::LargeDigitGroups => span_lint_and_sugg(
- cx,
- LARGE_DIGIT_GROUPS,
- span,
- "digit groups should be smaller",
- "consider",
- suggested_format,
- Applicability::MachineApplicable,
- ),
- Self::InconsistentDigitGrouping => span_lint_and_sugg(
- cx,
+ Self::UnreadableLiteral => (UNREADABLE_LITERAL, "long literal lacking separators", "consider"),
+ Self::LargeDigitGroups => (LARGE_DIGIT_GROUPS, "digit groups should be smaller", "consider"),
+ Self::InconsistentDigitGrouping => (
INCONSISTENT_DIGIT_GROUPING,
- span,
"digits grouped inconsistently by underscores",
"consider",
- suggested_format,
- Applicability::MachineApplicable,
),
- Self::DecimalRepresentation => span_lint_and_sugg(
- cx,
+ Self::DecimalRepresentation => (
DECIMAL_LITERAL_REPRESENTATION,
- span,
"integer literal has a better hexadecimal representation",
"consider",
- suggested_format,
- Applicability::MachineApplicable,
),
- Self::UnusualByteGroupings => span_lint_and_sugg(
- cx,
+ Self::UnusualByteGroupings => (
UNUSUAL_BYTE_GROUPINGS,
- span,
"digits of hex, binary or octal literal not in groups of equal size",
"consider",
- suggested_format,
- Applicability::MachineApplicable,
),
- };
+ }
+ }
+
+ fn display(&self, num_lit: &NumericLiteral<'_>, cx: &EarlyContext<'_>, span: Span) {
+ let (lint, message, try_msg) = self.lint_and_text();
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, lint, span, message, |diag| {
+ diag.span_suggestion(span, try_msg, num_lit.format(), Applicability::MaybeIncorrect);
+ });
}
}
@@ -293,7 +269,7 @@ fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => true,
};
if should_warn {
- warning_type.display(num_lit.format(), cx, span);
+ warning_type.display(&num_lit, cx, span);
}
}
}
@@ -346,11 +322,14 @@ fn check_for_mistyped_suffix(cx: &EarlyContext<'_>, span: Span, num_lit: &mut Nu
}
}
*part = main_part;
- let mut sugg = num_lit.format();
- sugg.push('_');
- sugg.push(missing_char);
- sugg.push_str(last_group);
- WarningType::MistypedLiteralSuffix.display(sugg, cx, span);
+ let (lint, message, try_msg) = WarningType::MistypedLiteralSuffix.lint_and_text();
+ span_lint_and_then(cx, lint, span, message, |diag| {
+ let mut sugg = num_lit.format();
+ sugg.push('_');
+ sugg.push(missing_char);
+ sugg.push_str(last_group);
+ diag.span_suggestion(span, try_msg, sugg, Applicability::MaybeIncorrect);
+ });
false
} else {
true
@@ -471,7 +450,7 @@ fn check_lit(&self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
let hex = format!("{val:#X}");
let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
- warning_type.display(num_lit.format(), cx, span);
+ warning_type.display(&num_lit, cx, span);
});
}
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
index f0ee64d..73a2361 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -2,6 +2,7 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{get_enclosing_block, is_integer_const};
+use rustc_ast::Label;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_block, walk_expr};
use rustc_hir::{Expr, Pat};
@@ -17,6 +18,7 @@ pub(super) fn check<'tcx>(
arg: &'tcx Expr<'_>,
body: &'tcx Expr<'_>,
expr: &'tcx Expr<'_>,
+ label: Option<Label>,
) {
// Look for variables that are incremented once per loop iteration.
let mut increment_visitor = IncrementVisitor::new(cx);
@@ -34,7 +36,7 @@ pub(super) fn check<'tcx>(
{
let mut applicability = Applicability::MaybeIncorrect;
let span = expr.span.with_hi(arg.span.hi());
-
+ let loop_label = label.map_or(String::new(), |l| format!("{}: ", l.ident.name));
let int_name = match ty.map(Ty::kind) {
// usize or inferred
Some(ty::Uint(UintTy::Usize)) | None => {
@@ -45,7 +47,7 @@ pub(super) fn check<'tcx>(
format!("the variable `{name}` is used as a loop counter"),
"consider using",
format!(
- "for ({name}, {}) in {}.enumerate()",
+ "{loop_label}for ({name}, {}) in {}.enumerate()",
snippet_with_applicability(cx, pat.span, "item", &mut applicability),
make_iterator_snippet(cx, arg, &mut applicability),
),
@@ -68,7 +70,7 @@ pub(super) fn check<'tcx>(
span,
"consider using",
format!(
- "for ({name}, {}) in (0_{int_name}..).zip({})",
+ "{loop_label}for ({name}, {}) in (0_{int_name}..).zip({})",
snippet_with_applicability(cx, pat.span, "item", &mut applicability),
make_iterator_snippet(cx, arg, &mut applicability),
),
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
index 6922533..185d834 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
@@ -1,8 +1,9 @@
use super::FOR_KV_MAP;
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{pat_is_wild, sugg};
+use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
@@ -40,13 +41,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
format!("you seem to want to iterate on a map's {kind}s"),
|diag| {
let map = sugg::Sugg::hir(cx, arg, "map");
- multispan_sugg(
- diag,
+ diag.multipart_suggestion(
"use the corresponding method",
vec![
(pat_span, snippet(cx, new_pat_span, kind).into_owned()),
(arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_par())),
],
+ Applicability::MachineApplicable,
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
index b00a082..57434f3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::{match_def_path, paths, SpanlessEq};
use rustc_errors::Applicability;
@@ -38,11 +38,10 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>,
};
let loop_replacement = format!("while let Some({}) = {}.pop()", pat, snippet(cx, receiver_span, ".."));
- multispan_sugg_with_applicability(
- diag,
+ diag.multipart_suggestion(
"consider using a `while..let` loop",
+ vec![(loop_span, loop_replacement), (pop_span, pop_replacement)],
Applicability::MachineApplicable,
- [(loop_span, loop_replacement), (pop_span, pop_replacement)],
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 7c2a809..92ccc0c 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -25,6 +25,7 @@
use clippy_config::msrvs::Msrv;
use clippy_config::Conf;
use clippy_utils::higher;
+use rustc_ast::Label;
use rustc_hir::{Expr, ExprKind, LoopSource, Pat};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
@@ -448,7 +449,7 @@
#[clippy::version = "1.80.0"]
pub WHILE_FLOAT,
nursery,
- "while loops comaparing floating point values"
+ "while loops comparing floating point values"
}
declare_clippy_lint! {
@@ -760,6 +761,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
body,
loop_id,
span,
+ label,
}) = for_loop
{
// we don't want to check expanded macros
@@ -768,7 +770,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if body.span.from_expansion() {
return;
}
- self.check_for_loop(cx, pat, arg, body, expr, span);
+ self.check_for_loop(cx, pat, arg, body, expr, span, label);
if let ExprKind::Block(block, _) = body.kind {
never_loop::check(cx, block, loop_id, span, for_loop.as_ref());
}
@@ -808,6 +810,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
}
impl Loops {
+ #[allow(clippy::too_many_arguments)]
fn check_for_loop<'tcx>(
&self,
cx: &LateContext<'tcx>,
@@ -816,11 +819,12 @@ fn check_for_loop<'tcx>(
body: &'tcx Expr<'_>,
expr: &'tcx Expr<'_>,
span: Span,
+ label: Option<Label>,
) {
let is_manual_memcpy_triggered = manual_memcpy::check(cx, pat, arg, body, expr);
if !is_manual_memcpy_triggered {
needless_range_loop::check(cx, pat, arg, body, expr);
- explicit_counter_loop::check(cx, pat, arg, body, expr);
+ explicit_counter_loop::check(cx, pat, arg, body, expr, label);
}
self.check_for_loop_arg(cx, pat, arg);
for_kv_map::check(cx, pat, arg, body);
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index de7ec81..e18e437 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -1,11 +1,12 @@
use super::NEEDLESS_RANGE_LOOP;
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::has_iter_method;
use clippy_utils::visitors::is_local_used;
use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath};
@@ -145,8 +146,7 @@ pub(super) fn check<'tcx>(
arg.span,
format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
|diag| {
- multispan_sugg(
- diag,
+ diag.multipart_suggestion(
"consider using an iterator and enumerate()",
vec![
(pat.span, format!("({}, <item>)", ident.name)),
@@ -155,6 +155,7 @@ pub(super) fn check<'tcx>(
format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
),
],
+ Applicability::HasPlaceholders,
);
},
);
@@ -171,10 +172,10 @@ pub(super) fn check<'tcx>(
arg.span,
format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
|diag| {
- multispan_sugg(
- diag,
+ diag.multipart_suggestion(
"consider using an iterator",
vec![(pat.span, "<item>".to_string()), (arg.span, repl)],
+ Applicability::HasPlaceholders,
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs
index 40ccfec..51e21aa 100644
--- a/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/unused_enumerate_index.rs
@@ -1,7 +1,8 @@
use super::UNUSED_ENUMERATE_INDEX;
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::{pat_is_wild, sugg};
+use rustc_errors::Applicability;
use rustc_hir::def::DefKind;
use rustc_hir::{Expr, ExprKind, Pat, PatKind};
use rustc_lint::LateContext;
@@ -28,13 +29,13 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, arg: &Expr<'_
"you seem to use `.enumerate()` and immediately discard the index",
|diag| {
let base_iter = sugg::Sugg::hir(cx, self_arg, "base iter");
- multispan_sugg(
- diag,
+ diag.multipart_suggestion(
"remove the `.enumerate()` call",
vec![
(pat.span, snippet(cx, elem.span, "..").into_owned()),
(arg.span, base_iter.to_string()),
],
+ Applicability::MachineApplicable,
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
index e7b3a2c..cc1bd59 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
@@ -1,5 +1,5 @@
use super::WHILE_IMMUTABLE_CONDITION;
-use clippy_utils::consts::constant;
+use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::usage::mutated_variables;
use rustc_hir::def::{DefKind, Res};
@@ -10,7 +10,7 @@
use std::ops::ControlFlow;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'tcx Expr<'_>) {
- if constant(cx, cx.typeck_results(), cond).is_some() {
+ if ConstEvalCtxt::new(cx).eval(cond).is_some() {
// A pure constant condition (e.g., `while false`) is not linted.
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index 194dd47..c171fa1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -14,7 +14,7 @@
use rustc_span::Symbol;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if let Some(higher::WhileLet { if_then, let_pat, let_expr, .. }) = higher::WhileLet::hir(expr)
+ if let Some(higher::WhileLet { if_then, let_pat, let_expr, label, .. }) = higher::WhileLet::hir(expr)
// check for `Some(..)` pattern
&& let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind
&& is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome)
@@ -27,6 +27,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
&& !uses_iter(cx, &iter_expr_struct, if_then)
{
let mut applicability = Applicability::MachineApplicable;
+
+ let loop_label = label.map_or(String::new(), |l| format!("{}: ", l.ident.name));
+
let loop_var = if let Some(some_pat) = some_pat.first() {
if is_refutable(cx, some_pat) {
// Refutable patterns don't work with for loops.
@@ -57,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
expr.span.with_hi(let_expr.span.hi()),
"this loop could be written as a `for` loop",
"try",
- format!("for {loop_var} in {iterator}{by_ref}"),
+ format!("{loop_label}for {loop_var} in {iterator}{by_ref}"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index a79ad01..4123c93 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -1,13 +1,13 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::higher::If;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::implements_trait;
use clippy_utils::visitors::is_const_evaluatable;
use clippy_utils::{
- eq_expr_value, in_constant, is_diag_trait_item, is_trait_method, path_res, path_to_local_id, peel_blocks,
+ eq_expr_value, is_diag_trait_item, is_in_const_context, is_trait_method, path_res, path_to_local_id, peel_blocks,
peel_blocks_with_stmt, MaybePath,
};
use itertools::Itertools;
@@ -122,8 +122,9 @@ fn min_less_than_max(&self, cx: &LateContext<'tcx>) -> bool {
if max_type != min_type {
return false;
}
- if let Some(max) = constant(cx, cx.typeck_results(), self.params.max)
- && let Some(min) = constant(cx, cx.typeck_results(), self.params.min)
+ let ecx = ConstEvalCtxt::new(cx);
+ if let Some(max) = ecx.eval(self.params.max)
+ && let Some(min) = ecx.eval(self.params.min)
&& let Some(ord) = Constant::partial_cmp(cx.tcx, max_type, &min, &max)
{
ord != Ordering::Greater
@@ -146,7 +147,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !self.msrv.meets(msrvs::CLAMP) {
return;
}
- if !expr.span.from_expansion() && !in_constant(cx, expr.hir_id) {
+ if !expr.span.from_expansion() && !is_in_const_context(cx) {
let suggestion = is_if_elseif_else_pattern(cx, expr)
.or_else(|| is_max_min_pattern(cx, expr))
.or_else(|| is_call_max_min_pattern(cx, expr))
@@ -159,7 +160,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
}
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
- if !self.msrv.meets(msrvs::CLAMP) || in_constant(cx, block.hir_id) {
+ if !self.msrv.meets(msrvs::CLAMP) || is_in_const_context(cx) {
return;
}
for suggestion in is_two_if_pattern(cx, block) {
diff --git a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
index 03416ba..6bdc791 100644
--- a/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_float_methods.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::{is_from_proc_macro, path_to_local};
@@ -95,8 +95,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|| cx.tcx.features().declared(sym!(const_float_classify))
)
&& let [first, second, const_1, const_2] = exprs
- && let Some(const_1) = constant(cx, cx.typeck_results(), const_1)
- && let Some(const_2) = constant(cx, cx.typeck_results(), const_2)
+ && let ecx = ConstEvalCtxt::new(cx)
+ && let Some(const_1) = ecx.eval(const_1)
+ && let Some(const_2) = ecx.eval(const_2)
&& path_to_local(first).is_some_and(|f| path_to_local(second).is_some_and(|s| f == s))
// The actual infinity check, we also allow `NEG_INFINITY` before` INFINITY` just in
// case somebody does that for some reason
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index a9f21d3..31c37c3 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -3,7 +3,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::sugg::Sugg;
-use clippy_utils::{higher, in_constant, path_to_local, peel_ref_operators};
+use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operators};
use rustc_ast::ast::RangeLimits;
use rustc_ast::LitKind::{Byte, Char};
use rustc_errors::Applicability;
@@ -95,7 +95,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
return;
}
- if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::IS_ASCII_DIGIT_CONST) {
+ if is_in_const_context(cx) && !self.msrv.meets(msrvs::IS_ASCII_DIGIT_CONST) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
index 78a750f..6cf5d27 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -1,9 +1,9 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant_full_int, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::{in_constant, path_to_local};
+use clippy_utils::{is_in_const_context, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -62,7 +62,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
&& add_rhs.span.ctxt() == ctxt
&& !in_external_macro(cx.sess(), expr.span)
&& self.msrv.meets(msrvs::REM_EUCLID)
- && (self.msrv.meets(msrvs::REM_EUCLID_CONST) || !in_constant(cx, expr.hir_id))
+ && (self.msrv.meets(msrvs::REM_EUCLID_CONST) || !is_in_const_context(cx))
&& let Some(const1) = check_for_unsigned_int_constant(cx, rem_rhs)
&& let Some((const2, add_other)) = check_for_either_unsigned_int_constant(cx, add_lhs, add_rhs)
&& let ExprKind::Binary(rem2_op, rem2_lhs, rem2_rhs) = add_other.kind
@@ -117,7 +117,7 @@ fn check_for_either_unsigned_int_constant<'a>(
}
fn check_for_unsigned_int_constant<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option<u128> {
- let int_const = constant_full_int(cx, cx.typeck_results(), expr)?;
+ let int_const = ConstEvalCtxt::new(cx).eval_full_int(expr)?;
match int_const {
FullInt::S(s) => s.try_into().ok(),
FullInt::U(u) => Some(u),
diff --git a/src/tools/clippy/clippy_lints/src/manual_rotate.rs b/src/tools/clippy/clippy_lints/src/manual_rotate.rs
index a517a4d..07537fc 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rotate.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rotate.rs
@@ -1,6 +1,6 @@
use std::fmt::Display;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg;
use rustc_errors::Applicability;
@@ -66,7 +66,7 @@ fn parse_shift<'tcx>(
BinOpKind::Shr => ShiftDirection::Right,
_ => return None,
};
- let const_expr = constant(cx, cx.typeck_results(), r)?;
+ let const_expr = ConstEvalCtxt::new(cx).eval(r)?;
if let Constant::Int(shift) = const_expr {
return Some((dir, shift, l));
}
diff --git a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs
index 429ee26..b24a0f4 100644
--- a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::{expr_or_init, in_constant, std_or_core};
+use clippy_utils::{expr_or_init, is_in_const_context, std_or_core};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@@ -44,7 +44,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
&& BinOpKind::Mul == op.node
&& !expr.span.from_expansion()
// Does not apply inside const because size_of_val is not cost in stable.
- && !in_constant(cx, expr.hir_id)
+ && !is_in_const_context(cx)
&& let Some(receiver) = simplify(cx, left, right)
{
let ctxt = expr.span.ctxt();
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 686eccc..85cabd2 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -1,11 +1,12 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
use rustc_ast::ast::LitKind;
+use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind};
@@ -14,6 +15,7 @@
use rustc_session::impl_lint_pass;
use rustc_span::source_map::Spanned;
use rustc_span::Span;
+use std::iter;
declare_clippy_lint! {
/// ### What it does
@@ -108,19 +110,19 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
format!("stripping a {kind_word} manually"),
|diag| {
diag.span_note(test_span, format!("the {kind_word} was tested here"));
- multispan_sugg(
- diag,
+ diag.multipart_suggestion(
format!("try using the `strip_{kind_word}` method"),
- vec![(
+ iter::once((
test_span,
format!(
"if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
snippet(cx, target_arg.span, ".."),
snippet(cx, pattern.span, "..")
),
- )]
- .into_iter()
- .chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
+ ))
+ .chain(strippings.into_iter().map(|span| (span, "<stripped>".into())))
+ .collect(),
+ Applicability::HasPlaceholders,
);
},
);
@@ -145,7 +147,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E
// Returns the length of the `expr` if it's a constant string or char.
fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
- let value = constant(cx, cx.typeck_results(), expr)?;
+ let value = ConstEvalCtxt::new(cx).eval(expr)?;
match value {
Constant::Str(value) => Some(value.len() as u128),
Constant::Char(value) => Some(value.len_utf8() as u128),
@@ -183,9 +185,9 @@ fn peel_ref<'a>(expr: &'a Expr<'_>) -> &'a Expr<'a> {
}
}
-// Find expressions where `target` is stripped using the length of `pattern`.
-// We'll suggest replacing these expressions with the result of the `strip_{prefix,suffix}`
-// method.
+/// Find expressions where `target` is stripped using the length of `pattern`.
+/// We'll suggest replacing these expressions with the result of the `strip_{prefix,suffix}`
+/// method.
fn find_stripping<'tcx>(
cx: &LateContext<'tcx>,
strip_kind: StripKind,
diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
index f1acc4b..8f8390b 100644
--- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs
@@ -10,7 +10,7 @@
use clippy_utils::higher::IfLetOrMatch;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{in_constant, is_default_equivalent, peel_blocks, span_contains_comment};
+use clippy_utils::{is_default_equivalent, is_in_const_context, peel_blocks, span_contains_comment};
declare_clippy_lint! {
/// ### What it does
@@ -174,7 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, expr)
&& !expr.span.from_expansion()
- && !in_constant(cx, expr.hir_id)
+ && !is_in_const_context(cx)
{
handle(cx, if_let_or_match, expr);
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index 85a08f8..2d4c8da 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::constant_simple;
+use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
@@ -69,7 +69,7 @@ fn check_and_lint<'tcx>(
&& let Some(ty_name) = find_type_name(cx, ty)
&& let Some(or_body_snippet) = snippet_opt(cx, else_expr.span)
&& let Some(indent) = indent_of(cx, expr.span)
- && constant_simple(cx, cx.typeck_results(), else_expr).is_some()
+ && ConstEvalCtxt::new(cx).eval_simple(else_expr).is_some()
{
lint(cx, expr, let_expr, ty_name, or_body_snippet, indent);
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_ref_pats.rs b/src/tools/clippy/clippy_lints/src/matches/match_ref_pats.rs
index aba4c85..5445ee1 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_ref_pats.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_ref_pats.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet, walk_span_to_context};
use clippy_utils::sugg::Sugg;
use core::iter::once;
@@ -54,7 +54,11 @@ pub(crate) fn check<'a, 'b, I>(cx: &LateContext<'_>, scrutinee: &Expr<'_>, pats:
span_lint_and_then(cx, MATCH_REF_PATS, expr.span, title, |diag| {
if !expr.span.from_expansion() {
- multispan_sugg(diag, msg, first_sugg.chain(remaining_suggs));
+ diag.multipart_suggestion(
+ msg,
+ first_sugg.chain(remaining_suggs).collect(),
+ Applicability::MachineApplicable,
+ );
}
});
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
index 8d22ceb..91e40e4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
use rustc_errors::Applicability;
@@ -148,23 +148,27 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
Applicability::MaybeIncorrect,
),
variants => {
- let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
- let message = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
- suggestions.push("_".into());
- "wildcard matches known variants and will also match future added variants"
+ let (message, add_wildcard) = if adt_def.is_variant_list_non_exhaustive() || has_external_hidden {
+ (
+ "wildcard matches known variants and will also match future added variants",
+ true,
+ )
} else {
- "wildcard match will also match any future added variants"
+ ("wildcard match will also match any future added variants", false)
};
- span_lint_and_sugg(
- cx,
- WILDCARD_ENUM_MATCH_ARM,
- wildcard_span,
- message,
- "try",
- suggestions.join(" | "),
- Applicability::MaybeIncorrect,
- );
+ span_lint_and_then(cx, WILDCARD_ENUM_MATCH_ARM, wildcard_span, message, |diag| {
+ let mut suggestions: Vec<_> = variants.iter().copied().map(format_suggestion).collect();
+ if add_wildcard {
+ suggestions.push("_".into());
+ }
+ diag.span_suggestion(
+ wildcard_span,
+ "try",
+ suggestions.join(" | "),
+ Applicability::MaybeIncorrect,
+ );
+ });
},
};
}
@@ -176,9 +180,8 @@ enum CommonPrefixSearcher<'a> {
}
impl<'a> CommonPrefixSearcher<'a> {
fn with_path(&mut self, path: &'a [PathSegment<'a>]) {
- match path {
- [path @ .., _] => self.with_prefix(path),
- [] => (),
+ if let [path @ .., _] = path {
+ self.with_prefix(path);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index 310675d..d0d2025 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -2,7 +2,7 @@
use clippy_utils::macros::{is_panic, root_macro_call};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::is_local_used;
-use clippy_utils::{in_constant, is_wild, peel_blocks_with_stmt};
+use clippy_utils::{is_in_const_context, is_wild, peel_blocks_with_stmt};
use rustc_hir::{Arm, Expr, PatKind};
use rustc_lint::LateContext;
use rustc_span::symbol::{kw, sym};
@@ -11,7 +11,7 @@
pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'tcx>]) {
// `unwrap`/`expect` is not (yet) const, so we want to allow this in const contexts for now
- if in_constant(cx, ex.hir_id) {
+ if is_in_const_context(cx) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index cec3504..cf5377e 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -27,7 +27,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
use clippy_utils::source::walk_span_to_context;
-use clippy_utils::{higher, in_constant, is_direct_expn_of, is_span_match, span_contains_cfg};
+use clippy_utils::{higher, is_direct_expn_of, is_in_const_context, is_span_match, span_contains_cfg};
use rustc_hir::{Arm, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -1069,7 +1069,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
match_str_case_mismatch::check(cx, ex, arms);
redundant_guards::check(cx, arms, &self.msrv);
- if !in_constant(cx, expr.hir_id) {
+ if !is_in_const_context(cx) {
manual_unwrap_or::check_match(cx, expr, ex, arms);
manual_map::check_match(cx, expr, ex, arms);
manual_filter::check_match(cx, ex, arms, expr);
@@ -1098,7 +1098,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
else_expr,
);
}
- if !in_constant(cx, expr.hir_id) {
+ if !is_in_const_context(cx) {
manual_unwrap_or::check_if_let(
cx,
expr,
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 45b375d..71f211b 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, constant_full_int, mir_to_const, FullInt};
+use clippy_utils::consts::{mir_to_const, ConstEvalCtxt, FullInt};
use clippy_utils::diagnostics::span_lint_and_note;
use core::cmp::Ordering;
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
@@ -33,22 +33,20 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
.filter_map(|arm| {
if let Arm { pat, guard: None, .. } = *arm {
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
- let lhs_const = match lhs {
- Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
- None => {
- let min_val_const = ty.numeric_min_val(cx.tcx)?;
- mir_to_const(cx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
- },
+ let lhs_const = if let Some(lhs) = lhs {
+ ConstEvalCtxt::new(cx).eval(lhs)?
+ } else {
+ let min_val_const = ty.numeric_min_val(cx.tcx)?;
+ mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
};
- let rhs_const = match rhs {
- Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
- None => {
- let max_val_const = ty.numeric_max_val(cx.tcx)?;
- mir_to_const(cx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
- },
+ let rhs_const = if let Some(rhs) = rhs {
+ ConstEvalCtxt::new(cx).eval(rhs)?
+ } else {
+ let max_val_const = ty.numeric_max_val(cx.tcx)?;
+ mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
};
- let lhs_val = lhs_const.int_value(cx, ty)?;
- let rhs_val = rhs_const.int_value(cx, ty)?;
+ let lhs_val = lhs_const.int_value(cx.tcx, ty)?;
+ let rhs_val = rhs_const.int_value(cx.tcx, ty)?;
let rhs_bound = match range_end {
RangeEnd::Included => EndBound::Included(rhs_val),
RangeEnd::Excluded => EndBound::Excluded(rhs_val),
@@ -60,7 +58,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
}
if let PatKind::Lit(value) = pat.kind {
- let value = constant_full_int(cx, cx.typeck_results(), value)?;
+ let value = ConstEvalCtxt::new(cx).eval_full_int(value)?;
return Some(SpannedRange {
span: pat.span,
node: (value, EndBound::Included(value)),
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
index c2c0fbf..8222c30 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_guards.rs
@@ -3,7 +3,7 @@
use clippy_utils::macros::matching_root_macro_call;
use clippy_utils::source::snippet;
use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used};
-use clippy_utils::{in_constant, path_to_local};
+use clippy_utils::{is_in_const_context, path_to_local};
use rustc_ast::{BorrowKind, LitKind};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@@ -116,7 +116,7 @@ fn check_method_calls<'tcx>(
// `s if s.is_empty()` becomes ""
// `arr if arr.is_empty()` becomes []
- if ty.is_str() && !in_constant(cx, if_expr.hir_id) {
+ if ty.is_str() && !is_in_const_context(cx) {
r#""""#.into()
} else if slice_like {
"[]".into()
diff --git a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
index 316b2f6..2154cd5 100644
--- a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir::{Pat, PatKind, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty;
@@ -15,13 +15,15 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
&& fields.len() == def.non_enum_variant().fields.len()
&& !def.non_enum_variant().is_field_list_non_exhaustive()
{
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
REST_PAT_IN_FULLY_BOUND_STRUCTS,
pat.span,
"unnecessary use of `..` pattern in struct binding. All fields were already bound",
- None,
- "consider removing `..` from this binding",
+ |diag| {
+ diag.help("consider removing `..` from this binding");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 99fdbcf..24dea03 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -1,12 +1,17 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{expr_block, snippet, SpanRangeExt};
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
-use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs};
-use core::cmp::max;
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{
+ is_lint_allowed, is_unit_expr, peel_blocks, peel_hir_pat_refs, peel_middle_ty_refs, peel_n_hir_expr_refs,
+};
+use core::ops::ControlFlow;
+use rustc_arena::DroplessArena;
use rustc_errors::Applicability;
-use rustc_hir::{Arm, BindingMode, Block, Expr, ExprKind, Pat, PatKind};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::intravisit::{walk_pat, Visitor};
+use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind, QPath};
use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, AdtDef, ParamEnv, TyCtxt, TypeckResults, VariantDef};
use rustc_span::{sym, Span};
use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
@@ -27,52 +32,58 @@ fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool {
}
#[rustfmt::skip]
-pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
- if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() {
- if expr.span.from_expansion() {
- // Don't lint match expressions present in
- // macro_rules! block
- return;
- }
- if let PatKind::Or(..) = arms[0].pat.kind {
- // don't lint for or patterns for now, this makes
- // the lint noisy in unnecessary situations
- return;
- }
- let els = arms[1].body;
- let els = if is_unit_expr(peel_blocks(els)) && !empty_arm_has_comment(cx, els.span) {
+pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>], expr: &'tcx Expr<'_>) {
+ if let [arm1, arm2] = arms
+ && arm1.guard.is_none()
+ && arm2.guard.is_none()
+ && !expr.span.from_expansion()
+ // don't lint for or patterns for now, this makes
+ // the lint noisy in unnecessary situations
+ && !matches!(arm1.pat.kind, PatKind::Or(..))
+ {
+ let els = if is_unit_expr(peel_blocks(arm2.body)) && !empty_arm_has_comment(cx, arm2.body.span) {
None
- } else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind {
- if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() {
+ } else if let ExprKind::Block(block, _) = arm2.body.kind {
+ if matches!((block.stmts, block.expr), ([], Some(_)) | ([_], None)) {
// single statement/expr "else" block, don't lint
return;
}
// block with 2+ statements or 1 expr and 1+ statement
- Some(els)
+ Some(arm2.body)
} else {
// not a block or an empty block w/ comments, don't lint
return;
};
- let ty = cx.typeck_results().expr_ty(ex);
- if (*ty.kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id)) &&
- (check_single_pattern(arms) || check_opt_like(cx, arms, ty)) {
- report_single_pattern(cx, ex, arms, expr, els);
+ let typeck = cx.typeck_results();
+ if *typeck.expr_ty(ex).peel_refs().kind() != ty::Bool || is_lint_allowed(cx, MATCH_BOOL, ex.hir_id) {
+ let mut v = PatVisitor {
+ typeck,
+ has_enum: false,
+ };
+ if v.visit_pat(arm2.pat).is_break() {
+ return;
+ }
+ if v.has_enum {
+ let cx = PatCtxt {
+ tcx: cx.tcx,
+ param_env: cx.param_env,
+ typeck,
+ arena: DroplessArena::default(),
+ };
+ let mut state = PatState::Other;
+ if !(state.add_pat(&cx, arm2.pat) || state.add_pat(&cx, arm1.pat)) {
+ // Don't lint if the pattern contains an enum which doesn't have a wild match.
+ return;
+ }
+ }
+
+ report_single_pattern(cx, ex, arm1, expr, els);
}
}
}
-fn check_single_pattern(arms: &[Arm<'_>]) -> bool {
- is_wild(arms[1].pat)
-}
-
-fn report_single_pattern(
- cx: &LateContext<'_>,
- ex: &Expr<'_>,
- arms: &[Arm<'_>],
- expr: &Expr<'_>,
- els: Option<&Expr<'_>>,
-) {
+fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, expr: &Expr<'_>, els: Option<&Expr<'_>>) {
let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH };
let ctxt = expr.span.ctxt();
let mut app = Applicability::MachineApplicable;
@@ -80,9 +91,9 @@ fn report_single_pattern(
format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app))
});
- let (pat, pat_ref_count) = peel_hir_pat_refs(arms[0].pat);
+ let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
let (msg, sugg) = if let PatKind::Path(_) | PatKind::Lit(_) = pat.kind
- && let (ty, ty_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(ex))
+ && let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))
&& let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait()
&& let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait()
&& (ty.is_integral()
@@ -114,17 +125,17 @@ fn report_single_pattern(
snippet(cx, ex.span, ".."),
// PartialEq for different reference counts may not exist.
"&".repeat(ref_count_diff),
- snippet(cx, arms[0].pat.span, ".."),
- expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
+ snippet(cx, arm.pat.span, ".."),
+ expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app),
);
(msg, sugg)
} else {
let msg = "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`";
let sugg = format!(
"if let {} = {} {}{els_str}",
- snippet(cx, arms[0].pat.span, ".."),
+ snippet(cx, arm.pat.span, ".."),
snippet(cx, ex.span, ".."),
- expr_block(cx, arms[0].body, ctxt, "..", Some(expr.span), &mut app),
+ expr_block(cx, arm.body, ctxt, "..", Some(expr.span), &mut app),
);
(msg, sugg)
};
@@ -132,106 +143,227 @@ fn report_single_pattern(
span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app);
}
-fn check_opt_like<'a>(cx: &LateContext<'a>, arms: &[Arm<'_>], ty: Ty<'a>) -> bool {
- // We don't want to lint if the second arm contains an enum which could
- // have more variants in the future.
- form_exhaustive_matches(cx, ty, arms[0].pat, arms[1].pat)
+struct PatVisitor<'tcx> {
+ typeck: &'tcx TypeckResults<'tcx>,
+ has_enum: bool,
}
-
-/// Returns `true` if all of the types in the pattern are enums which we know
-/// won't be expanded in the future
-fn pat_in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'a>, pat: &Pat<'_>) -> bool {
- let mut paths_and_types = Vec::new();
- collect_pat_paths(&mut paths_and_types, cx, pat, ty);
- paths_and_types.iter().all(|ty| in_candidate_enum(cx, *ty))
-}
-
-/// Returns `true` if the given type is an enum we know won't be expanded in the future
-fn in_candidate_enum(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
- // list of candidate `Enum`s we know will never get any more members
- let candidates = [sym::Cow, sym::Option, sym::Result];
-
- for candidate_ty in candidates {
- if is_type_diagnostic_item(cx, ty, candidate_ty) {
- return true;
+impl<'tcx> Visitor<'tcx> for PatVisitor<'tcx> {
+ type Result = ControlFlow<()>;
+ fn visit_pat(&mut self, pat: &'tcx Pat<'_>) -> Self::Result {
+ if matches!(pat.kind, PatKind::Binding(..)) {
+ ControlFlow::Break(())
+ } else {
+ self.has_enum |= self.typeck.pat_ty(pat).ty_adt_def().map_or(false, AdtDef::is_enum);
+ walk_pat(self, pat)
}
}
- false
}
-/// Collects types from the given pattern
-fn collect_pat_paths<'a>(acc: &mut Vec<Ty<'a>>, cx: &LateContext<'a>, pat: &Pat<'_>, ty: Ty<'a>) {
- match pat.kind {
- PatKind::Tuple(inner, _) => inner.iter().for_each(|p| {
- let p_ty = cx.typeck_results().pat_ty(p);
- collect_pat_paths(acc, cx, p, p_ty);
- }),
- PatKind::TupleStruct(..) | PatKind::Binding(BindingMode::NONE, .., None) | PatKind::Path(_) => {
- acc.push(ty);
- },
- _ => {},
+/// The context needed to manipulate a `PatState`.
+struct PatCtxt<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ typeck: &'tcx TypeckResults<'tcx>,
+ arena: DroplessArena,
+}
+
+/// State for tracking whether a match can become non-exhaustive by adding a variant to a contained
+/// enum.
+///
+/// This treats certain std enums as if they will never be extended.
+enum PatState<'a> {
+ /// Either a wild match or an uninteresting type. Uninteresting types include:
+ /// * builtin types (e.g. `i32` or `!`)
+ /// * A struct/tuple/array containing only uninteresting types.
+ /// * A std enum containing only uninteresting types.
+ Wild,
+ /// A std enum we know won't be extended. Tracks the states of each variant separately.
+ ///
+ /// This is not used for `Option` since it uses the current pattern to track it's state.
+ StdEnum(&'a mut [PatState<'a>]),
+ /// Either the initial state for a pattern or a non-std enum. There is currently no need to
+ /// distinguish these cases.
+ ///
+ /// For non-std enums there's no need to track the state of sub-patterns as the state of just
+ /// this pattern on it's own is enough for linting. Consider two cases:
+ /// * This enum has no wild match. This case alone is enough to determine we can lint.
+ /// * This enum has a wild match and therefore all sub-patterns also have a wild match.
+ ///
+ /// In both cases the sub patterns are not needed to determine whether to lint.
+ Other,
+}
+impl<'a> PatState<'a> {
+ /// Adds a set of patterns as a product type to the current state. Returns whether or not the
+ /// current state is a wild match after the merge.
+ fn add_product_pat<'tcx>(
+ &mut self,
+ cx: &'a PatCtxt<'tcx>,
+ pats: impl IntoIterator<Item = &'tcx Pat<'tcx>>,
+ ) -> bool {
+ // Ideally this would actually keep track of the state separately for each pattern. Doing so would
+ // require implementing something similar to exhaustiveness checking which is a significant increase
+ // in complexity.
+ //
+ // For now treat this as a wild match only if all the sub-patterns are wild
+ let is_wild = pats.into_iter().all(|p| {
+ let mut state = Self::Other;
+ state.add_pat(cx, p)
+ });
+ if is_wild {
+ *self = Self::Wild;
+ }
+ is_wild
}
-}
-/// Returns true if the given arm of pattern matching contains wildcard patterns.
-fn contains_only_wilds(pat: &Pat<'_>) -> bool {
- match pat.kind {
- PatKind::Wild => true,
- PatKind::Tuple(inner, _) | PatKind::TupleStruct(_, inner, ..) => inner.iter().all(contains_only_wilds),
- _ => false,
+ /// Attempts to get the state for the enum variant, initializing the current state if necessary.
+ fn get_std_enum_variant<'tcx>(
+ &mut self,
+ cx: &'a PatCtxt<'tcx>,
+ adt: AdtDef<'tcx>,
+ path: &'tcx QPath<'_>,
+ hir_id: HirId,
+ ) -> Option<(&mut Self, &'tcx VariantDef)> {
+ let states = match self {
+ Self::Wild => return None,
+ Self::Other => {
+ *self = Self::StdEnum(cx.arena.alloc_from_iter((0..adt.variants().len()).map(|_| Self::Other)));
+ let Self::StdEnum(x) = self else {
+ unreachable!();
+ };
+ x
+ },
+ Self::StdEnum(x) => x,
+ };
+ let i = match cx.typeck.qpath_res(path, hir_id) {
+ Res::Def(DefKind::Ctor(..), id) => adt.variant_index_with_ctor_id(id),
+ Res::Def(DefKind::Variant, id) => adt.variant_index_with_id(id),
+ _ => return None,
+ };
+ Some((&mut states[i.as_usize()], adt.variant(i)))
}
-}
-/// Returns true if the given patterns forms only exhaustive matches that don't contain enum
-/// patterns without a wildcard.
-fn form_exhaustive_matches<'a>(cx: &LateContext<'a>, ty: Ty<'a>, left: &Pat<'_>, right: &Pat<'_>) -> bool {
- match (&left.kind, &right.kind) {
- (PatKind::Wild, _) | (_, PatKind::Wild) => true,
- (PatKind::Tuple(left_in, left_pos), PatKind::Tuple(right_in, right_pos)) => {
- // We don't actually know the position and the presence of the `..` (dotdot) operator
- // in the arms, so we need to evaluate the correct offsets here in order to iterate in
- // both arms at the same time.
- let left_pos = left_pos.as_opt_usize();
- let right_pos = right_pos.as_opt_usize();
- let len = max(
- left_in.len() + usize::from(left_pos.is_some()),
- right_in.len() + usize::from(right_pos.is_some()),
- );
- let mut left_pos = left_pos.unwrap_or(usize::MAX);
- let mut right_pos = right_pos.unwrap_or(usize::MAX);
- let mut left_dot_space = 0;
- let mut right_dot_space = 0;
- for i in 0..len {
- let mut found_dotdot = false;
- if i == left_pos {
- left_dot_space += 1;
- if left_dot_space < len - left_in.len() {
- left_pos += 1;
- }
- found_dotdot = true;
- }
- if i == right_pos {
- right_dot_space += 1;
- if right_dot_space < len - right_in.len() {
- right_pos += 1;
- }
- found_dotdot = true;
- }
- if found_dotdot {
- continue;
- }
- if !contains_only_wilds(&left_in[i - left_dot_space])
- && !contains_only_wilds(&right_in[i - right_dot_space])
- {
- return false;
- }
- }
+ fn check_all_wild_enum(&mut self) -> bool {
+ if let Self::StdEnum(states) = self
+ && states.iter().all(|s| matches!(s, Self::Wild))
+ {
+ *self = Self::Wild;
true
- },
- (PatKind::TupleStruct(..), PatKind::Path(_)) => pat_in_candidate_enum(cx, ty, right),
- (PatKind::TupleStruct(..), PatKind::TupleStruct(_, inner, _)) => {
- pat_in_candidate_enum(cx, ty, right) && inner.iter().all(contains_only_wilds)
- },
- _ => false,
+ } else {
+ false
+ }
+ }
+
+ #[expect(clippy::similar_names)]
+ fn add_struct_pats<'tcx>(
+ &mut self,
+ cx: &'a PatCtxt<'tcx>,
+ pat: &'tcx Pat<'tcx>,
+ path: &'tcx QPath<'tcx>,
+ single_pat: Option<&'tcx Pat<'tcx>>,
+ pats: impl IntoIterator<Item = &'tcx Pat<'tcx>>,
+ ) -> bool {
+ let ty::Adt(adt, _) = *cx.typeck.pat_ty(pat).kind() else {
+ // Should never happen
+ *self = Self::Wild;
+ return true;
+ };
+ if adt.is_struct() {
+ return if let Some(pat) = single_pat
+ && adt.non_enum_variant().fields.len() == 1
+ {
+ self.add_pat(cx, pat)
+ } else {
+ self.add_product_pat(cx, pats)
+ };
+ }
+ match cx.tcx.get_diagnostic_name(adt.did()) {
+ Some(sym::Option) => {
+ if let Some(pat) = single_pat {
+ self.add_pat(cx, pat)
+ } else {
+ *self = Self::Wild;
+ true
+ }
+ },
+ Some(sym::Result | sym::Cow) => {
+ let Some((state, variant)) = self.get_std_enum_variant(cx, adt, path, pat.hir_id) else {
+ return matches!(self, Self::Wild);
+ };
+ let is_wild = if let Some(pat) = single_pat
+ && variant.fields.len() == 1
+ {
+ state.add_pat(cx, pat)
+ } else {
+ state.add_product_pat(cx, pats)
+ };
+ is_wild && self.check_all_wild_enum()
+ },
+ _ => matches!(self, Self::Wild),
+ }
+ }
+
+ /// Adds the pattern into the current state. Returns whether or not the current state is a wild
+ /// match after the merge.
+ #[expect(clippy::similar_names)]
+ fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
+ match pat.kind {
+ PatKind::Path(_)
+ if match *cx.typeck.pat_ty(pat).peel_refs().kind() {
+ ty::Adt(adt, _) => adt.is_enum() || (adt.is_struct() && !adt.non_enum_variant().fields.is_empty()),
+ ty::Tuple(tys) => !tys.is_empty(),
+ ty::Array(_, len) => len.try_eval_target_usize(cx.tcx, cx.param_env) != Some(1),
+ ty::Slice(..) => true,
+ _ => false,
+ } =>
+ {
+ matches!(self, Self::Wild)
+ },
+
+ // Patterns for things which can only contain a single sub-pattern.
+ PatKind::Binding(_, _, _, Some(pat)) | PatKind::Ref(pat, _) | PatKind::Box(pat) | PatKind::Deref(pat) => {
+ self.add_pat(cx, pat)
+ },
+ PatKind::Tuple([sub_pat], pos)
+ if pos.as_opt_usize().is_none() || cx.typeck.pat_ty(pat).tuple_fields().len() == 1 =>
+ {
+ self.add_pat(cx, sub_pat)
+ },
+ PatKind::Slice([sub_pat], _, []) | PatKind::Slice([], _, [sub_pat])
+ if let ty::Array(_, len) = *cx.typeck.pat_ty(pat).kind()
+ && len.try_eval_target_usize(cx.tcx, cx.param_env) == Some(1) =>
+ {
+ self.add_pat(cx, sub_pat)
+ },
+
+ PatKind::Or(pats) => pats.iter().any(|p| self.add_pat(cx, p)),
+ PatKind::Tuple(pats, _) => self.add_product_pat(cx, pats),
+ PatKind::Slice(head, _, tail) => self.add_product_pat(cx, head.iter().chain(tail)),
+
+ PatKind::TupleStruct(ref path, pats, _) => self.add_struct_pats(
+ cx,
+ pat,
+ path,
+ if let [pat] = pats { Some(pat) } else { None },
+ pats.iter(),
+ ),
+ PatKind::Struct(ref path, pats, _) => self.add_struct_pats(
+ cx,
+ pat,
+ path,
+ if let [pat] = pats { Some(pat.pat) } else { None },
+ pats.iter().map(|p| p.pat),
+ ),
+
+ PatKind::Wild
+ | PatKind::Binding(_, _, _, None)
+ | PatKind::Lit(_)
+ | PatKind::Range(..)
+ | PatKind::Path(_)
+ | PatKind::Never
+ | PatKind::Err(_) => {
+ *self = PatState::Wild;
+ true
+ },
+ }
}
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
index dd489fc..b7ffa8b 100644
--- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{get_parent_expr, is_res_lang_ctor, path_res};
@@ -48,29 +48,28 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
return;
};
- let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
- let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
- let mut applicability = Applicability::MachineApplicable;
- let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
- let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
- "" // already returns
- } else {
- "return "
- };
- let suggestion = if err_ty == expr_err_ty {
- format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
- } else {
- format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
- };
-
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
TRY_ERR,
expr.span,
"returning an `Err(_)` with the `?` operator",
- "try",
- suggestion,
- applicability,
+ |diag| {
+ let expr_err_ty = cx.typeck_results().expr_ty(err_arg);
+ let span = hygiene::walk_chain(err_arg.span, try_arg.span.ctxt());
+ let mut applicability = Applicability::MachineApplicable;
+ let origin_snippet = snippet_with_applicability(cx, span, "_", &mut applicability);
+ let ret_prefix = if get_parent_expr(cx, expr).map_or(false, |e| matches!(e.kind, ExprKind::Ret(_))) {
+ "" // already returns
+ } else {
+ "return "
+ };
+ let suggestion = if err_ty == expr_err_ty {
+ format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
+ } else {
+ format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
+ };
+ diag.span_suggestion(expr.span, "try", suggestion, applicability);
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 20f3722..2a8a5fc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -1,5 +1,5 @@
use super::{contains_return, BIND_INSTEAD_OF_MAP};
-use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::peel_blocks;
use clippy_utils::source::{snippet, snippet_with_context};
use clippy_utils::visitors::find_all_ret_expressions;
@@ -136,15 +136,16 @@ fn lint_closure(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>, closure_expr:
return false;
};
span_lint_and_then(cx, BIND_INSTEAD_OF_MAP, expr.span, msg, |diag| {
- multispan_sugg_with_applicability(
- diag,
- "try",
+ diag.multipart_suggestion(
+ format!("use `{}` instead", self.good_method_name),
+ std::iter::once((span, self.good_method_name.into()))
+ .chain(
+ suggs
+ .into_iter()
+ .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
+ )
+ .collect(),
Applicability::MachineApplicable,
- std::iter::once((span, self.good_method_name.into())).chain(
- suggs
- .into_iter()
- .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
- ),
);
});
true
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
index 926bd06..e0826b5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_context;
use rustc_errors::Applicability;
use rustc_hir as hir;
@@ -29,19 +29,22 @@ pub(super) fn check(
sym::RcWeak | sym::ArcWeak => "Weak",
_ => return,
};
-
- // Sometimes unnecessary ::<_> after Rc/Arc/Weak
- let mut app = Applicability::Unspecified;
- let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0;
-
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
CLONE_ON_REF_PTR,
expr.span,
"using `.clone()` on a ref-counted pointer",
- "try",
- format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
- app,
+ |diag| {
+ // Sometimes unnecessary ::<_> after Rc/Arc/Weak
+ let mut app = Applicability::Unspecified;
+ let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0;
+ diag.span_suggestion(
+ expr.span,
+ "try",
+ format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
+ app,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
index eab536b..2ab0401 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_parent_expr;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir as hir;
@@ -33,6 +33,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
span = expr.span;
}
let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files");
- let help_msg = format!("use `{help_unary}FileType::is_dir()` instead");
- span_lint_and_help(cx, FILETYPE_IS_FILE, span, lint_msg, None, help_msg);
+
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, FILETYPE_IS_FILE, span, lint_msg, |diag| {
+ diag.help(format!("use `{help_unary}FileType::is_dir()` instead"));
+ });
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
index 455274a..c6285c8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
@@ -1,5 +1,5 @@
use super::utils::derefs_to_slice;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_parent_expr;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
@@ -19,9 +19,7 @@ pub(super) fn check<'tcx>(
) {
// Note: we don't want to lint `get_mut().unwrap` for `HashMap` or `BTreeMap`,
// because they do not implement `IndexMut`
- let mut applicability = Applicability::MachineApplicable;
let expr_ty = cx.typeck_results().expr_ty(recv);
- let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability);
let caller_type = if derefs_to_slice(cx, recv, expr_ty).is_some() {
"slice"
} else if is_type_diagnostic_item(cx, expr_ty, sym::Vec) {
@@ -58,24 +56,34 @@ pub(super) fn check<'tcx>(
};
let mut_str = if is_mut { "_mut" } else { "" };
- let borrow_str = if !needs_ref {
- ""
- } else if is_mut {
- "&mut "
- } else {
- "&"
- };
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
GET_UNWRAP,
span,
- format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
- "try",
- format!(
- "{borrow_str}{}[{get_args_str}]",
- snippet_with_applicability(cx, recv.span, "..", &mut applicability)
- ),
- applicability,
+ format!("called `.get{mut_str}().unwrap()` on a {caller_type}"),
+ |diag| {
+ let mut applicability = Applicability::MachineApplicable;
+ let get_args_str = snippet_with_applicability(cx, get_arg.span, "..", &mut applicability);
+
+ let borrow_str = if !needs_ref {
+ ""
+ } else if is_mut {
+ "&mut "
+ } else {
+ "&"
+ };
+
+ diag.span_suggestion_with_style(
+ span,
+ "using `[]` is clearer and more concise",
+ format!(
+ "{borrow_str}{}[{get_args_str}]",
+ snippet_with_applicability(cx, recv.span, "..", &mut applicability)
+ ),
+ applicability,
+ rustc_errors::SuggestionStyle::ShowAlways,
+ );
+ },
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index c510cd9..5190914 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::{implements_trait, peel_mid_ty_refs};
-use clippy_utils::{is_diag_item_method, is_diag_trait_item};
+use clippy_utils::ty::implements_trait;
+use clippy_utils::{is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@@ -14,7 +14,7 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
&& is_clone_like(cx, method_name, method_def_id)
&& let return_type = cx.typeck_results().expr_ty(expr)
&& let input_type = cx.typeck_results().expr_ty(recv)
- && let (input_type, ref_count) = peel_mid_ty_refs(input_type)
+ && let (input_type, ref_count) = peel_middle_ty_refs(input_type)
&& !(ref_count > 0 && is_diag_trait_item(cx, method_def_id, sym::ToOwned))
&& let Some(ty_name) = input_type.ty_adt_def().map(|adt_def| cx.tcx.item_name(adt_def.did()))
&& return_type == input_type
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
index 210e4ae..22d8964 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
@@ -2,7 +2,7 @@
use super::IS_DIGIT_ASCII_RADIX;
use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::consts::{constant_full_int, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
@@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(
return;
}
- if let Some(radix_val) = constant_full_int(cx, cx.typeck_results(), radix) {
+ if let Some(radix_val) = ConstEvalCtxt::new(cx).eval_full_int(radix) {
let (num, replacement) = match radix_val {
FullInt::S(10) | FullInt::U(10) => (10, "is_ascii_digit"),
FullInt::S(16) | FullInt::U(16) => (16, "is_ascii_hexdigit"),
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
index d921b7e..cc82f6c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_empty.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::constant_is_empty;
+use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{find_binding_init, path_to_local};
use rustc_hir::{Expr, HirId};
@@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
if !receiver.span.eq_ctxt(init_expr.span) {
return;
}
- if let Some(init_is_empty) = constant_is_empty(cx, init_expr) {
+ if let Some(init_is_empty) = ConstEvalCtxt::new(cx).eval_is_empty(init_expr) {
span_lint(
cx,
CONST_IS_EMPTY,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
index 05e7738..33de3b8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -1,15 +1,12 @@
-#![allow(unused_imports)]
-
use super::ITER_KV_MAP;
use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::pat_is_wild;
+use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{pat_is_wild, sugg};
-use rustc_hir::{BindingMode, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
-use rustc_lint::{LateContext, LintContext};
-use rustc_middle::ty;
-use rustc_span::{sym, Span};
+use rustc_hir::{Body, Expr, ExprKind, PatKind};
+use rustc_lint::LateContext;
+use rustc_span::sym;
/// lint use of:
///
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index 262a57a..9ff6eaa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_lang_item_or_ctor, is_trait_method};
@@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
if let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id))
&& let def_id = item.owner_id.to_def_id()
&& is_trait_method(cx, expr, sym::Iterator)
- && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg)
+ && let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg)
&& !is_lang_item_or_ctor(cx, def_id, LangItem::IteratorNext)
{
let mut app = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_zero.rs
index 6b696b4..39e440e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_zero.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{is_from_proc_macro, is_trait_method};
use rustc_errors::Applicability;
@@ -11,7 +11,7 @@
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg_expr: &Expr<'_>) {
if !expr.span.from_expansion()
&& is_trait_method(cx, expr, sym::Iterator)
- && let Some(arg) = constant(cx, cx.typeck_results(), arg_expr).and_then(|constant| {
+ && let Some(arg) = ConstEvalCtxt::new(cx).eval(arg_expr).and_then(|constant| {
if let Constant::Int(arg) = constant {
Some(arg)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index b631cd0..9b35823 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_trait_method;
use rustc_hir as hir;
@@ -9,7 +9,7 @@
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
if is_trait_method(cx, expr, sym::Iterator) {
- if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) {
+ if let Some(Constant::Int(0)) = ConstEvalCtxt::new(cx).eval(arg) {
span_lint(
cx,
ITERATOR_STEP_BY_ZERO,
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index a5ba5e5..08ce7e2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -2,10 +2,10 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item, should_call_clone_as_function};
-use clippy_utils::{is_diag_trait_item, match_def_path, paths, peel_blocks};
+use clippy_utils::{is_diag_trait_item, peel_blocks};
use rustc_errors::Applicability;
-use rustc_hir as hir;
use rustc_hir::def_id::DefId;
+use rustc_hir::{self as hir, LangItem};
use rustc_lint::LateContext;
use rustc_middle::mir::Mutability;
use rustc_middle::ty;
@@ -114,7 +114,7 @@ fn handle_path(
recv: &hir::Expr<'_>,
) {
if let Some(path_def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
- && match_def_path(cx, path_def_id, &paths::CLONE_TRAIT_METHOD)
+ && cx.tcx.lang_items().get(LangItem::CloneFn) == Some(path_def_id)
{
// The `copied` and `cloned` methods are only available on `&T` and `&mut T` in `Option`
// and `Result`.
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
index fbb83c8..162f0ac 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_err_ignore.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir::{CaptureBy, Closure, Expr, ExprKind, PatKind};
use rustc_lint::LateContext;
@@ -22,13 +22,17 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, arg: &Expr<'_>) {
{
// span the area of the closure capture and warn that the
// original error will be thrown away
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
MAP_ERR_IGNORE,
fn_decl_span,
"`map_err(|_|...` wildcard pattern discards the original error",
- None,
- "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
+ |diag| {
+ diag.help(
+ "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index aa4cad9..1d7b10f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -133,7 +133,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::macros::FormatArgsStorage;
use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
@@ -749,7 +749,6 @@
///
/// ### Example
/// ```no_run
- /// # #![allow(unused)]
/// (0_i32..10)
/// .filter(|n| n.checked_add(1).is_some())
/// .map(|n| n.checked_add(1).unwrap());
@@ -757,7 +756,6 @@
///
/// Use instead:
/// ```no_run
- /// # #[allow(unused)]
/// (0_i32..10).filter_map(|n| n.checked_add(1));
/// ```
#[clippy::version = "1.51.0"]
@@ -850,7 +848,6 @@
///
/// ### Example
/// ```no_run
- /// # #![allow(unused)]
/// let vec = vec![1];
/// vec.iter().find(|x| **x == 0).is_some();
///
@@ -862,7 +859,6 @@
/// let vec = vec![1];
/// vec.iter().any(|x| *x == 0);
///
- /// # #[allow(unused)]
/// !"hello world".contains("world");
/// ```
#[clippy::version = "pre 1.29.0"]
@@ -1505,7 +1501,6 @@
///
/// ### Example
/// ```no_run
- /// # #[allow(unused)]
/// (0..3).fold(false, |acc, x| acc || x > 2);
/// ```
///
@@ -1897,7 +1892,9 @@
/// trait.
///
/// ### Why is this bad?
- /// It is recommended style to use collect. See
+ /// If it's needed to create a collection from the contents of an iterator, the `Iterator::collect(_)`
+ /// method is preferred. However, when it's needed to specify the container type,
+ /// `Vec::from_iter(_)` can be more readable than using a turbofish (e.g. `_.collect::<Vec<_>>()`). See
/// [FromIterator documentation](https://doc.rust-lang.org/std/iter/trait.FromIterator.html)
///
/// ### Example
@@ -1916,6 +1913,14 @@
///
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
+ /// but prefer to use
+ /// ```no_run
+ /// let numbers: Vec<i32> = FromIterator::from_iter(1..=5);
+ /// ```
+ /// instead of
+ /// ```no_run
+ /// let numbers = (1..=5).collect::<Vec<_>>();
+ /// ```
#[clippy::version = "1.49.0"]
pub FROM_ITER_INSTEAD_OF_COLLECT,
pedantic,
@@ -2008,13 +2013,11 @@
///
/// ### Example
/// ```no_run
- /// # #[allow(unused)]
/// "Hello".bytes().nth(3);
/// ```
///
/// Use instead:
/// ```no_run
- /// # #[allow(unused)]
/// "Hello".as_bytes().get(3);
/// ```
#[clippy::version = "1.52.0"]
@@ -2059,7 +2062,6 @@
///
/// ### Example
/// ```no_run
- /// # #![allow(unused)]
/// let some_vec = vec![0, 1, 2, 3];
///
/// some_vec.iter().count();
@@ -3656,7 +3658,6 @@
///
/// ### Example
/// ```no_run
- /// # #![allow(unused)]
/// let owned_string = "This is a string".to_owned();
/// owned_string.as_str().as_bytes()
/// # ;
@@ -3664,7 +3665,6 @@
///
/// Use instead:
/// ```no_run
- /// # #![allow(unused)]
/// let owned_string = "This is a string".to_owned();
/// owned_string.as_bytes()
/// # ;
@@ -4915,13 +4915,13 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
str_split::check(cx, expr, recv, arg);
},
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
- if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
+ if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) {
suspicious_splitn::check(cx, name, expr, recv, count);
str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
}
},
("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
- if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
+ if let Some(Constant::Int(count)) = ConstEvalCtxt::new(cx).eval(count_arg) {
suspicious_splitn::check(cx, name, expr, recv, count);
}
},
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index d425b50..cbeb48b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -151,7 +151,7 @@ fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, S
cx,
NONSENSICAL_OPEN_OPTIONS,
prev_span,
- format!("the method `{}` is called more than once", &option),
+ format!("the method `{option}` is called more than once"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
index bb4cdd2..7837517 100644
--- a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_lang_item;
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(
recv: &'tcx Expr<'_>,
repeat_arg: &'tcx Expr<'_>,
) {
- if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) {
+ if ConstEvalCtxt::new(cx).eval(repeat_arg) == Some(Constant::Int(1)) {
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
if ty.is_str() {
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 4f42fb7..12cabd4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -1,5 +1,5 @@
use clippy_config::msrvs::{self, Msrv};
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_context;
use clippy_utils::usage::local_used_after_expr;
@@ -301,7 +301,7 @@ fn parse_iter_usage<'tcx>(
};
},
("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
- if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
+ if let Some(Constant::Int(idx)) = ConstEvalCtxt::new(cx).eval(idx_expr) {
let span = if name.ident.as_str() == "nth" {
e.span
} else if let Some((_, Node::Expr(next_expr))) = iter.next()
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
index 78851d4..86c0a63 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_min_or_max.rs
@@ -3,7 +3,7 @@
use super::UNNECESSARY_MIN_OR_MAX;
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::consts::{constant, constant_with_source, Constant, ConstantSource, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, Constant, ConstantSource, FullInt};
use clippy_utils::source::snippet;
use rustc_errors::Applicability;
@@ -20,10 +20,9 @@ pub(super) fn check<'tcx>(
arg: &'tcx Expr<'_>,
) {
let typeck_results = cx.typeck_results();
- if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) =
- constant_with_source(cx, typeck_results, recv)
- && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) =
- constant_with_source(cx, typeck_results, arg)
+ let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck_results);
+ if let Some((left, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(recv)
+ && let Some((right, ConstantSource::Local | ConstantSource::CoreConstant)) = ecx.eval_with_source(arg)
{
let Some(ord) = Constant::partial_cmp(cx.tcx, typeck_results.expr_ty(recv), &left, &right) else {
return;
@@ -78,9 +77,9 @@ enum Extrema {
fn detect_extrema<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Extrema> {
let ty = cx.typeck_results().expr_ty(expr);
- let cv = constant(cx, cx.typeck_results(), expr)?;
+ let cv = ConstEvalCtxt::new(cx).eval(expr)?;
- match (cv.int_value(cx, ty)?, ty.kind()) {
+ match (cv.int_value(cx.tcx, ty)?, ty.kind()) {
(FullInt::S(i), &ty::Int(ity)) if i == i128::MIN >> (128 - ity.bit_width()?) => Some(Extrema::Minimum),
(FullInt::S(i), &ty::Int(ity)) if i == i128::MAX >> (128 - ity.bit_width()?) => Some(Extrema::Maximum),
(FullInt::U(i), &ty::Uint(uty)) if i == u128::MAX >> (128 - uty.bit_width()?) => Some(Extrema::Maximum),
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 5d899415..fed2b12 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -3,12 +3,11 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_opt};
-use clippy_utils::ty::{
- get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item, peel_mid_ty_refs,
-};
+use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{
- fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, return_ty,
+ fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, peel_middle_ty_refs,
+ return_ty,
};
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
@@ -120,8 +119,8 @@ fn check_addr_of_expr(
},
] = adjustments[..]
&& let receiver_ty = cx.typeck_results().expr_ty(receiver)
- && let (target_ty, n_target_refs) = peel_mid_ty_refs(*target_ty)
- && let (receiver_ty, n_receiver_refs) = peel_mid_ty_refs(receiver_ty)
+ && let (target_ty, n_target_refs) = peel_middle_ty_refs(*target_ty)
+ && let (receiver_ty, n_receiver_refs) = peel_middle_ty_refs(receiver_ty)
// Only flag cases satisfying at least one of the following three conditions:
// * the referent and receiver types are distinct
// * the referent/receiver type is a copyable array
@@ -382,7 +381,7 @@ fn check_other_call_arg<'tcx>(
&& let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder()
&& let Some(i) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == maybe_arg.hir_id)
&& let Some(input) = fn_sig.inputs().get(i)
- && let (input, n_refs) = peel_mid_ty_refs(*input)
+ && let (input, n_refs) = peel_middle_ty_refs(*input)
&& let (trait_predicates, _) = get_input_traits_and_projections(cx, callee_def_id, input)
&& let Some(sized_def_id) = cx.tcx.lang_items().sized_trait()
&& let [trait_predicate] = trait_predicates
diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
index 8b8a965..3004d9c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_hir_and_then};
+use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::{snippet, snippet_opt};
use clippy_utils::{expr_or_init, is_trait_method, pat_is_wild};
use rustc_errors::Applicability;
@@ -97,10 +97,8 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
enumerate_span,
"you seem to use `.enumerate()` and immediately discard the index",
|diag| {
- multispan_sugg_with_applicability(
- diag,
+ diag.multipart_suggestion(
"remove the `.enumerate()` call",
- Applicability::MachineApplicable,
vec![
(closure_param.span, new_closure_param),
(
@@ -108,6 +106,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
String::new(),
),
],
+ Applicability::MachineApplicable,
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index ae2b6e6..ebad4ae 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -2,10 +2,10 @@
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{should_call_clone_as_function, walk_ptrs_ty_depth};
use clippy_utils::{
- get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, paths, peel_blocks, strip_pat_refs,
+ get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, peel_blocks, strip_pat_refs,
};
use rustc_errors::Applicability;
-use rustc_hir as hir;
+use rustc_hir::{self as hir, LangItem};
use rustc_lint::LateContext;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -104,7 +104,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
fn check_qpath(cx: &LateContext<'_>, qpath: hir::QPath<'_>, hir_id: hir::HirId) -> bool {
// We check it's calling the `clone` method of the `Clone` trait.
if let Some(path_def_id) = cx.qpath_res(&qpath, hir_id).opt_def_id() {
- match_def_path(cx, path_def_id, &paths::CLONE_TRAIT_METHOD)
+ cx.tcx.lang_items().get(LangItem::CloneFn) == Some(path_def_id)
} else {
false
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/methods/verbose_file_reads.rs
index 181b413..8ed6163 100644
--- a/src/tools/clippy/clippy_lints/src/methods/verbose_file_reads.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/verbose_file_reads.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_trait_method;
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir::{Expr, ExprKind, QPath};
@@ -23,6 +23,9 @@ pub(super) fn check<'tcx>(
&& matches!(recv.kind, ExprKind::Path(QPath::Resolved(None, _)))
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty_adjusted(recv).peel_refs(), sym::File)
{
- span_lint_and_help(cx, VERBOSE_FILE_READS, expr.span, msg, None, help);
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, VERBOSE_FILE_READS, expr.span, msg, |diag| {
+ diag.help(help);
+ });
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
index 28068c6..7384e53 100644
--- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
@@ -127,7 +127,7 @@ pub(super) fn check<'tcx>(
.collect::<Vec<_>>()
.join(" and ");
- format!("methods with the following characteristics: ({})", &s)
+ format!("methods with the following characteristics: ({s})")
} else {
format!("methods called {}", &conventions[0])
}
diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs
index c3fbca1..e95864c 100644
--- a/src/tools/clippy/clippy_lints/src/minmax.rs
+++ b/src/tools/clippy/clippy_lints/src/minmax.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::is_trait_method;
use rustc_hir::{Expr, ExprKind};
@@ -106,15 +106,11 @@ fn fetch_const<'a, 'tcx>(
if args.next().is_some() {
return None;
}
- constant_simple(cx, cx.typeck_results(), first_arg).map_or_else(
- || constant_simple(cx, cx.typeck_results(), second_arg).map(|c| (m, c, first_arg)),
- |c| {
- if constant_simple(cx, cx.typeck_results(), second_arg).is_none() {
- // otherwise ignore
- Some((m, c, second_arg))
- } else {
- None
- }
- },
- )
+ let ecx = ConstEvalCtxt::new(cx);
+ match (ecx.eval_simple(first_arg), ecx.eval_simple(second_arg)) {
+ (Some(c), None) => Some((m, c, second_arg)),
+ (None, Some(c)) => Some((m, c, first_arg)),
+ // otherwise ignore
+ _ => None,
+ }
}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
index e0a5e40..2246799 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_lint::EarlyContext;
use rustc_span::Span;
@@ -12,24 +12,36 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi
// Do not lint when literal is unsuffixed.
if !suffix.is_empty() {
if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
SEPARATED_LITERAL_SUFFIX,
lit_span,
format!("{sugg_type} type suffix should not be separated by an underscore"),
- "remove the underscore",
- format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion(
+ lit_span,
+ "remove the underscore",
+ format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
+ Applicability::MachineApplicable,
+ );
+ },
);
} else {
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
UNSEPARATED_LITERAL_SUFFIX,
lit_span,
format!("{sugg_type} type suffix should be separated by an underscore"),
- "add an underscore",
- format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion(
+ lit_span,
+ "add an underscore",
+ format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
+ Applicability::MachineApplicable,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
index cb305cf..6db03ad 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Pat, PatKind};
use rustc_lint::EarlyContext;
@@ -21,13 +21,15 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
}
}
if !pfields.is_empty() && wilds == pfields.len() {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
UNNEEDED_FIELD_PATTERN,
pat.span,
"all the struct fields are matched to a wildcard pattern, consider using `..`",
- None,
- format!("try with `{type_name} {{ .. }}` instead"),
+ |diag| {
+ diag.help(format!("try with `{type_name} {{ .. }}` instead"));
+ },
);
return;
}
@@ -56,14 +58,15 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
}
}
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
UNNEEDED_FIELD_PATTERN,
field.span,
- "you matched a field with a wildcard pattern, consider using `..` \
- instead",
- None,
- format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
+ "you matched a field with a wildcard pattern, consider using `..` instead",
+ |diag| {
+ diag.help(format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")));
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
index 935ed48..a9ea11f 100644
--- a/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_assert_message.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_in_test;
use clippy_utils::macros::{find_assert_args, find_assert_eq_args, root_macro_call_first_node, PanicExpn};
use rustc_hir::Expr;
@@ -79,13 +79,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
};
if let PanicExpn::Empty = panic_expn {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
MISSING_ASSERT_MESSAGE,
macro_call.span,
"assert without any message",
- None,
- "consider describing why the failing assert is problematic",
+ |diag| {
+ diag.help("consider describing why the failing assert is problematic");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 68c1583..052d738 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -186,7 +186,7 @@ fn already_const(header: hir::FnHeader) -> bool {
fn could_be_const_with_abi(cx: &LateContext<'_>, msrv: &Msrv, abi: Abi) -> bool {
match abi {
Abi::Rust => true,
- // `const extern "C"` was stablized after 1.62.0
+ // `const extern "C"` was stabilized after 1.62.0
Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_FN),
// Rest ABIs are still unstable and need the `const_extern_fn` feature enabled.
_ => cx.tcx.features().const_extern_fn,
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
index 85029a5..7ee7463 100644
--- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -1,10 +1,9 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::macros::span_is_local;
-use rustc_hir::def_id::DefIdMap;
+use rustc_hir::def_id::DefIdSet;
use rustc_hir::{Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::AssocItem;
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
@@ -68,33 +67,26 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
}) = item.kind
&& let Some(trait_id) = trait_ref.trait_def_id()
{
- let mut provided: DefIdMap<&AssocItem> = cx
- .tcx
- .provided_trait_methods(trait_id)
- .map(|assoc| (assoc.def_id, assoc))
+ let trait_item_ids: DefIdSet = items
+ .iter()
+ .filter_map(|impl_item| impl_item.trait_item_def_id)
.collect();
- for impl_item in *items {
- if let Some(def_id) = impl_item.trait_item_def_id {
- provided.remove(&def_id);
- }
+ for assoc in cx
+ .tcx
+ .provided_trait_methods(trait_id)
+ .filter(|assoc| !trait_item_ids.contains(&assoc.def_id))
+ {
+ span_lint_and_then(
+ cx,
+ MISSING_TRAIT_METHODS,
+ cx.tcx.def_span(item.owner_id),
+ format!("missing trait method provided by default: `{}`", assoc.name),
+ |diag| {
+ diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method");
+ },
+ );
}
-
- cx.tcx.with_stable_hashing_context(|hcx| {
- for assoc in provided.values_sorted(&hcx, true) {
- let source_map = cx.tcx.sess.source_map();
- let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id));
-
- span_lint_and_help(
- cx,
- MISSING_TRAIT_METHODS,
- source_map.guess_head_span(item.span),
- format!("missing trait method provided by default: `{}`", assoc.name),
- Some(definition_span),
- "implement the method",
- );
- }
- });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 9c5a8a0..6964d8c 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, LetStmt, Node, Stmt, StmtKind};
@@ -324,13 +324,17 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if path_to_local_id(expr, self.var) {
// Check that this is a read, not a write.
if !is_in_assignment_position(self.cx, expr) {
- span_lint_and_note(
+ span_lint_and_then(
self.cx,
MIXED_READ_WRITE_IN_EXPRESSION,
expr.span,
format!("unsequenced read of `{}`", self.cx.tcx.hir().name(self.var)),
- Some(self.write_expr.span),
- "whether read occurs before this write depends on evaluation order",
+ |diag| {
+ diag.span_note(
+ self.write_expr.span,
+ "whether read occurs before this write depends on evaluation order",
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 305499f..e9c5f64 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
@@ -121,17 +121,18 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
for folder in &folder_segments {
if !mod_folders.contains(folder) {
if let Some((file, path)) = file_map.get(folder) {
- let mut correct = path.to_path_buf();
- correct.pop();
- correct.push(folder);
- correct.push("mod.rs");
- span_lint_and_help(
+ span_lint_and_then(
cx,
SELF_NAMED_MODULE_FILES,
Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
format!("`mod.rs` files are required, found `{}`", path.display()),
- None,
- format!("move `{}` to `{}`", path.display(), correct.display(),),
+ |diag| {
+ let mut correct = path.to_path_buf();
+ correct.pop();
+ correct.push(folder);
+ correct.push("mod.rs");
+ diag.help(format!("move `{}` to `{}`", path.display(), correct.display(),));
+ },
);
}
}
@@ -161,17 +162,18 @@ fn process_paths_for_mod_files<'a>(
/// for code-sharing between tests.
fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &SourceFile) {
if path.ends_with("mod.rs") && !path.starts_with("tests") {
- let mut mod_file = path.to_path_buf();
- mod_file.pop();
- mod_file.set_extension("rs");
-
- span_lint_and_help(
+ span_lint_and_then(
cx,
MOD_MODULE_FILES,
Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
format!("`mod.rs` files are not allowed, found `{}`", path.display()),
- None,
- format!("move `{}` to `{}`", path.display(), mod_file.display()),
+ |diag| {
+ let mut mod_file = path.to_path_buf();
+ mod_file.pop();
+ mod_file.set_extension("rs");
+
+ diag.help(format!("move `{}` to `{}`", path.display(), mod_file.display()));
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
index 67f9b52..32e7fde 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs
@@ -1,7 +1,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::mir::PossibleBorrowerMap;
+use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
use clippy_utils::source::snippet_with_context;
use clippy_utils::ty::{implements_trait, is_copy};
use clippy_utils::{expr_use_ctxt, peel_n_hir_expr_refs, DefinedTy, ExprUseNode};
@@ -12,6 +12,7 @@
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::mir::{Rvalue, StatementKind};
use rustc_middle::ty::{
self, ClauseKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, ParamTy, ProjectionPredicate, Ty,
};
@@ -107,6 +108,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
}
&& let count = needless_borrow_count(
cx,
+ &mut self.possible_borrowers,
fn_id,
cx.typeck_results().node_args(hir_id),
i,
@@ -155,9 +157,14 @@ fn path_has_args(p: &QPath<'_>) -> bool {
/// The following constraints will be checked:
/// * The borrowed expression meets all the generic type's constraints.
/// * The generic type appears only once in the functions signature.
-/// * The borrowed value is Copy itself OR not a variable (created by a function call)
+/// * The borrowed value is:
+/// - `Copy` itself, or
+/// - the only use of a mutable reference, or
+/// - not a variable (created by a function call)
+#[expect(clippy::too_many_arguments)]
fn needless_borrow_count<'tcx>(
cx: &LateContext<'tcx>,
+ possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
fn_id: DefId,
callee_args: ty::GenericArgsRef<'tcx>,
arg_index: usize,
@@ -232,9 +239,9 @@ fn needless_borrow_count<'tcx>(
let referent_ty = cx.typeck_results().expr_ty(referent);
- if (!is_copy(cx, referent_ty) && !referent_ty.is_ref())
- && let ExprKind::AddrOf(_, _, inner) = reference.kind
- && !matches!(inner.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))
+ if !(is_copy(cx, referent_ty)
+ || referent_ty.is_ref() && referent_used_exactly_once(cx, possible_borrowers, reference)
+ || matches!(referent.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)))
{
return false;
}
@@ -337,6 +344,37 @@ fn is_mixed_projection_predicate<'tcx>(
}
}
+fn referent_used_exactly_once<'tcx>(
+ cx: &LateContext<'tcx>,
+ possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
+ reference: &Expr<'tcx>,
+) -> bool {
+ if let Some(mir) = enclosing_mir(cx.tcx, reference.hir_id)
+ && let Some(local) = expr_local(cx.tcx, reference)
+ && let [location] = *local_assignments(mir, local).as_slice()
+ && let block_data = &mir.basic_blocks[location.block]
+ && let Some(statement) = block_data.statements.get(location.statement_index)
+ && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
+ && !place.is_indirect_first_projection()
+ {
+ let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id);
+ if possible_borrowers
+ .last()
+ .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id)
+ {
+ possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
+ }
+ let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
+ // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
+ // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
+ // itself. See the comment in that method for an explanation as to why.
+ possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
+ && used_exactly_once(mir, place.local).unwrap_or(false)
+ } else {
+ false
+ }
+}
+
// Iteratively replaces `param_ty` with `new_ty` in `args`, and similarly for each resulting
// projected type that is a type parameter. Returns `false` if replacing the types would have an
// effect on the function signature beyond substituting `new_ty` for `param_ty`.
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index f2e00ce..a0bbf6b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_self;
use clippy_utils::ptr::get_spans;
use clippy_utils::source::{snippet, snippet_opt};
@@ -278,9 +278,12 @@ fn check_fn(
}
}
- let spans = vec![(input.span, format!("&{}", snippet(cx, input.span, "_")))];
-
- multispan_sugg(diag, "consider taking a reference instead", spans);
+ diag.span_suggestion(
+ input.span,
+ "consider taking a reference instead",
+ format!("&{}", snippet(cx, input.span, "_")),
+ Applicability::MaybeIncorrect,
+ );
};
span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 9d326c0..8232e69 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -273,7 +273,7 @@ fn check_unnecessary_operation(cx: &LateContext<'_>, stmt: &Stmt<'_>) {
}
let snippet =
if let (Some(arr), Some(func)) = (snippet_opt(cx, reduced[0].span), snippet_opt(cx, reduced[1].span)) {
- format!("assert!({}.len() > {});", &arr, &func)
+ format!("assert!({arr}.len() > {func});")
} else {
return;
};
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 15bb328..6915cd4 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -6,7 +6,7 @@
use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::in_constant;
+use clippy_utils::is_in_const_context;
use clippy_utils::macros::macro_backtrace;
use clippy_utils::ty::{implements_trait, InteriorMut};
use rustc_hir::def::{DefKind, Res};
@@ -406,7 +406,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Path(qpath) = &expr.kind {
// Only lint if we use the const item inside a function.
- if in_constant(cx, expr.hir_id) {
+ if is_in_const_context(cx) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index 8b8aabe..aadd729 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -243,7 +243,6 @@ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) {
owner_id,
..
}) => {
- #[allow(trivial_casts)]
if let Node::Item(item) = cx.tcx.parent_hir_node(owner_id.into())
&& let Some(trait_ref) = cx
.tcx
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index 9769da6..a0de5ea 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -3,7 +3,7 @@
use rustc_middle::ty;
use clippy_utils::comparisons::{normalize_comparison, Rel};
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_isize_or_usize;
@@ -121,7 +121,7 @@ fn detect_absurd_comparison<'tcx>(
fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
let ty = cx.typeck_results().expr_ty(expr);
- let cv = constant(cx, cx.typeck_results(), expr)?;
+ let cv = ConstEvalCtxt::new(cx).eval(expr)?;
let which = match (ty.kind(), cv) {
(&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index a7e381b..bc71a47 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -1,6 +1,6 @@
use super::ARITHMETIC_SIDE_EFFECTS;
use clippy_config::Conf;
-use clippy_utils::consts::{constant, constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
@@ -162,7 +162,7 @@ fn literal_integer(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<u128> {
{
return Some(n.get());
}
- if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
+ if let Some(Constant::Int(n)) = ConstEvalCtxt::new(cx).eval(expr) {
return Some(n);
}
None
@@ -200,7 +200,7 @@ fn manage_bin_ops<'tcx>(
lhs: &'tcx hir::Expr<'_>,
rhs: &'tcx hir::Expr<'_>,
) {
- if constant_simple(cx, cx.typeck_results(), expr).is_some() {
+ if ConstEvalCtxt::new(cx).eval_simple(expr).is_some() {
return;
}
if !matches!(
@@ -280,7 +280,7 @@ fn manage_method_call<'tcx>(
let Some(arg) = args.first() else {
return;
};
- if constant_simple(cx, cx.typeck_results(), receiver).is_some() {
+ if ConstEvalCtxt::new(cx).eval_simple(receiver).is_some() {
return;
}
let instance_ty = cx.typeck_results().expr_ty(receiver);
@@ -308,7 +308,7 @@ fn manage_unary_ops<'tcx>(
let hir::UnOp::Neg = un_op else {
return;
};
- if constant(cx, cx.typeck_results(), un_expr).is_some() {
+ if ConstEvalCtxt::new(cx).eval(un_expr).is_some() {
return;
}
let ty = cx.typeck_results().expr_ty(expr).peel_refs();
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 545e680..4414056 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
@@ -166,7 +166,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
}
fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> {
- match constant(cx, cx.typeck_results(), lit)? {
+ match ConstEvalCtxt::new(cx).eval(lit)? {
Constant::Int(n) => Some(n),
_ => None,
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
index 7bf9b8ef..c131752 100644
--- a/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/const_comparisons.rs
@@ -2,7 +2,7 @@
use std::cmp::Ordering;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::layout::HasTyCtxt;
@@ -20,13 +20,14 @@
// Flip yoda conditionals, turnings expressions like `42 < x` into `x > 42`
fn comparison_to_const<'tcx>(
cx: &LateContext<'tcx>,
- typeck: &TypeckResults<'tcx>,
+ typeck: &'tcx TypeckResults<'tcx>,
expr: &'tcx Expr<'tcx>,
) -> Option<(CmpOp, &'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Constant<'tcx>, Ty<'tcx>)> {
if let ExprKind::Binary(operator, left, right) = expr.kind
&& let Ok(cmp_op) = CmpOp::try_from(operator.node)
{
- match (constant(cx, typeck, left), constant(cx, typeck, right)) {
+ let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
+ match (ecx.eval(left), ecx.eval(right)) {
(Some(_), Some(_)) => None,
(_, Some(con)) => Some((cmp_op, left, right, con, typeck.expr_ty(right))),
(Some(con), _) => Some((cmp_op.reverse(), right, left, con, typeck.expr_ty(left))),
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index ca3112c..e3029f8 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(
if op == BinOpKind::Div
&& let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
- && let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right)
+ && let Some(Constant::Int(divisor)) = ConstEvalCtxt::new(cx).eval(right)
{
let suggested_fn = match (method_path.ident.as_str(), divisor) {
("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
diff --git a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs
index 066e08f..24bfe2b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/erasing_op.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::same_type_and_consts;
@@ -34,12 +34,12 @@ fn different_types(tck: &TypeckResults<'_>, input: &Expr<'_>, output: &Expr<'_>)
fn check_op<'tcx>(
cx: &LateContext<'tcx>,
- tck: &TypeckResults<'tcx>,
+ tck: &'tcx TypeckResults<'tcx>,
op: &Expr<'tcx>,
other: &Expr<'tcx>,
parent: &Expr<'tcx>,
) {
- if constant_simple(cx, tck, op) == Some(Constant::Int(0)) {
+ if ConstEvalCtxt::with_env(cx.tcx, cx.param_env, tck).eval_simple(op) == Some(Constant::Int(0)) {
if different_types(tck, other, parent) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index 0e5b440..df6e674 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_with_source, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_item_name;
use clippy_utils::sugg::Sugg;
@@ -17,12 +17,14 @@ pub(crate) fn check<'tcx>(
right: &'tcx Expr<'_>,
) {
if (op == BinOpKind::Eq || op == BinOpKind::Ne) && is_float(cx, left) {
- let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
+ let typeck = cx.typeck_results();
+ let ecx = ConstEvalCtxt::with_env(cx.tcx, cx.param_env, typeck);
+ let left_is_local = match ecx.eval_with_source(left) {
Some((c, s)) if !is_allowed(&c) => s.is_local(),
Some(_) => return,
None => true,
};
- let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) {
+ let right_is_local = match ecx.eval_with_source(right) {
Some((c, s)) if !is_allowed(&c) => s.is_local(),
Some(_) => return,
None => true,
diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
index 0879dcd..830be50 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_full_int, constant_simple, Constant, FullInt};
+use clippy_utils::consts::{ConstEvalCtxt, Constant, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{clip, peel_hir_expr_refs, unsext};
@@ -184,14 +184,13 @@ fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Exp
&& cx.typeck_results().expr_ty(right).peel_refs().is_integral()
// `1 << 0` is a common pattern in bit manipulation code
&& !(cmp == BinOpKind::Shl
- && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
- && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1)))
+ && ConstEvalCtxt::new(cx).eval_simple(right) == Some(Constant::Int(0))
+ && ConstEvalCtxt::new(cx).eval_simple(left) == Some(Constant::Int(1)))
}
fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span: Span, arg: Span) {
- let lhs_const = constant_full_int(cx, cx.typeck_results(), left);
- let rhs_const = constant_full_int(cx, cx.typeck_results(), right);
- if match (lhs_const, rhs_const) {
+ let ecx = ConstEvalCtxt::new(cx);
+ if match (ecx.eval_full_int(left), ecx.eval_full_int(right)) {
(Some(FullInt::S(lv)), Some(FullInt::S(rv))) => lv.abs() < rv.abs(),
(Some(FullInt::U(lv)), Some(FullInt::U(rv))) => lv < rv,
_ => return,
@@ -201,7 +200,7 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span
}
fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) -> bool {
- if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) {
+ if let Some(Constant::Int(v)) = ConstEvalCtxt::new(cx).eval_simple(e).map(Constant::peel_refs) {
let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() {
ty::Int(ity) => unsext(cx.tcx, -1_i128, ity),
ty::Uint(uty) => clip(cx.tcx, !0, uty),
diff --git a/src/tools/clippy/clippy_lints/src/operators/integer_division.rs b/src/tools/clippy/clippy_lints/src/operators/integer_division.rs
index 631d10f..76eba73 100644
--- a/src/tools/clippy/clippy_lints/src/operators/integer_division.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/integer_division.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir as hir;
use rustc_lint::LateContext;
@@ -15,13 +15,9 @@ pub(crate) fn check<'tcx>(
&& cx.typeck_results().expr_ty(left).is_integral()
&& cx.typeck_results().expr_ty(right).is_integral()
{
- span_lint_and_help(
- cx,
- INTEGER_DIVISION,
- expr.span,
- "integer division",
- None,
- "division of integers may cause loss of precision. consider using floats",
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, INTEGER_DIVISION, expr.span, "integer division", |diag| {
+ diag.help("division of integers may cause loss of precision. consider using floats");
+ });
}
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index d65fffa..c83bdda 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::sext;
use rustc_hir::{BinOpKind, Expr, ExprKind, Node};
@@ -42,15 +42,11 @@ fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
};
if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne {
- if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), rhs) {
- return true;
- }
- if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), lhs) {
- return true;
- }
+ let ecx = ConstEvalCtxt::new(cx);
+ matches!(ecx.eval(lhs), Some(Constant::Int(0))) || matches!(ecx.eval(rhs), Some(Constant::Int(0)))
+ } else {
+ false
}
-
- false
}
struct OperandInfo {
@@ -60,7 +56,7 @@ struct OperandInfo {
}
fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
- match constant(cx, cx.typeck_results(), operand) {
+ match ConstEvalCtxt::new(cx).eval(operand) {
Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
ty::Int(ity) => {
let value = sext(cx.tcx, v, ity);
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index ea93316..565294b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,5 +1,5 @@
use super::FLOAT_ARITHMETIC;
-use clippy_utils::consts::constant_simple;
+use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::diagnostics::span_lint;
use rustc_hir as hir;
use rustc_lint::LateContext;
@@ -55,7 +55,7 @@ pub fn check_negate<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Ex
return;
}
let ty = cx.typeck_results().expr_ty(arg);
- if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() {
+ if ConstEvalCtxt::new(cx).eval_simple(expr).is_none() && ty.is_floating_point() {
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
self.expr_id = Some(expr.hir_id);
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
index c2b27c9..82b9d10 100644
--- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::get_enclosing_block;
use clippy_utils::source::snippet;
use clippy_utils::ty::{implements_trait, is_copy};
@@ -64,10 +64,10 @@ pub(crate) fn check<'tcx>(
|diag| {
let lsnip = snippet(cx, l.span, "...").to_string();
let rsnip = snippet(cx, r.span, "...").to_string();
- multispan_sugg(
- diag,
+ diag.multipart_suggestion(
"use the values directly",
vec![(left.span, lsnip), (right.span, rsnip)],
+ Applicability::MachineApplicable,
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index d490632..ae02d22 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_res_lang_ctor, peel_blocks,
- peel_hir_expr_while, CaptureKind,
+ can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, is_res_lang_ctor,
+ peel_blocks, peel_hir_expr_while, CaptureKind,
};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
@@ -294,7 +294,7 @@ fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
impl<'tcx> LateLintPass<'tcx> for OptionIfLetElse {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
// Don't lint macros and constants
- if expr.span.from_expansion() || in_constant(cx, expr.hir_id) {
+ if expr.span.from_expansion() || is_in_const_context(cx) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
index 2d20cbe..267e206 100644
--- a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Item, ItemKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -57,24 +57,16 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
for field in fields {
if all_priv && field.vis.kind.is_pub() {
- span_lint_and_help(
- cx,
- PARTIAL_PUB_FIELDS,
- field.vis.span,
- msg,
- None,
- "consider using private field here",
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, PARTIAL_PUB_FIELDS, field.vis.span, msg, |diag| {
+ diag.help("consider using private field here");
+ });
return;
} else if all_pub && !field.vis.kind.is_pub() {
- span_lint_and_help(
- cx,
- PARTIAL_PUB_FIELDS,
- field.vis.span,
- msg,
- None,
- "consider using public field here",
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, PARTIAL_PUB_FIELDS, field.vis.span, msg, |diag| {
+ diag.help("consider using public field here");
+ });
return;
}
}
diff --git a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
index 0008f15..18bfb58 100644
--- a/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/pathbuf_init_then_push.rs
@@ -21,8 +21,8 @@
/// `PathBuf::from` instead.
///
/// ### Known problems
- /// `.join()` introduces an implicit `clone()`. `PathBuf::from` can alternativly be
- /// used when the `PathBuf` is newly constructed. This will avoild the implicit clone.
+ /// `.join()` introduces an implicit `clone()`. `PathBuf::from` can alternatively be
+ /// used when the `PathBuf` is newly constructed. This will avoid the implicit clone.
///
/// ### Example
/// ```rust
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index 9661a57..c1296b0 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_hir::{
intravisit, Body, Expr, ExprKind, FnDecl, LetExpr, LocalSource, Mutability, Pat, PatKind, Stmt, StmtKind,
};
@@ -133,23 +133,25 @@ enum DerefPossible {
fn apply_lint(cx: &LateContext<'_>, pat: &Pat<'_>, deref_possible: DerefPossible) -> bool {
let maybe_mismatch = find_first_mismatch(cx, pat);
if let Some((span, mutability, level)) = maybe_mismatch {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
PATTERN_TYPE_MISMATCH,
span,
"type of pattern does not match the expression type",
- None,
- format!(
- "{}explicitly match against a `{}` pattern and adjust the enclosed variable bindings",
- match (deref_possible, level) {
- (DerefPossible::Possible, Level::Top) => "use `*` to dereference the match expression or ",
- _ => "",
- },
- match mutability {
- Mutability::Mut => "&mut _",
- Mutability::Not => "&_",
- },
- ),
+ |diag| {
+ diag.help(format!(
+ "{}explicitly match against a `{}` pattern and adjust the enclosed variable bindings",
+ match (deref_possible, level) {
+ (DerefPossible::Possible, Level::Top) => "use `*` to dereference the match expression or ",
+ _ => "",
+ },
+ match mutability {
+ Mutability::Mut => "&mut _",
+ Mutability::Not => "&_",
+ },
+ ));
+ },
);
true
} else {
diff --git a/src/tools/clippy/clippy_lints/src/pub_use.rs b/src/tools/clippy/clippy_lints/src/pub_use.rs
index ab8f8a16..5b973a7 100644
--- a/src/tools/clippy/clippy_lints/src/pub_use.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_use.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Item, ItemKind, VisibilityKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -42,14 +42,10 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if let ItemKind::Use(_) = item.kind
&& let VisibilityKind::Public = item.vis.kind
{
- span_lint_and_help(
- cx,
- PUB_USE,
- item.span,
- "using `pub use`",
- None,
- "move the exported item to a public module instead",
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, PUB_USE, item.span, "using `pub use`", |diag| {
+ diag.help("move the exported item to a public module instead");
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index ef6b4d3..e1e3ded 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -7,7 +7,7 @@
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{
- eq_expr_value, higher, in_constant, is_else_clause, is_lint_allowed, is_path_lang_item, is_res_lang_ctor,
+ eq_expr_value, higher, is_else_clause, is_in_const_context, is_lint_allowed, is_path_lang_item, is_res_lang_ctor,
pat_and_expr_can_be_question_mark, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
span_contains_comment,
};
@@ -346,15 +346,13 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
return;
}
- if !self.inside_try_block() && !in_constant(cx, stmt.hir_id) {
+ if !self.inside_try_block() && !is_in_const_context(cx) {
check_let_some_else_return_none(cx, stmt);
}
self.check_manual_let_else(cx, stmt);
}
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if !self.inside_try_block()
- && !in_constant(cx, expr.hir_id)
- && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
+ if !self.inside_try_block() && !is_in_const_context(cx) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id)
{
check_is_none_or_err_and_early_return(cx, expr);
check_if_let_some_or_err_and_early_return(cx, expr);
diff --git a/src/tools/clippy/clippy_lints/src/question_mark_used.rs b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
index f5e6cb8..0a974bf 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark_used.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local;
use rustc_hir::{Expr, ExprKind, MatchSource};
@@ -39,13 +39,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
return;
}
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
QUESTION_MARK_USED,
expr.span,
"question mark operator was used",
- None,
- "consider using a custom macro or match expression",
+ |diag| {
+ diag.help("consider using a custom macro or match expression");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 829fb58..81189fe 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -1,10 +1,10 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_with_applicability, SpanRangeExt};
use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_expr, higher, in_constant, is_integer_const, path_to_local};
+use clippy_utils::{get_parent_expr, higher, is_in_const_context, is_integer_const, path_to_local};
use rustc_ast::ast::RangeLimits;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, HirId};
@@ -202,7 +202,7 @@ fn check_possible_range_contains(
expr: &Expr<'_>,
span: Span,
) {
- if in_constant(cx, expr.hir_id) {
+ if is_in_const_context(cx) {
return;
}
@@ -319,7 +319,7 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) ->
_ => return None,
};
if let Some(id) = path_to_local(l) {
- if let Some(c) = constant(cx, cx.typeck_results(), r) {
+ if let Some(c) = ConstEvalCtxt::new(cx).eval(r) {
return Some(RangeBounds {
val: c,
expr: r,
@@ -331,7 +331,7 @@ fn check_range_bounds<'a, 'tcx>(cx: &'a LateContext<'tcx>, ex: &'a Expr<'_>) ->
});
}
} else if let Some(id) = path_to_local(r) {
- if let Some(c) = constant(cx, cx.typeck_results(), l) {
+ if let Some(c) = ConstEvalCtxt::new(cx).eval(l) {
return Some(RangeBounds {
val: c,
expr: l,
@@ -451,8 +451,9 @@ fn is_empty_range(limits: RangeLimits, ordering: Ordering) -> bool {
}) = higher::Range::hir(expr)
&& let ty = cx.typeck_results().expr_ty(start)
&& let ty::Int(_) | ty::Uint(_) = ty.kind()
- && let Some(start_idx) = constant(cx, cx.typeck_results(), start)
- && let Some(end_idx) = constant(cx, cx.typeck_results(), end)
+ && let ecx = ConstEvalCtxt::new(cx)
+ && let Some(start_idx) = ecx.eval(start)
+ && let Some(end_idx) = ecx.eval(end)
&& let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx)
&& is_empty_range(limits, ordering)
{
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 3416a93..a1231c0 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -96,7 +96,7 @@ fn check_fn(
let (fn_def_id, arg, arg_ty, clone_ret) =
unwrap_or_continue!(is_call_with_ref_arg(cx, mir, &terminator.kind));
- let from_borrow = match_def_path(cx, fn_def_id, &paths::CLONE_TRAIT_METHOD)
+ let from_borrow = cx.tcx.lang_items().get(LangItem::CloneFn) == Some(fn_def_id)
|| cx.tcx.is_diagnostic_item(sym::to_owned_method, fn_def_id)
|| (cx.tcx.is_diagnostic_item(sym::to_string_method, fn_def_id)
&& is_type_lang_item(cx, arg_ty, LangItem::String));
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 82f22ad..1c10e84 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -1,7 +1,7 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::get_parent_expr;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::{is_type_lang_item, peel_mid_ty_refs};
+use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{get_parent_expr, peel_middle_ty_refs};
use rustc_ast::util::parser::PREC_PREFIX;
use rustc_errors::Applicability;
use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
@@ -82,13 +82,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
&& let ExprKind::Index(indexed, range, _) = addressee.kind
&& is_type_lang_item(cx, cx.typeck_results().expr_ty_adjusted(range), LangItem::RangeFull)
{
- let (expr_ty, expr_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(expr));
- let (indexed_ty, indexed_ref_count) = peel_mid_ty_refs(cx.typeck_results().expr_ty(indexed));
+ let (expr_ty, expr_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(expr));
+ let (indexed_ty, indexed_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(indexed));
let parent_expr = get_parent_expr(cx, expr);
let needs_parens_for_prefix = parent_expr.map_or(false, |parent| parent.precedence().order() > PREC_PREFIX);
- let mut app = Applicability::MachineApplicable;
- let ((lint, msg), help, sugg) = if expr_ty == indexed_ty {
+ if expr_ty == indexed_ty {
if expr_ref_count > indexed_ref_count {
// Indexing takes self by reference and can't return a reference to that
// reference as it's a local variable. The only way this could happen is if
@@ -99,7 +98,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
}
let deref_count = indexed_ref_count - expr_ref_count;
- let (lint, reborrow_str, help_str) = if mutability == Mutability::Mut {
+ let ((lint, msg), reborrow_str, help_msg) = if mutability == Mutability::Mut {
// The slice was used to reborrow the mutable reference.
(DEREF_BY_SLICING_LINT, "&mut *", "reborrow the original value instead")
} else if matches!(
@@ -113,8 +112,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
a.kind,
Adjust::Borrow(AutoBorrow::Ref(_, AutoBorrowMutability::Mut { .. }))
)
- }) {
- // The slice was used to make a temporary reference.
+ }) || (matches!(
+ cx.typeck_results().expr_ty(indexed).ref_mutability(),
+ Some(Mutability::Mut)
+ ) && mutability == Mutability::Not)
+ {
(DEREF_BY_SLICING_LINT, "&*", "reborrow the original value instead")
} else if deref_count != 0 {
(DEREF_BY_SLICING_LINT, "", "dereference the original value instead")
@@ -122,38 +124,36 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
(REDUNDANT_SLICING_LINT, "", "use the original value instead")
};
- let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
- let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
- format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
- } else {
- format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
- };
-
- (lint, help_str, sugg)
+ span_lint_and_then(cx, lint, expr.span, msg, |diag| {
+ let mut app = Applicability::MachineApplicable;
+ let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
+ let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
+ format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
+ } else {
+ format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
+ };
+ diag.span_suggestion(expr.span, help_msg, sugg, app);
+ });
} else if let Some(target_id) = cx.tcx.lang_items().deref_target() {
if let Ok(deref_ty) = cx.tcx.try_normalize_erasing_regions(
cx.param_env,
Ty::new_projection_from_args(cx.tcx, target_id, cx.tcx.mk_args(&[GenericArg::from(indexed_ty)])),
) {
if deref_ty == expr_ty {
- let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
- let sugg = if needs_parens_for_prefix {
- format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
- } else {
- format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
- };
- (DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg)
- } else {
- return;
+ let (lint, msg) = DEREF_BY_SLICING_LINT;
+ span_lint_and_then(cx, lint, expr.span, msg, |diag| {
+ let mut app = Applicability::MachineApplicable;
+ let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
+ let sugg = if needs_parens_for_prefix {
+ format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
+ } else {
+ format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
+ };
+ diag.span_suggestion(expr.span, "dereference the original value instead", sugg, app);
+ });
}
- } else {
- return;
}
- } else {
- return;
- };
-
- span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg, app);
+ }
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/ref_patterns.rs b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
index 4670385..002c6c4 100644
--- a/src/tools/clippy/clippy_lints/src/ref_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{BindingMode, Pat, PatKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
@@ -33,14 +33,10 @@ fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind
&& !pat.span.from_expansion()
{
- span_lint_and_help(
- cx,
- REF_PATTERNS,
- pat.span,
- "usage of ref pattern",
- None,
- "consider using `&` for clarity instead",
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, REF_PATTERNS, pat.span, "usage of ref pattern", |diag| {
+ diag.help("consider using `&` for clarity instead");
+ });
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 8cacb64..95014b2 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -1,6 +1,6 @@
use std::fmt::Display;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::source::snippet_opt;
use clippy_utils::{def_path_def_ids, path_def_id, paths};
@@ -148,7 +148,7 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: ®ex_syntax::Error, unescape
}
fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
- constant(cx, cx.typeck_results(), e).and_then(|c| match c {
+ ConstEvalCtxt::new(cx).eval(e).and_then(|c| match c {
Constant::Str(s) => Some(s),
_ => None,
})
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
deleted file mode 100644
index 8e999f3..0000000
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-// This file is managed by `cargo dev rename_lint`. Prefer using that when possible.
-
-#[rustfmt::skip]
-pub static RENAMED_LINTS: &[(&str, &str)] = &[
- ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"),
- ("clippy::blacklisted_name", "clippy::disallowed_names"),
- ("clippy::block_in_if_condition_expr", "clippy::blocks_in_conditions"),
- ("clippy::block_in_if_condition_stmt", "clippy::blocks_in_conditions"),
- ("clippy::blocks_in_if_conditions", "clippy::blocks_in_conditions"),
- ("clippy::box_vec", "clippy::box_collection"),
- ("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
- ("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
- ("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"),
- ("clippy::disallowed_method", "clippy::disallowed_methods"),
- ("clippy::disallowed_type", "clippy::disallowed_types"),
- ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
- ("clippy::identity_conversion", "clippy::useless_conversion"),
- ("clippy::if_let_some_result", "clippy::match_result_ok"),
- ("clippy::incorrect_clone_impl_on_copy_type", "clippy::non_canonical_clone_impl"),
- ("clippy::incorrect_partial_ord_impl_on_ord_type", "clippy::non_canonical_partial_ord_impl"),
- ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
- ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
- ("clippy::new_without_default_derive", "clippy::new_without_default"),
- ("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
- ("clippy::option_expect_used", "clippy::expect_used"),
- ("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"),
- ("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"),
- ("clippy::option_unwrap_used", "clippy::unwrap_used"),
- ("clippy::overflow_check_conditional", "clippy::panicking_overflow_checks"),
- ("clippy::ref_in_deref", "clippy::needless_borrow"),
- ("clippy::result_expect_used", "clippy::expect_used"),
- ("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"),
- ("clippy::result_unwrap_used", "clippy::unwrap_used"),
- ("clippy::single_char_push_str", "clippy::single_char_add_str"),
- ("clippy::stutter", "clippy::module_name_repetitions"),
- ("clippy::thread_local_initializer_can_be_made_const", "clippy::missing_const_for_thread_local"),
- ("clippy::to_string_in_display", "clippy::recursive_format_impl"),
- ("clippy::unwrap_or_else_default", "clippy::unwrap_or_default"),
- ("clippy::zero_width_space", "clippy::invisible_characters"),
- ("clippy::cast_ref_to_mut", "invalid_reference_casting"),
- ("clippy::clone_double_ref", "suspicious_double_ref_op"),
- ("clippy::cmp_nan", "invalid_nan_comparisons"),
- ("clippy::drop_bounds", "drop_bounds"),
- ("clippy::drop_copy", "dropping_copy_types"),
- ("clippy::drop_ref", "dropping_references"),
- ("clippy::fn_null_check", "useless_ptr_null_checks"),
- ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
- ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
- ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
- ("clippy::forget_copy", "forgetting_copy_types"),
- ("clippy::forget_ref", "forgetting_references"),
- ("clippy::into_iter_on_array", "array_into_iter"),
- ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
- ("clippy::invalid_ref", "invalid_value"),
- ("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"),
- ("clippy::let_underscore_drop", "let_underscore_drop"),
- ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
- ("clippy::panic_params", "non_fmt_panics"),
- ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
- ("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
- ("clippy::undropped_manually_drops", "undropped_manually_drops"),
- ("clippy::unknown_clippy_lints", "unknown_lints"),
- ("clippy::unused_label", "unused_labels"),
- ("clippy::vtable_address_comparisons", "ambiguous_wide_pointer_comparisons"),
-];
diff --git a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
index 792d8fc..678681e 100644
--- a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::VecArgs;
use clippy_utils::macros::matching_root_macro_call;
@@ -69,7 +69,7 @@ fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) {
&& let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr)
&& fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
&& !len_expr.span.from_expansion()
- && let Some(Constant::Int(2..)) = constant(cx, cx.typeck_results(), expr_or_init(cx, len_expr))
+ && let Some(Constant::Int(2..)) = ConstEvalCtxt::new(cx).eval(expr_or_init(cx, len_expr))
{
emit_lint(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 8ced47b..13016cd 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -395,7 +395,7 @@ fn check_final_expr<'tcx>(
// Returns may be used to turn an expression into a statement in rustc's AST.
// This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
// `#[expect(clippy::needless_return)]` needs to be handled separatly to
- // actually fullfil the expectation (clippy::#12998)
+ // actually fulfill the expectation (clippy::#12998)
match cx.tcx.hir().attrs(expr.hir_id) {
[] => {},
[attr] => {
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_block.rs b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
index 7615c21..09f1c11 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_block.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_block.rs
@@ -1,5 +1,5 @@
use clippy_config::Conf;
-use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::{Block, Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -92,11 +92,10 @@ fn semicolon_inside_block(&self, cx: &LateContext<'_>, block: &Block<'_>, tail:
semi_span,
"consider moving the `;` inside the block for consistent formatting",
|diag| {
- multispan_sugg_with_applicability(
- diag,
+ diag.multipart_suggestion(
"put the `;` here",
+ vec![(remove_span, String::new()), (insert_span, ";".to_owned())],
Applicability::MachineApplicable,
- [(remove_span, String::new()), (insert_span, ";".to_owned())],
);
},
);
@@ -124,11 +123,10 @@ fn semicolon_outside_block(
block.span,
"consider moving the `;` outside the block for consistent formatting",
|diag| {
- multispan_sugg_with_applicability(
- diag,
+ diag.multipart_suggestion(
"put the `;` here",
+ vec![(remove_span, String::new()), (insert_span, ";".to_owned())],
Applicability::MachineApplicable,
- [(remove_span, String::new()), (insert_span, ";".to_owned())],
);
},
);
diff --git a/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs b/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
index 5e65b9f..e6fe764 100644
--- a/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
+++ b/src/tools/clippy/clippy_lints/src/set_contains_or_insert.rs
@@ -12,8 +12,8 @@
declare_clippy_lint! {
/// ### What it does
- /// Checks for usage of `contains` to see if a value is not
- /// present on `HashSet` followed by a `insert`.
+ /// Checks for usage of `contains` to see if a value is not present
+ /// in a set like `HashSet` or `BTreeSet`, followed by an `insert`.
///
/// ### Why is this bad?
/// Using just `insert` and checking the returned `bool` is more efficient.
@@ -45,12 +45,12 @@
#[clippy::version = "1.80.0"]
pub SET_CONTAINS_OR_INSERT,
nursery,
- "call to `HashSet::contains` followed by `HashSet::insert`"
+ "call to `<set>::contains` followed by `<set>::insert`"
}
-declare_lint_pass!(HashsetInsertAfterContains => [SET_CONTAINS_OR_INSERT]);
+declare_lint_pass!(SetContainsOrInsert => [SET_CONTAINS_OR_INSERT]);
-impl<'tcx> LateLintPass<'tcx> for HashsetInsertAfterContains {
+impl<'tcx> LateLintPass<'tcx> for SetContainsOrInsert {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !expr.span.from_expansion()
&& let Some(higher::If {
@@ -58,14 +58,14 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
then: then_expr,
..
}) = higher::If::hir(expr)
- && let Some(contains_expr) = try_parse_op_call(cx, cond_expr, sym!(contains))//try_parse_contains(cx, cond_expr)
+ && let Some((contains_expr, sym)) = try_parse_op_call(cx, cond_expr, sym!(contains))//try_parse_contains(cx, cond_expr)
&& let Some(insert_expr) = find_insert_calls(cx, &contains_expr, then_expr)
{
span_lint(
cx,
SET_CONTAINS_OR_INSERT,
vec![contains_expr.span, insert_expr.span],
- "usage of `HashSet::insert` after `HashSet::contains`",
+ format!("usage of `{sym}::insert` after `{sym}::contains`"),
);
}
}
@@ -77,7 +77,11 @@ struct OpExpr<'tcx> {
span: Span,
}
-fn try_parse_op_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, symbol: Symbol) -> Option<OpExpr<'tcx>> {
+fn try_parse_op_call<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ symbol: Symbol,
+) -> Option<(OpExpr<'tcx>, Symbol)> {
let expr = peel_hir_expr_while(expr, |e| {
if let ExprKind::Unary(UnOp::Not, e) = e.kind {
Some(e)
@@ -97,11 +101,12 @@ fn try_parse_op_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, symbol:
});
let receiver = receiver.peel_borrows();
let receiver_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
- if value.span.eq_ctxt(expr.span)
- && is_type_diagnostic_item(cx, receiver_ty, sym::HashSet)
- && path.ident.name == symbol
- {
- return Some(OpExpr { receiver, value, span });
+ if value.span.eq_ctxt(expr.span) && path.ident.name == symbol {
+ for sym in &[sym::HashSet, sym::BTreeSet] {
+ if is_type_diagnostic_item(cx, receiver_ty, *sym) {
+ return Some((OpExpr { receiver, value, span }, *sym));
+ }
+ }
}
}
None
@@ -113,7 +118,7 @@ fn find_insert_calls<'tcx>(
expr: &'tcx Expr<'_>,
) -> Option<OpExpr<'tcx>> {
for_each_expr(cx, expr, |e| {
- if let Some(insert_expr) = try_parse_op_call(cx, e, sym!(insert))
+ if let Some((insert_expr, _)) = try_parse_op_call(cx, e, sym!(insert))
&& SpanlessEq::new(cx).eq_expr(contains_expr.receiver, insert_expr.receiver)
&& SpanlessEq::new(cx).eq_expr(contains_expr.value, insert_expr.value)
{
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index 80f5fd0..7ae0310 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used;
use rustc_data_structures::fx::FxHashMap;
@@ -194,14 +194,9 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
(SHADOW_UNRELATED, msg)
},
};
- span_lint_and_note(
- cx,
- lint,
- span,
- msg,
- Some(cx.tcx.hir().span(shadowed)),
- "previous binding is here",
- );
+ span_lint_and_then(cx, lint, span, msg, |diag| {
+ diag.span_note(cx.tcx.hir().span(shadowed), "previous binding is here");
+ });
}
/// Returns true if the expression is a simple transformation of a local binding such as `&x`
diff --git a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs
index 72feb97..d92b890 100644
--- a/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs
+++ b/src/tools/clippy/clippy_lints/src/single_char_lifetime_names.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{GenericParam, GenericParamKind};
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -48,13 +48,15 @@ fn check_generic_param(&mut self, ctx: &EarlyContext<'_>, param: &GenericParam)
if let GenericParamKind::Lifetime = param.kind {
if !param.is_placeholder && param.ident.as_str().len() <= 2 {
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
ctx,
SINGLE_CHAR_LIFETIME_NAMES,
param.ident.span,
"single-character lifetime names are likely uninformative",
- None,
- "use a more informative name",
+ |diag| {
+ diag.help("use a more informative name");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs
index 8d7f12a..b3d32a6 100644
--- a/src/tools/clippy/clippy_lints/src/size_of_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs
@@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::path_def_id;
-use clippy_utils::ty::peel_mid_ty_refs;
+use clippy_utils::{path_def_id, peel_middle_ty_refs};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
@@ -60,7 +59,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
&& let Some(def_id) = path_def_id(cx, path)
&& cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id)
&& let arg_ty = cx.typeck_results().expr_ty(arg)
- && peel_mid_ty_refs(arg_ty).1 > 1
+ && peel_middle_ty_refs(arg_ty).1 > 1
{
span_lint_and_help(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index 12b7007..974e21d 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -1,11 +1,15 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_config::msrvs::Msrv;
+use clippy_config::Conf;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
+use rustc_attr::{StabilityLevel, StableSince};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_hir::{HirId, Path, PathSegment};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
+use rustc_semver::RustcVersion;
use rustc_session::impl_lint_pass;
use rustc_span::symbol::kw;
use rustc_span::{sym, Span};
@@ -66,6 +70,10 @@
/// imported from core to ensure disabling `alloc` does not cause the crate to fail to compile. This lint
/// is also useful for crates migrating to become `no_std` compatible.
///
+ /// ### Known problems
+ /// The lint is only partially aware of the required MSRV for items that were originally in `std` but moved
+ /// to `core`.
+ ///
/// ### Example
/// ```no_run
/// # extern crate alloc;
@@ -81,20 +89,30 @@
"type is imported from alloc when available in core"
}
-#[derive(Default)]
pub struct StdReexports {
// Paths which can be either a module or a macro (e.g. `std::env`) will cause this check to happen
// twice. First for the mod, second for the macro. This is used to avoid the lint reporting for the macro
// when the path could be also be used to access the module.
prev_span: Span,
+ msrv: Msrv,
}
+
+impl StdReexports {
+ pub fn new(conf: &'static Conf) -> Self {
+ Self {
+ prev_span: Span::default(),
+ msrv: conf.msrv.clone(),
+ }
+ }
+}
+
impl_lint_pass!(StdReexports => [STD_INSTEAD_OF_CORE, STD_INSTEAD_OF_ALLOC, ALLOC_INSTEAD_OF_CORE]);
impl<'tcx> LateLintPass<'tcx> for StdReexports {
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
if let Res::Def(_, def_id) = path.res
&& let Some(first_segment) = get_first_segment(path)
- && is_stable(cx, def_id)
+ && is_stable(cx, def_id, &self.msrv)
&& !in_external_macro(cx.sess(), path.span)
&& !is_from_proc_macro(cx, &first_segment.ident)
{
@@ -118,19 +136,27 @@ fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
_ => return,
};
if first_segment.ident.span != self.prev_span {
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
lint,
first_segment.ident.span,
format!("used import from `{used_mod}` instead of `{replace_with}`"),
- format!("consider importing the item from `{replace_with}`"),
- replace_with.to_string(),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion(
+ first_segment.ident.span,
+ format!("consider importing the item from `{replace_with}`"),
+ replace_with.to_string(),
+ Applicability::MachineApplicable,
+ );
+ },
);
self.prev_span = first_segment.ident.span;
}
}
}
+
+ extract_msrv_attr!(LateContext);
}
/// Returns the first named segment of a [`Path`].
@@ -146,16 +172,29 @@ fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>>
}
}
-/// Checks if all ancestors of `def_id` are stable, to avoid linting
-/// [unstable moves](https://github.com/rust-lang/rust/pull/95956)
-fn is_stable(cx: &LateContext<'_>, mut def_id: DefId) -> bool {
+/// Checks if all ancestors of `def_id` meet `msrv` to avoid linting [unstable moves](https://github.com/rust-lang/rust/pull/95956)
+/// or now stable moves that were once unstable.
+///
+/// Does not catch individually moved items
+fn is_stable(cx: &LateContext<'_>, mut def_id: DefId, msrv: &Msrv) -> bool {
loop {
- if cx
- .tcx
- .lookup_stability(def_id)
- .map_or(false, |stability| stability.is_unstable())
+ if let Some(stability) = cx.tcx.lookup_stability(def_id)
+ && let StabilityLevel::Stable {
+ since,
+ allowed_through_unstable_modules: false,
+ } = stability.level
{
- return false;
+ let stable = match since {
+ StableSince::Version(v) => {
+ msrv.meets(RustcVersion::new(v.major.into(), v.minor.into(), v.patch.into()))
+ },
+ StableSince::Current => msrv.current().is_none(),
+ StableSince::Err => false,
+ };
+
+ if !stable {
+ return false;
+ }
}
match cx.tcx.opt_parent(def_id) {
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 7da6614..cfc3878 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{
@@ -399,17 +399,16 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
&& let ty::Ref(_, ty, ..) = ty.kind()
&& ty.is_str()
{
- let mut applicability = Applicability::MachineApplicable;
- let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
-
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
STR_TO_STRING,
expr.span,
"`to_string()` called on a `&str`",
- "try",
- format!("{snippet}.to_owned()"),
- applicability,
+ |diag| {
+ let mut applicability = Applicability::MachineApplicable;
+ let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
+ diag.span_suggestion(expr.span, "try", format!("{snippet}.to_owned()"), applicability);
+ },
);
}
}
@@ -455,13 +454,15 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
&& let ty = cx.typeck_results().expr_ty(self_arg)
&& is_type_lang_item(cx, ty, LangItem::String)
{
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
STRING_TO_STRING,
expr.span,
"`to_string()` called on a `String`",
- None,
- "consider using `.clone()`",
+ |diag| {
+ diag.help("consider using `.clone()`");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
index d150a5f..d1d822a 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_xor_used_as_pow.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet;
use rustc_ast::LitKind;
@@ -43,14 +43,19 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
&& NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node)
.is_some_and(|x| x.is_decimal())
{
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
SUSPICIOUS_XOR_USED_AS_POW,
expr.span,
"`^` is not the exponentiation operator",
- "did you mean to write",
- format!("{}.pow({})", lit_left.node, lit_right.node),
- Applicability::MaybeIncorrect,
+ |diag| {
+ diag.span_suggestion_verbose(
+ expr.span,
+ "did you mean to write",
+ format!("{}.pow({})", lit_left.node, lit_right.node),
+ Applicability::MaybeIncorrect,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 93bad86..197011c 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -3,7 +3,7 @@
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{can_mut_borrow_both, eq_expr_value, in_constant, std_or_core};
+use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core};
use itertools::Itertools;
use rustc_hir::intravisit::{walk_expr, Visitor};
@@ -170,7 +170,7 @@ fn generate_swap_warning<'tcx>(
/// Implementation of the `MANUAL_SWAP` lint.
fn check_manual_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
- if in_constant(cx, block.hir_id) {
+ if is_in_const_context(cx) {
return;
}
diff --git a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
index 58e4289..25d0a16 100644
--- a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
+++ b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{is_in_cfg_test, is_in_test_function};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl};
@@ -61,13 +61,15 @@ fn check_fn(
&& is_in_test_function(cx.tcx, body.id().hir_id)
&& !is_in_cfg_test(cx.tcx, body.id().hir_id)
{
- span_lint_and_note(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
TESTS_OUTSIDE_TEST_MODULE,
sp,
"this function marked with #[test] is outside a #[cfg(test)] module",
- None,
- "move it to a testing module marked with #[cfg(test)]",
+ |diag| {
+ diag.note("move it to a testing module marked with #[cfg(test)]");
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index 9c6813a..373bf61 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -21,7 +21,7 @@
use clippy_config::msrvs::Msrv;
use clippy_config::Conf;
-use clippy_utils::in_constant;
+use clippy_utils::is_in_const_context;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
@@ -595,7 +595,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
// - from/to bits (https://github.com/rust-lang/rust/issues/73736)
// - dereferencing raw pointers (https://github.com/rust-lang/rust/issues/51911)
// - char conversions (https://github.com/rust-lang/rust/issues/89259)
- let const_context = in_constant(cx, e.hir_id);
+ let const_context = is_in_const_context(cx);
let (from_ty, from_ty_adjusted) = match cx.typeck_results().expr_adjustments(arg) {
[] => (cx.typeck_results().expr_ty(arg), false),
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
index b26365e..7acf3be 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
use rustc_hir::{Expr, ExprKind};
@@ -33,10 +33,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
// Catching:
// transmute over constants that resolve to `null`.
ExprKind::Path(ref _qpath)
- if matches!(
- constant(cx, cx.typeck_results(), casts_peeled),
- Some(Constant::RawPtr(0))
- ) =>
+ if matches!(ConstEvalCtxt::new(cx).eval(casts_peeled), Some(Constant::RawPtr(0))) =>
{
lint_expr(cx, expr);
true
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index 471bd44..544014b 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
use rustc_hir::{Expr, ExprKind};
@@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
// Catching transmute over constants that resolve to `null`.
if let ExprKind::Path(ref _qpath) = arg.kind
- && let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg)
+ && let Some(Constant::RawPtr(0)) = ConstEvalCtxt::new(cx).eval(arg)
{
span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
return true;
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 83cc9f2..2fcfc71 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -48,15 +48,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
let inner_snippet = snippet(cx, inner.span, "..");
let suggestion = match &inner.kind {
TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
- format!("&{ltopt}({})", &inner_snippet)
+ format!("&{ltopt}({inner_snippet})")
},
TyKind::Path(qpath)
if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
.map_or(false, |bounds| bounds.len() > 1) =>
{
- format!("&{ltopt}({})", &inner_snippet)
+ format!("&{ltopt}({inner_snippet})")
},
- _ => format!("&{ltopt}{}", &inner_snippet),
+ _ => format!("&{ltopt}{inner_snippet}"),
};
span_lint_and_sugg(
cx,
@@ -82,16 +82,14 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
// Returns true if given type is `Any` trait.
fn is_any_trait(cx: &LateContext<'_>, t: &hir::Ty<'_>) -> bool {
if let TyKind::TraitObject(traits, ..) = t.kind {
- return traits
- .iter()
- .any(|(bound, _)| {
- if let Some(trait_did) = bound.trait_ref.trait_def_id()
- && cx.tcx.is_diagnostic_item(sym::Any, trait_did)
- {
- return true;
- }
- false
- });
+ return traits.iter().any(|(bound, _)| {
+ if let Some(trait_did) = bound.trait_ref.trait_def_id()
+ && cx.tcx.is_diagnostic_item(sym::Any, trait_did)
+ {
+ return true;
+ }
+ false
+ });
}
false
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
index f6c2d8d..d691f18 100644
--- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
+++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_errors::Applicability;
@@ -13,14 +13,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
let app = Applicability::Unspecified;
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
if let Some(alternate) = match_buffer_type(cx, qpath) {
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
RC_BUFFER,
hir_ty.span,
"usage of `Rc<T>` when T is a buffer type",
- "try",
- format!("Rc<{alternate}>"),
- app,
+ |diag| {
+ diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app);
+ },
);
} else {
let Some(ty) = qpath_generic_tys(qpath).next() else {
@@ -35,31 +36,37 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
Some(ty) => ty.span,
None => return false,
};
- let mut applicability = app;
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
RC_BUFFER,
hir_ty.span,
"usage of `Rc<T>` when T is a buffer type",
- "try",
- format!(
- "Rc<[{}]>",
- snippet_with_applicability(cx, inner_span, "..", &mut applicability)
- ),
- app,
+ |diag| {
+ let mut applicability = app;
+ diag.span_suggestion(
+ hir_ty.span,
+ "try",
+ format!(
+ "Rc<[{}]>",
+ snippet_with_applicability(cx, inner_span, "..", &mut applicability)
+ ),
+ app,
+ );
+ },
);
return true;
}
} else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
if let Some(alternate) = match_buffer_type(cx, qpath) {
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
RC_BUFFER,
hir_ty.span,
"usage of `Arc<T>` when T is a buffer type",
- "try",
- format!("Arc<{alternate}>"),
- app,
+ |diag| {
+ diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app);
+ },
);
} else if let Some(ty) = qpath_generic_tys(qpath).next() {
let Some(id) = path_def_id(cx, ty) else { return false };
@@ -71,18 +78,23 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
Some(ty) => ty.span,
None => return false,
};
- let mut applicability = app;
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
RC_BUFFER,
hir_ty.span,
"usage of `Arc<T>` when T is a buffer type",
- "try",
- format!(
- "Arc<[{}]>",
- snippet_with_applicability(cx, inner_span, "..", &mut applicability)
- ),
- app,
+ |diag| {
+ let mut applicability = app;
+ diag.span_suggestion(
+ hir_ty.span,
+ "try",
+ format!(
+ "Arc<[{}]>",
+ snippet_with_applicability(cx, inner_span, "..", &mut applicability)
+ ),
+ app,
+ );
+ },
);
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
index afc3192..7b13deb 100644
--- a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{path_def_id, qpath_generic_tys};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, QPath};
@@ -13,14 +13,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
&& let Some(id) = path_def_id(cx, arg)
&& cx.tcx.is_diagnostic_item(sym::Mutex, id)
{
- span_lint_and_help(
- cx,
- RC_MUTEX,
- hir_ty.span,
- "usage of `Rc<Mutex<_>>`",
- None,
- "consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, RC_MUTEX, hir_ty.span, "usage of `Rc<Mutex<_>>`", |diag| {
+ diag.help("consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead");
+ });
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index 3ab30bf..f51c5f7 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -1,7 +1,7 @@
use std::ops::ControlFlow;
use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::source::walk_span_to_context;
use clippy_utils::visitors::{for_each_expr, Descend};
@@ -129,13 +129,15 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
block.span
};
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
UNDOCUMENTED_UNSAFE_BLOCKS,
span,
"unsafe block missing a safety comment",
- None,
- "consider adding a safety comment on the preceding line",
+ |diag| {
+ diag.help("consider adding a safety comment on the preceding line");
+ },
);
}
@@ -145,13 +147,14 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
&& let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, tail.span, tail.hir_id)
&& let Some(help_span) = expr_has_unnecessary_safety_comment(cx, tail, pos)
{
- span_lint_and_help(
+ span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
tail.span,
"expression has unnecessary safety comment",
- Some(help_span),
- "consider removing the safety comment",
+ |diag| {
+ diag.span_help(help_span, "consider removing the safety comment");
+ },
);
}
}
@@ -168,13 +171,14 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &hir::Stmt<'tcx>) {
&& let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, stmt.span, stmt.hir_id)
&& let Some(help_span) = expr_has_unnecessary_safety_comment(cx, expr, pos)
{
- span_lint_and_help(
+ span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
stmt.span,
"statement has unnecessary safety comment",
- Some(help_span),
- "consider removing the safety comment",
+ |diag| {
+ diag.span_help(help_span, "consider removing the safety comment");
+ },
);
}
}
@@ -210,13 +214,15 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
item.span
};
- span_lint_and_help(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
UNDOCUMENTED_UNSAFE_BLOCKS,
span,
"unsafe impl missing a safety comment",
- None,
- "consider adding a safety comment on the preceding line",
+ |diag| {
+ diag.help("consider adding a safety comment on the preceding line");
+ },
);
}
},
@@ -225,13 +231,14 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
let (span, help_span) = mk_spans(pos);
- span_lint_and_help(
+ span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
span,
"impl has unnecessary safety comment",
- Some(help_span),
- "consider removing the safety comment",
+ |diag| {
+ diag.span_help(help_span, "consider removing the safety comment");
+ },
);
}
},
@@ -246,13 +253,14 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
) {
let (span, help_span) = mk_spans(pos);
- span_lint_and_help(
+ span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
span,
format!("{} has unnecessary safety comment", item.kind.descr()),
- Some(help_span),
- "consider removing the safety comment",
+ |diag| {
+ diag.span_help(help_span, "consider removing the safety comment");
+ },
);
}
}
@@ -263,13 +271,14 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) {
let (span, help_span) = mk_spans(pos);
- span_lint_and_help(
+ span_lint_and_then(
cx,
UNNECESSARY_SAFETY_COMMENT,
span,
format!("{} has unnecessary safety comment", item.kind.descr()),
- Some(help_span),
- "consider removing the safety comment",
+ |diag| {
+ diag.span_help(help_span, "consider removing the safety comment");
+ },
);
}
},
diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs
index d42697b..e1fc644 100644
--- a/src/tools/clippy/clippy_lints/src/unicode.rs
+++ b/src/tools/clippy/clippy_lints/src/unicode.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::macros::span_is_local;
use clippy_utils::source::snippet;
@@ -105,45 +105,51 @@ fn check_str(cx: &LateContext<'_>, span: Span, id: HirId) {
let string = snippet(cx, span, "");
if string.chars().any(|c| ['\u{200B}', '\u{ad}', '\u{2060}'].contains(&c)) {
- span_lint_and_sugg(
- cx,
- INVISIBLE_CHARACTERS,
- span,
- "invisible character detected",
- "consider replacing the string with",
- string
- .replace('\u{200B}', "\\u{200B}")
- .replace('\u{ad}', "\\u{AD}")
- .replace('\u{2060}', "\\u{2060}"),
- Applicability::MachineApplicable,
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, INVISIBLE_CHARACTERS, span, "invisible character detected", |diag| {
+ diag.span_suggestion(
+ span,
+ "consider replacing the string with",
+ string
+ .replace('\u{200B}', "\\u{200B}")
+ .replace('\u{ad}', "\\u{AD}")
+ .replace('\u{2060}', "\\u{2060}"),
+ Applicability::MachineApplicable,
+ );
+ });
}
if string.chars().any(|c| c as u32 > 0x7F) {
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
NON_ASCII_LITERAL,
span,
"literal non-ASCII character detected",
- "consider replacing the string with",
- if is_lint_allowed(cx, UNICODE_NOT_NFC, id) {
- escape(string.chars())
- } else {
- escape(string.nfc())
+ |diag| {
+ diag.span_suggestion(
+ span,
+ "consider replacing the string with",
+ if is_lint_allowed(cx, UNICODE_NOT_NFC, id) {
+ escape(string.chars())
+ } else {
+ escape(string.nfc())
+ },
+ Applicability::MachineApplicable,
+ );
},
- Applicability::MachineApplicable,
);
}
if is_lint_allowed(cx, NON_ASCII_LITERAL, id) && string.chars().zip(string.nfc()).any(|(a, b)| a != b) {
- span_lint_and_sugg(
- cx,
- UNICODE_NOT_NFC,
- span,
- "non-NFC Unicode sequence detected",
- "consider replacing the string with",
- string.nfc().collect::<String>(),
- Applicability::MachineApplicable,
- );
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(cx, UNICODE_NOT_NFC, span, "non-NFC Unicode sequence detected", |diag| {
+ diag.span_suggestion(
+ span,
+ "consider replacing the string with",
+ string.nfc().collect::<String>(),
+ Applicability::MachineApplicable,
+ );
+ });
}
}
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index e4e7f7d..080efe9 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -145,7 +145,9 @@ fn check_fn(
(
"this function's return value is unnecessary".to_string(),
"remove the return type...".to_string(),
- snippet(cx, fn_decl.output.span(), "..").to_string(),
+ // FIXME: we should instead get the span including the `->` and suggest an
+ // empty string for this case.
+ "()".to_string(),
"...and then remove returned values",
)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/unused_result_ok.rs b/src/tools/clippy/clippy_lints/src/unused_result_ok.rs
new file mode 100644
index 0000000..297288d
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unused_result_ok.rs
@@ -0,0 +1,59 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_errors::Applicability;
+use rustc_hir::{ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::declare_lint_pass;
+use rustc_span::sym;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for calls to `Result::ok()` without using the returned `Option`.
+ ///
+ /// ### Why is this bad?
+ /// Using `Result::ok()` may look like the result is checked like `unwrap` or `expect` would do
+ /// but it only silences the warning caused by `#[must_use]` on the `Result`.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// # fn some_function() -> Result<(), ()> { Ok(()) }
+ /// some_function().ok();
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// # fn some_function() -> Result<(), ()> { Ok(()) }
+ /// let _ = some_function();
+ /// ```
+ #[clippy::version = "1.70.0"]
+ pub UNUSED_RESULT_OK,
+ restriction,
+ "Use of `.ok()` to silence `Result`'s `#[must_use]` is misleading. Use `let _ =` instead."
+}
+declare_lint_pass!(UnusedResultOk => [UNUSED_RESULT_OK]);
+
+impl LateLintPass<'_> for UnusedResultOk {
+ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+ if let StmtKind::Semi(expr) = stmt.kind
+ && let ExprKind::MethodCall(ok_path, recv, [], ..) = expr.kind //check is expr.ok() has type Result<T,E>.ok(, _)
+ && ok_path.ident.as_str() == "ok"
+ && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result)
+ && !in_external_macro(cx.sess(), stmt.span)
+ {
+ let ctxt = expr.span.ctxt();
+ let mut applicability = Applicability::MaybeIncorrect;
+ let snippet = snippet_with_context(cx, recv.span, ctxt, "", &mut applicability).0;
+ let sugg = format!("let _ = {snippet}");
+ span_lint_and_sugg(
+ cx,
+ UNUSED_RESULT_OK,
+ expr.span,
+ "ignoring a result with `.ok()` is misleading",
+ "consider using `let _ =` and removing the call to `.ok()` instead",
+ sugg,
+ applicability,
+ );
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index b017a6b..7c2e239 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::match_type;
@@ -93,7 +93,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Call(func, [arg]) = &expr.kind
&& let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind()
&& match_def_path(cx, *def_id, &paths::SYMBOL_INTERN)
- && let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg)
+ && let Some(Constant::Str(arg)) = ConstEvalCtxt::new(cx).eval_simple(arg)
&& let value = Symbol::intern(&arg).as_u32()
&& let Some(&def_id) = self.symbol_map.get(&value)
{
@@ -199,7 +199,7 @@ fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>)
});
}
// is a string constant
- if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) {
+ if let Some(Constant::Str(s)) = ConstEvalCtxt::new(cx).eval_simple(expr) {
let value = Symbol::intern(&s).as_u32();
// ...which matches a symbol constant
if let Some(&def_id) = self.symbol_map.get(&value) {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 9804372..0ffcb43 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::def_path_res;
use clippy_utils::diagnostics::span_lint;
use rustc_hir as hir;
@@ -32,9 +32,9 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
if mod_name.as_str() == "paths"
&& let hir::ItemKind::Const(.., body_id) = item.kind
- && let body = cx.tcx.hir().body(body_id)
- && let typeck_results = cx.tcx.typeck_body(body_id)
- && let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value)
+ && let Some(Constant::Vec(path)) =
+ ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(item.owner_id), cx.tcx.typeck(item.owner_id))
+ .eval_simple(cx.tcx.hir().body(body_id).value)
&& let Some(path) = path
.iter()
.map(|x| {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
index 84f8478..df342e4 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -1,4 +1,3 @@
-use crate::utils::internal_lints::metadata_collector::is_deprecated_lint;
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::{is_lint_allowed, match_def_path, paths};
@@ -87,82 +86,32 @@
"found clippy lint without `clippy::version` attribute"
}
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for cases of an auto-generated deprecated lint without an updated reason,
- /// i.e. `"default deprecation note"`.
- ///
- /// ### Why is this bad?
- /// Indicates that the documentation is incomplete.
- ///
- /// ### Example
- /// ```rust,ignore
- /// declare_deprecated_lint! {
- /// /// ### What it does
- /// /// Nothing. This lint has been deprecated.
- /// ///
- /// /// ### Deprecation reason
- /// /// TODO
- /// #[clippy::version = "1.63.0"]
- /// pub COOL_LINT,
- /// "default deprecation note"
- /// }
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// declare_deprecated_lint! {
- /// /// ### What it does
- /// /// Nothing. This lint has been deprecated.
- /// ///
- /// /// ### Deprecation reason
- /// /// This lint has been replaced by `cooler_lint`
- /// #[clippy::version = "1.63.0"]
- /// pub COOL_LINT,
- /// "this lint has been replaced by `cooler_lint`"
- /// }
- /// ```
- pub DEFAULT_DEPRECATION_REASON,
- internal,
- "found 'default deprecation note' in a deprecated lint declaration"
-}
-
#[derive(Clone, Debug, Default)]
pub struct LintWithoutLintPass {
declared_lints: FxHashMap<Symbol, Span>,
registered_lints: FxHashSet<Symbol>,
}
-impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE, DEFAULT_DEPRECATION_REASON]);
+impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE]);
impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
- if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id())
- || is_lint_allowed(cx, DEFAULT_DEPRECATION_REASON, item.hir_id())
- {
+ if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id()) {
return;
}
if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
- let is_lint_ref_ty = is_lint_ref_type(cx, ty);
- if is_deprecated_lint(cx, ty) || is_lint_ref_ty {
+ if is_lint_ref_type(cx, ty) {
check_invalid_clippy_version_attribute(cx, item);
let expr = &cx.tcx.hir().body(body_id).value;
- let fields;
- if is_lint_ref_ty {
- if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
- && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind
- {
- fields = struct_fields;
- } else {
- return;
- }
- } else if let ExprKind::Struct(_, struct_fields, _) = expr.kind {
- fields = struct_fields;
+ let fields = if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
+ && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind
+ {
+ struct_fields
} else {
return;
- }
+ };
let field = fields
.iter()
@@ -175,25 +124,15 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
}) = field.expr.kind
{
let sym_str = sym.as_str();
- if is_lint_ref_ty {
- if sym_str == "default lint description" {
- span_lint(
- cx,
- DEFAULT_LINT,
- item.span,
- format!("the lint `{}` has the default lint description", item.ident.name),
- );
- }
-
- self.declared_lints.insert(item.ident.name, item.span);
- } else if sym_str == "default deprecation note" {
+ if sym_str == "default lint description" {
span_lint(
cx,
- DEFAULT_DEPRECATION_REASON,
+ DEFAULT_LINT,
item.span,
- format!("the lint `{}` has the default deprecation reason", item.ident.name),
+ format!("the lint `{}` has the default lint description", item.ident.name),
);
}
+ self.declared_lints.insert(item.ident.name, item.span);
}
}
} else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 1c149f2..57f45aa 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -7,13 +7,12 @@
//! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such
//! a simple mistake)
-use crate::renamed_lints::RENAMED_LINTS;
use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
use clippy_config::{get_configuration_metadata, ClippyConfiguration};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
-use clippy_utils::{last_path_segment, match_def_path, match_function_call, match_path, paths};
+use clippy_utils::{last_path_segment, match_function_call, match_path, paths};
use itertools::Itertools;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
@@ -85,11 +84,6 @@
("tool_only_multipart_suggestion", true),
("span_suggestions", true),
];
-const SUGGESTION_FUNCTIONS: [&[&str]; 2] = [
- &["clippy_utils", "diagnostics", "multispan_sugg"],
- &["clippy_utils", "diagnostics", "multispan_sugg_with_applicability"],
-];
-const DEPRECATED_LINT_TYPE: [&str; 3] = ["clippy_lints", "deprecated_lints", "ClippyDeprecatedLint"];
/// The index of the applicability name of `paths::APPLICABILITY_VALUES`
const APPLICABILITY_NAME_INDEX: usize = 2;
@@ -165,9 +159,9 @@ pub fn new() -> Self {
fn get_lint_configs(&self, lint_name: &str) -> Option<String> {
self.config
.iter()
- .filter(|config| config.lints.iter().any(|lint| lint == lint_name))
+ .filter(|config| config.lints.iter().any(|&lint| lint == lint_name))
.map(ToString::to_string)
- .reduce(|acc, x| acc + &x)
+ .reduce(|acc, x| acc + "\n\n" + &x)
.map(|configurations| {
format!(
r#"
@@ -216,6 +210,13 @@ fn drop(&mut self) {
let mut applicability_info = std::mem::take(&mut self.applicability_info);
+ // Add deprecated lints
+ self.lints.extend(
+ crate::deprecated_lints::DEPRECATED
+ .iter()
+ .zip(crate::deprecated_lints::DEPRECATED_VERSION)
+ .filter_map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)),
+ );
// Mapping the final data
let mut lints = std::mem::take(&mut self.lints).into_sorted_vec();
for x in &mut lints {
@@ -261,7 +262,7 @@ fn drop(&mut self) {
#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord)]
struct LintMetadata {
id: String,
- id_span: SerializableSpan,
+ id_span: Option<SerializableSpan>,
group: String,
level: String,
docs: String,
@@ -285,7 +286,7 @@ fn new(
) -> Self {
Self {
id,
- id_span,
+ id_span: Some(id_span),
group,
level: level.to_string(),
version,
@@ -294,6 +295,29 @@ fn new(
former_ids: BTreeSet::new(),
}
}
+
+ fn new_deprecated(name: &str, reason: &str, version: &str) -> Option<Self> {
+ // The reason starts with a lowercase letter and end without a period.
+ // This needs to be fixed for the website.
+ let mut reason = reason.to_owned();
+ if let Some(reason) = reason.get_mut(0..1) {
+ reason.make_ascii_uppercase();
+ }
+ name.strip_prefix("clippy::").map(|name| Self {
+ id: name.into(),
+ id_span: None,
+ group: DEPRECATED_LINT_GROUP_STR.into(),
+ level: DEPRECATED_LINT_LEVEL.into(),
+ version: version.into(),
+ docs: format!(
+ "### What it does\n\n\
+ Nothing. This lint has been deprecated\n\n\
+ ### Deprecation reason\n\n{reason}.\n",
+ ),
+ applicability: None,
+ former_ids: BTreeSet::new(),
+ })
+ }
}
fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Path) {
@@ -564,24 +588,6 @@ fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) {
raw_docs,
));
}
-
- if is_deprecated_lint(cx, ty)
- // disallow check
- && let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase()
- // Metadata the little we can get from a deprecated lint
- && let Some(raw_docs) = extract_attr_docs_or_lint(cx, item)
- {
- let version = get_lint_version(cx, item);
-
- self.lints.push(LintMetadata::new(
- lint_name,
- SerializableSpan::from_item(cx, item),
- DEPRECATED_LINT_GROUP_STR.to_string(),
- DEPRECATED_LINT_LEVEL,
- version,
- raw_docs,
- ));
- }
}
}
@@ -684,6 +690,11 @@ fn cleanup_docs(docs_collection: &Vec<String>) -> String {
.find(|&s| !matches!(s, "" | "ignore" | "no_run" | "should_panic"))
// if no language is present, fill in "rust"
.unwrap_or("rust");
+ let len_diff = line.len() - line.trim_start().len();
+ if len_diff != 0 {
+ // We put back the indentation.
+ docs.push_str(&line[..len_diff]);
+ }
docs.push_str("```");
docs.push_str(lang);
@@ -766,16 +777,6 @@ fn get_lint_level_from_group(lint_group: &str) -> Option<&'static str> {
.find_map(|(group_name, group_level)| (*group_name == lint_group).then_some(*group_level))
}
-pub(super) fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
- if let hir::TyKind::Path(ref path) = ty.kind {
- if let hir::def::Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, ty.hir_id) {
- return match_def_path(cx, def_id, &DEPRECATED_LINT_TYPE);
- }
- }
-
- false
-}
-
fn collect_renames(lints: &mut Vec<LintMetadata>) {
for lint in lints {
let mut collected = String::new();
@@ -783,7 +784,7 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
loop {
if let Some(lint_name) = names.pop() {
- for (k, v) in RENAMED_LINTS {
+ for (k, v) in crate::deprecated_lints::RENAMED {
if let Some(name) = v.strip_prefix(CLIPPY_LINT_GROUP_PREFIX)
&& name == lint_name
&& let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX)
@@ -1055,33 +1056,21 @@ fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
return;
}
- match &expr.kind {
- ExprKind::Call(fn_expr, _args) => {
- let found_function = SUGGESTION_FUNCTIONS
- .iter()
- .any(|func_path| match_function_call(self.cx, fn_expr, func_path).is_some());
- if found_function {
- // These functions are all multi part suggestions
- self.add_single_span_suggestion();
- }
- },
- ExprKind::MethodCall(path, recv, _, _arg_span) => {
- let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv));
- if match_type(self.cx, self_ty, &paths::DIAG) {
- let called_method = path.ident.name.as_str().to_string();
- for (method_name, is_multi_part) in &SUGGESTION_DIAG_METHODS {
- if *method_name == called_method {
- if *is_multi_part {
- self.add_multi_part_suggestion();
- } else {
- self.add_single_span_suggestion();
- }
- break;
+ if let ExprKind::MethodCall(path, recv, _, _arg_span) = &expr.kind {
+ let (self_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(recv));
+ if match_type(self.cx, self_ty, &paths::DIAG) {
+ let called_method = path.ident.name.as_str().to_string();
+ for (method_name, is_multi_part) in &SUGGESTION_DIAG_METHODS {
+ if *method_name == called_method {
+ if *is_multi_part {
+ self.add_multi_part_suggestion();
+ } else {
+ self.add_single_span_suggestion();
}
+ break;
}
}
- },
- _ => {},
+ }
}
intravisit::walk_expr(self, expr);
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index a831234..228db14 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -3,7 +3,7 @@
use clippy_config::msrvs::{self, Msrv};
use clippy_config::Conf;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_copy;
@@ -159,7 +159,7 @@ fn check_vec_macro<'tcx>(
let snippet = match *vec_args {
higher::VecArgs::Repeat(elem, len) => {
- if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
+ if let Some(Constant::Int(len_constant)) = ConstEvalCtxt::new(cx).eval(len) {
// vec![ty; N] works when ty is Clone, [ty; N] requires it to be Copy also
if !is_copy(cx, cx.typeck_results().expr_ty(elem)) {
return;
diff --git a/src/tools/clippy/clippy_lints/src/visibility.rs b/src/tools/clippy/clippy_lints/src/visibility.rs
index 11dccec..63f3a5d 100644
--- a/src/tools/clippy/clippy_lints/src/visibility.rs
+++ b/src/tools/clippy/clippy_lints/src/visibility.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Item, VisibilityKind};
use rustc_errors::Applicability;
@@ -85,14 +85,19 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if **path == kw::SelfLower
&& let Some(false) = is_from_proc_macro(cx, item.vis.span)
{
- span_lint_and_sugg(
+ span_lint_and_then(
cx,
NEEDLESS_PUB_SELF,
item.vis.span,
format!("unnecessary `pub({}self)`", if *shorthand { "" } else { "in " }),
- "remove it",
- String::new(),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion_hidden(
+ item.vis.span,
+ "remove it",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ },
);
}
@@ -101,14 +106,20 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
&& let [.., last] = &*path.segments
&& let Some(false) = is_from_proc_macro(cx, item.vis.span)
{
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
PUB_WITHOUT_SHORTHAND,
item.vis.span,
"usage of `pub` with `in`",
- "remove it",
- format!("pub({})", last.ident),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion(
+ item.vis.span,
+ "remove it",
+ format!("pub({})", last.ident),
+ Applicability::MachineApplicable,
+ );
+ },
);
}
@@ -116,14 +127,20 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
&& let [.., last] = &*path.segments
&& let Some(false) = is_from_proc_macro(cx, item.vis.span)
{
- span_lint_and_sugg(
+ #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+ span_lint_and_then(
cx,
PUB_WITH_SHORTHAND,
item.vis.span,
"usage of `pub` without `in`",
- "add it",
- format!("pub(in {})", last.ident),
- Applicability::MachineApplicable,
+ |diag| {
+ diag.span_suggestion(
+ item.vis.span,
+ "add it",
+ format!("pub(in {})", last.ident),
+ Applicability::MachineApplicable,
+ );
+ },
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
index 60d8a13..5eb207a 100644
--- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::consts::{ConstEvalCtxt, Constant};
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@@ -36,8 +36,9 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// TODO - constant_simple does not fold many operations involving floats.
// That's probably fine for this lint - it's pretty unlikely that someone would
// do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
- && let Some(lhs_value) = constant_simple(cx, cx.typeck_results(), left)
- && let Some(rhs_value) = constant_simple(cx, cx.typeck_results(), right)
+ && let ecx = ConstEvalCtxt::new(cx)
+ && let Some(lhs_value) = ecx.eval_simple(left)
+ && let Some(rhs_value) = ecx.eval_simple(right)
// FIXME(f16_f128): add these types when eq is available on all platforms
&& (Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value)
&& (Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value)
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index f0c64fd..9fefd94 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -12,9 +12,6 @@
# FIXME(f16_f128): remove when no longer needed for parsing
rustc_apfloat = "0.2.0"
-[features]
-deny-warnings = ["clippy_config/deny-warnings"]
-
[package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)]
rustc_private = true
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index de6ccfe..e907e40 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -14,12 +14,13 @@
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{alloc_range, Scalar};
use rustc_middle::mir::ConstValue;
-use rustc_middle::ty::{self, EarlyBinder, FloatTy, GenericArgsRef, IntTy, List, ScalarInt, Ty, TyCtxt, UintTy};
+use rustc_middle::ty::{self, FloatTy, IntTy, ParamEnv, ScalarInt, Ty, TyCtxt, TypeckResults, UintTy};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::def_id::DefId;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::Ident;
use rustc_span::{sym, SyntaxContext};
use rustc_target::abi::Size;
+use std::cell::Cell;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::iter;
@@ -263,10 +264,10 @@ pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self)
}
/// Returns the integer value or `None` if `self` or `val_type` is not integer type.
- pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option<FullInt> {
+ pub fn int_value(&self, tcx: TyCtxt<'_>, val_type: Ty<'_>) -> Option<FullInt> {
if let Constant::Int(const_int) = *self {
match *val_type.kind() {
- ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
+ ty::Int(ity) => Some(FullInt::S(sext(tcx, const_int, ity))),
ty::Uint(_) => Some(FullInt::U(const_int)),
_ => None,
}
@@ -322,6 +323,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option<Ty<'tcx>>) -> Constan
}
/// The source of a constant value.
+#[derive(Clone, Copy)]
pub enum ConstantSource {
/// The value is determined solely from the expression.
Local,
@@ -331,54 +333,11 @@ pub enum ConstantSource {
CoreConstant,
}
impl ConstantSource {
- pub fn is_local(&self) -> bool {
+ pub fn is_local(self) -> bool {
matches!(self, Self::Local)
}
}
-/// Attempts to check whether the expression is a constant representing an empty slice, str, array,
-/// etc…
-pub fn constant_is_empty(lcx: &LateContext<'_>, e: &Expr<'_>) -> Option<bool> {
- ConstEvalLateContext::new(lcx, lcx.typeck_results()).expr_is_empty(e)
-}
-
-/// Attempts to evaluate the expression as a constant.
-pub fn constant<'tcx>(
- lcx: &LateContext<'tcx>,
- typeck_results: &ty::TypeckResults<'tcx>,
- e: &Expr<'_>,
-) -> Option<Constant<'tcx>> {
- ConstEvalLateContext::new(lcx, typeck_results).expr(e)
-}
-
-/// Attempts to evaluate the expression as a constant.
-pub fn constant_with_source<'tcx>(
- lcx: &LateContext<'tcx>,
- typeck_results: &ty::TypeckResults<'tcx>,
- e: &Expr<'_>,
-) -> Option<(Constant<'tcx>, ConstantSource)> {
- let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
- let res = ctxt.expr(e);
- res.map(|x| (x, ctxt.source))
-}
-
-/// Attempts to evaluate an expression only if its value is not dependent on other items.
-pub fn constant_simple<'tcx>(
- lcx: &LateContext<'tcx>,
- typeck_results: &ty::TypeckResults<'tcx>,
- e: &Expr<'_>,
-) -> Option<Constant<'tcx>> {
- constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
-}
-
-pub fn constant_full_int<'tcx>(
- lcx: &LateContext<'tcx>,
- typeck_results: &ty::TypeckResults<'tcx>,
- e: &Expr<'_>,
-) -> Option<FullInt> {
- constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e))
-}
-
#[derive(Copy, Clone, Debug, Eq)]
pub enum FullInt {
S(i128),
@@ -417,44 +376,87 @@ fn cmp_s_u(s: i128, u: u128) -> Ordering {
}
}
-pub struct ConstEvalLateContext<'a, 'tcx> {
- lcx: &'a LateContext<'tcx>,
- typeck_results: &'a ty::TypeckResults<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- source: ConstantSource,
- args: GenericArgsRef<'tcx>,
+/// The context required to evaluate a constant expression.
+///
+/// This is currently limited to constant folding and reading the value of named constants.
+pub struct ConstEvalCtxt<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ typeck: &'tcx TypeckResults<'tcx>,
+ source: Cell<ConstantSource>,
}
-impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
- pub fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
+impl<'tcx> ConstEvalCtxt<'tcx> {
+ /// Creates the evaluation context from the lint context. This requires the lint context to be
+ /// in a body (i.e. `cx.enclosing_body.is_some()`).
+ pub fn new(cx: &LateContext<'tcx>) -> Self {
Self {
- lcx,
- typeck_results,
- param_env: lcx.param_env,
- source: ConstantSource::Local,
- args: List::empty(),
+ tcx: cx.tcx,
+ param_env: cx.param_env,
+ typeck: cx.typeck_results(),
+ source: Cell::new(ConstantSource::Local),
+ }
+ }
+
+ /// Creates an evaluation context.
+ pub fn with_env(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, typeck: &'tcx TypeckResults<'tcx>) -> Self {
+ Self {
+ tcx,
+ param_env,
+ typeck,
+ source: Cell::new(ConstantSource::Local),
+ }
+ }
+
+ /// Attempts to evaluate the expression and returns both the value and whether it's dependant on
+ /// other items.
+ pub fn eval_with_source(&self, e: &Expr<'_>) -> Option<(Constant<'tcx>, ConstantSource)> {
+ self.source.set(ConstantSource::Local);
+ self.expr(e).map(|c| (c, self.source.get()))
+ }
+
+ /// Attempts to evaluate the expression.
+ pub fn eval(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
+ self.expr(e)
+ }
+
+ /// Attempts to evaluate the expression without accessing other items.
+ pub fn eval_simple(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
+ match self.eval_with_source(e) {
+ Some((x, ConstantSource::Local)) => Some(x),
+ _ => None,
+ }
+ }
+
+ /// Attempts to evaluate the expression as an integer without accessing other items.
+ pub fn eval_full_int(&self, e: &Expr<'_>) -> Option<FullInt> {
+ match self.eval_with_source(e) {
+ Some((x, ConstantSource::Local)) => x.int_value(self.tcx, self.typeck.expr_ty(e)),
+ _ => None,
}
}
/// Simple constant folding: Insert an expression, get a constant or none.
- pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
+ fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
match e.kind {
- ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.lcx.tcx.hir().body(body).value),
+ ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
ExprKind::DropTemps(e) => self.expr(e),
ExprKind::Path(ref qpath) => {
- let is_core_crate = if let Some(def_id) = self.lcx.qpath_res(qpath, e.hir_id()).opt_def_id() {
- self.lcx.tcx.crate_name(def_id.krate) == sym::core
+ let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, e.hir_id()).opt_def_id() {
+ self.tcx.crate_name(def_id.krate) == sym::core
} else {
false
};
- self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
- let result = mir_to_const(this.lcx, result)?;
+ self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| {
+ let result = mir_to_const(self_.tcx, result)?;
// If source is already Constant we wouldn't want to override it with CoreConstant
- this.source = if is_core_crate && !matches!(this.source, ConstantSource::Constant) {
- ConstantSource::CoreConstant
- } else {
- ConstantSource::Constant
- };
+ self_.source.set(
+ if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
+ ConstantSource::CoreConstant
+ } else {
+ ConstantSource::Constant
+ },
+ );
Some(result)
})
},
@@ -463,21 +465,21 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
if is_direct_expn_of(e.span, "cfg").is_some() {
None
} else {
- Some(lit_to_mir_constant(&lit.node, self.typeck_results.expr_ty_opt(e)))
+ Some(lit_to_mir_constant(&lit.node, self.typeck.expr_ty_opt(e)))
}
},
ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),
ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
ExprKind::Repeat(value, _) => {
- let n = match self.typeck_results.expr_ty(e).kind() {
- ty::Array(_, n) => n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)?,
+ let n = match self.typeck.expr_ty(e).kind() {
+ ty::Array(_, n) => n.try_eval_target_usize(self.tcx, self.param_env)?,
_ => span_bug!(e.span, "typeck error"),
};
self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
},
ExprKind::Unary(op, operand) => self.expr(operand).and_then(|o| match op {
- UnOp::Not => self.constant_not(&o, self.typeck_results.expr_ty(e)),
- UnOp::Neg => self.constant_negate(&o, self.typeck_results.expr_ty(e)),
+ UnOp::Not => self.constant_not(&o, self.typeck.expr_ty(e)),
+ UnOp::Neg => self.constant_negate(&o, self.typeck.expr_ty(e)),
UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }),
}),
ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
@@ -486,21 +488,16 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
// We only handle a few const functions for now.
if args.is_empty()
&& let ExprKind::Path(qpath) = &callee.kind
- && let res = self.typeck_results.qpath_res(qpath, callee.hir_id)
- && let Some(def_id) = res.opt_def_id()
- && let def_path = self.lcx.get_def_path(def_id)
- && let def_path = def_path.iter().take(4).map(Symbol::as_str).collect::<Vec<_>>()
- && let ["core", "num", int_impl, "max_value"] = *def_path
+ && let Some(did) = self.typeck.qpath_res(qpath, callee.hir_id).opt_def_id()
{
- let value = match int_impl {
- "<impl i8>" => i8::MAX as u128,
- "<impl i16>" => i16::MAX as u128,
- "<impl i32>" => i32::MAX as u128,
- "<impl i64>" => i64::MAX as u128,
- "<impl i128>" => i128::MAX as u128,
- _ => return None,
- };
- Some(Constant::Int(value))
+ match self.tcx.get_diagnostic_name(did) {
+ Some(sym::i8_legacy_fn_max_value) => Some(Constant::Int(i8::MAX as u128)),
+ Some(sym::i16_legacy_fn_max_value) => Some(Constant::Int(i16::MAX as u128)),
+ Some(sym::i32_legacy_fn_max_value) => Some(Constant::Int(i32::MAX as u128)),
+ Some(sym::i64_legacy_fn_max_value) => Some(Constant::Int(i64::MAX as u128)),
+ Some(sym::i128_legacy_fn_max_value) => Some(Constant::Int(i128::MAX as u128)),
+ _ => None,
+ }
} else {
None
}
@@ -512,9 +509,9 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
if let Some(Constant::Adt(constant)) = &self.expr(local_expr)
&& let ty::Adt(adt_def, _) = constant.ty().kind()
&& adt_def.is_struct()
- && let Some(desired_field) = field_of_struct(*adt_def, self.lcx, *constant, field)
+ && let Some(desired_field) = field_of_struct(*adt_def, self.tcx, *constant, field)
{
- mir_to_const(self.lcx, desired_field)
+ mir_to_const(self.tcx, desired_field)
} else {
result
}
@@ -526,21 +523,21 @@ pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
/// Simple constant folding to determine if an expression is an empty slice, str, array, …
/// `None` will be returned if the constness cannot be determined, or if the resolution
/// leaves the local crate.
- pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
+ pub fn eval_is_empty(&self, e: &Expr<'_>) -> Option<bool> {
match e.kind {
- ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr_is_empty(self.lcx.tcx.hir().body(body).value),
- ExprKind::DropTemps(e) => self.expr_is_empty(e),
+ ExprKind::ConstBlock(ConstBlock { body, .. }) => self.eval_is_empty(self.tcx.hir().body(body).value),
+ ExprKind::DropTemps(e) => self.eval_is_empty(e),
ExprKind::Path(ref qpath) => {
if !self
- .typeck_results
+ .typeck
.qpath_res(qpath, e.hir_id)
.opt_def_id()
.is_some_and(DefId::is_local)
{
return None;
}
- self.fetch_path_and_apply(qpath, e.hir_id, self.typeck_results.expr_ty(e), |this, result| {
- mir_is_empty(this.lcx, result)
+ self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| {
+ mir_is_empty(self_.tcx, result)
})
},
ExprKind::Lit(lit) => {
@@ -556,8 +553,8 @@ pub fn expr_is_empty(&mut self, e: &Expr<'_>) -> Option<bool> {
},
ExprKind::Array(vec) => self.multi(vec).map(|v| v.is_empty()),
ExprKind::Repeat(..) => {
- if let ty::Array(_, n) = self.typeck_results.expr_ty(e).kind() {
- Some(n.try_eval_target_usize(self.lcx.tcx, self.lcx.param_env)? == 0)
+ if let ty::Array(_, n) = self.typeck.expr_ty(e).kind() {
+ Some(n.try_eval_target_usize(self.tcx, self.param_env)? == 0)
} else {
span_bug!(e.span, "typeck error");
}
@@ -574,8 +571,8 @@ fn constant_not(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tcx>>
Int(value) => {
let value = !value;
match *ty.kind() {
- ty::Int(ity) => Some(Int(unsext(self.lcx.tcx, value as i128, ity))),
- ty::Uint(ity) => Some(Int(clip(self.lcx.tcx, value, ity))),
+ ty::Int(ity) => Some(Int(unsext(self.tcx, value as i128, ity))),
+ ty::Uint(ity) => Some(Int(clip(self.tcx, value, ity))),
_ => None,
}
},
@@ -590,7 +587,7 @@ fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tc
let ty::Int(ity) = *ty.kind() else { return None };
let (min, _) = ity.min_max()?;
// sign extend
- let value = sext(self.lcx.tcx, value, ity);
+ let value = sext(self.tcx, value, ity);
// Applying unary - to the most negative value of any signed integer type panics.
if value == min {
@@ -599,7 +596,7 @@ fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tc
let value = value.checked_neg()?;
// clear unused bits
- Some(Int(unsext(self.lcx.tcx, value, ity)))
+ Some(Int(unsext(self.tcx, value, ity)))
},
F32(f) => Some(F32(-f)),
F64(f) => Some(F64(-f)),
@@ -609,21 +606,21 @@ fn constant_negate(&self, o: &Constant<'tcx>, ty: Ty<'_>) -> Option<Constant<'tc
/// Create `Some(Vec![..])` of all constants, unless there is any
/// non-constant part.
- fn multi(&mut self, vec: &[Expr<'_>]) -> Option<Vec<Constant<'tcx>>> {
+ fn multi(&self, vec: &[Expr<'_>]) -> Option<Vec<Constant<'tcx>>> {
vec.iter().map(|elem| self.expr(elem)).collect::<Option<_>>()
}
/// Lookup a possibly constant expression from an `ExprKind::Path` and apply a function on it.
- fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option<T>
+ fn fetch_path_and_apply<T, F>(&self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>, f: F) -> Option<T>
where
- F: FnOnce(&mut Self, mir::Const<'tcx>) -> Option<T>,
+ F: FnOnce(&Self, mir::Const<'tcx>) -> Option<T>,
{
- let res = self.typeck_results.qpath_res(qpath, id);
+ let res = self.typeck.qpath_res(qpath, id);
match res {
Res::Def(DefKind::Const | DefKind::AssocConst, def_id) => {
// Check if this constant is based on `cfg!(..)`,
// which is NOT constant for our purposes.
- if let Some(node) = self.lcx.tcx.hir().get_if_local(def_id)
+ if let Some(node) = self.tcx.hir().get_if_local(def_id)
&& let Node::Item(Item {
kind: ItemKind::Const(.., body_id),
..
@@ -632,20 +629,14 @@ fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'t
kind: ExprKind::Lit(_),
span,
..
- }) = self.lcx.tcx.hir_node(body_id.hir_id)
+ }) = self.tcx.hir_node(body_id.hir_id)
&& is_direct_expn_of(*span, "cfg").is_some()
{
return None;
}
- let args = self.typeck_results.node_args(id);
- let args = if self.args.is_empty() {
- args
- } else {
- EarlyBinder::bind(args).instantiate(self.lcx.tcx, self.args)
- };
+ let args = self.typeck.node_args(id);
let result = self
- .lcx
.tcx
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), qpath.span())
.ok()
@@ -656,7 +647,7 @@ fn fetch_path_and_apply<T, F>(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'t
}
}
- fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant<'tcx>> {
+ fn index(&self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant<'tcx>> {
let lhs = self.expr(lhs);
let index = self.expr(index);
@@ -685,8 +676,8 @@ fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant<'
}
}
- /// A block can only yield a constant if it only has one constant expression.
- fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
+ /// A block can only yield a constant if it has exactly one constant expression.
+ fn block(&self, block: &Block<'_>) -> Option<Constant<'tcx>> {
if block.stmts.is_empty()
&& let Some(expr) = block.expr
{
@@ -696,7 +687,7 @@ fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
&& let expr_lo = expr_span.lo()
&& expr_lo >= span.lo
- && let Some(src) = (span.lo..expr_lo).get_source_text(self.lcx)
+ && let Some(src) = (span.lo..expr_lo).get_source_text(&self.tcx)
&& let Some(src) = src.as_str()
{
use rustc_lexer::TokenKind::{BlockComment, LineComment, OpenBrace, Semi, Whitespace};
@@ -705,11 +696,11 @@ fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
.filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
.eq([OpenBrace])
{
- self.source = ConstantSource::Constant;
+ self.source.set(ConstantSource::Constant);
}
} else {
// Unable to access the source. Assume a non-local dependency.
- self.source = ConstantSource::Constant;
+ self.source.set(ConstantSource::Constant);
}
}
@@ -719,7 +710,7 @@ fn block(&mut self, block: &Block<'_>) -> Option<Constant<'tcx>> {
}
}
- fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant<'tcx>> {
+ fn ifthenelse(&self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant<'tcx>> {
if let Some(Constant::Bool(b)) = self.expr(cond) {
if b {
self.expr(then)
@@ -731,16 +722,16 @@ fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Ex
}
}
- fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> {
+ fn binop(&self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Constant<'tcx>> {
let l = self.expr(left)?;
let r = self.expr(right);
match (l, r) {
- (Constant::Int(l), Some(Constant::Int(r))) => match *self.typeck_results.expr_ty_opt(left)?.kind() {
+ (Constant::Int(l), Some(Constant::Int(r))) => match *self.typeck.expr_ty_opt(left)?.kind() {
ty::Int(ity) => {
let (ty_min_value, _) = ity.min_max()?;
let bits = ity.bits();
- let l = sext(self.lcx.tcx, l, ity);
- let r = sext(self.lcx.tcx, r, ity);
+ let l = sext(self.tcx, l, ity);
+ let r = sext(self.tcx, r, ity);
// Using / or %, where the left-hand argument is the smallest integer of a signed integer type and
// the right-hand argument is -1 always panics, even with overflow-checks disabled
@@ -751,7 +742,7 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
return None;
}
- let zext = |n: i128| Constant::Int(unsext(self.lcx.tcx, n, ity));
+ let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
match op.node {
// When +, * or binary - create a value greater than the maximum value, or less than
// the minimum value that can be stored, it panics.
@@ -845,7 +836,7 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
}
}
-pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
+pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
let mir::Const::Val(val, _) = result else {
// We only work on evaluated consts.
return None;
@@ -863,13 +854,13 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
_ => None,
},
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
- let data = val.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
+ let data = val.try_get_slice_bytes_for_diagnostics(tcx)?;
String::from_utf8(data.to_owned()).ok().map(Constant::Str)
},
(_, ty::Adt(adt_def, _)) if adt_def.is_struct() => Some(Constant::Adt(result)),
(ConstValue::Indirect { alloc_id, offset }, ty::Array(sub_type, len)) => {
- let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
- let len = len.try_to_target_usize(lcx.tcx)?;
+ let alloc = tcx.global_alloc(alloc_id).unwrap_memory().inner();
+ let len = len.try_to_target_usize(tcx)?;
let ty::Float(flt) = sub_type.kind() else {
return None;
};
@@ -877,7 +868,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
let mut res = Vec::new();
for idx in 0..len {
let range = alloc_range(offset + size * idx, size);
- let val = alloc.read_scalar(&lcx.tcx, range, /* read_provenance */ false).ok()?;
+ let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?;
res.push(match flt {
FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().ok()?)),
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().ok()?)),
@@ -891,7 +882,7 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
}
}
-fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<bool> {
+fn mir_is_empty<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option<bool> {
let mir::Const::Val(val, _) = result else {
// We only work on evaluated consts.
return None;
@@ -902,26 +893,26 @@ fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Opti
if let ConstValue::Indirect { alloc_id, offset } = val {
// Get the length from the slice, using the same formula as
// [`ConstValue::try_get_slice_bytes_for_diagnostics`].
- let a = lcx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
- let ptr_size = lcx.tcx.data_layout.pointer_size;
+ let a = tcx.global_alloc(alloc_id).unwrap_memory().inner();
+ let ptr_size = tcx.data_layout.pointer_size;
if a.size() < offset + 2 * ptr_size {
// (partially) dangling reference
return None;
}
let len = a
- .read_scalar(&lcx.tcx, alloc_range(offset + ptr_size, ptr_size), false)
+ .read_scalar(&tcx, alloc_range(offset + ptr_size, ptr_size), false)
.ok()?
- .to_target_usize(&lcx.tcx)
+ .to_target_usize(&tcx)
.ok()?;
Some(len == 0)
} else {
None
}
},
- ty::Array(_, len) => Some(len.try_to_target_usize(lcx.tcx)? == 0),
+ ty::Array(_, len) => Some(len.try_to_target_usize(tcx)? == 0),
_ => None,
},
- (ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(lcx.tcx)? == 0),
+ (ConstValue::Indirect { .. }, ty::Array(_, len)) => Some(len.try_to_target_usize(tcx)? == 0),
(ConstValue::ZeroSized, _) => Some(true),
_ => None,
}
@@ -929,12 +920,12 @@ fn mir_is_empty<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Opti
fn field_of_struct<'tcx>(
adt_def: ty::AdtDef<'tcx>,
- lcx: &LateContext<'tcx>,
+ tcx: TyCtxt<'tcx>,
result: mir::Const<'tcx>,
field: &Ident,
) -> Option<mir::Const<'tcx>> {
if let mir::Const::Val(result, ty) = result
- && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_user_output(result, ty)
+ && let Some(dc) = tcx.try_destructure_mir_constant_for_user_output(result, ty)
&& let Some(dc_variant) = dc.variant
&& let Some(variant) = adt_def.variants().get(dc_variant)
&& let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 0641d37..4877fb6 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -330,32 +330,3 @@ pub fn span_lint_and_sugg<T: LintContext>(
diag.span_suggestion(sp, help.into(), sugg, applicability);
});
}
-
-/// Create a suggestion made from several `span → replacement`.
-///
-/// Note: in the JSON format (used by `compiletest_rs`), the help message will
-/// appear once per
-/// replacement. In human-readable format though, it only appears once before
-/// the whole suggestion.
-pub fn multispan_sugg<I>(diag: &mut Diag<'_, ()>, help_msg: impl Into<SubdiagMessage>, sugg: I)
-where
- I: IntoIterator<Item = (Span, String)>,
-{
- multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg);
-}
-
-/// Create a suggestion made from several `span → replacement`.
-///
-/// rustfix currently doesn't support the automatic application of suggestions with
-/// multiple spans. This is tracked in issue [rustfix#141](https://github.com/rust-lang/rustfix/issues/141).
-/// Suggestions with multiple spans will be silently ignored.
-pub fn multispan_sugg_with_applicability<I>(
- diag: &mut Diag<'_, ()>,
- help_msg: impl Into<SubdiagMessage>,
- applicability: Applicability,
- sugg: I,
-) where
- I: IntoIterator<Item = (Span, String)>,
-{
- diag.multipart_suggestion(help_msg.into(), sugg.into_iter().collect(), applicability);
-}
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 6c40029..a6dd12a 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -9,7 +9,7 @@
//! - or-fun-call
//! - option-if-let-else
-use crate::consts::{constant, FullInt};
+use crate::consts::{ConstEvalCtxt, FullInt};
use crate::ty::{all_predicates_of, is_copy};
use crate::visitors::is_const_evaluatable;
use rustc_hir::def::{DefKind, Res};
@@ -206,7 +206,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
},
// `-i32::MIN` panics with overflow checks
- ExprKind::Unary(UnOp::Neg, right) if constant(self.cx, self.cx.typeck_results(), right).is_none() => {
+ ExprKind::Unary(UnOp::Neg, right) if ConstEvalCtxt::new(self.cx).eval(right).is_none() => {
self.eagerness |= NoChange;
},
@@ -232,7 +232,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
// Thus, we would realistically only delay the lint.
ExprKind::Binary(op, _, right)
if matches!(op.node, BinOpKind::Shl | BinOpKind::Shr)
- && constant(self.cx, self.cx.typeck_results(), right).is_none() =>
+ && ConstEvalCtxt::new(self.cx).eval(right).is_none() =>
{
self.eagerness |= NoChange;
},
@@ -240,9 +240,9 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
ExprKind::Binary(op, left, right)
if matches!(op.node, BinOpKind::Div | BinOpKind::Rem)
&& let right_ty = self.cx.typeck_results().expr_ty(right)
- && let left = constant(self.cx, self.cx.typeck_results(), left)
- && let right = constant(self.cx, self.cx.typeck_results(), right)
- .and_then(|c| c.int_value(self.cx, right_ty))
+ && let ecx = ConstEvalCtxt::new(self.cx)
+ && let left = ecx.eval(left)
+ && let right = ecx.eval(right).and_then(|c| c.int_value(self.cx.tcx, right_ty))
&& matches!(
(left, right),
// `1 / x`: x might be zero
@@ -261,8 +261,8 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
ExprKind::Binary(op, left, right)
if matches!(op.node, BinOpKind::Add | BinOpKind::Sub | BinOpKind::Mul)
&& !self.cx.typeck_results().expr_ty(e).is_floating_point()
- && (constant(self.cx, self.cx.typeck_results(), left).is_none()
- || constant(self.cx, self.cx.typeck_results(), right).is_none()) =>
+ && let ecx = ConstEvalCtxt::new(self.cx)
+ && (ecx.eval(left).is_none() || ecx.eval(right).is_none()) =>
{
self.eagerness |= NoChange;
},
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 277ba84..8970b4d 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -2,7 +2,7 @@
#![deny(clippy::missing_docs_in_private_items)]
-use crate::consts::{constant_simple, Constant};
+use crate::consts::{ConstEvalCtxt, Constant};
use crate::ty::is_type_diagnostic_item;
use crate::{is_expn_of, match_def_path, paths};
@@ -25,6 +25,8 @@ pub struct ForLoop<'tcx> {
pub loop_id: HirId,
/// entire `for` loop span
pub span: Span,
+ /// label
+ pub label: Option<ast::Label>,
}
impl<'tcx> ForLoop<'tcx> {
@@ -33,7 +35,7 @@ pub fn hir(expr: &Expr<'tcx>) -> Option<Self> {
if let ExprKind::DropTemps(e) = expr.kind
&& let ExprKind::Match(iterexpr, [arm], MatchSource::ForLoopDesugar) = e.kind
&& let ExprKind::Call(_, [arg]) = iterexpr.kind
- && let ExprKind::Loop(block, ..) = arm.body.kind
+ && let ExprKind::Loop(block, label, ..) = arm.body.kind
&& let [stmt] = block.stmts
&& let hir::StmtKind::Expr(e) = stmt.kind
&& let ExprKind::Match(_, [_, some_arm], _) = e.kind
@@ -45,6 +47,7 @@ pub fn hir(expr: &Expr<'tcx>) -> Option<Self> {
body: some_arm.body,
loop_id: arm.body.hir_id,
span: expr.span.ctxt().outer_expn_data().call_site,
+ label,
});
}
None
@@ -367,6 +370,7 @@ pub struct WhileLet<'hir> {
pub let_expr: &'hir Expr<'hir>,
/// `while let` loop body
pub if_then: &'hir Expr<'hir>,
+ pub label: Option<ast::Label>,
/// `while let PAT = EXPR`
/// ^^^^^^^^^^^^^^
pub let_span: Span,
@@ -399,7 +403,7 @@ pub const fn hir(expr: &Expr<'hir>) -> Option<Self> {
}),
..
},
- _,
+ label,
LoopSource::While,
_,
) = expr.kind
@@ -408,6 +412,7 @@ pub const fn hir(expr: &Expr<'hir>) -> Option<Self> {
let_pat,
let_expr,
if_then,
+ label,
let_span,
});
}
@@ -466,7 +471,7 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -
return Some(VecInitKind::Default);
} else if name.ident.name.as_str() == "with_capacity" {
let arg = args.first()?;
- return match constant_simple(cx, cx.typeck_results(), arg) {
+ return match ConstEvalCtxt::new(cx).eval_simple(arg) {
Some(Constant::Int(num)) => Some(VecInitKind::WithConstCapacity(num)),
_ => Some(VecInitKind::WithExprCapacity(arg.hir_id)),
};
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 28178a6..f325e4e 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,4 +1,4 @@
-use crate::consts::constant_simple;
+use crate::consts::ConstEvalCtxt;
use crate::macros::macro_backtrace;
use crate::source::{snippet_opt, walk_span_to_context, SpanRange, SpanRangeExt};
use crate::tokenize_with_text;
@@ -255,8 +255,8 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results
&& typeck_lhs.expr_ty(left) == typeck_rhs.expr_ty(right)
&& let (Some(l), Some(r)) = (
- constant_simple(self.inner.cx, typeck_lhs, left),
- constant_simple(self.inner.cx, typeck_rhs, right),
+ ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_lhs).eval_simple(left),
+ ConstEvalCtxt::with_env(self.inner.cx.tcx, self.inner.cx.param_env, typeck_rhs).eval_simple(right),
)
&& l == r
{
@@ -714,9 +714,9 @@ pub fn hash_block(&mut self, b: &Block<'_>) {
#[expect(clippy::too_many_lines)]
pub fn hash_expr(&mut self, e: &Expr<'_>) {
- let simple_const = self
- .maybe_typeck_results
- .and_then(|typeck_results| constant_simple(self.cx, typeck_results, e));
+ let simple_const = self.maybe_typeck_results.and_then(|typeck_results| {
+ ConstEvalCtxt::with_env(self.cx.tcx, self.cx.param_env, typeck_results).eval_simple(e)
+ });
// const hashing may result in the same hash as some unrelated node, so add a sort of
// discriminant depending on which path we're choosing next
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 3a9714c..28755ae 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -5,13 +5,11 @@
#![feature(f16)]
#![feature(if_let_guard)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
#![feature(never_type)]
#![feature(rustc_private)]
#![feature(assert_matches)]
#![feature(unwrap_infallible)]
#![recursion_limit = "512"]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![allow(
clippy::missing_errors_doc,
clippy::missing_panics_doc,
@@ -127,7 +125,7 @@
use rustc_target::abi::Integer;
use visitors::Visitable;
-use crate::consts::{constant, mir_to_const, Constant};
+use crate::consts::{mir_to_const, ConstEvalCtxt, Constant};
use crate::higher::Range;
use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type};
use crate::visitors::for_each_expr_without_closures;
@@ -212,20 +210,24 @@ pub fn local_is_initialized(cx: &LateContext<'_>, local: HirId) -> bool {
false
}
-/// Returns `true` if the given `HirId` is inside a constant context.
+/// Checks if we are currently in a const context (e.g. `const fn`, `static`/`const` initializer).
///
-/// This is the same as `is_inside_always_const_context`, but also includes
-/// `const fn`.
+/// The current context is determined based on the current body which is set before calling a lint's
+/// entry point (any function on `LateLintPass`). If you need to check in a different context use
+/// `tcx.hir().is_inside_const_context(_)`.
///
-/// # Example
-///
-/// ```rust,ignore
-/// if in_constant(cx, expr.hir_id) {
-/// // Do something
-/// }
-/// ```
-pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
- cx.tcx.hir().is_inside_const_context(id)
+/// Do not call this unless the `LateContext` has an enclosing body. For release build this case
+/// will safely return `false`, but debug builds will ICE. Note that `check_expr`, `check_block`,
+/// `check_pat` and a few other entry points will always have an enclosing body. Some entry points
+/// like `check_path` or `check_ty` may or may not have one.
+pub fn is_in_const_context(cx: &LateContext<'_>) -> bool {
+ debug_assert!(cx.enclosing_body.is_some(), "`LateContext` has no enclosing body");
+ cx.enclosing_body.is_some_and(|id| {
+ cx.tcx
+ .hir()
+ .body_const_context(cx.tcx.hir().body_owner_def_id(id))
+ .is_some()
+ })
}
/// Returns `true` if the given `HirId` is inside an always constant context.
@@ -590,9 +592,8 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<It
"u128" => SimplifiedType::Uint(UintTy::U128),
"f32" => SimplifiedType::Float(FloatTy::F32),
"f64" => SimplifiedType::Float(FloatTy::F64),
- #[allow(trivial_casts)]
_ => {
- return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_])
+ return Result::<&[_], rustc_errors::ErrorGuaranteed>::Ok(&[])
.into_iter()
.flatten()
.copied();
@@ -1580,8 +1581,8 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
if let rustc_ty::Adt(_, subst) = ty.kind()
&& let bnd_ty = subst.type_at(0)
&& let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
- && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, bnd_ty, cx.tcx))
- && let Some(start_const) = constant(cx, cx.typeck_results(), start)
+ && let Some(min_const) = mir_to_const(cx.tcx, Const::from_ty_const(min_val, bnd_ty, cx.tcx))
+ && let Some(start_const) = ConstEvalCtxt::new(cx).eval(start)
{
start_const == min_const
} else {
@@ -1593,8 +1594,8 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
if let rustc_ty::Adt(_, subst) = ty.kind()
&& let bnd_ty = subst.type_at(0)
&& let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
- && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, bnd_ty, cx.tcx))
- && let Some(end_const) = constant(cx, cx.typeck_results(), end)
+ && let Some(max_const) = mir_to_const(cx.tcx, Const::from_ty_const(max_val, bnd_ty, cx.tcx))
+ && let Some(end_const) = ConstEvalCtxt::new(cx).eval(end)
{
end_const == max_const
} else {
@@ -1625,7 +1626,9 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
return true;
}
let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
- if let Some(Constant::Int(v)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
+ if let Some(Constant::Int(v)) =
+ ConstEvalCtxt::with_env(cx.tcx, cx.tcx.param_env(enclosing_body), cx.tcx.typeck(enclosing_body)).eval(e)
+ {
return value == v;
}
false
@@ -2928,6 +2931,7 @@ pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> ExprU
moved_before_use,
same_ctxt,
},
+ #[allow(unreachable_patterns)]
Some(ControlFlow::Break(_)) => unreachable!("type of node is ControlFlow<!>"),
None => ExprUseCtxt {
node: Node::Crate(cx.tcx.hir().root_module()),
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index d5a3d8b..684c645 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -16,7 +16,6 @@
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
-pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index f206b2c..553af91 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -142,7 +142,7 @@ fn check_rvalue<'tcx>(
// We cannot allow this for now.
return Err((span, "unsizing casts are only allowed for references right now".into()));
};
- let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
+ let unsized_ty = tcx.struct_tail_for_codegen(pointee_ty, tcx.param_env(def_id));
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
check_operand(tcx, op, span, body, msrv)?;
// Casting/coercing things to slices is fine.
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 496c8f5..96dd3c5 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -6,7 +6,8 @@
use rustc_data_structures::sync::Lrc;
use rustc_errors::Applicability;
use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource};
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::{EarlyContext, LateContext};
+use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::source_map::{original_sp, SourceMap};
use rustc_span::{
@@ -17,6 +18,30 @@
use std::fmt;
use std::ops::Range;
+pub trait HasSession {
+ fn sess(&self) -> &Session;
+}
+impl HasSession for Session {
+ fn sess(&self) -> &Session {
+ self
+ }
+}
+impl HasSession for TyCtxt<'_> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+}
+impl HasSession for EarlyContext<'_> {
+ fn sess(&self) -> &Session {
+ ::rustc_lint::LintContext::sess(self)
+ }
+}
+impl HasSession for LateContext<'_> {
+ fn sess(&self) -> &Session {
+ self.tcx.sess()
+ }
+}
+
/// Conversion of a value into the range portion of a `Span`.
pub trait SpanRange: Sized {
fn into_range(self) -> Range<BytePos>;
@@ -71,19 +96,19 @@ fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
pub trait SpanRangeExt: SpanRange {
/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
/// extends through multiple files, or is malformed.
- fn get_source_text(self, cx: &impl LintContext) -> Option<SourceFileRange> {
+ fn get_source_text(self, cx: &impl HasSession) -> Option<SourceFileRange> {
get_source_text(cx.sess().source_map(), self.into_range())
}
/// Calls the given function with the source text referenced and returns the value. Returns
/// `None` if the source text cannot be retrieved.
- fn with_source_text<T>(self, cx: &impl LintContext, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
+ fn with_source_text<T>(self, cx: &impl HasSession, f: impl for<'a> FnOnce(&'a str) -> T) -> Option<T> {
with_source_text(cx.sess().source_map(), self.into_range(), f)
}
/// Checks if the referenced source text satisfies the given predicate. Returns `false` if the
/// source text cannot be retrieved.
- fn check_source_text(self, cx: &impl LintContext, pred: impl for<'a> FnOnce(&'a str) -> bool) -> bool {
+ fn check_source_text(self, cx: &impl HasSession, pred: impl for<'a> FnOnce(&'a str) -> bool) -> bool {
self.with_source_text(cx, pred).unwrap_or(false)
}
@@ -91,7 +116,7 @@ fn check_source_text(self, cx: &impl LintContext, pred: impl for<'a> FnOnce(&'a
/// and returns the value. Returns `None` if the source text cannot be retrieved.
fn with_source_text_and_range<T>(
self,
- cx: &impl LintContext,
+ cx: &impl HasSession,
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> T,
) -> Option<T> {
with_source_text_and_range(cx.sess().source_map(), self.into_range(), f)
@@ -104,30 +129,30 @@ fn with_source_text_and_range<T>(
/// The new range must reside within the same source file.
fn map_range(
self,
- cx: &impl LintContext,
+ cx: &impl HasSession,
f: impl for<'a> FnOnce(&'a str, Range<usize>) -> Option<Range<usize>>,
) -> Option<Range<BytePos>> {
map_range(cx.sess().source_map(), self.into_range(), f)
}
/// Extends the range to include all preceding whitespace characters.
- fn with_leading_whitespace(self, cx: &impl LintContext) -> Range<BytePos> {
+ fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
with_leading_whitespace(cx.sess().source_map(), self.into_range())
}
/// Trims the leading whitespace from the range.
- fn trim_start(self, cx: &impl LintContext) -> Range<BytePos> {
+ fn trim_start(self, cx: &impl HasSession) -> Range<BytePos> {
trim_start(cx.sess().source_map(), self.into_range())
}
/// Writes the referenced source text to the given writer. Will return `Err` if the source text
/// could not be retrieved.
- fn write_source_text_to(self, cx: &impl LintContext, dst: &mut impl fmt::Write) -> fmt::Result {
+ fn write_source_text_to(self, cx: &impl HasSession, dst: &mut impl fmt::Write) -> fmt::Result {
write_source_text_to(cx.sess().source_map(), self.into_range(), dst)
}
/// Extracts the referenced source text as an owned string.
- fn source_text_to_string(self, cx: &impl LintContext) -> Option<String> {
+ fn source_text_to_string(self, cx: &impl HasSession) -> Option<String> {
self.with_source_text(cx, ToOwned::to_owned)
}
}
@@ -227,15 +252,15 @@ pub fn as_str(&self) -> Option<&str> {
}
/// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
-pub fn expr_block<T: LintContext>(
- cx: &T,
+pub fn expr_block(
+ sess: &impl HasSession,
expr: &Expr<'_>,
outer: SyntaxContext,
default: &str,
indent_relative_to: Option<Span>,
app: &mut Applicability,
) -> String {
- let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app);
+ let (code, from_macro) = snippet_block_with_context(sess, expr.span, outer, default, indent_relative_to, app);
if !from_macro
&& let ExprKind::Block(block, _) = expr.kind
&& block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
@@ -260,13 +285,13 @@ pub fn expr_block<T: LintContext>(
/// let x = ();
/// // ^^^^^^^^^^
/// ```
-pub fn first_line_of_span<T: LintContext>(cx: &T, span: Span) -> Span {
- first_char_in_first_line(cx, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
+pub fn first_line_of_span(sess: &impl HasSession, span: Span) -> Span {
+ first_char_in_first_line(sess, span).map_or(span, |first_char_pos| span.with_lo(first_char_pos))
}
-fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePos> {
- let line_span = line_span(cx, span);
- snippet_opt(cx, line_span).and_then(|snip| {
+fn first_char_in_first_line(sess: &impl HasSession, span: Span) -> Option<BytePos> {
+ let line_span = line_span(sess, span);
+ snippet_opt(sess, line_span).and_then(|snip| {
snip.find(|c: char| !c.is_whitespace())
.map(|pos| line_span.lo() + BytePos::from_usize(pos))
})
@@ -281,9 +306,9 @@ fn first_char_in_first_line<T: LintContext>(cx: &T, span: Span) -> Option<BytePo
/// let x = ();
/// // ^^^^^^^^^^^^^^
/// ```
-fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
+fn line_span(sess: &impl HasSession, span: Span) -> Span {
let span = original_sp(span, DUMMY_SP);
- let SourceFileAndLine { sf, line } = cx.sess().source_map().lookup_line(span.lo()).unwrap();
+ let SourceFileAndLine { sf, line } = sess.sess().source_map().lookup_line(span.lo()).unwrap();
let line_start = sf.lines()[line];
let line_start = sf.absolute_position(line_start);
span.with_lo(line_start)
@@ -297,13 +322,13 @@ fn line_span<T: LintContext>(cx: &T, span: Span) -> Span {
/// let x = ();
/// // ^^ -- will return 4
/// ```
-pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
- snippet_opt(cx, line_span(cx, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
+pub fn indent_of(sess: &impl HasSession, span: Span) -> Option<usize> {
+ snippet_opt(sess, line_span(sess, span)).and_then(|snip| snip.find(|c: char| !c.is_whitespace()))
}
/// Gets a snippet of the indentation of the line of a span
-pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> {
- snippet_opt(cx, line_span(cx, span)).map(|mut s| {
+pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option<String> {
+ snippet_opt(sess, line_span(sess, span)).map(|mut s| {
let len = s.len() - s.trim_start().len();
s.truncate(len);
s
@@ -315,8 +340,8 @@ pub fn snippet_indent<T: LintContext>(cx: &T, span: Span) -> Option<String> {
// sources that the user has no control over.
// For some reason these attributes don't have any expansion info on them, so
// we have to check it this way until there is a better way.
-pub fn is_present_in_source<T: LintContext>(cx: &T, span: Span) -> bool {
- if let Some(snippet) = snippet_opt(cx, span) {
+pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool {
+ if let Some(snippet) = snippet_opt(sess, span) {
if snippet.is_empty() {
return false;
}
@@ -407,8 +432,8 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>,
/// snippet(cx, span1, "..") // -> "value"
/// snippet(cx, span2, "..") // -> "Vec::new()"
/// ```
-pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
- snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
+pub fn snippet<'a>(sess: &impl HasSession, span: Span, default: &'a str) -> Cow<'a, str> {
+ snippet_opt(sess, span).map_or_else(|| Cow::Borrowed(default), From::from)
}
/// Same as [`snippet`], but it adapts the applicability level by following rules:
@@ -417,13 +442,13 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
/// - If the default value is used and the applicability level is `MachineApplicable`, change it to
/// `HasPlaceholders`
-pub fn snippet_with_applicability<'a, T: LintContext>(
- cx: &T,
+pub fn snippet_with_applicability<'a>(
+ sess: &impl HasSession,
span: Span,
default: &'a str,
applicability: &mut Applicability,
) -> Cow<'a, str> {
- snippet_with_applicability_sess(cx.sess(), span, default, applicability)
+ snippet_with_applicability_sess(sess.sess(), span, default, applicability)
}
fn snippet_with_applicability_sess<'a>(
@@ -435,7 +460,7 @@ fn snippet_with_applicability_sess<'a>(
if *applicability != Applicability::Unspecified && span.from_expansion() {
*applicability = Applicability::MaybeIncorrect;
}
- snippet_opt_sess(sess, span).map_or_else(
+ snippet_opt(sess, span).map_or_else(
|| {
if *applicability == Applicability::MachineApplicable {
*applicability = Applicability::HasPlaceholders;
@@ -447,12 +472,8 @@ fn snippet_with_applicability_sess<'a>(
}
/// Converts a span to a code snippet. Returns `None` if not available.
-pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option<String> {
- snippet_opt_sess(cx.sess(), span)
-}
-
-fn snippet_opt_sess(sess: &Session, span: Span) -> Option<String> {
- sess.source_map().span_to_snippet(span).ok()
+pub fn snippet_opt(sess: &impl HasSession, span: Span) -> Option<String> {
+ sess.sess().source_map().span_to_snippet(span).ok()
}
/// Converts a span (from a block) to a code snippet if available, otherwise use default.
@@ -489,41 +510,41 @@ fn snippet_opt_sess(sess: &Session, span: Span) -> Option<String> {
/// } // aligned with `if`
/// ```
/// Note that the first line of the snippet always has 0 indentation.
-pub fn snippet_block<'a, T: LintContext>(
- cx: &T,
+pub fn snippet_block<'a>(
+ sess: &impl HasSession,
span: Span,
default: &'a str,
indent_relative_to: Option<Span>,
) -> Cow<'a, str> {
- let snip = snippet(cx, span, default);
- let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
+ let snip = snippet(sess, span, default);
+ let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
reindent_multiline(snip, true, indent)
}
/// Same as `snippet_block`, but adapts the applicability level by the rules of
/// `snippet_with_applicability`.
pub fn snippet_block_with_applicability<'a>(
- cx: &impl LintContext,
+ sess: &impl HasSession,
span: Span,
default: &'a str,
indent_relative_to: Option<Span>,
applicability: &mut Applicability,
) -> Cow<'a, str> {
- let snip = snippet_with_applicability(cx, span, default, applicability);
- let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
+ let snip = snippet_with_applicability(sess, span, default, applicability);
+ let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
reindent_multiline(snip, true, indent)
}
pub fn snippet_block_with_context<'a>(
- cx: &impl LintContext,
+ sess: &impl HasSession,
span: Span,
outer: SyntaxContext,
default: &'a str,
indent_relative_to: Option<Span>,
app: &mut Applicability,
) -> (Cow<'a, str>, bool) {
- let (snip, from_macro) = snippet_with_context(cx, span, outer, default, app);
- let indent = indent_relative_to.and_then(|s| indent_of(cx, s));
+ let (snip, from_macro) = snippet_with_context(sess, span, outer, default, app);
+ let indent = indent_relative_to.and_then(|s| indent_of(sess, s));
(reindent_multiline(snip, true, indent), from_macro)
}
@@ -537,13 +558,13 @@ pub fn snippet_block_with_context<'a>(
///
/// This will also return whether or not the snippet is a macro call.
pub fn snippet_with_context<'a>(
- cx: &impl LintContext,
+ sess: &impl HasSession,
span: Span,
outer: SyntaxContext,
default: &'a str,
applicability: &mut Applicability,
) -> (Cow<'a, str>, bool) {
- snippet_with_context_sess(cx.sess(), span, outer, default, applicability)
+ snippet_with_context_sess(sess.sess(), span, outer, default, applicability)
}
fn snippet_with_context_sess<'a>(
@@ -661,15 +682,15 @@ pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
/// writeln!(o, "") -> writeln!(o, "")
/// ^^ ^^^^
/// ```
-pub fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
- let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true);
+pub fn expand_past_previous_comma(sess: &impl HasSession, span: Span) -> Span {
+ let extended = sess.sess().source_map().span_extend_to_prev_char(span, ',', true);
extended.with_lo(extended.lo() - BytePos(1))
}
/// Converts `expr` to a `char` literal if it's a `str` literal containing a single
/// character (or a single byte with `ascii_only`)
pub fn str_literal_to_char_literal(
- cx: &LateContext<'_>,
+ sess: &impl HasSession,
expr: &Expr<'_>,
applicability: &mut Applicability,
ascii_only: bool,
@@ -684,7 +705,7 @@ pub fn str_literal_to_char_literal(
}
&& len == 1
{
- let snip = snippet_with_applicability(cx, expr.span, string, applicability);
+ let snip = snippet_with_applicability(sess, expr.span, string, applicability);
let ch = if let StrStyle::Raw(nhash) = style {
let nhash = nhash as usize;
// for raw string: r##"a"##
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 812fb64..bd48990 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -525,19 +525,6 @@ fn needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &m
needs_ordered_drop_inner(cx, ty, &mut FxHashSet::default())
}
-/// Peels off all references on the type. Returns the underlying type and the number of references
-/// removed.
-pub fn peel_mid_ty_refs(ty: Ty<'_>) -> (Ty<'_>, usize) {
- fn peel(ty: Ty<'_>, count: usize) -> (Ty<'_>, usize) {
- if let ty::Ref(_, ty, _) = ty.kind() {
- peel(*ty, count + 1)
- } else {
- (ty, count)
- }
- }
- peel(ty, 0)
-}
-
/// Peels off all references on the type. Returns the underlying type, the number of references
/// removed, and whether the pointer is ultimately mutable or not.
pub fn peel_mid_ty_refs_is_mutable(ty: Ty<'_>) -> (Ty<'_>, usize, Mutability) {
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 7066c9a..2a5d353 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -1,6 +1,7 @@
use crate::ty::needs_ordered_drop;
use crate::{get_enclosing_block, path_to_local_id};
use core::ops::ControlFlow;
+use rustc_ast::visit::{try_visit, VisitorResult};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
@@ -50,16 +51,17 @@ fn descend(&self) -> bool {
/// A type which can be visited.
pub trait Visitable<'tcx> {
/// Calls the corresponding `visit_*` function on the visitor.
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result;
}
impl<'tcx, T> Visitable<'tcx> for &'tcx [T]
where
&'tcx T: Visitable<'tcx>,
{
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
for x in self {
- x.visit(visitor);
+ try_visit!(x.visit(visitor));
}
+ V::Result::output()
}
}
impl<'tcx, A, B> Visitable<'tcx> for (A, B)
@@ -67,27 +69,28 @@ impl<'tcx, A, B> Visitable<'tcx> for (A, B)
A: Visitable<'tcx>,
B: Visitable<'tcx>,
{
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
let (a, b) = self;
- a.visit(visitor);
- b.visit(visitor);
+ try_visit!(a.visit(visitor));
+ b.visit(visitor)
}
}
impl<'tcx, T> Visitable<'tcx> for Option<T>
where
T: Visitable<'tcx>,
{
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
if let Some(x) = self {
- x.visit(visitor);
+ try_visit!(x.visit(visitor));
}
+ V::Result::output()
}
}
macro_rules! visitable_ref {
($t:ident, $f:ident) => {
impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
- visitor.$f(self);
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) -> V::Result {
+ visitor.$f(self)
}
}
};
@@ -104,45 +107,37 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
node: impl Visitable<'tcx>,
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
) -> Option<B> {
- struct V<B, F> {
+ struct V<F> {
f: F,
- res: Option<B>,
}
- impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<B, F> {
- type Result = ControlFlow<()>;
+ impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<F> {
+ type Result = ControlFlow<B>;
- fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> ControlFlow<()> {
- if self.res.is_some() {
- return ControlFlow::Break(());
- }
+ fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
match (self.f)(e) {
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
- ControlFlow::Break(b) => {
- self.res = Some(b);
- ControlFlow::Break(())
- },
+ ControlFlow::Break(b) => ControlFlow::Break(b),
ControlFlow::Continue(_) => ControlFlow::Continue(()),
}
}
// Avoid unnecessary `walk_*` calls.
- fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> ControlFlow<()> {
+ fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
ControlFlow::Continue(())
}
- fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> ControlFlow<()> {
+ fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
ControlFlow::Continue(())
}
- fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> ControlFlow<()> {
+ fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result {
ControlFlow::Continue(())
}
// Avoid monomorphising all `visit_*` functions.
- fn visit_nested_item(&mut self, _: ItemId) -> ControlFlow<()> {
+ fn visit_nested_item(&mut self, _: ItemId) -> Self::Result {
ControlFlow::Continue(())
}
}
- let mut v = V { f, res: None };
- node.visit(&mut v);
- v.res
+ let mut v = V { f };
+ node.visit(&mut v).break_value()
}
/// Calls the given function once for each expression contained. This will enter bodies, but not
@@ -152,44 +147,47 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
node: impl Visitable<'tcx>,
f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
) -> Option<B> {
- struct V<'tcx, B, F> {
+ struct V<'tcx, F> {
tcx: TyCtxt<'tcx>,
f: F,
- res: Option<B>,
}
- impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, B, F> {
+ impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, F> {
type NestedFilter = nested_filter::OnlyBodies;
+ type Result = ControlFlow<B>;
+
fn nested_visit_map(&mut self) -> Self::Map {
self.tcx.hir()
}
- fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
- if self.res.is_some() {
- return;
- }
+ fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) -> Self::Result {
match (self.f)(e) {
ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
- ControlFlow::Break(b) => self.res = Some(b),
- ControlFlow::Continue(_) => (),
+ ControlFlow::Break(b) => ControlFlow::Break(b),
+ ControlFlow::Continue(_) => ControlFlow::Continue(()),
}
}
// Only walk closures
- fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
+ fn visit_anon_const(&mut self, _: &'tcx AnonConst) -> Self::Result {
+ ControlFlow::Continue(())
+ }
// Avoid unnecessary `walk_*` calls.
- fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) {}
- fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
- fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
+ fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
+ ControlFlow::Continue(())
+ }
+ fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
+ ControlFlow::Continue(())
+ }
+ fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) -> Self::Result {
+ ControlFlow::Continue(())
+ }
// Avoid monomorphising all `visit_*` functions.
- fn visit_nested_item(&mut self, _: ItemId) {}
+ fn visit_nested_item(&mut self, _: ItemId) -> Self::Result {
+ ControlFlow::Continue(())
+ }
}
- let mut v = V {
- tcx: cx.tcx,
- f,
- res: None,
- };
- node.visit(&mut v);
- v.res
+ let mut v = V { tcx: cx.tcx, f };
+ node.visit(&mut v).break_value()
}
/// returns `true` if expr contains match expr desugared from try
diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml
index 80106f6..3127024 100644
--- a/src/tools/clippy/declare_clippy_lint/Cargo.toml
+++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml
@@ -11,6 +11,3 @@
itertools = "0.12"
quote = "1.0.21"
syn = "2.0"
-
-[features]
-deny-warnings = []
diff --git a/src/tools/clippy/declare_clippy_lint/src/lib.rs b/src/tools/clippy/declare_clippy_lint/src/lib.rs
index 25b2fc9..ca070f6 100644
--- a/src/tools/clippy/declare_clippy_lint/src/lib.rs
+++ b/src/tools/clippy/declare_clippy_lint/src/lib.rs
@@ -1,5 +1,4 @@
#![feature(let_chains)]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml
index 350418e..b0e4e3e 100644
--- a/src/tools/clippy/lintcheck/Cargo.toml
+++ b/src/tools/clippy/lintcheck/Cargo.toml
@@ -25,6 +25,3 @@
toml = "0.7.3"
ureq = { version = "2.2", features = ["json"] }
walkdir = "2.3"
-
-[features]
-deny-warnings = []
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index 6bec175..bd4fcc5 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -33,13 +33,13 @@ pub(crate) struct LintcheckConfig {
/// Runs cargo clippy --fix and checks if all suggestions apply
#[clap(long, conflicts_with("max_jobs"))]
pub fix: bool,
- /// Apply a filter to only collect specified lints, this also overrides `allow` attributes
+ /// Apply a filter to only collect specified lints
#[clap(long = "filter", value_name = "clippy_lint_name", use_value_delimiter = true)]
pub lint_filter: Vec<String>,
- /// Set all lints to the "warn" lint level, even resitriction ones. Usually,
- /// it's better to use `--filter` instead
+ /// Check all Clippy lints, by default only `clippy::all` and `clippy::pedantic` are checked.
+ /// Usually, it's better to use `--filter` instead
#[clap(long, conflicts_with("lint_filter"))]
- pub warn_all: bool,
+ pub all_lints: bool,
/// Set the output format of the log file
#[clap(long, short, default_value = "text")]
pub format: OutputFormat,
diff --git a/src/tools/clippy/lintcheck/src/input.rs b/src/tools/clippy/lintcheck/src/input.rs
index 3b26367..3383d50 100644
--- a/src/tools/clippy/lintcheck/src/input.rs
+++ b/src/tools/clippy/lintcheck/src/input.rs
@@ -98,12 +98,12 @@ pub fn read_crates(toml_path: &Path) -> (Vec<CrateWithSource>, RecursiveOptions)
let crate_list: SourceList =
toml::from_str(&toml_content).unwrap_or_else(|e| panic!("Failed to parse {}: \n{e}", toml_path.display()));
// parse the hashmap of the toml file into a list of crates
- let tomlcrates: Vec<TomlCrate> = crate_list.crates.into_values().collect();
+ let toml_crates: Vec<TomlCrate> = crate_list.crates.into_values().collect();
// flatten TomlCrates into CrateSources (one TomlCrates may represent several versions of a crate =>
- // multiple Cratesources)
+ // multiple CrateSources)
let mut crate_sources = Vec::new();
- for tk in tomlcrates {
+ for tk in toml_crates {
if let Some(ref path) = tk.path {
crate_sources.push(CrateWithSource {
name: tk.name.clone(),
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 0dd62de..acb6eaa 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -119,7 +119,8 @@ fn run_clippy_lints(
cmd.arg(if config.fix { "fix" } else { "check" })
.arg("--quiet")
.current_dir(&self.path)
- .env("CLIPPY_ARGS", clippy_args.join("__CLIPPY_HACKERY__"));
+ .env("CLIPPY_ARGS", clippy_args.join("__CLIPPY_HACKERY__"))
+ .env("CLIPPY_DISABLE_DOCS_LINKS", "1");
if let Some(server) = server {
// `cargo clippy` is a wrapper around `cargo check` that mainly sets `RUSTC_WORKSPACE_WRAPPER` to
@@ -284,29 +285,24 @@ fn lintcheck(config: LintcheckConfig) {
let (crates, recursive_options) = read_crates(&config.sources_toml_path);
let counter = AtomicUsize::new(1);
- let mut lint_level_args: Vec<String> = vec![];
+ let mut lint_level_args: Vec<String> = vec!["--cap-lints=allow".into()];
if config.lint_filter.is_empty() {
- lint_level_args.push("--cap-lints=warn".to_string());
-
- // Set allow-by-default to warn
- if config.warn_all {
- [
+ let groups = if config.all_lints {
+ &[
+ "clippy::all",
"clippy::cargo",
"clippy::nursery",
"clippy::pedantic",
"clippy::restriction",
- ]
- .iter()
- .map(|group| format!("--warn={group}"))
- .collect_into(&mut lint_level_args);
+ ][..]
} else {
- ["clippy::cargo", "clippy::pedantic"]
- .iter()
- .map(|group| format!("--warn={group}"))
- .collect_into(&mut lint_level_args);
- }
+ &["clippy::all", "clippy::pedantic"]
+ };
+ groups
+ .iter()
+ .map(|group| format!("--force-warn={group}"))
+ .collect_into(&mut lint_level_args);
} else {
- lint_level_args.push("--cap-lints=allow".to_string());
config
.lint_filter
.iter()
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 69fb11a..5fbe4e5 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,4 +1,4 @@
[toolchain]
-channel = "nightly-2024-07-25"
+channel = "nightly-2024-08-08"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
profile = "minimal"
diff --git a/src/tools/clippy/rustc_tools_util/Cargo.toml b/src/tools/clippy/rustc_tools_util/Cargo.toml
index 877049a..37b592d 100644
--- a/src/tools/clippy/rustc_tools_util/Cargo.toml
+++ b/src/tools/clippy/rustc_tools_util/Cargo.toml
@@ -10,6 +10,3 @@
edition = "2018"
[dependencies]
-
-[features]
-deny-warnings = []
diff --git a/src/tools/clippy/rustc_tools_util/src/lib.rs b/src/tools/clippy/rustc_tools_util/src/lib.rs
index 4c1d8c3..2cc3813 100644
--- a/src/tools/clippy/rustc_tools_util/src/lib.rs
+++ b/src/tools/clippy/rustc_tools_util/src/lib.rs
@@ -1,4 +1,4 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+use std::str;
/// This macro creates the version string during compilation from the
/// current environment
@@ -101,49 +101,46 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#[must_use]
pub fn get_commit_hash() -> Option<String> {
- std::process::Command::new("git")
- .args(["rev-parse", "--short", "HEAD"])
+ let output = std::process::Command::new("git")
+ .args(["rev-parse", "HEAD"])
.output()
- .ok()
- .and_then(|r| String::from_utf8(r.stdout).ok())
+ .ok()?;
+ let mut stdout = output.status.success().then_some(output.stdout)?;
+ stdout.truncate(10);
+ String::from_utf8(stdout).ok()
}
#[must_use]
pub fn get_commit_date() -> Option<String> {
- std::process::Command::new("git")
+ let output = std::process::Command::new("git")
.args(["log", "-1", "--date=short", "--pretty=format:%cd"])
.output()
- .ok()
- .and_then(|r| String::from_utf8(r.stdout).ok())
+ .ok()?;
+ let stdout = output.status.success().then_some(output.stdout)?;
+ String::from_utf8(stdout).ok()
}
#[must_use]
pub fn get_channel() -> String {
- match std::env::var("CFG_RELEASE_CHANNEL") {
- Ok(channel) => channel,
- Err(_) => {
- // if that failed, try to ask rustc -V, do some parsing and find out
- match std::process::Command::new("rustc")
- .arg("-V")
- .output()
- .ok()
- .and_then(|r| String::from_utf8(r.stdout).ok())
- {
- Some(rustc_output) => {
- if rustc_output.contains("beta") {
- String::from("beta")
- } else if rustc_output.contains("stable") {
- String::from("stable")
- } else {
- // default to nightly if we fail to parse
- String::from("nightly")
- }
- },
- // default to nightly
- None => String::from("nightly"),
- }
- },
+ if let Ok(channel) = std::env::var("CFG_RELEASE_CHANNEL") {
+ return channel;
}
+
+ // if that failed, try to ask rustc -V, do some parsing and find out
+ if let Ok(output) = std::process::Command::new("rustc").arg("-V").output() {
+ if output.status.success() {
+ if let Ok(rustc_output) = str::from_utf8(&output.stdout) {
+ if rustc_output.contains("beta") {
+ return String::from("beta");
+ } else if rustc_output.contains("stable") {
+ return String::from("stable");
+ }
+ }
+ }
+ }
+
+ // default to nightly
+ String::from("nightly")
}
#[cfg(test)]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9b1577f..0ac3f35 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -2,8 +2,6 @@
#![allow(rustc::untranslatable_diagnostic)]
#![feature(rustc_private)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
// warn on rustc internal lints
@@ -152,7 +150,6 @@ fn config(&mut self, config: &mut interface::Config) {
let conf = clippy_config::Conf::read(sess, &conf_path);
clippy_lints::register_lints(lint_store, conf);
clippy_lints::register_pre_expansion_lints(lint_store, conf);
- clippy_lints::register_renamed(lint_store);
}));
// FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index 30beaae..c9853e5 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -1,4 +1,6 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+// We need this feature as it changes `dylib` linking behavior and allows us to link to
+// `rustc_driver`.
+#![feature(rustc_private)]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/clippy/tests/check-fmt.rs b/src/tools/clippy/tests/check-fmt.rs
index e106583..cd3fed8 100644
--- a/src/tools/clippy/tests/check-fmt.rs
+++ b/src/tools/clippy/tests/check-fmt.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
use std::path::PathBuf;
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 4e51204..6425351 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -1,4 +1,6 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+// We need this feature as it changes `dylib` linking behavior and allows us to link to
+// `rustc_driver`.
+#![feature(rustc_private)]
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(unused_extern_crates)]
@@ -208,7 +210,8 @@ fn run_ui_toml() {
ui_test::run_tests_generic(
vec![config],
ui_test::default_file_filter,
- |config, path, _file_contents| {
+ |config, file_contents| {
+ let path = file_contents.span().file;
config
.program
.envs
@@ -260,7 +263,7 @@ fn run_ui_cargo() {
path.ends_with("Cargo.toml")
.then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path))
},
- |_config, _path, _file_contents| {},
+ |_config, _file_contents| {},
status_emitter::Text::from(args.format),
)
.unwrap();
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index c8a761b..8d10d5e 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -3,7 +3,6 @@
//!
//! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
use itertools::Itertools;
diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs
index 77b7bb6..13cf368 100644
--- a/src/tools/clippy/tests/integration.rs
+++ b/src/tools/clippy/tests/integration.rs
@@ -8,7 +8,6 @@
//! Clippy doesn't produce an ICE. Lint warnings are ignored by this test.
#![cfg(feature = "integration")]
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
use std::env;
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index 6ce7e44..7ed1f48 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
use std::ffi::OsStr;
diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs
index 141c11d..a8225d0 100644
--- a/src/tools/clippy/tests/missing-test-files.rs
+++ b/src/tools/clippy/tests/missing-test-files.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(clippy::assertions_on_constants)]
#![feature(path_file_prefix)]
diff --git a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.rs b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.rs
deleted file mode 100644
index c8961d5..0000000
--- a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate clippy_lints;
-use clippy_lints::deprecated_lints::ClippyDeprecatedLint;
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// TODO
- #[clippy::version = "1.63.0"]
- pub COOL_LINT_DEFAULT,
- "default deprecation note"
-}
-
-declare_deprecated_lint! {
- /// ### What it does
- /// Nothing. This lint has been deprecated.
- ///
- /// ### Deprecation reason
- /// This lint has been replaced by `cooler_lint`
- #[clippy::version = "1.63.0"]
- pub COOL_LINT,
- "this lint has been replaced by `cooler_lint`"
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr b/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr
deleted file mode 100644
index 3b7c747..0000000
--- a/src/tools/clippy/tests/ui-internal/default_deprecation_reason.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: the lint `COOL_LINT_DEFAULT` has the default deprecation reason
- --> tests/ui-internal/default_deprecation_reason.rs:8:1
- |
-LL | / declare_deprecated_lint! {
-LL | | /// ### What it does
-LL | | /// Nothing. This lint has been deprecated.
-LL | | ///
-... |
-LL | | "default deprecation note"
-LL | | }
- | |_^
- |
-note: the lint level is defined here
- --> tests/ui-internal/default_deprecation_reason.rs:1:9
- |
-LL | #![deny(clippy::internal)]
- | ^^^^^^^^^^^^^^^^
- = note: `#[deny(clippy::default_deprecation_reason)]` implied by `#[deny(clippy::internal)]`
- = note: this error originates in the macro `declare_deprecated_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs
index 4375f32..858aab5 100644
--- a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.rs
@@ -1,15 +1,19 @@
//@aux-build:../../ui/auxiliary/proc_macros.rs
#![rustfmt::skip]
#![feature(custom_inner_attributes)]
-#![allow(unused)]
-#![allow(clippy::let_and_return)]
-#![allow(clippy::redundant_closure_call)]
-#![allow(clippy::no_effect)]
-#![allow(clippy::unnecessary_operation)]
-#![allow(clippy::never_loop)]
-#![allow(clippy::needless_if)]
#![warn(clippy::excessive_nesting)]
-#![allow(clippy::collapsible_if, clippy::blocks_in_conditions)]
+#![allow(
+ unused,
+ clippy::let_and_return,
+ clippy::redundant_closure_call,
+ clippy::no_effect,
+ clippy::unnecessary_operation,
+ clippy::never_loop,
+ clippy::needless_if,
+ clippy::collapsible_if,
+ clippy::blocks_in_conditions,
+ clippy::single_match,
+)]
#[macro_use]
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
index dafcd44..ccdaecd 100644
--- a/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
+++ b/src/tools/clippy/tests/ui-toml/excessive_nesting/excessive_nesting.stderr
@@ -1,5 +1,5 @@
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:21:25
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:25:25
|
LL | let w = { 3 };
| ^^^^^
@@ -9,7 +9,7 @@
= help: to override `-D warnings` add `#[allow(clippy::excessive_nesting)]`
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:67:17
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:71:17
|
LL | / impl C {
LL | | pub fn c() {}
@@ -19,7 +19,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:81:25
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:85:25
|
LL | let x = { 1 }; // not a warning, but cc is
| ^^^^^
@@ -27,7 +27,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:98:17
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:102:17
|
LL | / pub mod e {
LL | | pub mod f {}
@@ -37,7 +37,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:111:18
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:115:18
|
LL | a_but_not({{{{{{{{0}}}}}}}});
| ^^^^^^^^^^^
@@ -45,7 +45,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:112:12
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:116:12
|
LL | a.a({{{{{{{{{0}}}}}}}}});
| ^^^^^^^^^^^^^
@@ -53,7 +53,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:113:12
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:117:12
|
LL | (0, {{{{{{{1}}}}}}});
| ^^^^^^^^^
@@ -61,7 +61,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:118:25
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:122:25
|
LL | if true {
| _________________________^
@@ -74,7 +74,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:130:29
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:134:29
|
LL | let z = (|| {
| _____________________________^
@@ -86,7 +86,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:149:13
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:153:13
|
LL | y += {{{{{5}}}}};
| ^^^^^
@@ -94,7 +94,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:150:20
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:154:20
|
LL | let z = y + {{{{{{{{{5}}}}}}}}};
| ^^^^^^^^^^^^^
@@ -102,7 +102,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:151:12
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:155:12
|
LL | [0, {{{{{{{{{{0}}}}}}}}}}];
| ^^^^^^^^^^^^^^^
@@ -110,7 +110,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:152:25
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:156:25
|
LL | let mut xx = [0; {{{{{{{{100}}}}}}}}];
| ^^^^^^^^^^^^^
@@ -118,7 +118,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:153:11
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:157:11
|
LL | xx[{{{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}}}];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -126,7 +126,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:154:13
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:158:13
|
LL | &mut {{{{{{{{{{y}}}}}}}}}};
| ^^^^^^^^^^^^^^^
@@ -134,7 +134,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:156:17
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:160:17
|
LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}}
| ^^^^
@@ -142,7 +142,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:156:28
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:160:28
|
LL | for i in {{{{xx}}}} {{{{{{{{}}}}}}}}
| ^^^^^^^^^^
@@ -150,7 +150,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:158:28
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:28
|
LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}}
| ^^^^^^^^^^^^^
@@ -158,7 +158,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:158:48
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:48
|
LL | while let Some(i) = {{{{{{Some(1)}}}}}} {{{{{{{}}}}}}}
| ^^^^^^^^
@@ -166,7 +166,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:160:14
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:14
|
LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}}
| ^^^^^^^^^^^^^^
@@ -174,7 +174,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:160:35
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:35
|
LL | while {{{{{{{{true}}}}}}}} {{{{{{{{{}}}}}}}}}
| ^^^^^^^^^^^^
@@ -182,7 +182,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:162:23
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:166:23
|
LL | let d = D { d: {{{{{{{{{{{{{{{{{{{{{{{3}}}}}}}}}}}}}}}}}}}}}}} };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -190,7 +190,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:8
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:8
|
LL | {{{{1;}}}}..{{{{{{3}}}}}};
| ^^^^
@@ -198,7 +198,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:164:20
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:20
|
LL | {{{{1;}}}}..{{{{{{3}}}}}};
| ^^^^^^^
@@ -206,7 +206,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:165:8
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:169:8
|
LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}};
| ^^^^
@@ -214,7 +214,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:165:21
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:169:21
|
LL | {{{{1;}}}}..={{{{{{{{{{{{{{{{{{{{{{{{{{6}}}}}}}}}}}}}}}}}}}}}}}}}};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +222,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:166:10
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:170:10
|
LL | ..{{{{{{{5}}}}}}};
| ^^^^^^^^^
@@ -230,7 +230,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:167:11
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:171:11
|
LL | ..={{{{{3}}}}};
| ^^^^^
@@ -238,7 +238,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:168:8
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:172:8
|
LL | {{{{{1;}}}}}..;
| ^^^^^^
@@ -246,7 +246,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:170:20
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:174:20
|
LL | loop { break {{{{1}}}} };
| ^^^^^
@@ -254,7 +254,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:171:13
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:13
|
LL | loop {{{{{{}}}}}}
| ^^^^^^
@@ -262,7 +262,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:173:14
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:177:14
|
LL | match {{{{{{true}}}}}} {
| ^^^^^^^^^^
@@ -270,7 +270,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:174:20
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:178:20
|
LL | true => {{{{}}}},
| ^^
@@ -278,7 +278,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:175:21
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:179:21
|
LL | false => {{{{}}}},
| ^^
@@ -286,7 +286,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:181:17
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:185:17
|
LL | / {
LL | | println!("warning! :)");
@@ -296,7 +296,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:190:28
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:194:28
|
LL | async fn c() -> u32 {{{{{{{0}}}}}}}
| ^^^^^^^^^
@@ -304,7 +304,7 @@
= help: try refactoring your code to minimize nesting
error: this block is too nested
- --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:196:8
+ --> tests/ui-toml/excessive_nesting/excessive_nesting.rs:200:8
|
LL | {{{{b().await}}}};
| ^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 41d5afd..320578b 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -1,11 +1,15 @@
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:38:17
|
LL | let _ = boxed_slice.get(1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::get-unwrap` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::get_unwrap)]`
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &boxed_slice[1];
+ | ~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:38:17
@@ -18,11 +22,16 @@
= note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]`
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:39:17
|
LL | let _ = some_slice.get(0).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_slice[0];
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:39:17
@@ -33,11 +42,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:40:17
|
LL | let _ = some_vec.get(0).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_vec[0];
+ | ~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:40:17
@@ -48,11 +62,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a VecDeque
--> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17
|
LL | let _ = some_vecdeque.get(0).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_vecdeque[0];
+ | ~~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:41:17
@@ -63,11 +82,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a HashMap
--> tests/ui-toml/unwrap_used/unwrap_used.rs:42:17
|
LL | let _ = some_hashmap.get(&1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_hashmap[&1];
+ | ~~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:42:17
@@ -78,11 +102,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a BTreeMap
--> tests/ui-toml/unwrap_used/unwrap_used.rs:43:17
|
LL | let _ = some_btreemap.get(&1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_btreemap[&1];
+ | ~~~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:43:17
@@ -93,11 +122,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:47:21
|
LL | let _: u8 = *boxed_slice.get(1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _: u8 = boxed_slice[1];
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:47:22
@@ -108,11 +142,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:52:9
|
LL | *boxed_slice.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | boxed_slice[0] = 1;
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:52:10
@@ -123,11 +162,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:53:9
|
LL | *some_slice.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | some_slice[0] = 1;
+ | ~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:53:10
@@ -138,11 +182,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:54:9
|
LL | *some_vec.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | some_vec[0] = 1;
+ | ~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:54:10
@@ -153,11 +202,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a VecDeque
--> tests/ui-toml/unwrap_used/unwrap_used.rs:55:9
|
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | some_vecdeque[0] = 1;
+ | ~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:55:10
@@ -168,11 +222,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:67:17
|
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = some_vec[0..1].to_vec();
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:67:17
@@ -183,11 +242,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a Vec
--> tests/ui-toml/unwrap_used/unwrap_used.rs:68:17
|
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = some_vec[0..1].to_vec();
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui-toml/unwrap_used/unwrap_used.rs:68:17
@@ -198,17 +262,27 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:75:13
|
LL | let _ = boxed_slice.get(1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &boxed_slice[1];
+ | ~~~~~~~~~~~~~~~
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui-toml/unwrap_used/unwrap_used.rs:93:17
|
LL | let _ = Box::new([0]).get(1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&Box::new([0])[1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &Box::new([0])[1];
+ | ~~~~~~~~~~~~~~~~~
error: aborting due to 28 previous errors
diff --git a/src/tools/clippy/tests/ui/assigning_clones.fixed b/src/tools/clippy/tests/ui/assigning_clones.fixed
index 60f6a38..b376d55 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.fixed
+++ b/src/tools/clippy/tests/ui/assigning_clones.fixed
@@ -3,6 +3,7 @@
#![allow(clippy::ptr_arg)] // https://github.com/rust-lang/rust-clippy/issues/10612
#![allow(clippy::needless_late_init)]
#![allow(clippy::box_collection)]
+#![allow(clippy::boxed_local)]
#![warn(clippy::assigning_clones)]
use std::borrow::ToOwned;
@@ -182,6 +183,31 @@
}
}
+// Deref handling
+fn clone_into_deref_method(mut a: DerefWrapper<HasCloneFrom>, b: HasCloneFrom) {
+ (*a).clone_from(&b);
+}
+
+fn clone_into_deref_with_clone_method(mut a: DerefWrapperWithClone<HasCloneFrom>, b: HasCloneFrom) {
+ (*a).clone_from(&b);
+}
+
+fn clone_into_box_method(mut a: Box<HasCloneFrom>, b: HasCloneFrom) {
+ (*a).clone_from(&b);
+}
+
+fn clone_into_self_deref_method(a: &mut DerefWrapperWithClone<HasCloneFrom>, b: DerefWrapperWithClone<HasCloneFrom>) {
+ a.clone_from(&b);
+}
+
+fn clone_into_deref_function(mut a: DerefWrapper<HasCloneFrom>, b: HasCloneFrom) {
+ Clone::clone_from(&mut *a, &b);
+}
+
+fn clone_into_box_function(mut a: Box<HasCloneFrom>, b: HasCloneFrom) {
+ Clone::clone_from(&mut *a, &b);
+}
+
// ToOwned
fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) {
ref_str.clone_into(mut_string);
@@ -328,3 +354,45 @@
path = path.components().as_path().to_owned();
}
}
+
+struct DerefWrapper<T>(T);
+
+impl<T> Deref for DerefWrapper<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for DerefWrapper<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+struct DerefWrapperWithClone<T>(T);
+
+impl<T> Deref for DerefWrapperWithClone<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for DerefWrapperWithClone<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+impl<T: Clone> Clone for DerefWrapperWithClone<T> {
+ fn clone(&self) -> Self {
+ Self(self.0.clone())
+ }
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = Self(source.0.clone());
+ }
+}
diff --git a/src/tools/clippy/tests/ui/assigning_clones.rs b/src/tools/clippy/tests/ui/assigning_clones.rs
index 6eb85be..11a5d44 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.rs
+++ b/src/tools/clippy/tests/ui/assigning_clones.rs
@@ -3,6 +3,7 @@
#![allow(clippy::ptr_arg)] // https://github.com/rust-lang/rust-clippy/issues/10612
#![allow(clippy::needless_late_init)]
#![allow(clippy::box_collection)]
+#![allow(clippy::boxed_local)]
#![warn(clippy::assigning_clones)]
use std::borrow::ToOwned;
@@ -182,6 +183,31 @@ fn clone_from(&mut self, source: &Self) {
}
}
+// Deref handling
+fn clone_into_deref_method(mut a: DerefWrapper<HasCloneFrom>, b: HasCloneFrom) {
+ *a = b.clone();
+}
+
+fn clone_into_deref_with_clone_method(mut a: DerefWrapperWithClone<HasCloneFrom>, b: HasCloneFrom) {
+ *a = b.clone();
+}
+
+fn clone_into_box_method(mut a: Box<HasCloneFrom>, b: HasCloneFrom) {
+ *a = b.clone();
+}
+
+fn clone_into_self_deref_method(a: &mut DerefWrapperWithClone<HasCloneFrom>, b: DerefWrapperWithClone<HasCloneFrom>) {
+ *a = b.clone();
+}
+
+fn clone_into_deref_function(mut a: DerefWrapper<HasCloneFrom>, b: HasCloneFrom) {
+ *a = Clone::clone(&b);
+}
+
+fn clone_into_box_function(mut a: Box<HasCloneFrom>, b: HasCloneFrom) {
+ *a = Clone::clone(&b);
+}
+
// ToOwned
fn owned_method_mut_ref(mut_string: &mut String, ref_str: &str) {
*mut_string = ref_str.to_owned();
@@ -328,3 +354,45 @@ fn issue12749() {
path = path.components().as_path().to_owned();
}
}
+
+struct DerefWrapper<T>(T);
+
+impl<T> Deref for DerefWrapper<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for DerefWrapper<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+struct DerefWrapperWithClone<T>(T);
+
+impl<T> Deref for DerefWrapperWithClone<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for DerefWrapperWithClone<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.0
+ }
+}
+
+impl<T: Clone> Clone for DerefWrapperWithClone<T> {
+ fn clone(&self) -> Self {
+ Self(self.0.clone())
+ }
+
+ fn clone_from(&mut self, source: &Self) {
+ *self = Self(source.0.clone());
+ }
+}
diff --git a/src/tools/clippy/tests/ui/assigning_clones.stderr b/src/tools/clippy/tests/ui/assigning_clones.stderr
index a685163..19724a6 100644
--- a/src/tools/clippy/tests/ui/assigning_clones.stderr
+++ b/src/tools/clippy/tests/ui/assigning_clones.stderr
@@ -1,5 +1,5 @@
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:24:5
+ --> tests/ui/assigning_clones.rs:25:5
|
LL | *mut_thing = value_thing.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(&value_thing)`
@@ -8,142 +8,178 @@
= help: to override `-D warnings` add `#[allow(clippy::assigning_clones)]`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:28:5
+ --> tests/ui/assigning_clones.rs:29:5
|
LL | *mut_thing = ref_thing.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:32:5
+ --> tests/ui/assigning_clones.rs:33:5
|
LL | mut_thing = ref_thing.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:36:5
+ --> tests/ui/assigning_clones.rs:37:5
|
LL | *mut_thing = Clone::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:40:5
+ --> tests/ui/assigning_clones.rs:41:5
|
LL | mut_thing = Clone::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:44:5
+ --> tests/ui/assigning_clones.rs:45:5
|
LL | *mut_thing = Clone::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:48:5
+ --> tests/ui/assigning_clones.rs:49:5
|
LL | *mut_thing = HasCloneFrom::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:52:5
+ --> tests/ui/assigning_clones.rs:53:5
|
LL | *mut_thing = <HasCloneFrom as Clone>::clone(ref_thing);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(mut_thing, ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:57:5
+ --> tests/ui/assigning_clones.rs:58:5
|
LL | *(mut_thing + &mut HasCloneFrom) = ref_thing.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `(mut_thing + &mut HasCloneFrom).clone_from(ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:62:5
+ --> tests/ui/assigning_clones.rs:63:5
|
LL | *mut_thing = (ref_thing + ref_thing).clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `mut_thing.clone_from(ref_thing + ref_thing)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:67:5
+ --> tests/ui/assigning_clones.rs:68:5
|
LL | s = format!("{} {}", "hello", "world").clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `s.clone_from(&format!("{} {}", "hello", "world"))`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:72:5
+ --> tests/ui/assigning_clones.rs:73:5
|
LL | s = Clone::clone(&format!("{} {}", "hello", "world"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut s, &format!("{} {}", "hello", "world"))`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:78:9
+ --> tests/ui/assigning_clones.rs:79:9
|
LL | a = b.clone();
| ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:149:5
+ --> tests/ui/assigning_clones.rs:150:5
|
LL | a = b.clone();
| ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
error: assigning the result of `Clone::clone()` may be inefficient
- --> tests/ui/assigning_clones.rs:156:5
+ --> tests/ui/assigning_clones.rs:157:5
|
LL | a = b.clone();
| ^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:157:5
+ --> tests/ui/assigning_clones.rs:158:5
|
LL | a = c.to_owned();
| ^^^^^^^^^^^^^^^^ help: use `clone_into()`: `c.clone_into(&mut a)`
+error: assigning the result of `Clone::clone()` may be inefficient
+ --> tests/ui/assigning_clones.rs:188:5
+ |
+LL | *a = b.clone();
+ | ^^^^^^^^^^^^^^ help: use `clone_from()`: `(*a).clone_from(&b)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+ --> tests/ui/assigning_clones.rs:192:5
+ |
+LL | *a = b.clone();
+ | ^^^^^^^^^^^^^^ help: use `clone_from()`: `(*a).clone_from(&b)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+ --> tests/ui/assigning_clones.rs:196:5
+ |
+LL | *a = b.clone();
+ | ^^^^^^^^^^^^^^ help: use `clone_from()`: `(*a).clone_from(&b)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+ --> tests/ui/assigning_clones.rs:200:5
+ |
+LL | *a = b.clone();
+ | ^^^^^^^^^^^^^^ help: use `clone_from()`: `a.clone_from(&b)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+ --> tests/ui/assigning_clones.rs:204:5
+ |
+LL | *a = Clone::clone(&b);
+ | ^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut *a, &b)`
+
+error: assigning the result of `Clone::clone()` may be inefficient
+ --> tests/ui/assigning_clones.rs:208:5
+ |
+LL | *a = Clone::clone(&b);
+ | ^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `Clone::clone_from(&mut *a, &b)`
+
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:187:5
+ --> tests/ui/assigning_clones.rs:213:5
|
LL | *mut_string = ref_str.to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(mut_string)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:191:5
+ --> tests/ui/assigning_clones.rs:217:5
|
LL | mut_string = ref_str.to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut mut_string)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:212:5
+ --> tests/ui/assigning_clones.rs:238:5
|
LL | **mut_box_string = ref_str.to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:216:5
+ --> tests/ui/assigning_clones.rs:242:5
|
LL | **mut_box_string = ref_str.to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ref_str.clone_into(&mut (*mut_box_string))`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:220:5
+ --> tests/ui/assigning_clones.rs:246:5
|
LL | *mut_thing = ToOwned::to_owned(ref_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, mut_thing)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:224:5
+ --> tests/ui/assigning_clones.rs:250:5
|
LL | mut_thing = ToOwned::to_owned(ref_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(ref_str, &mut mut_thing)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:229:5
+ --> tests/ui/assigning_clones.rs:255:5
|
LL | s = format!("{} {}", "hello", "world").to_owned();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `format!("{} {}", "hello", "world").clone_into(&mut s)`
error: assigning the result of `ToOwned::to_owned()` may be inefficient
- --> tests/ui/assigning_clones.rs:234:5
+ --> tests/ui/assigning_clones.rs:260:5
|
LL | s = ToOwned::to_owned(&format!("{} {}", "hello", "world"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_into()`: `ToOwned::clone_into(&format!("{} {}", "hello", "world"), &mut s)`
-error: aborting due to 24 previous errors
+error: aborting due to 30 previous errors
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr
index b15857c..2adaecc 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map_multipart.stderr
@@ -9,7 +9,7 @@
|
LL | #![deny(clippy::bind_instead_of_map)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: try
+help: use `map` instead
|
LL | let _ = Some("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
| ~~~ ~ ~~~~~~~
@@ -20,7 +20,7 @@
LL | let _ = Ok::<_, ()>("42").and_then(|s| if s.len() < 42 { Ok(0) } else { Ok(s.len()) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: try
+help: use `map` instead
|
LL | let _ = Ok::<_, ()>("42").map(|s| if s.len() < 42 { 0 } else { s.len() });
| ~~~ ~ ~~~~~~~
@@ -31,7 +31,7 @@
LL | let _ = Err::<(), _>("42").or_else(|s| if s.len() < 42 { Err(s.len() + 20) } else { Err(s.len()) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: try
+help: use `map_err` instead
|
LL | let _ = Err::<(), _>("42").map_err(|s| if s.len() < 42 { s.len() + 20 } else { s.len() });
| ~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~
@@ -48,7 +48,7 @@
LL | | });
| |______^
|
-help: try
+help: use `map` instead
|
LL ~ Some("42").map(|s| {
LL | if {
@@ -82,7 +82,7 @@
LL | let _ = Some("").and_then(|s| if s.len() == 20 { Some(m!()) } else { Some(Some(20)) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: try
+help: use `map` instead
|
LL | let _ = Some("").map(|s| if s.len() == 20 { m!() } else { Some(20) });
| ~~~ ~~~~ ~~~~~~~~
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
index 0ea93dd..452d1b198 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.rs
@@ -10,7 +10,7 @@
const ATOMIC: AtomicUsize = AtomicUsize::new(5);
const CELL: Cell<usize> = Cell::new(6);
-const ATOMIC_TUPLE: ([AtomicUsize; 1], Vec<AtomicUsize>, u8) = ([ATOMIC], Vec::new(), 7);
+const ATOMIC_TUPLE: ([AtomicUsize; 1], Option<Box<AtomicUsize>>, u8) = ([ATOMIC], None, 7);
const INTEGER: u8 = 8;
const STRING: String = String::new();
const STR: &str = "012345";
@@ -74,7 +74,6 @@ fn main() {
let _ = &(&&&&ATOMIC_TUPLE).0; //~ ERROR: interior mutability
let _ = &ATOMIC_TUPLE.0[0]; //~ ERROR: interior mutability
let _ = ATOMIC_TUPLE.0[0].load(Ordering::SeqCst); //~ ERROR: interior mutability
- let _ = &*ATOMIC_TUPLE.1;
let _ = &ATOMIC_TUPLE.2;
let _ = (&&&&ATOMIC_TUPLE).0;
let _ = (&&&&ATOMIC_TUPLE).2;
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
index 33c7746..9a9028c 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
@@ -92,7 +92,7 @@
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
- --> tests/ui/borrow_interior_mutable_const/others.rs:82:13
+ --> tests/ui/borrow_interior_mutable_const/others.rs:81:13
|
LL | let _ = ATOMIC_TUPLE.0[0];
| ^^^^^^^^^^^^
@@ -100,7 +100,7 @@
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
- --> tests/ui/borrow_interior_mutable_const/others.rs:87:5
+ --> tests/ui/borrow_interior_mutable_const/others.rs:86:5
|
LL | CELL.set(2);
| ^^^^
@@ -108,7 +108,7 @@
= help: assign this const to a local or static variable, and use the variable here
error: a `const` item with interior mutability should not be borrowed
- --> tests/ui/borrow_interior_mutable_const/others.rs:88:16
+ --> tests/ui/borrow_interior_mutable_const/others.rs:87:16
|
LL | assert_eq!(CELL.get(), 6);
| ^^^^
diff --git a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr
index 01627ff..4b4618e 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-3717.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-3717.stderr
@@ -9,14 +9,13 @@
|
LL | #![deny(clippy::implicit_hasher)]
| ^^^^^^^^^^^^^^^^^^^^^^^
-help: consider adding a type parameter
+help: add a type parameter for `BuildHasher`
|
-LL | pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) {
- | +++++++++++++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~
-help: ...and use generic constructor
+LL ~ pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) {
+LL |
+LL | let _ = [0u8; 0];
+LL ~ let _: HashSet<usize> = HashSet::default();
|
-LL | let _: HashSet<usize> = HashSet::default();
- | ~~~~~~~~~~~~~~~~~~
error: aborting due to 1 previous error
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6254.rs b/src/tools/clippy/tests/ui/crashes/ice-6254.rs
index 8af6089..aaca32a 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6254.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-6254.rs
@@ -2,7 +2,8 @@
// panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())',
// compiler/rustc_mir_build/src/thir/pattern/_match.rs:2030:5
-#[allow(clippy::derive_partial_eq_without_eq)]
+#![allow(clippy::derive_partial_eq_without_eq, clippy::single_match)]
+
#[derive(PartialEq)]
struct Foo(i32);
const FOO_REF_REF: &&Foo = &&Foo(42);
diff --git a/src/tools/clippy/tests/ui/create_dir.stderr b/src/tools/clippy/tests/ui/create_dir.stderr
index 9c6e640..ab51705 100644
--- a/src/tools/clippy/tests/ui/create_dir.stderr
+++ b/src/tools/clippy/tests/ui/create_dir.stderr
@@ -2,16 +2,25 @@
--> tests/ui/create_dir.rs:10:5
|
LL | std::fs::create_dir("foo");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `create_dir_all("foo")`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::create-dir` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::create_dir)]`
+help: consider calling `std::fs::create_dir_all` instead
+ |
+LL | create_dir_all("foo");
+ | ~~~~~~~~~~~~~~~~~~~~~
error: calling `std::fs::create_dir` where there may be a better way
--> tests/ui/create_dir.rs:11:5
|
LL | std::fs::create_dir("bar").unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `std::fs::create_dir_all` instead: `create_dir_all("bar")`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider calling `std::fs::create_dir_all` instead
+ |
+LL | create_dir_all("bar").unwrap();
+ | ~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
index 7d3c3f7..b3d74b9 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr
@@ -81,7 +81,7 @@
--> tests/ui/dbg_macro/dbg_macro.rs:48:5
|
LL | dbg!();
- | ^^^^^^^
+ | ^^^^^^
|
help: remove the invocation before committing it to a version control system
|
@@ -136,7 +136,7 @@
--> tests/ui/dbg_macro/dbg_macro.rs:43:13
|
LL | dbg!();
- | ^^^^^^^
+ | ^^^^^^
...
LL | expand_to_dbg!();
| ---------------- in this macro invocation
diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr
index 16e51f4..b8e9190 100644
--- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro_unfixable.stderr
@@ -2,7 +2,7 @@
--> tests/ui/dbg_macro/auxiliary/submodule.rs:2:5
|
LL | dbg!();
- | ^^^^^^^
+ | ^^^^^^
|
= note: `-D clippy::dbg-macro` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::dbg_macro)]`
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index d3c34fb..5617db9 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -2,23 +2,18 @@
// Use that command to update this file and do not edit by hand.
// Manual edits will be overwritten.
-#![warn(clippy::should_assert_eq)]
-#![warn(clippy::extend_from_slice)]
-#![warn(clippy::range_step_by_zero)]
-#![warn(clippy::unstable_as_slice)]
-#![warn(clippy::unstable_as_mut_slice)]
-#![warn(clippy::misaligned_transmute)]
-#![warn(clippy::assign_ops)]
-#![warn(clippy::if_let_redundant_pattern_matching)]
-#![warn(clippy::unsafe_vector_initialization)]
-#![warn(clippy::unused_collect)]
-#![warn(clippy::replace_consts)]
-#![warn(clippy::regex_macro)]
-#![warn(clippy::find_map)]
-#![warn(clippy::filter_map)]
-#![warn(clippy::pub_enum_variant_names)]
-#![warn(clippy::wrong_pub_self_convention)]
-#![warn(clippy::maybe_misused_cfg)]
-#![warn(clippy::mismatched_target_os)]
+#![warn(clippy::should_assert_eq)] //~ ERROR: lint `clippy::should_assert_eq`
+#![warn(clippy::extend_from_slice)] //~ ERROR: lint `clippy::extend_from_slice`
+#![warn(clippy::range_step_by_zero)] //~ ERROR: lint `clippy::range_step_by_zero`
+#![warn(clippy::unstable_as_slice)] //~ ERROR: lint `clippy::unstable_as_slice`
+#![warn(clippy::unstable_as_mut_slice)] //~ ERROR: lint `clippy::unstable_as_mut_slice`
+#![warn(clippy::misaligned_transmute)] //~ ERROR: lint `clippy::misaligned_transmute`
+#![warn(clippy::assign_ops)] //~ ERROR: lint `clippy::assign_ops`
+#![warn(clippy::unsafe_vector_initialization)] //~ ERROR: lint `clippy::unsafe_vector_initialization`
+#![warn(clippy::unused_collect)] //~ ERROR: lint `clippy::unused_collect`
+#![warn(clippy::replace_consts)] //~ ERROR: lint `clippy::replace_consts`
+#![warn(clippy::regex_macro)] //~ ERROR: lint `clippy::regex_macro`
+#![warn(clippy::pub_enum_variant_names)] //~ ERROR: lint `clippy::pub_enum_variant_names`
+#![warn(clippy::wrong_pub_self_convention)] //~ ERROR: lint `clippy::wrong_pub_self_convention`
fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index 49b90c7..b3e1646 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -1,4 +1,4 @@
-error: lint `clippy::should_assert_eq` has been removed: `assert!()` will be more flexible with RFC 2011
+error: lint `clippy::should_assert_eq` has been removed: `assert!(a == b)` can now print the values the same way `assert_eq!(a, b) can
--> tests/ui/deprecated.rs:5:9
|
LL | #![warn(clippy::should_assert_eq)]
@@ -7,107 +7,77 @@
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
-error: lint `clippy::extend_from_slice` has been removed: `.extend_from_slice(_)` is a faster way to extend a Vec by a slice
+error: lint `clippy::extend_from_slice` has been removed: `Vec::extend_from_slice` is no longer faster than `Vec::extend` due to specialization
--> tests/ui/deprecated.rs:6:9
|
LL | #![warn(clippy::extend_from_slice)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::range_step_by_zero` has been removed: `iterator.step_by(0)` panics nowadays
+error: lint `clippy::range_step_by_zero` has been removed: `Iterator::step_by(0)` now panics and is no longer an infinite iterator
--> tests/ui/deprecated.rs:7:9
|
LL | #![warn(clippy::range_step_by_zero)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
+error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` is now stable
--> tests/ui/deprecated.rs:8:9
|
LL | #![warn(clippy::unstable_as_slice)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
+error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` is now stable
--> tests/ui/deprecated.rs:9:9
|
LL | #![warn(clippy::unstable_as_mut_slice)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
+error: lint `clippy::misaligned_transmute` has been removed: split into `clippy::cast_ptr_alignment` and `clippy::transmute_ptr_to_ptr`
--> tests/ui/deprecated.rs:10:9
|
LL | #![warn(clippy::misaligned_transmute)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::assign_ops` has been removed: using compound assignment operators (e.g., `+=`) is harmless
+error: lint `clippy::assign_ops` has been removed: compound operators are harmless and linting on them is not in scope for clippy
--> tests/ui/deprecated.rs:11:9
|
LL | #![warn(clippy::assign_ops)]
| ^^^^^^^^^^^^^^^^^^
-error: lint `clippy::if_let_redundant_pattern_matching` has been removed: this lint has been changed to redundant_pattern_matching
+error: lint `clippy::unsafe_vector_initialization` has been removed: the suggested alternative could be substantially slower
--> tests/ui/deprecated.rs:12:9
|
-LL | #![warn(clippy::if_let_redundant_pattern_matching)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: lint `clippy::unsafe_vector_initialization` has been removed: the replacement suggested by this lint had substantially different behavior
- --> tests/ui/deprecated.rs:13:9
- |
LL | #![warn(clippy::unsafe_vector_initialization)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
- --> tests/ui/deprecated.rs:14:9
+error: lint `clippy::unused_collect` has been removed: `Iterator::collect` is now marked as `#[must_use]`
+ --> tests/ui/deprecated.rs:13:9
|
LL | #![warn(clippy::unused_collect)]
| ^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::replace_consts` has been removed: associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants
- --> tests/ui/deprecated.rs:15:9
+error: lint `clippy::replace_consts` has been removed: `min_value` and `max_value` are now deprecated
+ --> tests/ui/deprecated.rs:14:9
|
LL | #![warn(clippy::replace_consts)]
| ^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
- --> tests/ui/deprecated.rs:16:9
+error: lint `clippy::regex_macro` has been removed: the `regex!` macro was removed from the regex crate in 2018
+ --> tests/ui/deprecated.rs:15:9
|
LL | #![warn(clippy::regex_macro)]
| ^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::find_map` has been removed: this lint has been replaced by `manual_find_map`, a more specific lint
- --> tests/ui/deprecated.rs:17:9
- |
-LL | #![warn(clippy::find_map)]
- | ^^^^^^^^^^^^^^^^
-
-error: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
- --> tests/ui/deprecated.rs:18:9
- |
-LL | #![warn(clippy::filter_map)]
- | ^^^^^^^^^^^^^^^^^^
-
-error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items
- --> tests/ui/deprecated.rs:19:9
+error: lint `clippy::pub_enum_variant_names` has been removed: `clippy::enum_variant_names` now covers this case via the `avoid-breaking-exported-api` config
+ --> tests/ui/deprecated.rs:16:9
|
LL | #![warn(clippy::pub_enum_variant_names)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items
- --> tests/ui/deprecated.rs:20:9
+error: lint `clippy::wrong_pub_self_convention` has been removed: `clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config
+ --> tests/ui/deprecated.rs:17:9
|
LL | #![warn(clippy::wrong_pub_self_convention)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::maybe_misused_cfg` has been removed: this lint has been replaced by `unexpected_cfgs`
- --> tests/ui/deprecated.rs:21:9
- |
-LL | #![warn(clippy::maybe_misused_cfg)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: lint `clippy::mismatched_target_os` has been removed: this lint has been replaced by `unexpected_cfgs`
- --> tests/ui/deprecated.rs:22:9
- |
-LL | #![warn(clippy::mismatched_target_os)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 18 previous errors
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/deprecated_old.rs b/src/tools/clippy/tests/ui/deprecated_old.rs
deleted file mode 100644
index 356ad5f..0000000
--- a/src/tools/clippy/tests/ui/deprecated_old.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#[warn(unstable_as_slice)]
-//~^ ERROR: lint `unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized
-//~| NOTE: `-D renamed-and-removed-lints` implied by `-D warnings`
-#[warn(unstable_as_mut_slice)]
-//~^ ERROR: lint `unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been st
-#[warn(misaligned_transmute)]
-//~^ ERROR: lint `misaligned_transmute` has been removed: this lint has been split into ca
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated_old.stderr b/src/tools/clippy/tests/ui/deprecated_old.stderr
deleted file mode 100644
index 685bca6..0000000
--- a/src/tools/clippy/tests/ui/deprecated_old.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: lint `unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
- --> tests/ui/deprecated_old.rs:1:8
- |
-LL | #[warn(unstable_as_slice)]
- | ^^^^^^^^^^^^^^^^^
- |
- = note: `-D renamed-and-removed-lints` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
-
-error: lint `unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
- --> tests/ui/deprecated_old.rs:4:8
- |
-LL | #[warn(unstable_as_mut_slice)]
- | ^^^^^^^^^^^^^^^^^^^^^
-
-error: lint `misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
- --> tests/ui/deprecated_old.rs:6:8
- |
-LL | #[warn(misaligned_transmute)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/deref_by_slicing.fixed b/src/tools/clippy/tests/ui/deref_by_slicing.fixed
index a3c2e84..87b33b1 100644
--- a/src/tools/clippy/tests/ui/deref_by_slicing.fixed
+++ b/src/tools/clippy/tests/ui/deref_by_slicing.fixed
@@ -25,4 +25,8 @@
let bytes: &[u8] = &[];
let _ = (&*bytes).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice
+
+ // issue 12751
+ let a = &mut [1, 2, 3][..];
+ let _ = &*a;
}
diff --git a/src/tools/clippy/tests/ui/deref_by_slicing.rs b/src/tools/clippy/tests/ui/deref_by_slicing.rs
index 5b4a737..8d8882a 100644
--- a/src/tools/clippy/tests/ui/deref_by_slicing.rs
+++ b/src/tools/clippy/tests/ui/deref_by_slicing.rs
@@ -25,4 +25,8 @@ fn main() {
let bytes: &[u8] = &[];
let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice
+
+ // issue 12751
+ let a = &mut [1, 2, 3][..];
+ let _ = &a[..];
}
diff --git a/src/tools/clippy/tests/ui/deref_by_slicing.stderr b/src/tools/clippy/tests/ui/deref_by_slicing.stderr
index 17b0061..ceb9ab6 100644
--- a/src/tools/clippy/tests/ui/deref_by_slicing.stderr
+++ b/src/tools/clippy/tests/ui/deref_by_slicing.stderr
@@ -55,5 +55,11 @@
LL | let _ = (&bytes[..]).read_to_end(&mut vec![]).unwrap(); // Err, re-borrows slice
| ^^^^^^^^^^^^ help: reborrow the original value instead: `(&*bytes)`
-error: aborting due to 9 previous errors
+error: slicing when dereferencing would work
+ --> tests/ui/deref_by_slicing.rs:31:13
+ |
+LL | let _ = &a[..];
+ | ^^^^^^ help: reborrow the original value instead: `&*a`
+
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/doc/footnote_issue_13183.rs b/src/tools/clippy/tests/ui/doc/footnote_issue_13183.rs
new file mode 100644
index 0000000..a18b4c3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/doc/footnote_issue_13183.rs
@@ -0,0 +1,10 @@
+// This is a regression test for <https://github.com/rust-lang/rust-clippy/issues/13183>.
+// It should not warn on missing backticks on footnote references.
+
+#![warn(clippy::doc_markdown)]
+// Should not warn!
+//! Here's a footnote[^example_footnote_identifier]
+//!
+//! [^example_footnote_identifier]: This is merely an example.
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_drop.stderr b/src/tools/clippy/tests/ui/empty_drop.stderr
index 4223dda..d4d020f 100644
--- a/src/tools/clippy/tests/ui/empty_drop.stderr
+++ b/src/tools/clippy/tests/ui/empty_drop.stderr
@@ -4,10 +4,11 @@
LL | / impl Drop for Foo {
LL | | fn drop(&mut self) {}
LL | | }
- | |_^ help: try removing this impl
+ | |_^
|
= note: `-D clippy::empty-drop` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::empty_drop)]`
+ = help: try removing this impl
error: empty drop implementation
--> tests/ui/empty_drop.rs:23:1
@@ -17,7 +18,9 @@
LL | | {}
LL | | }
LL | | }
- | |_^ help: try removing this impl
+ | |_^
+ |
+ = help: try removing this impl
error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index 7126f27..ca422ee 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -2,6 +2,7 @@
#![allow(unused)]
#![allow(
clippy::needless_borrow,
+ clippy::needless_option_as_deref,
clippy::needless_pass_by_value,
clippy::no_effect,
clippy::option_map_unit_fn,
@@ -482,3 +483,19 @@
x();
}
}
+
+mod issue_13073 {
+ fn get_default() -> Option<&'static str> {
+ Some("foo")
+ }
+
+ pub fn foo() {
+ // shouldn't lint
+ let bind: Option<String> = None;
+ let _field = bind.as_deref().or_else(|| get_default()).unwrap();
+ let bind: Option<&'static str> = None;
+ let _field = bind.as_deref().or_else(|| get_default()).unwrap();
+ // should lint
+ let _field = bind.or_else(get_default).unwrap();
+ }
+}
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index 0787abf..c0db91c 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -2,6 +2,7 @@
#![allow(unused)]
#![allow(
clippy::needless_borrow,
+ clippy::needless_option_as_deref,
clippy::needless_pass_by_value,
clippy::no_effect,
clippy::option_map_unit_fn,
@@ -482,3 +483,19 @@ fn f_by_ref<F: Fn(u32)>(f: &F) {
x();
}
}
+
+mod issue_13073 {
+ fn get_default() -> Option<&'static str> {
+ Some("foo")
+ }
+
+ pub fn foo() {
+ // shouldn't lint
+ let bind: Option<String> = None;
+ let _field = bind.as_deref().or_else(|| get_default()).unwrap();
+ let bind: Option<&'static str> = None;
+ let _field = bind.as_deref().or_else(|| get_default()).unwrap();
+ // should lint
+ let _field = bind.or_else(|| get_default()).unwrap();
+ }
+}
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index c757601..5540261 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -1,5 +1,5 @@
error: redundant closure
- --> tests/ui/eta.rs:29:27
+ --> tests/ui/eta.rs:30:27
|
LL | let a = Some(1u8).map(|a| foo(a));
| ^^^^^^^^^^ help: replace the closure with the function itself: `foo`
@@ -8,31 +8,31 @@
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
error: redundant closure
- --> tests/ui/eta.rs:33:40
+ --> tests/ui/eta.rs:34:40
|
LL | let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec!
| ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new`
error: redundant closure
- --> tests/ui/eta.rs:34:35
+ --> tests/ui/eta.rs:35:35
|
LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted?
| ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2`
error: redundant closure
- --> tests/ui/eta.rs:35:26
+ --> tests/ui/eta.rs:36:26
|
LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted
| ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below`
error: redundant closure
- --> tests/ui/eta.rs:42:27
+ --> tests/ui/eta.rs:43:27
|
LL | let e = Some(1u8).map(|a| generic(a));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
error: redundant closure
- --> tests/ui/eta.rs:94:51
+ --> tests/ui/eta.rs:95:51
|
LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
| ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@@ -41,166 +41,172 @@
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure_for_method_calls)]`
error: redundant closure
- --> tests/ui/eta.rs:95:51
+ --> tests/ui/eta.rs:96:51
|
LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo`
error: redundant closure
- --> tests/ui/eta.rs:97:42
+ --> tests/ui/eta.rs:98:42
|
LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
| ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear`
error: redundant closure
- --> tests/ui/eta.rs:101:29
+ --> tests/ui/eta.rs:102:29
|
LL | let e = Some("str").map(|s| s.to_string());
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string`
error: redundant closure
- --> tests/ui/eta.rs:102:27
+ --> tests/ui/eta.rs:103:27
|
LL | let e = Some('a').map(|s| s.to_uppercase());
| ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase`
error: redundant closure
- --> tests/ui/eta.rs:104:65
+ --> tests/ui/eta.rs:105:65
|
LL | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
error: redundant closure
- --> tests/ui/eta.rs:167:22
+ --> tests/ui/eta.rs:168:22
|
LL | requires_fn_once(|| x());
| ^^^^^^ help: replace the closure with the function itself: `x`
error: redundant closure
- --> tests/ui/eta.rs:174:27
+ --> tests/ui/eta.rs:175:27
|
LL | let a = Some(1u8).map(|a| foo_ptr(a));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
error: redundant closure
- --> tests/ui/eta.rs:179:27
+ --> tests/ui/eta.rs:180:27
|
LL | let a = Some(1u8).map(|a| closure(a));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
error: redundant closure
- --> tests/ui/eta.rs:211:28
+ --> tests/ui/eta.rs:212:28
|
LL | x.into_iter().for_each(|x| add_to_res(x));
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
error: redundant closure
- --> tests/ui/eta.rs:212:28
+ --> tests/ui/eta.rs:213:28
|
LL | y.into_iter().for_each(|x| add_to_res(x));
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res`
error: redundant closure
- --> tests/ui/eta.rs:213:28
+ --> tests/ui/eta.rs:214:28
|
LL | z.into_iter().for_each(|x| add_to_res(x));
| ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res`
error: redundant closure
- --> tests/ui/eta.rs:220:21
+ --> tests/ui/eta.rs:221:21
|
LL | Some(1).map(|n| closure(n));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure`
error: redundant closure
- --> tests/ui/eta.rs:224:21
+ --> tests/ui/eta.rs:225:21
|
LL | Some(1).map(|n| in_loop(n));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
error: redundant closure
- --> tests/ui/eta.rs:317:18
+ --> tests/ui/eta.rs:318:18
|
LL | takes_fn_mut(|| f());
| ^^^^^^ help: replace the closure with the function itself: `&mut f`
error: redundant closure
- --> tests/ui/eta.rs:320:19
+ --> tests/ui/eta.rs:321:19
|
LL | takes_fn_once(|| f());
| ^^^^^^ help: replace the closure with the function itself: `&mut f`
error: redundant closure
- --> tests/ui/eta.rs:324:26
+ --> tests/ui/eta.rs:325:26
|
LL | move || takes_fn_mut(|| f_used_once())
| ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
error: redundant closure
- --> tests/ui/eta.rs:336:19
+ --> tests/ui/eta.rs:337:19
|
LL | array_opt.map(|a| a.as_slice());
| ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice`
error: redundant closure
- --> tests/ui/eta.rs:339:19
+ --> tests/ui/eta.rs:340:19
|
LL | slice_opt.map(|s| s.len());
| ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len`
error: redundant closure
- --> tests/ui/eta.rs:342:17
+ --> tests/ui/eta.rs:343:17
|
LL | ptr_opt.map(|p| p.is_null());
| ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null`
error: redundant closure
- --> tests/ui/eta.rs:346:17
+ --> tests/ui/eta.rs:347:17
|
LL | dyn_opt.map(|d| d.method_on_dyn());
| ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn`
error: redundant closure
- --> tests/ui/eta.rs:406:19
+ --> tests/ui/eta.rs:407:19
|
LL | let _ = f(&0, |x, y| f2(x, y));
| ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2`
error: redundant closure
- --> tests/ui/eta.rs:434:22
+ --> tests/ui/eta.rs:435:22
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method`
error: redundant closure
- --> tests/ui/eta.rs:438:22
+ --> tests/ui/eta.rs:439:22
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method`
error: redundant closure
- --> tests/ui/eta.rs:451:18
+ --> tests/ui/eta.rs:452:18
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method`
error: redundant closure
- --> tests/ui/eta.rs:458:30
+ --> tests/ui/eta.rs:459:30
|
LL | test.map(|t| t.method())
| ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method`
error: redundant closure
- --> tests/ui/eta.rs:477:38
+ --> tests/ui/eta.rs:478:38
|
LL | let x = Box::new(|| None.map(|x| f(x)));
| ^^^^^^^^ help: replace the closure with the function itself: `&f`
error: redundant closure
- --> tests/ui/eta.rs:481:38
+ --> tests/ui/eta.rs:482:38
|
LL | let x = Box::new(|| None.map(|x| f(x)));
| ^^^^^^^^ help: replace the closure with the function itself: `f`
-error: aborting due to 33 previous errors
+error: redundant closure
+ --> tests/ui/eta.rs:499:35
+ |
+LL | let _field = bind.or_else(|| get_default()).unwrap();
+ | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default`
+
+error: aborting due to 34 previous errors
diff --git a/src/tools/clippy/tests/ui/excessive_precision.stderr b/src/tools/clippy/tests/ui/excessive_precision.stderr
index 6d8e166..81e4fb6 100644
--- a/src/tools/clippy/tests/ui/excessive_precision.stderr
+++ b/src/tools/clippy/tests/ui/excessive_precision.stderr
@@ -2,100 +2,179 @@
--> tests/ui/excessive_precision.rs:20:26
|
LL | const BAD32_1: f32 = 0.123_456_789_f32;
- | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79_f32`
+ | ^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::excessive-precision` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::excessive_precision)]`
+help: consider changing the type or truncating it to
+ |
+LL | const BAD32_1: f32 = 0.123_456_79_f32;
+ | ~~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:21:26
|
LL | const BAD32_2: f32 = 0.123_456_789;
- | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
+ | ^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | const BAD32_2: f32 = 0.123_456_79;
+ | ~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:22:26
|
LL | const BAD32_3: f32 = 0.100_000_000_000_1;
- | ^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | const BAD32_3: f32 = 0.1;
+ | ~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:23:29
|
LL | const BAD32_EDGE: f32 = 1.000_000_9;
- | ^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.000_001`
+ | ^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | const BAD32_EDGE: f32 = 1.000_001;
+ | ~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:27:26
|
LL | const BAD64_3: f64 = 0.100_000_000_000_000_000_1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.1`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | const BAD64_3: f64 = 0.1;
+ | ~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:30:22
|
LL | println!("{:?}", 8.888_888_888_888_888_888_888);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `8.888_888_888_888_89`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | println!("{:?}", 8.888_888_888_888_89);
+ | ~~~~~~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:41:22
|
LL | let bad32: f32 = 1.123_456_789;
- | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8`
+ | ^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad32: f32 = 1.123_456_8;
+ | ~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:42:26
|
LL | let bad32_suf: f32 = 1.123_456_789_f32;
- | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32`
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad32_suf: f32 = 1.123_456_8_f32;
+ | ~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:43:21
|
LL | let bad32_inf = 1.123_456_789_f32;
- | ^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8_f32`
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad32_inf = 1.123_456_8_f32;
+ | ~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:53:36
|
LL | let bad_vec32: Vec<f32> = vec![0.123_456_789];
- | ^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_79`
+ | ^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad_vec32: Vec<f32> = vec![0.123_456_79];
+ | ~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:54:36
|
LL | let bad_vec64: Vec<f64> = vec![0.123_456_789_123_456_789];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0.123_456_789_123_456_78`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad_vec64: Vec<f64> = vec![0.123_456_789_123_456_78];
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:58:24
|
LL | let bad_e32: f32 = 1.123_456_788_888e-10;
- | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8e-10`
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad_e32: f32 = 1.123_456_8e-10;
+ | ~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:61:27
|
LL | let bad_bige32: f32 = 1.123_456_788_888E-10;
- | ^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `1.123_456_8E-10`
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let bad_bige32: f32 = 1.123_456_8E-10;
+ | ~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:70:13
|
LL | let _ = 2.225_073_858_507_201_1e-308_f64;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `2.225_073_858_507_201e-308_f64`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let _ = 2.225_073_858_507_201e-308_f64;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:73:13
|
LL | let _ = 1.000_000_000_000_001e-324_f64;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `0_f64`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | let _ = 0_f64;
+ | ~~~~~
error: float has excessive precision
--> tests/ui/excessive_precision.rs:83:20
|
LL | const _: f64 = 3.0000000000000000e+00;
- | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or truncating it to: `3.0`
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or truncating it to
+ |
+LL | const _: f64 = 3.0;
+ | ~~~
error: aborting due to 16 previous errors
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.rs b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
index c25e79a..28b477b 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.rs
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
@@ -278,3 +278,16 @@ pub fn test2() {
}
}
}
+
+mod issue_13123 {
+ pub fn test() {
+ let mut vec = vec![1, 2, 3, 4];
+ let mut _index = 0;
+ 'label: for v in vec {
+ _index += 1;
+ if v == 1 {
+ break 'label;
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.stderr b/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
index e28f878..1b2d1f8 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
@@ -57,5 +57,11 @@
|
= note: `idx_u32` is of type `u32`, making it ineligible for `Iterator::enumerate`
-error: aborting due to 9 previous errors
+error: the variable `_index` is used as a loop counter
+ --> tests/ui/explicit_counter_loop.rs:286:9
+ |
+LL | 'label: for v in vec {
+ | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `'label: for (_index, v) in vec.into_iter().enumerate()`
+
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr b/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr
index e5bb8d1..a05b713 100644
--- a/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr
+++ b/src/tools/clippy/tests/ui/fn_to_numeric_cast_any.stderr
@@ -2,106 +2,190 @@
--> tests/ui/fn_to_numeric_cast_any.rs:23:13
|
LL | let _ = foo as i8;
- | ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i8`
+ | ^^^^^^^^^
|
= note: `-D clippy::fn-to-numeric-cast-any` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::fn_to_numeric_cast_any)]`
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as i8;
+ | ~~~~~~~~~~~
error: casting function pointer `foo` to `i16`
--> tests/ui/fn_to_numeric_cast_any.rs:26:13
|
LL | let _ = foo as i16;
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i16`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as i16;
+ | ~~~~~~~~~~~~
error: casting function pointer `foo` to `i32`
--> tests/ui/fn_to_numeric_cast_any.rs:28:13
|
LL | let _ = foo as i32;
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i32`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as i32;
+ | ~~~~~~~~~~~~
error: casting function pointer `foo` to `i64`
--> tests/ui/fn_to_numeric_cast_any.rs:30:13
|
LL | let _ = foo as i64;
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i64`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as i64;
+ | ~~~~~~~~~~~~
error: casting function pointer `foo` to `i128`
--> tests/ui/fn_to_numeric_cast_any.rs:32:13
|
LL | let _ = foo as i128;
- | ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as i128`
+ | ^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as i128;
+ | ~~~~~~~~~~~~~
error: casting function pointer `foo` to `isize`
--> tests/ui/fn_to_numeric_cast_any.rs:34:13
|
LL | let _ = foo as isize;
- | ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as isize`
+ | ^^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as isize;
+ | ~~~~~~~~~~~~~~
error: casting function pointer `foo` to `u8`
--> tests/ui/fn_to_numeric_cast_any.rs:37:13
|
LL | let _ = foo as u8;
- | ^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u8`
+ | ^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as u8;
+ | ~~~~~~~~~~~
error: casting function pointer `foo` to `u16`
--> tests/ui/fn_to_numeric_cast_any.rs:39:13
|
LL | let _ = foo as u16;
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u16`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as u16;
+ | ~~~~~~~~~~~~
error: casting function pointer `foo` to `u32`
--> tests/ui/fn_to_numeric_cast_any.rs:41:13
|
LL | let _ = foo as u32;
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u32`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as u32;
+ | ~~~~~~~~~~~~
error: casting function pointer `foo` to `u64`
--> tests/ui/fn_to_numeric_cast_any.rs:43:13
|
LL | let _ = foo as u64;
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u64`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as u64;
+ | ~~~~~~~~~~~~
error: casting function pointer `foo` to `u128`
--> tests/ui/fn_to_numeric_cast_any.rs:45:13
|
LL | let _ = foo as u128;
- | ^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as u128`
+ | ^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as u128;
+ | ~~~~~~~~~~~~~
error: casting function pointer `foo` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:47:13
|
LL | let _ = foo as usize;
- | ^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as usize`
+ | ^^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as usize;
+ | ~~~~~~~~~~~~~~
error: casting function pointer `Struct::static_method` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:52:13
|
LL | let _ = Struct::static_method as usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `Struct::static_method() as usize`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = Struct::static_method() as usize;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: casting function pointer `f` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:57:5
|
LL | f as usize
- | ^^^^^^^^^^ help: did you mean to invoke the function?: `f() as usize`
+ | ^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | f() as usize
+ |
error: casting function pointer `T::static_method` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:62:5
|
LL | T::static_method as usize
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `T::static_method() as usize`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | T::static_method() as usize
+ |
error: casting function pointer `(clos as fn(u32) -> u32)` to `usize`
--> tests/ui/fn_to_numeric_cast_any.rs:69:13
|
LL | let _ = (clos as fn(u32) -> u32) as usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `(clos as fn(u32) -> u32)() as usize`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = (clos as fn(u32) -> u32)() as usize;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: casting function pointer `foo` to `*const ()`
--> tests/ui/fn_to_numeric_cast_any.rs:74:13
|
LL | let _ = foo as *const ();
- | ^^^^^^^^^^^^^^^^ help: did you mean to invoke the function?: `foo() as *const ()`
+ | ^^^^^^^^^^^^^^^^
+ |
+help: did you mean to invoke the function?
+ |
+LL | let _ = foo() as *const ();
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/for_kv_map.fixed b/src/tools/clippy/tests/ui/for_kv_map.fixed
index a2112d7..1733b29 100644
--- a/src/tools/clippy/tests/ui/for_kv_map.fixed
+++ b/src/tools/clippy/tests/ui/for_kv_map.fixed
@@ -40,6 +40,16 @@
let _k = k;
}
+ let m: HashMap<u64, u64> = HashMap::new();
+ let rm = &m;
+ 'label: for k in rm.keys() {
+ //~^ ERROR: you seem to want to iterate on a map's keys
+ let _k = k;
+ if *k == 0u64 {
+ break 'label;
+ }
+ }
+
// The following should not produce warnings.
let m: HashMap<u64, u64> = HashMap::new();
diff --git a/src/tools/clippy/tests/ui/for_kv_map.rs b/src/tools/clippy/tests/ui/for_kv_map.rs
index 1b7959b..de465a7 100644
--- a/src/tools/clippy/tests/ui/for_kv_map.rs
+++ b/src/tools/clippy/tests/ui/for_kv_map.rs
@@ -40,6 +40,16 @@ fn main() {
let _k = k;
}
+ let m: HashMap<u64, u64> = HashMap::new();
+ let rm = &m;
+ 'label: for (k, _value) in rm {
+ //~^ ERROR: you seem to want to iterate on a map's keys
+ let _k = k;
+ if *k == 0u64 {
+ break 'label;
+ }
+ }
+
// The following should not produce warnings.
let m: HashMap<u64, u64> = HashMap::new();
diff --git a/src/tools/clippy/tests/ui/for_kv_map.stderr b/src/tools/clippy/tests/ui/for_kv_map.stderr
index f4ce473..adcc3ab 100644
--- a/src/tools/clippy/tests/ui/for_kv_map.stderr
+++ b/src/tools/clippy/tests/ui/for_kv_map.stderr
@@ -55,5 +55,16 @@
LL | for k in rm.keys() {
| ~ ~~~~~~~~~
-error: aborting due to 5 previous errors
+error: you seem to want to iterate on a map's keys
+ --> tests/ui/for_kv_map.rs:45:32
+ |
+LL | 'label: for (k, _value) in rm {
+ | ^^
+ |
+help: use the corresponding method
+ |
+LL | 'label: for k in rm.keys() {
+ | ~ ~~~~~~~~~
+
+error: aborting due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr
index a08b665..0f8b279 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/get_unwrap.stderr
@@ -1,14 +1,18 @@
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:37:17
|
LL | let _ = boxed_slice.get(1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&boxed_slice[1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/get_unwrap.rs:9:9
|
LL | #![deny(clippy::get_unwrap)]
| ^^^^^^^^^^^^^^^^^^
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &boxed_slice[1];
+ | ~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:37:17
@@ -21,11 +25,16 @@
= note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::unwrap_used)]`
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:38:17
|
LL | let _ = some_slice.get(0).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_slice[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_slice[0];
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:38:17
@@ -36,11 +45,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:39:17
|
LL | let _ = some_vec.get(0).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vec[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_vec[0];
+ | ~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:39:17
@@ -51,11 +65,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a VecDeque
--> tests/ui/get_unwrap.rs:40:17
|
LL | let _ = some_vecdeque.get(0).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_vecdeque[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_vecdeque[0];
+ | ~~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:40:17
@@ -66,11 +85,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a HashMap. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a HashMap
--> tests/ui/get_unwrap.rs:41:17
|
LL | let _ = some_hashmap.get(&1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_hashmap[&1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_hashmap[&1];
+ | ~~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:41:17
@@ -81,11 +105,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a BTreeMap. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a BTreeMap
--> tests/ui/get_unwrap.rs:42:17
|
LL | let _ = some_btreemap.get(&1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&some_btreemap[&1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = &some_btreemap[&1];
+ | ~~~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:42:17
@@ -96,11 +125,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:46:21
|
LL | let _: u8 = *boxed_slice.get(1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _: u8 = boxed_slice[1];
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:46:22
@@ -111,11 +145,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:51:9
|
LL | *boxed_slice.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `boxed_slice[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | boxed_slice[0] = 1;
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:51:10
@@ -126,11 +165,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:52:9
|
LL | *some_slice.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_slice[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | some_slice[0] = 1;
+ | ~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:52:10
@@ -141,11 +185,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:53:9
|
LL | *some_vec.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | some_vec[0] = 1;
+ | ~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:53:10
@@ -156,11 +205,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a VecDeque. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a VecDeque
--> tests/ui/get_unwrap.rs:54:9
|
LL | *some_vecdeque.get_mut(0).unwrap() = 1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vecdeque[0]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | some_vecdeque[0] = 1;
+ | ~~~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:54:10
@@ -171,11 +225,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:66:17
|
LL | let _ = some_vec.get(0..1).unwrap().to_vec();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = some_vec[0..1].to_vec();
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:66:17
@@ -186,11 +245,16 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get_mut().unwrap()` on a Vec. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a Vec
--> tests/ui/get_unwrap.rs:67:17
|
LL | let _ = some_vec.get_mut(0..1).unwrap().to_vec();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `some_vec[0..1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _ = some_vec[0..1].to_vec();
+ | ~~~~~~~~~~~~~~
error: used `unwrap()` on an `Option` value
--> tests/ui/get_unwrap.rs:67:17
@@ -201,29 +265,49 @@
= note: if this value is `None`, it will panic
= help: consider using `expect()` to provide a better panic message
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:77:24
|
LL | let _x: &i32 = f.get(1 + 2).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&f[1 + 2]`
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _x: &i32 = &f[1 + 2];
+ | ~~~~~~~~~
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:80:18
|
LL | let _x = f.get(1 + 2).unwrap().to_string();
- | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]`
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _x = f[1 + 2].to_string();
+ | ~~~~~~~~
-error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:83:18
|
LL | let _x = f.get(1 + 2).unwrap().abs();
- | ^^^^^^^^^^^^^^^^^^^^^ help: try: `f[1 + 2]`
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let _x = f[1 + 2].abs();
+ | ~~~~~~~~
-error: called `.get_mut().unwrap()` on a slice. Using `[]` is more clear and more concise
+error: called `.get_mut().unwrap()` on a slice
--> tests/ui/get_unwrap.rs:100:33
|
LL | let b = rest.get_mut(linidx(j, k) - linidx(i, k) - 1).unwrap();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut rest[linidx(j, k) - linidx(i, k) - 1]`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: using `[]` is clearer and more concise
+ |
+LL | let b = &mut rest[linidx(j, k) - linidx(i, k) - 1];
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 30 previous errors
diff --git a/src/tools/clippy/tests/ui/if_let_mutex.rs b/src/tools/clippy/tests/ui/if_let_mutex.rs
index cb6915e..bb0eadf 100644
--- a/src/tools/clippy/tests/ui/if_let_mutex.rs
+++ b/src/tools/clippy/tests/ui/if_let_mutex.rs
@@ -1,4 +1,5 @@
#![warn(clippy::if_let_mutex)]
+#![allow(clippy::redundant_pattern_matching)]
use std::ops::Deref;
use std::sync::Mutex;
@@ -50,4 +51,12 @@ fn mutex_ref(mutex: &Mutex<i32>) {
};
}
+fn multiple_mutexes(m1: &Mutex<()>, m2: &Mutex<()>) {
+ if let Ok(_) = m1.lock() {
+ m2.lock();
+ } else {
+ m1.lock();
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/if_let_mutex.stderr b/src/tools/clippy/tests/ui/if_let_mutex.stderr
index 6e0115c..45df4ac4 100644
--- a/src/tools/clippy/tests/ui/if_let_mutex.stderr
+++ b/src/tools/clippy/tests/ui/if_let_mutex.stderr
@@ -1,5 +1,5 @@
error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
- --> tests/ui/if_let_mutex.rs:10:5
+ --> tests/ui/if_let_mutex.rs:11:5
|
LL | if let Err(locked) = m.lock() {
| ^ - this Mutex will remain locked for the entire `if let`-block...
@@ -19,7 +19,7 @@
= help: to override `-D warnings` add `#[allow(clippy::if_let_mutex)]`
error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
- --> tests/ui/if_let_mutex.rs:23:5
+ --> tests/ui/if_let_mutex.rs:24:5
|
LL | if let Some(locked) = m.lock().unwrap().deref() {
| ^ - this Mutex will remain locked for the entire `if let`-block...
@@ -37,7 +37,7 @@
= help: move the lock call outside of the `if let ...` expression
error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
- --> tests/ui/if_let_mutex.rs:45:5
+ --> tests/ui/if_let_mutex.rs:46:5
|
LL | if let Ok(i) = mutex.lock() {
| ^ ----- this Mutex will remain locked for the entire `if let`-block...
@@ -53,5 +53,21 @@
|
= help: move the lock call outside of the `if let ...` expression
-error: aborting due to 3 previous errors
+error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
+ --> tests/ui/if_let_mutex.rs:55:5
+ |
+LL | if let Ok(_) = m1.lock() {
+ | ^ -- this Mutex will remain locked for the entire `if let`-block...
+ | _____|
+ | |
+LL | | m2.lock();
+LL | | } else {
+LL | | m1.lock();
+ | | -- ... and is tried to lock again here, which will always deadlock.
+LL | | }
+ | |_____^
+ |
+ = help: move the lock call outside of the `if let ...` expression
+
+error: aborting due to 4 previous errors
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.fixed b/src/tools/clippy/tests/ui/if_then_some_else_none.fixed
new file mode 100644
index 0000000..ad13372
--- /dev/null
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.fixed
@@ -0,0 +1,119 @@
+#![warn(clippy::if_then_some_else_none)]
+#![allow(clippy::redundant_pattern_matching, clippy::unnecessary_lazy_evaluations)]
+
+fn main() {
+ // Should issue an error.
+ let _ = foo().then(|| { println!("true!"); "foo" });
+
+ // Should issue an error when macros are used.
+ let _ = matches!(true, true).then(|| { println!("true!"); matches!(true, false) });
+
+ // Should issue an error. Binary expression `o < 32` should be parenthesized.
+ let x = Some(5);
+ let _ = x.and_then(|o| (o < 32).then_some(o));
+ //~^ ERROR: this could be simplified with `bool::then_some`
+
+ // Should issue an error. Unary expression `!x` should be parenthesized.
+ let x = true;
+ let _ = (!x).then_some(0);
+ //~^ ERROR: this could be simplified with `bool::then_some`
+
+ // Should not issue an error since the `else` block has a statement besides `None`.
+ let _ = if foo() {
+ println!("true!");
+ Some("foo")
+ } else {
+ eprintln!("false...");
+ None
+ };
+
+ // Should not issue an error since there are more than 2 blocks in the if-else chain.
+ let _ = if foo() {
+ println!("foo true!");
+ Some("foo")
+ } else if bar() {
+ println!("bar true!");
+ Some("bar")
+ } else {
+ None
+ };
+
+ let _ = if foo() {
+ println!("foo true!");
+ Some("foo")
+ } else {
+ bar().then(|| {
+ println!("bar true!");
+ "bar"
+ })
+ };
+
+ // Should not issue an error since the `then` block has `None`, not `Some`.
+ let _ = if foo() { None } else { Some("foo is false") };
+
+ // Should not issue an error since the `else` block doesn't use `None` directly.
+ let _ = if foo() { Some("foo is true") } else { into_none() };
+
+ // Should not issue an error since the `then` block doesn't use `Some` directly.
+ let _ = if foo() { into_some("foo") } else { None };
+}
+
+#[clippy::msrv = "1.49"]
+fn _msrv_1_49() {
+ // `bool::then` was stabilized in 1.50. Do not lint this
+ let _ = if foo() {
+ println!("true!");
+ Some(149)
+ } else {
+ None
+ };
+}
+
+#[clippy::msrv = "1.50"]
+fn _msrv_1_50() {
+ let _ = foo().then(|| { println!("true!"); 150 });
+}
+
+fn foo() -> bool {
+ unimplemented!()
+}
+
+fn bar() -> bool {
+ unimplemented!()
+}
+
+fn into_some<T>(v: T) -> Option<T> {
+ Some(v)
+}
+
+fn into_none<T>() -> Option<T> {
+ None
+}
+
+// Should not warn
+fn f(b: bool, v: Option<()>) -> Option<()> {
+ if b {
+ v?; // This is a potential early return, is not equivalent with `bool::then`
+
+ Some(())
+ } else {
+ None
+ }
+}
+
+fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
+ let x = if b {
+ #[allow(clippy::let_unit_value)]
+ let _ = v?;
+ Some(())
+ } else {
+ None
+ };
+
+ Ok(())
+}
+
+const fn issue12103(x: u32) -> Option<u32> {
+ // Should not issue an error in `const` context
+ if x > 42 { Some(150) } else { None }
+}
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.rs b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
index ccde154..73edbb7 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.rs
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
@@ -1,5 +1,5 @@
#![warn(clippy::if_then_some_else_none)]
-#![allow(clippy::redundant_pattern_matching)]
+#![allow(clippy::redundant_pattern_matching, clippy::unnecessary_lazy_evaluations)]
fn main() {
// Should issue an error.
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
index e0a95ae..aed01e0 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
@@ -9,9 +9,8 @@
LL | | } else {
LL | | None
LL | | };
- | |_____^
+ | |_____^ help: try: `foo().then(|| { println!("true!"); "foo" })`
|
- = help: consider using `bool::then` like: `foo().then(|| { /* snippet */ "foo" })`
= note: `-D clippy::if-then-some-else-none` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::if_then_some_else_none)]`
@@ -26,25 +25,19 @@
LL | | } else {
LL | | None
LL | | };
- | |_____^
- |
- = help: consider using `bool::then` like: `matches!(true, true).then(|| { /* snippet */ matches!(true, false) })`
+ | |_____^ help: try: `matches!(true, true).then(|| { println!("true!"); matches!(true, false) })`
error: this could be simplified with `bool::then_some`
--> tests/ui/if_then_some_else_none.rs:25:28
|
LL | let _ = x.and_then(|o| if o < 32 { Some(o) } else { None });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider using `bool::then_some` like: `(o < 32).then_some(o)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(o < 32).then_some(o)`
error: this could be simplified with `bool::then_some`
--> tests/ui/if_then_some_else_none.rs:30:13
|
LL | let _ = if !x { Some(0) } else { None };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider using `bool::then_some` like: `(!x).then_some(0)`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(!x).then_some(0)`
error: this could be simplified with `bool::then`
--> tests/ui/if_then_some_else_none.rs:86:13
@@ -57,9 +50,7 @@
LL | | } else {
LL | | None
LL | | };
- | |_____^
- |
- = help: consider using `bool::then` like: `foo().then(|| { /* snippet */ 150 })`
+ | |_____^ help: try: `foo().then(|| { println!("true!"); 150 })`
error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.fixed b/src/tools/clippy/tests/ui/implicit_hasher.fixed
new file mode 100644
index 0000000..2d6dc02
--- /dev/null
+++ b/src/tools/clippy/tests/ui/implicit_hasher.fixed
@@ -0,0 +1,102 @@
+//@aux-build:proc_macros.rs
+#![deny(clippy::implicit_hasher)]
+
+#[macro_use]
+extern crate proc_macros;
+
+use std::cmp::Eq;
+use std::collections::{HashMap, HashSet};
+use std::hash::{BuildHasher, Hash};
+
+pub trait Foo<T>: Sized {
+ fn make() -> (Self, Self);
+}
+
+impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<i8> for HashMap<K, V, S> {
+ fn make() -> (Self, Self) {
+ // OK, don't suggest to modify these
+ let _: HashMap<i32, i32> = HashMap::new();
+ let _: HashSet<i32> = HashSet::new();
+
+ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
+ }
+}
+impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<i8> for (HashMap<K, V, S>,) {
+ fn make() -> (Self, Self) {
+ ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),))
+ }
+}
+impl<S: ::std::hash::BuildHasher + Default> Foo<i16> for HashMap<String, String, S> {
+ fn make() -> (Self, Self) {
+ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
+ }
+}
+
+impl<K: Hash + Eq, V, S: BuildHasher + Default> Foo<i32> for HashMap<K, V, S> {
+ fn make() -> (Self, Self) {
+ (HashMap::default(), HashMap::with_capacity_and_hasher(10, S::default()))
+ }
+}
+impl<S: BuildHasher + Default> Foo<i64> for HashMap<String, String, S> {
+ fn make() -> (Self, Self) {
+ (HashMap::default(), HashMap::with_capacity_and_hasher(10, S::default()))
+ }
+}
+
+impl<T: Hash + Eq, S: ::std::hash::BuildHasher + Default> Foo<i8> for HashSet<T, S> {
+ fn make() -> (Self, Self) {
+ (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default()))
+ }
+}
+impl<S: ::std::hash::BuildHasher + Default> Foo<i16> for HashSet<String, S> {
+ fn make() -> (Self, Self) {
+ (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default()))
+ }
+}
+
+impl<T: Hash + Eq, S: BuildHasher + Default> Foo<i32> for HashSet<T, S> {
+ fn make() -> (Self, Self) {
+ (HashSet::default(), HashSet::with_capacity_and_hasher(10, S::default()))
+ }
+}
+impl<S: BuildHasher + Default> Foo<i64> for HashSet<String, S> {
+ fn make() -> (Self, Self) {
+ (HashSet::default(), HashSet::with_capacity_and_hasher(10, S::default()))
+ }
+}
+
+pub fn map<S: ::std::hash::BuildHasher>(map: &mut HashMap<i32, i32, S>) {}
+
+pub fn set<S: ::std::hash::BuildHasher>(set: &mut HashSet<i32, S>) {}
+
+#[inline_macros]
+pub mod gen {
+ use super::*;
+ inline! {
+ impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u8> for HashMap<K, V, S> {
+ fn make() -> (Self, Self) {
+ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
+ }
+ }
+
+ pub fn bar(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
+ }
+}
+
+// When the macro is in a different file, the suggestion spans can't be combined properly
+// and should not cause an ICE
+// See #2707
+#[macro_use]
+#[path = "auxiliary/test_macro.rs"]
+pub mod test_macro;
+__implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::A);
+
+// #4260
+external! {
+ pub fn f(input: &HashMap<u32, u32>) {}
+}
+
+// #7712
+pub async fn election_vote<S: ::std::hash::BuildHasher>(_data: HashMap<i32, i32, S>) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.rs b/src/tools/clippy/tests/ui/implicit_hasher.rs
index f7cd541..0a33435 100644
--- a/src/tools/clippy/tests/ui/implicit_hasher.rs
+++ b/src/tools/clippy/tests/ui/implicit_hasher.rs
@@ -1,11 +1,8 @@
//@aux-build:proc_macros.rs
-//@no-rustfix
#![deny(clippy::implicit_hasher)]
-#![allow(unused)]
#[macro_use]
extern crate proc_macros;
-use proc_macros::external;
use std::cmp::Eq;
use std::collections::{HashMap, HashSet};
@@ -68,9 +65,11 @@ fn make() -> (Self, Self) {
}
}
-pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
+pub fn map(map: &mut HashMap<i32, i32>) {}
-#[proc_macros::inline_macros]
+pub fn set(set: &mut HashSet<i32>) {}
+
+#[inline_macros]
pub mod gen {
use super::*;
inline! {
diff --git a/src/tools/clippy/tests/ui/implicit_hasher.stderr b/src/tools/clippy/tests/ui/implicit_hasher.stderr
index a3df8ed..48c6ebc 100644
--- a/src/tools/clippy/tests/ui/implicit_hasher.stderr
+++ b/src/tools/clippy/tests/ui/implicit_hasher.stderr
@@ -1,40 +1,121 @@
-error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
- --> tests/ui/implicit_hasher.rs:14:1
+error: impl for `HashMap` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:15:35
|
-LL | pub trait Foo<T>: Sized {
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
+ | ^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> tests/ui/implicit_hasher.rs:2:9
+ |
+LL | #![deny(clippy::implicit_hasher)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+help: add a type parameter for `BuildHasher`
+ |
+LL ~ impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<i8> for HashMap<K, V, S> {
+LL | fn make() -> (Self, Self) {
+...
+LL |
+LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
+ |
-error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
- --> tests/ui/implicit_hasher.rs:71:1
+error: impl for `HashMap` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:24:36
|
-LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
+ | ^^^^^^^^^^^^^
+ |
+help: add a type parameter for `BuildHasher`
+ |
+LL ~ impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<i8> for (HashMap<K, V, S>,) {
+LL | fn make() -> (Self, Self) {
+LL ~ ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Default::default()),))
+ |
-error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
- --> tests/ui/implicit_hasher.rs:74:1
+error: impl for `HashMap` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:29:19
|
-LL | pub mod gen {
- | ^^^^^^^^^^^
+LL | impl Foo<i16> for HashMap<String, String> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add a type parameter for `BuildHasher`
+ |
+LL ~ impl<S: ::std::hash::BuildHasher + Default> Foo<i16> for HashMap<String, String, S> {
+LL | fn make() -> (Self, Self) {
+LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
+ |
-error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
- --> tests/ui/implicit_hasher.rs:92:1
+error: impl for `HashSet` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:46:32
|
-LL | pub mod test_macro;
- | ^^^^^^^^^^^^^^^^^^^
+LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
+ | ^^^^^^^^^^
+ |
+help: add a type parameter for `BuildHasher`
+ |
+LL ~ impl<T: Hash + Eq, S: ::std::hash::BuildHasher + Default> Foo<i8> for HashSet<T, S> {
+LL | fn make() -> (Self, Self) {
+LL ~ (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default()))
+ |
-error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
- --> tests/ui/implicit_hasher.rs:96:1
+error: impl for `HashSet` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:51:19
|
-LL | external! {
- | ^^^^^^^^^
+LL | impl Foo<i16> for HashSet<String> {
+ | ^^^^^^^^^^^^^^^
|
- = note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: add a type parameter for `BuildHasher`
+ |
+LL ~ impl<S: ::std::hash::BuildHasher + Default> Foo<i16> for HashSet<String, S> {
+LL | fn make() -> (Self, Self) {
+LL ~ (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default()))
+ |
-error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
- --> tests/ui/implicit_hasher.rs:101:1
+error: parameter of type `HashMap` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:68:22
+ |
+LL | pub fn map(map: &mut HashMap<i32, i32>) {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: add a type parameter for `BuildHasher`
+ |
+LL | pub fn map<S: ::std::hash::BuildHasher>(map: &mut HashMap<i32, i32, S>) {}
+ | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
+
+error: parameter of type `HashSet` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:70:22
+ |
+LL | pub fn set(set: &mut HashSet<i32>) {}
+ | ^^^^^^^^^^^^
+ |
+help: add a type parameter for `BuildHasher`
+ |
+LL | pub fn set<S: ::std::hash::BuildHasher>(set: &mut HashSet<i32, S>) {}
+ | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~
+
+error: impl for `HashMap` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:76:43
+ |
+LL | impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
+ | ^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `__inline_mac_mod_gen` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: add a type parameter for `BuildHasher`
+ |
+LL ~ impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<u8> for HashMap<K, V, S> {
+LL | fn make() -> (Self, Self) {
+LL ~ (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
+ |
+
+error: parameter of type `HashMap` should be generalized over different hashers
+ --> tests/ui/implicit_hasher.rs:100:35
|
LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: add a type parameter for `BuildHasher`
+ |
+LL | pub async fn election_vote<S: ::std::hash::BuildHasher>(_data: HashMap<i32, i32, S>) {}
+ | +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/implicit_return.stderr b/src/tools/clippy/tests/ui/implicit_return.stderr
index f06d4e9..3b06f26f 100644
--- a/src/tools/clippy/tests/ui/implicit_return.stderr
+++ b/src/tools/clippy/tests/ui/implicit_return.stderr
@@ -2,88 +2,157 @@
--> tests/ui/implicit_return.rs:15:5
|
LL | true
- | ^^^^ help: add `return` as shown: `return true`
+ | ^^^^
|
= note: `-D clippy::implicit-return` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::implicit_return)]`
+help: add `return` as shown
+ |
+LL | return true
+ |
error: missing `return` statement
--> tests/ui/implicit_return.rs:19:15
|
LL | if true { true } else { false }
- | ^^^^ help: add `return` as shown: `return true`
+ | ^^^^
+ |
+help: add `return` as shown
+ |
+LL | if true { return true } else { false }
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:19:29
|
LL | if true { true } else { false }
- | ^^^^^ help: add `return` as shown: `return false`
+ | ^^^^^
+ |
+help: add `return` as shown
+ |
+LL | if true { true } else { return false }
+ | ~~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:25:17
|
LL | true => false,
- | ^^^^^ help: add `return` as shown: `return false`
+ | ^^^^^
+ |
+help: add `return` as shown
+ |
+LL | true => return false,
+ | ~~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:26:20
|
LL | false => { true },
- | ^^^^ help: add `return` as shown: `return true`
+ | ^^^^
+ |
+help: add `return` as shown
+ |
+LL | false => { return true },
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:39:9
|
LL | break true;
- | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
+ | ^^^^^^^^^^
+ |
+help: change `break` to `return` as shown
+ |
+LL | return true;
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:46:13
|
LL | break true;
- | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
+ | ^^^^^^^^^^
+ |
+help: change `break` to `return` as shown
+ |
+LL | return true;
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:54:13
|
LL | break true;
- | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
+ | ^^^^^^^^^^
+ |
+help: change `break` to `return` as shown
+ |
+LL | return true;
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:72:18
|
LL | let _ = || { true };
- | ^^^^ help: add `return` as shown: `return true`
+ | ^^^^
+ |
+help: add `return` as shown
+ |
+LL | let _ = || { return true };
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:73:16
|
LL | let _ = || true;
- | ^^^^ help: add `return` as shown: `return true`
+ | ^^^^
+ |
+help: add `return` as shown
+ |
+LL | let _ = || return true;
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:81:5
|
LL | format!("test {}", "test")
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: add `return` as shown
+ |
+LL | return format!("test {}", "test")
+ |
error: missing `return` statement
--> tests/ui/implicit_return.rs:90:5
|
LL | m!(true, false)
- | ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)`
+ | ^^^^^^^^^^^^^^^
+ |
+help: add `return` as shown
+ |
+LL | return m!(true, false)
+ |
error: missing `return` statement
--> tests/ui/implicit_return.rs:96:13
|
LL | break true;
- | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
+ | ^^^^^^^^^^
+ |
+help: change `break` to `return` as shown
+ |
+LL | return true;
+ | ~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:101:17
|
LL | break 'outer false;
- | ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false`
+ | ^^^^^^^^^^^^^^^^^^
+ |
+help: change `break` to `return` as shown
+ |
+LL | return false;
+ | ~~~~~~~~~~~~
error: missing `return` statement
--> tests/ui/implicit_return.rs:116:5
@@ -104,7 +173,12 @@
--> tests/ui/implicit_return.rs:130:5
|
LL | true
- | ^^^^ help: add `return` as shown: `return true`
+ | ^^^^
+ |
+help: add `return` as shown
+ |
+LL | return true
+ |
error: aborting due to 16 previous errors
diff --git a/src/tools/clippy/tests/ui/lossy_float_literal.stderr b/src/tools/clippy/tests/ui/lossy_float_literal.stderr
index b5a0741..3026854 100644
--- a/src/tools/clippy/tests/ui/lossy_float_literal.stderr
+++ b/src/tools/clippy/tests/ui/lossy_float_literal.stderr
@@ -2,70 +2,124 @@
--> tests/ui/lossy_float_literal.rs:14:18
|
LL | let _: f32 = 16_777_217.0;
- | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_216.0`
+ | ^^^^^^^^^^^^
|
= note: `-D clippy::lossy-float-literal` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::lossy_float_literal)]`
+help: consider changing the type or replacing it with
+ |
+LL | let _: f32 = 16_777_216.0;
+ | ~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:15:18
|
LL | let _: f32 = 16_777_219.0;
- | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
+ | ^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f32 = 16_777_220.0;
+ | ~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:16:18
|
LL | let _: f32 = 16_777_219.;
- | ^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
+ | ^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f32 = 16_777_220.0;
+ | ~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:17:18
|
LL | let _: f32 = 16_777_219.000;
- | ^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
+ | ^^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f32 = 16_777_220.0;
+ | ~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:18:13
|
LL | let _ = 16_777_219f32;
- | ^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220_f32`
+ | ^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _ = 16_777_220_f32;
+ | ~~~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:19:19
|
LL | let _: f32 = -16_777_219.0;
- | ^^^^^^^^^^^^ help: consider changing the type or replacing it with: `16_777_220.0`
+ | ^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f32 = -16_777_220.0;
+ | ~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:21:18
|
LL | let _: f64 = 9_007_199_254_740_993.0;
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f64 = 9_007_199_254_740_992.0;
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:22:18
|
LL | let _: f64 = 9_007_199_254_740_993.;
- | ^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f64 = 9_007_199_254_740_992.0;
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:23:18
|
LL | let _: f64 = 9_007_199_254_740_993.00;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f64 = 9_007_199_254_740_992.0;
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:24:13
|
LL | let _ = 9_007_199_254_740_993f64;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992_f64`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _ = 9_007_199_254_740_992_f64;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
error: literal cannot be represented as the underlying type without loss of precision
--> tests/ui/lossy_float_literal.rs:25:19
|
LL | let _: f64 = -9_007_199_254_740_993.0;
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the type or replacing it with: `9_007_199_254_740_992.0`
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the type or replacing it with
+ |
+LL | let _: f64 = -9_007_199_254_740_992.0;
+ | ~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 11 previous errors
diff --git a/src/tools/clippy/tests/ui/missing_trait_methods.rs b/src/tools/clippy/tests/ui/missing_trait_methods.rs
index 1b09b71..55b904b 100644
--- a/src/tools/clippy/tests/ui/missing_trait_methods.rs
+++ b/src/tools/clippy/tests/ui/missing_trait_methods.rs
@@ -49,4 +49,12 @@ fn b<T: AsRef<[u8]>>(a: &T) -> &[u8] {
}
}
+trait MissingMultiple {
+ fn one() {}
+ fn two() {}
+ fn three() {}
+}
+
+impl MissingMultiple for Partial {}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_trait_methods.stderr b/src/tools/clippy/tests/ui/missing_trait_methods.stderr
index f5d5d44..9c4968b 100644
--- a/src/tools/clippy/tests/ui/missing_trait_methods.stderr
+++ b/src/tools/clippy/tests/ui/missing_trait_methods.stderr
@@ -24,5 +24,41 @@
LL | fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: missing trait method provided by default: `one`
+ --> tests/ui/missing_trait_methods.rs:58:1
+ |
+LL | impl MissingMultiple for Partial {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: implement the method
+ --> tests/ui/missing_trait_methods.rs:53:5
+ |
+LL | fn one() {}
+ | ^^^^^^^^
+
+error: missing trait method provided by default: `two`
+ --> tests/ui/missing_trait_methods.rs:58:1
+ |
+LL | impl MissingMultiple for Partial {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: implement the method
+ --> tests/ui/missing_trait_methods.rs:54:5
+ |
+LL | fn two() {}
+ | ^^^^^^^^
+
+error: missing trait method provided by default: `three`
+ --> tests/ui/missing_trait_methods.rs:58:1
+ |
+LL | impl MissingMultiple for Partial {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: implement the method
+ --> tests/ui/missing_trait_methods.rs:55:5
+ |
+LL | fn three() {}
+ | ^^^^^^^^^^
+
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed
index 5478372..c1dc8b5 100644
--- a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.fixed
@@ -333,4 +333,12 @@
f(&y); // Don't lint
f("".to_owned()); // Lint
}
+ {
+ fn takes_writer<T: std::io::Write>(_: T) {}
+
+ fn issue_12856(mut buffer: &mut Vec<u8>) {
+ takes_writer(&mut buffer); // Don't lint, would make buffer unavailable later
+ buffer.extend(b"\n");
+ }
+ }
}
diff --git a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs
index 2643815..c7f6682 100644
--- a/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs
+++ b/src/tools/clippy/tests/ui/needless_borrows_for_generic_args.rs
@@ -333,4 +333,12 @@ fn f(_: impl AsRef<str>) {}
f(&y); // Don't lint
f(&"".to_owned()); // Lint
}
+ {
+ fn takes_writer<T: std::io::Write>(_: T) {}
+
+ fn issue_12856(mut buffer: &mut Vec<u8>) {
+ takes_writer(&mut buffer); // Don't lint, would make buffer unavailable later
+ buffer.extend(b"\n");
+ }
+ }
}
diff --git a/src/tools/clippy/tests/ui/needless_pub_self.stderr b/src/tools/clippy/tests/ui/needless_pub_self.stderr
index 0bff2e4..1fdd841 100644
--- a/src/tools/clippy/tests/ui/needless_pub_self.stderr
+++ b/src/tools/clippy/tests/ui/needless_pub_self.stderr
@@ -2,22 +2,27 @@
--> tests/ui/needless_pub_self.rs:13:1
|
LL | pub(self) fn a() {}
- | ^^^^^^^^^ help: remove it
+ | ^^^^^^^^^
|
= note: `-D clippy::needless-pub-self` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::needless_pub_self)]`
+ = help: remove it
error: unnecessary `pub(in self)`
--> tests/ui/needless_pub_self.rs:14:1
|
LL | pub(in self) fn b() {}
- | ^^^^^^^^^^^^ help: remove it
+ | ^^^^^^^^^^^^
+ |
+ = help: remove it
error: unnecessary `pub(self)`
--> tests/ui/needless_pub_self.rs:20:5
|
LL | pub(self) fn f() {}
- | ^^^^^^^^^ help: remove it
+ | ^^^^^^^^^
+ |
+ = help: remove it
error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index d117e8b..52b0155 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -177,3 +177,9 @@ fn issue_12371(x: usize) -> bool {
// Should not warn!
!x != 0
}
+
+// Not linted because it is slow to do so
+// https://github.com/rust-lang/rust-clippy/issues/13206
+fn many_ops(a: bool, b: bool, c: bool, d: bool, e: bool, f: bool) -> bool {
+ (a && c && f) || (!a && b && !d) || (!b && !c && !e) || (d && e && !f)
+}
diff --git a/src/tools/clippy/tests/ui/patterns.fixed b/src/tools/clippy/tests/ui/patterns.fixed
index 332cba9..feaec33 100644
--- a/src/tools/clippy/tests/ui/patterns.fixed
+++ b/src/tools/clippy/tests/ui/patterns.fixed
@@ -1,7 +1,7 @@
//@aux-build:proc_macros.rs
#![warn(clippy::all)]
#![allow(unused)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::single_match)]
#[macro_use]
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/patterns.rs b/src/tools/clippy/tests/ui/patterns.rs
index 45d9076..53812c7 100644
--- a/src/tools/clippy/tests/ui/patterns.rs
+++ b/src/tools/clippy/tests/ui/patterns.rs
@@ -1,7 +1,7 @@
//@aux-build:proc_macros.rs
#![warn(clippy::all)]
#![allow(unused)]
-#![allow(clippy::uninlined_format_args)]
+#![allow(clippy::uninlined_format_args, clippy::single_match)]
#[macro_use]
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index d70c9f8..b810fd8 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -13,7 +13,10 @@
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
+#![allow(clippy::manual_find_map)]
+#![allow(clippy::manual_filter_map)]
#![allow(clippy::useless_conversion)]
+#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::match_result_ok)]
#![allow(clippy::non_canonical_clone_impl)]
#![allow(clippy::non_canonical_partial_ord_impl)]
@@ -47,6 +50,7 @@
#![allow(invalid_value)]
#![allow(invalid_from_utf8_unchecked)]
#![allow(let_underscore_drop)]
+#![allow(unexpected_cfgs)]
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
#![allow(named_arguments_used_positionally)]
@@ -55,65 +59,72 @@
#![allow(unknown_lints)]
#![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)]
-#![warn(clippy::almost_complete_range)]
-#![warn(clippy::disallowed_names)]
-#![warn(clippy::blocks_in_conditions)]
-#![warn(clippy::blocks_in_conditions)]
-#![warn(clippy::blocks_in_conditions)]
-#![warn(clippy::box_collection)]
-#![warn(clippy::redundant_static_lifetimes)]
-#![warn(clippy::cognitive_complexity)]
-#![warn(clippy::derived_hash_with_manual_eq)]
-#![warn(clippy::disallowed_methods)]
-#![warn(clippy::disallowed_types)]
-#![warn(clippy::mixed_read_write_in_expression)]
-#![warn(clippy::useless_conversion)]
-#![warn(clippy::match_result_ok)]
-#![warn(clippy::non_canonical_clone_impl)]
-#![warn(clippy::non_canonical_partial_ord_impl)]
-#![warn(clippy::arithmetic_side_effects)]
-#![warn(clippy::overly_complex_bool_expr)]
-#![warn(clippy::new_without_default)]
-#![warn(clippy::bind_instead_of_map)]
-#![warn(clippy::expect_used)]
-#![warn(clippy::map_unwrap_or)]
-#![warn(clippy::map_unwrap_or)]
-#![warn(clippy::unwrap_used)]
-#![warn(clippy::panicking_overflow_checks)]
-#![warn(clippy::needless_borrow)]
-#![warn(clippy::expect_used)]
-#![warn(clippy::map_unwrap_or)]
-#![warn(clippy::unwrap_used)]
-#![warn(clippy::single_char_add_str)]
-#![warn(clippy::module_name_repetitions)]
-#![warn(clippy::missing_const_for_thread_local)]
-#![warn(clippy::recursive_format_impl)]
-#![warn(clippy::unwrap_or_default)]
-#![warn(clippy::invisible_characters)]
-#![warn(invalid_reference_casting)]
-#![warn(suspicious_double_ref_op)]
-#![warn(invalid_nan_comparisons)]
-#![warn(drop_bounds)]
-#![warn(dropping_copy_types)]
-#![warn(dropping_references)]
-#![warn(useless_ptr_null_checks)]
-#![warn(for_loops_over_fallibles)]
-#![warn(for_loops_over_fallibles)]
-#![warn(for_loops_over_fallibles)]
-#![warn(forgetting_copy_types)]
-#![warn(forgetting_references)]
-#![warn(array_into_iter)]
-#![warn(invalid_atomic_ordering)]
-#![warn(invalid_value)]
-#![warn(invalid_from_utf8_unchecked)]
-#![warn(let_underscore_drop)]
-#![warn(enum_intrinsics_non_enums)]
-#![warn(non_fmt_panics)]
-#![warn(named_arguments_used_positionally)]
-#![warn(temporary_cstring_as_ptr)]
-#![warn(undropped_manually_drops)]
-#![warn(unknown_lints)]
-#![warn(unused_labels)]
-#![warn(ambiguous_wide_pointer_comparisons)]
+#![allow(clippy::reversed_empty_ranges)]
+#![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
+#![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name`
+#![warn(clippy::blocks_in_conditions)] //~ ERROR: lint `clippy::block_in_if_condition_expr`
+#![warn(clippy::blocks_in_conditions)] //~ ERROR: lint `clippy::block_in_if_condition_stmt`
+#![warn(clippy::blocks_in_conditions)] //~ ERROR: lint `clippy::blocks_in_if_conditions`
+#![warn(clippy::box_collection)] //~ ERROR: lint `clippy::box_vec`
+#![warn(clippy::redundant_static_lifetimes)] //~ ERROR: lint `clippy::const_static_lifetime`
+#![warn(clippy::cognitive_complexity)] //~ ERROR: lint `clippy::cyclomatic_complexity`
+#![warn(clippy::derived_hash_with_manual_eq)] //~ ERROR: lint `clippy::derive_hash_xor_eq`
+#![warn(clippy::disallowed_methods)] //~ ERROR: lint `clippy::disallowed_method`
+#![warn(clippy::disallowed_types)] //~ ERROR: lint `clippy::disallowed_type`
+#![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence`
+#![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map`
+#![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion`
+#![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
+#![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result`
+#![warn(clippy::non_canonical_clone_impl)] //~ ERROR: lint `clippy::incorrect_clone_impl_on_copy_type`
+#![warn(clippy::non_canonical_partial_ord_impl)] //~ ERROR: lint `clippy::incorrect_partial_ord_impl_on_ord_type`
+#![warn(clippy::arithmetic_side_effects)] //~ ERROR: lint `clippy::integer_arithmetic`
+#![warn(clippy::overly_complex_bool_expr)] //~ ERROR: lint `clippy::logic_bug`
+#![warn(clippy::new_without_default)] //~ ERROR: lint `clippy::new_without_default_derive`
+#![warn(clippy::bind_instead_of_map)] //~ ERROR: lint `clippy::option_and_then_some`
+#![warn(clippy::expect_used)] //~ ERROR: lint `clippy::option_expect_used`
+#![warn(clippy::map_unwrap_or)] //~ ERROR: lint `clippy::option_map_unwrap_or`
+#![warn(clippy::map_unwrap_or)] //~ ERROR: lint `clippy::option_map_unwrap_or_else`
+#![warn(clippy::unwrap_used)] //~ ERROR: lint `clippy::option_unwrap_used`
+#![warn(clippy::panicking_overflow_checks)] //~ ERROR: lint `clippy::overflow_check_conditional`
+#![warn(clippy::needless_borrow)] //~ ERROR: lint `clippy::ref_in_deref`
+#![warn(clippy::expect_used)] //~ ERROR: lint `clippy::result_expect_used`
+#![warn(clippy::map_unwrap_or)] //~ ERROR: lint `clippy::result_map_unwrap_or_else`
+#![warn(clippy::unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used`
+#![warn(clippy::single_char_add_str)] //~ ERROR: lint `clippy::single_char_push_str`
+#![warn(clippy::module_name_repetitions)] //~ ERROR: lint `clippy::stutter`
+#![warn(clippy::missing_const_for_thread_local)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const`
+#![warn(clippy::recursive_format_impl)] //~ ERROR: lint `clippy::to_string_in_display`
+#![warn(clippy::unwrap_or_default)] //~ ERROR: lint `clippy::unwrap_or_else_default`
+#![warn(clippy::invisible_characters)] //~ ERROR: lint `clippy::zero_width_space`
+#![warn(invalid_reference_casting)] //~ ERROR: lint `clippy::cast_ref_to_mut`
+#![warn(suspicious_double_ref_op)] //~ ERROR: lint `clippy::clone_double_ref`
+#![warn(invalid_nan_comparisons)] //~ ERROR: lint `clippy::cmp_nan`
+#![warn(drop_bounds)] //~ ERROR: lint `clippy::drop_bounds`
+#![warn(dropping_copy_types)] //~ ERROR: lint `clippy::drop_copy`
+#![warn(dropping_references)] //~ ERROR: lint `clippy::drop_ref`
+#![warn(useless_ptr_null_checks)] //~ ERROR: lint `clippy::fn_null_check`
+#![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_option`
+#![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_result`
+#![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loops_over_fallibles`
+#![warn(forgetting_copy_types)] //~ ERROR: lint `clippy::forget_copy`
+#![warn(forgetting_references)] //~ ERROR: lint `clippy::forget_ref`
+#![warn(array_into_iter)] //~ ERROR: lint `clippy::into_iter_on_array`
+#![warn(invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
+#![warn(invalid_value)] //~ ERROR: lint `clippy::invalid_ref`
+#![warn(invalid_from_utf8_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
+#![warn(let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
+#![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::maybe_misused_cfg`
+#![warn(enum_intrinsics_non_enums)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
+#![warn(unexpected_cfgs)] //~ ERROR: lint `clippy::mismatched_target_os`
+#![warn(non_fmt_panics)] //~ ERROR: lint `clippy::panic_params`
+#![warn(named_arguments_used_positionally)] //~ ERROR: lint `clippy::positional_named_format_parameters`
+#![warn(temporary_cstring_as_ptr)] //~ ERROR: lint `clippy::temporary_cstring_as_ptr`
+#![warn(undropped_manually_drops)] //~ ERROR: lint `clippy::undropped_manually_drops`
+#![warn(unknown_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
+#![warn(unused_labels)] //~ ERROR: lint `clippy::unused_label`
+#![warn(ambiguous_wide_pointer_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons`
+#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop`
fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 8d0ac3c..e03df16 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -13,7 +13,10 @@
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
+#![allow(clippy::manual_find_map)]
+#![allow(clippy::manual_filter_map)]
#![allow(clippy::useless_conversion)]
+#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::match_result_ok)]
#![allow(clippy::non_canonical_clone_impl)]
#![allow(clippy::non_canonical_partial_ord_impl)]
@@ -47,6 +50,7 @@
#![allow(invalid_value)]
#![allow(invalid_from_utf8_unchecked)]
#![allow(let_underscore_drop)]
+#![allow(unexpected_cfgs)]
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
#![allow(named_arguments_used_positionally)]
@@ -55,65 +59,72 @@
#![allow(unknown_lints)]
#![allow(unused_labels)]
#![allow(ambiguous_wide_pointer_comparisons)]
-#![warn(clippy::almost_complete_letter_range)]
-#![warn(clippy::blacklisted_name)]
-#![warn(clippy::block_in_if_condition_expr)]
-#![warn(clippy::block_in_if_condition_stmt)]
-#![warn(clippy::blocks_in_if_conditions)]
-#![warn(clippy::box_vec)]
-#![warn(clippy::const_static_lifetime)]
-#![warn(clippy::cyclomatic_complexity)]
-#![warn(clippy::derive_hash_xor_eq)]
-#![warn(clippy::disallowed_method)]
-#![warn(clippy::disallowed_type)]
-#![warn(clippy::eval_order_dependence)]
-#![warn(clippy::identity_conversion)]
-#![warn(clippy::if_let_some_result)]
-#![warn(clippy::incorrect_clone_impl_on_copy_type)]
-#![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
-#![warn(clippy::integer_arithmetic)]
-#![warn(clippy::logic_bug)]
-#![warn(clippy::new_without_default_derive)]
-#![warn(clippy::option_and_then_some)]
-#![warn(clippy::option_expect_used)]
-#![warn(clippy::option_map_unwrap_or)]
-#![warn(clippy::option_map_unwrap_or_else)]
-#![warn(clippy::option_unwrap_used)]
-#![warn(clippy::overflow_check_conditional)]
-#![warn(clippy::ref_in_deref)]
-#![warn(clippy::result_expect_used)]
-#![warn(clippy::result_map_unwrap_or_else)]
-#![warn(clippy::result_unwrap_used)]
-#![warn(clippy::single_char_push_str)]
-#![warn(clippy::stutter)]
-#![warn(clippy::thread_local_initializer_can_be_made_const)]
-#![warn(clippy::to_string_in_display)]
-#![warn(clippy::unwrap_or_else_default)]
-#![warn(clippy::zero_width_space)]
-#![warn(clippy::cast_ref_to_mut)]
-#![warn(clippy::clone_double_ref)]
-#![warn(clippy::cmp_nan)]
-#![warn(clippy::drop_bounds)]
-#![warn(clippy::drop_copy)]
-#![warn(clippy::drop_ref)]
-#![warn(clippy::fn_null_check)]
-#![warn(clippy::for_loop_over_option)]
-#![warn(clippy::for_loop_over_result)]
-#![warn(clippy::for_loops_over_fallibles)]
-#![warn(clippy::forget_copy)]
-#![warn(clippy::forget_ref)]
-#![warn(clippy::into_iter_on_array)]
-#![warn(clippy::invalid_atomic_ordering)]
-#![warn(clippy::invalid_ref)]
-#![warn(clippy::invalid_utf8_in_unchecked)]
-#![warn(clippy::let_underscore_drop)]
-#![warn(clippy::mem_discriminant_non_enum)]
-#![warn(clippy::panic_params)]
-#![warn(clippy::positional_named_format_parameters)]
-#![warn(clippy::temporary_cstring_as_ptr)]
-#![warn(clippy::undropped_manually_drops)]
-#![warn(clippy::unknown_clippy_lints)]
-#![warn(clippy::unused_label)]
-#![warn(clippy::vtable_address_comparisons)]
+#![allow(clippy::reversed_empty_ranges)]
+#![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range`
+#![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name`
+#![warn(clippy::block_in_if_condition_expr)] //~ ERROR: lint `clippy::block_in_if_condition_expr`
+#![warn(clippy::block_in_if_condition_stmt)] //~ ERROR: lint `clippy::block_in_if_condition_stmt`
+#![warn(clippy::blocks_in_if_conditions)] //~ ERROR: lint `clippy::blocks_in_if_conditions`
+#![warn(clippy::box_vec)] //~ ERROR: lint `clippy::box_vec`
+#![warn(clippy::const_static_lifetime)] //~ ERROR: lint `clippy::const_static_lifetime`
+#![warn(clippy::cyclomatic_complexity)] //~ ERROR: lint `clippy::cyclomatic_complexity`
+#![warn(clippy::derive_hash_xor_eq)] //~ ERROR: lint `clippy::derive_hash_xor_eq`
+#![warn(clippy::disallowed_method)] //~ ERROR: lint `clippy::disallowed_method`
+#![warn(clippy::disallowed_type)] //~ ERROR: lint `clippy::disallowed_type`
+#![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence`
+#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map`
+#![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map`
+#![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion`
+#![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching`
+#![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result`
+#![warn(clippy::incorrect_clone_impl_on_copy_type)] //~ ERROR: lint `clippy::incorrect_clone_impl_on_copy_type`
+#![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] //~ ERROR: lint `clippy::incorrect_partial_ord_impl_on_ord_type`
+#![warn(clippy::integer_arithmetic)] //~ ERROR: lint `clippy::integer_arithmetic`
+#![warn(clippy::logic_bug)] //~ ERROR: lint `clippy::logic_bug`
+#![warn(clippy::new_without_default_derive)] //~ ERROR: lint `clippy::new_without_default_derive`
+#![warn(clippy::option_and_then_some)] //~ ERROR: lint `clippy::option_and_then_some`
+#![warn(clippy::option_expect_used)] //~ ERROR: lint `clippy::option_expect_used`
+#![warn(clippy::option_map_unwrap_or)] //~ ERROR: lint `clippy::option_map_unwrap_or`
+#![warn(clippy::option_map_unwrap_or_else)] //~ ERROR: lint `clippy::option_map_unwrap_or_else`
+#![warn(clippy::option_unwrap_used)] //~ ERROR: lint `clippy::option_unwrap_used`
+#![warn(clippy::overflow_check_conditional)] //~ ERROR: lint `clippy::overflow_check_conditional`
+#![warn(clippy::ref_in_deref)] //~ ERROR: lint `clippy::ref_in_deref`
+#![warn(clippy::result_expect_used)] //~ ERROR: lint `clippy::result_expect_used`
+#![warn(clippy::result_map_unwrap_or_else)] //~ ERROR: lint `clippy::result_map_unwrap_or_else`
+#![warn(clippy::result_unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used`
+#![warn(clippy::single_char_push_str)] //~ ERROR: lint `clippy::single_char_push_str`
+#![warn(clippy::stutter)] //~ ERROR: lint `clippy::stutter`
+#![warn(clippy::thread_local_initializer_can_be_made_const)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const`
+#![warn(clippy::to_string_in_display)] //~ ERROR: lint `clippy::to_string_in_display`
+#![warn(clippy::unwrap_or_else_default)] //~ ERROR: lint `clippy::unwrap_or_else_default`
+#![warn(clippy::zero_width_space)] //~ ERROR: lint `clippy::zero_width_space`
+#![warn(clippy::cast_ref_to_mut)] //~ ERROR: lint `clippy::cast_ref_to_mut`
+#![warn(clippy::clone_double_ref)] //~ ERROR: lint `clippy::clone_double_ref`
+#![warn(clippy::cmp_nan)] //~ ERROR: lint `clippy::cmp_nan`
+#![warn(clippy::drop_bounds)] //~ ERROR: lint `clippy::drop_bounds`
+#![warn(clippy::drop_copy)] //~ ERROR: lint `clippy::drop_copy`
+#![warn(clippy::drop_ref)] //~ ERROR: lint `clippy::drop_ref`
+#![warn(clippy::fn_null_check)] //~ ERROR: lint `clippy::fn_null_check`
+#![warn(clippy::for_loop_over_option)] //~ ERROR: lint `clippy::for_loop_over_option`
+#![warn(clippy::for_loop_over_result)] //~ ERROR: lint `clippy::for_loop_over_result`
+#![warn(clippy::for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loops_over_fallibles`
+#![warn(clippy::forget_copy)] //~ ERROR: lint `clippy::forget_copy`
+#![warn(clippy::forget_ref)] //~ ERROR: lint `clippy::forget_ref`
+#![warn(clippy::into_iter_on_array)] //~ ERROR: lint `clippy::into_iter_on_array`
+#![warn(clippy::invalid_atomic_ordering)] //~ ERROR: lint `clippy::invalid_atomic_ordering`
+#![warn(clippy::invalid_ref)] //~ ERROR: lint `clippy::invalid_ref`
+#![warn(clippy::invalid_utf8_in_unchecked)] //~ ERROR: lint `clippy::invalid_utf8_in_unchecked`
+#![warn(clippy::let_underscore_drop)] //~ ERROR: lint `clippy::let_underscore_drop`
+#![warn(clippy::maybe_misused_cfg)] //~ ERROR: lint `clippy::maybe_misused_cfg`
+#![warn(clippy::mem_discriminant_non_enum)] //~ ERROR: lint `clippy::mem_discriminant_non_enum`
+#![warn(clippy::mismatched_target_os)] //~ ERROR: lint `clippy::mismatched_target_os`
+#![warn(clippy::panic_params)] //~ ERROR: lint `clippy::panic_params`
+#![warn(clippy::positional_named_format_parameters)] //~ ERROR: lint `clippy::positional_named_format_parameters`
+#![warn(clippy::temporary_cstring_as_ptr)] //~ ERROR: lint `clippy::temporary_cstring_as_ptr`
+#![warn(clippy::undropped_manually_drops)] //~ ERROR: lint `clippy::undropped_manually_drops`
+#![warn(clippy::unknown_clippy_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints`
+#![warn(clippy::unused_label)] //~ ERROR: lint `clippy::unused_label`
+#![warn(clippy::vtable_address_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons`
+#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop`
fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index d663732..46d9f0f 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
- --> tests/ui/rename.rs:58:9
+ --> tests/ui/rename.rs:63:9
|
LL | #![warn(clippy::almost_complete_letter_range)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,358 +8,394 @@
= help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
- --> tests/ui/rename.rs:59:9
+ --> tests/ui/rename.rs:64:9
|
LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_conditions`
- --> tests/ui/rename.rs:60:9
+ --> tests/ui/rename.rs:65:9
|
LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_conditions`
- --> tests/ui/rename.rs:61:9
+ --> tests/ui/rename.rs:66:9
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::blocks_in_if_conditions` has been renamed to `clippy::blocks_in_conditions`
- --> tests/ui/rename.rs:62:9
+ --> tests/ui/rename.rs:67:9
|
LL | #![warn(clippy::blocks_in_if_conditions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
- --> tests/ui/rename.rs:63:9
+ --> tests/ui/rename.rs:68:9
|
LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
- --> tests/ui/rename.rs:64:9
+ --> tests/ui/rename.rs:69:9
|
LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
- --> tests/ui/rename.rs:65:9
+ --> tests/ui/rename.rs:70:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
- --> tests/ui/rename.rs:66:9
+ --> tests/ui/rename.rs:71:9
|
LL | #![warn(clippy::derive_hash_xor_eq)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
- --> tests/ui/rename.rs:67:9
+ --> tests/ui/rename.rs:72:9
|
LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
- --> tests/ui/rename.rs:68:9
+ --> tests/ui/rename.rs:73:9
|
LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
- --> tests/ui/rename.rs:69:9
+ --> tests/ui/rename.rs:74:9
|
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
+error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map`
+ --> tests/ui/rename.rs:75:9
+ |
+LL | #![warn(clippy::find_map)]
+ | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map`
+
+error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map`
+ --> tests/ui/rename.rs:76:9
+ |
+LL | #![warn(clippy::filter_map)]
+ | ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map`
+
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
- --> tests/ui/rename.rs:70:9
+ --> tests/ui/rename.rs:77:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
+error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching`
+ --> tests/ui/rename.rs:78:9
+ |
+LL | #![warn(clippy::if_let_redundant_pattern_matching)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching`
+
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
- --> tests/ui/rename.rs:71:9
+ --> tests/ui/rename.rs:79:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
- --> tests/ui/rename.rs:72:9
+ --> tests/ui/rename.rs:80:9
|
LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
- --> tests/ui/rename.rs:73:9
+ --> tests/ui/rename.rs:81:9
|
LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
- --> tests/ui/rename.rs:74:9
+ --> tests/ui/rename.rs:82:9
|
LL | #![warn(clippy::integer_arithmetic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
- --> tests/ui/rename.rs:75:9
+ --> tests/ui/rename.rs:83:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> tests/ui/rename.rs:76:9
+ --> tests/ui/rename.rs:84:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
- --> tests/ui/rename.rs:77:9
+ --> tests/ui/rename.rs:85:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
- --> tests/ui/rename.rs:78:9
+ --> tests/ui/rename.rs:86:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
- --> tests/ui/rename.rs:79:9
+ --> tests/ui/rename.rs:87:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> tests/ui/rename.rs:80:9
+ --> tests/ui/rename.rs:88:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> tests/ui/rename.rs:81:9
+ --> tests/ui/rename.rs:89:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks`
- --> tests/ui/rename.rs:82:9
+ --> tests/ui/rename.rs:90:9
|
LL | #![warn(clippy::overflow_check_conditional)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
- --> tests/ui/rename.rs:83:9
+ --> tests/ui/rename.rs:91:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
- --> tests/ui/rename.rs:84:9
+ --> tests/ui/rename.rs:92:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> tests/ui/rename.rs:85:9
+ --> tests/ui/rename.rs:93:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> tests/ui/rename.rs:86:9
+ --> tests/ui/rename.rs:94:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
- --> tests/ui/rename.rs:87:9
+ --> tests/ui/rename.rs:95:9
|
LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
- --> tests/ui/rename.rs:88:9
+ --> tests/ui/rename.rs:96:9
|
LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::thread_local_initializer_can_be_made_const` has been renamed to `clippy::missing_const_for_thread_local`
- --> tests/ui/rename.rs:89:9
+ --> tests/ui/rename.rs:97:9
|
LL | #![warn(clippy::thread_local_initializer_can_be_made_const)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::missing_const_for_thread_local`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
- --> tests/ui/rename.rs:90:9
+ --> tests/ui/rename.rs:98:9
|
LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
- --> tests/ui/rename.rs:91:9
+ --> tests/ui/rename.rs:99:9
|
LL | #![warn(clippy::unwrap_or_else_default)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
- --> tests/ui/rename.rs:92:9
+ --> tests/ui/rename.rs:100:9
|
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
- --> tests/ui/rename.rs:93:9
+ --> tests/ui/rename.rs:101:9
|
LL | #![warn(clippy::cast_ref_to_mut)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
- --> tests/ui/rename.rs:94:9
+ --> tests/ui/rename.rs:102:9
|
LL | #![warn(clippy::clone_double_ref)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
- --> tests/ui/rename.rs:95:9
+ --> tests/ui/rename.rs:103:9
|
LL | #![warn(clippy::cmp_nan)]
| ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
- --> tests/ui/rename.rs:96:9
+ --> tests/ui/rename.rs:104:9
|
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
- --> tests/ui/rename.rs:97:9
+ --> tests/ui/rename.rs:105:9
|
LL | #![warn(clippy::drop_copy)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
error: lint `clippy::drop_ref` has been renamed to `dropping_references`
- --> tests/ui/rename.rs:98:9
+ --> tests/ui/rename.rs:106:9
|
LL | #![warn(clippy::drop_ref)]
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
- --> tests/ui/rename.rs:99:9
+ --> tests/ui/rename.rs:107:9
|
LL | #![warn(clippy::fn_null_check)]
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
- --> tests/ui/rename.rs:100:9
+ --> tests/ui/rename.rs:108:9
|
LL | #![warn(clippy::for_loop_over_option)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
- --> tests/ui/rename.rs:101:9
+ --> tests/ui/rename.rs:109:9
|
LL | #![warn(clippy::for_loop_over_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
- --> tests/ui/rename.rs:102:9
+ --> tests/ui/rename.rs:110:9
|
LL | #![warn(clippy::for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
- --> tests/ui/rename.rs:103:9
+ --> tests/ui/rename.rs:111:9
|
LL | #![warn(clippy::forget_copy)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
- --> tests/ui/rename.rs:104:9
+ --> tests/ui/rename.rs:112:9
|
LL | #![warn(clippy::forget_ref)]
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> tests/ui/rename.rs:105:9
+ --> tests/ui/rename.rs:113:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> tests/ui/rename.rs:106:9
+ --> tests/ui/rename.rs:114:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> tests/ui/rename.rs:107:9
+ --> tests/ui/rename.rs:115:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
- --> tests/ui/rename.rs:108:9
+ --> tests/ui/rename.rs:116:9
|
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
- --> tests/ui/rename.rs:109:9
+ --> tests/ui/rename.rs:117:9
|
LL | #![warn(clippy::let_underscore_drop)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
+error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs`
+ --> tests/ui/rename.rs:118:9
+ |
+LL | #![warn(clippy::maybe_misused_cfg)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
+
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> tests/ui/rename.rs:110:9
+ --> tests/ui/rename.rs:119:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
+error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs`
+ --> tests/ui/rename.rs:120:9
+ |
+LL | #![warn(clippy::mismatched_target_os)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs`
+
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> tests/ui/rename.rs:111:9
+ --> tests/ui/rename.rs:121:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
- --> tests/ui/rename.rs:112:9
+ --> tests/ui/rename.rs:122:9
|
LL | #![warn(clippy::positional_named_format_parameters)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
- --> tests/ui/rename.rs:113:9
+ --> tests/ui/rename.rs:123:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
- --> tests/ui/rename.rs:114:9
+ --> tests/ui/rename.rs:124:9
|
LL | #![warn(clippy::undropped_manually_drops)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> tests/ui/rename.rs:115:9
+ --> tests/ui/rename.rs:125:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> tests/ui/rename.rs:116:9
+ --> tests/ui/rename.rs:126:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
- --> tests/ui/rename.rs:117:9
+ --> tests/ui/rename.rs:127:9
|
LL | #![warn(clippy::vtable_address_comparisons)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
-error: aborting due to 60 previous errors
+error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges`
+ --> tests/ui/rename.rs:128:9
+ |
+LL | #![warn(clippy::reverse_range_loop)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges`
+
+error: aborting due to 66 previous errors
diff --git a/src/tools/clippy/tests/ui/set_contains_or_insert.rs b/src/tools/clippy/tests/ui/set_contains_or_insert.rs
index 8465007..d3a3e1c 100644
--- a/src/tools/clippy/tests/ui/set_contains_or_insert.rs
+++ b/src/tools/clippy/tests/ui/set_contains_or_insert.rs
@@ -3,15 +3,9 @@
#![allow(clippy::needless_borrow)]
#![warn(clippy::set_contains_or_insert)]
-use std::collections::HashSet;
+use std::collections::{BTreeSet, HashSet};
-fn main() {
- should_warn_cases();
-
- should_not_warn_cases();
-}
-
-fn should_warn_cases() {
+fn should_warn_hashset() {
let mut set = HashSet::new();
let value = 5;
@@ -49,7 +43,7 @@ fn should_warn_cases() {
}
}
-fn should_not_warn_cases() {
+fn should_not_warn_hashset() {
let mut set = HashSet::new();
let value = 5;
let another_value = 6;
@@ -78,6 +72,81 @@ fn should_not_warn_cases() {
}
}
+fn should_warn_btreeset() {
+ let mut set = BTreeSet::new();
+ let value = 5;
+
+ if !set.contains(&value) {
+ set.insert(value);
+ println!("Just a comment");
+ }
+
+ if set.contains(&value) {
+ set.insert(value);
+ println!("Just a comment");
+ }
+
+ if !set.contains(&value) {
+ set.insert(value);
+ }
+
+ if !!set.contains(&value) {
+ set.insert(value);
+ println!("Just a comment");
+ }
+
+ if (&set).contains(&value) {
+ set.insert(value);
+ }
+
+ let borrow_value = &6;
+ if !set.contains(borrow_value) {
+ set.insert(*borrow_value);
+ }
+
+ let borrow_set = &mut set;
+ if !borrow_set.contains(&value) {
+ borrow_set.insert(value);
+ }
+}
+
+fn should_not_warn_btreeset() {
+ let mut set = BTreeSet::new();
+ let value = 5;
+ let another_value = 6;
+
+ if !set.contains(&value) {
+ set.insert(another_value);
+ }
+
+ if !set.contains(&value) {
+ println!("Just a comment");
+ }
+
+ if simply_true() {
+ set.insert(value);
+ }
+
+ if !set.contains(&value) {
+ set.replace(value); //it is not insert
+ println!("Just a comment");
+ }
+
+ if set.contains(&value) {
+ println!("value is already in set");
+ } else {
+ set.insert(value);
+ }
+}
+
fn simply_true() -> bool {
true
}
+
+// This is placed last in order to be able to add new tests without changing line numbers
+fn main() {
+ should_warn_hashset();
+ should_warn_btreeset();
+ should_not_warn_hashset();
+ should_not_warn_btreeset();
+}
diff --git a/src/tools/clippy/tests/ui/set_contains_or_insert.stderr b/src/tools/clippy/tests/ui/set_contains_or_insert.stderr
index 507e209..14ad630 100644
--- a/src/tools/clippy/tests/ui/set_contains_or_insert.stderr
+++ b/src/tools/clippy/tests/ui/set_contains_or_insert.stderr
@@ -1,5 +1,5 @@
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:18:13
+ --> tests/ui/set_contains_or_insert.rs:12:13
|
LL | if !set.contains(&value) {
| ^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@
= help: to override `-D warnings` add `#[allow(clippy::set_contains_or_insert)]`
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:23:12
+ --> tests/ui/set_contains_or_insert.rs:17:12
|
LL | if set.contains(&value) {
| ^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@
| ^^^^^^^^^^^^^
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:28:13
+ --> tests/ui/set_contains_or_insert.rs:22:13
|
LL | if !set.contains(&value) {
| ^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@
| ^^^^^^^^^^^^^
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:32:14
+ --> tests/ui/set_contains_or_insert.rs:26:14
|
LL | if !!set.contains(&value) {
| ^^^^^^^^^^^^^^^^
@@ -34,7 +34,7 @@
| ^^^^^^^^^^^^^
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:37:15
+ --> tests/ui/set_contains_or_insert.rs:31:15
|
LL | if (&set).contains(&value) {
| ^^^^^^^^^^^^^^^^
@@ -42,7 +42,7 @@
| ^^^^^^^^^^^^^
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:42:13
+ --> tests/ui/set_contains_or_insert.rs:36:13
|
LL | if !set.contains(borrow_value) {
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -50,12 +50,68 @@
| ^^^^^^^^^^^^^^^^^^^^^
error: usage of `HashSet::insert` after `HashSet::contains`
- --> tests/ui/set_contains_or_insert.rs:47:20
+ --> tests/ui/set_contains_or_insert.rs:41:20
|
LL | if !borrow_set.contains(&value) {
| ^^^^^^^^^^^^^^^^
LL | borrow_set.insert(value);
| ^^^^^^^^^^^^^
-error: aborting due to 7 previous errors
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:79:13
+ |
+LL | if !set.contains(&value) {
+ | ^^^^^^^^^^^^^^^^
+LL | set.insert(value);
+ | ^^^^^^^^^^^^^
+
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:84:12
+ |
+LL | if set.contains(&value) {
+ | ^^^^^^^^^^^^^^^^
+LL | set.insert(value);
+ | ^^^^^^^^^^^^^
+
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:89:13
+ |
+LL | if !set.contains(&value) {
+ | ^^^^^^^^^^^^^^^^
+LL | set.insert(value);
+ | ^^^^^^^^^^^^^
+
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:93:14
+ |
+LL | if !!set.contains(&value) {
+ | ^^^^^^^^^^^^^^^^
+LL | set.insert(value);
+ | ^^^^^^^^^^^^^
+
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:98:15
+ |
+LL | if (&set).contains(&value) {
+ | ^^^^^^^^^^^^^^^^
+LL | set.insert(value);
+ | ^^^^^^^^^^^^^
+
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:103:13
+ |
+LL | if !set.contains(borrow_value) {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | set.insert(*borrow_value);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: usage of `BTreeSet::insert` after `BTreeSet::contains`
+ --> tests/ui/set_contains_or_insert.rs:108:20
+ |
+LL | if !borrow_set.contains(&value) {
+ | ^^^^^^^^^^^^^^^^
+LL | borrow_set.insert(value);
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed
index acd7041..5249c44 100644
--- a/src/tools/clippy/tests/ui/single_match.fixed
+++ b/src/tools/clippy/tests/ui/single_match.fixed
@@ -253,3 +253,46 @@
}
}
}
+
+fn issue11365() {
+ enum Foo {
+ A,
+ B,
+ C,
+ }
+ use Foo::{A, B, C};
+
+ match Some(A) {
+ Some(A | B | C) => println!(),
+ None => {},
+ }
+
+ match Some(A) {
+ Some(A | B) => println!(),
+ Some { 0: C } | None => {},
+ }
+
+ match [A, A] {
+ [A, _] => println!(),
+ [_, A | B | C] => {},
+ }
+
+ match Ok::<_, u32>(Some(A)) {
+ Ok(Some(A)) => println!(),
+ Err(_) | Ok(None | Some(B | C)) => {},
+ }
+
+ if let Ok(Some(A)) = Ok::<_, u32>(Some(A)) { println!() }
+
+ match &Some(A) {
+ Some(A | B | C) => println!(),
+ None => {},
+ }
+
+ match &Some(A) {
+ &Some(A | B | C) => println!(),
+ None => {},
+ }
+
+ if let Some(A | B) = &Some(A) { println!() }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index bde7819..882098a 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -311,3 +311,52 @@ fn block_comment(x: Result<i32, SomeError>) {
}
}
}
+
+fn issue11365() {
+ enum Foo {
+ A,
+ B,
+ C,
+ }
+ use Foo::{A, B, C};
+
+ match Some(A) {
+ Some(A | B | C) => println!(),
+ None => {},
+ }
+
+ match Some(A) {
+ Some(A | B) => println!(),
+ Some { 0: C } | None => {},
+ }
+
+ match [A, A] {
+ [A, _] => println!(),
+ [_, A | B | C] => {},
+ }
+
+ match Ok::<_, u32>(Some(A)) {
+ Ok(Some(A)) => println!(),
+ Err(_) | Ok(None | Some(B | C)) => {},
+ }
+
+ match Ok::<_, u32>(Some(A)) {
+ Ok(Some(A)) => println!(),
+ Err(_) | Ok(None | Some(_)) => {},
+ }
+
+ match &Some(A) {
+ Some(A | B | C) => println!(),
+ None => {},
+ }
+
+ match &Some(A) {
+ &Some(A | B | C) => println!(),
+ None => {},
+ }
+
+ match &Some(A) {
+ Some(A | B) => println!(),
+ None | Some(_) => {},
+ }
+}
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index a249c12..ceb2a19 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -198,5 +198,23 @@
LL + }
|
-error: aborting due to 18 previous errors
+error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
+ --> tests/ui/single_match.rs:343:5
+ |
+LL | / match Ok::<_, u32>(Some(A)) {
+LL | | Ok(Some(A)) => println!(),
+LL | | Err(_) | Ok(None | Some(_)) => {},
+LL | | }
+ | |_____^ help: try: `if let Ok(Some(A)) = Ok::<_, u32>(Some(A)) { println!() }`
+
+error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
+ --> tests/ui/single_match.rs:358:5
+ |
+LL | / match &Some(A) {
+LL | | Some(A | B) => println!(),
+LL | | None | Some(_) => {},
+LL | | }
+ | |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }`
+
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed
index e840adf..163be16 100644
--- a/src/tools/clippy/tests/ui/single_match_else.fixed
+++ b/src/tools/clippy/tests/ui/single_match_else.fixed
@@ -89,7 +89,7 @@
// lint here
use std::convert::Infallible;
- if let Ok(a) = Result::<i32, Infallible>::Ok(1) { println!("${:?}", a) } else {
+ if let Ok(a) = Result::<i32, &Infallible>::Ok(1) { println!("${:?}", a) } else {
println!("else block");
return;
}
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index 430c4da..3f1fd2b 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -98,7 +98,7 @@ fn main() {
// lint here
use std::convert::Infallible;
- match Result::<i32, Infallible>::Ok(1) {
+ match Result::<i32, &Infallible>::Ok(1) {
Ok(a) => println!("${:?}", a),
Err(_) => {
println!("else block");
diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr
index f8f8837..61c3482 100644
--- a/src/tools/clippy/tests/ui/single_match_else.stderr
+++ b/src/tools/clippy/tests/ui/single_match_else.stderr
@@ -64,7 +64,7 @@
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> tests/ui/single_match_else.rs:101:5
|
-LL | / match Result::<i32, Infallible>::Ok(1) {
+LL | / match Result::<i32, &Infallible>::Ok(1) {
LL | | Ok(a) => println!("${:?}", a),
LL | | Err(_) => {
LL | | println!("else block");
@@ -75,7 +75,7 @@
|
help: try
|
-LL ~ if let Ok(a) = Result::<i32, Infallible>::Ok(1) { println!("${:?}", a) } else {
+LL ~ if let Ok(a) = Result::<i32, &Infallible>::Ok(1) { println!("${:?}", a) } else {
LL + println!("else block");
LL + return;
LL + }
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
index 6ede7bf..227b98c 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed
@@ -75,8 +75,17 @@
struct B {}
}
-fn main() {
- std_instead_of_core();
- std_instead_of_alloc();
- alloc_instead_of_core();
+// Some intrinsics are usable on stable but live in an unstable module, but should still suggest
+// replacing std -> core
+fn intrinsic(a: *mut u8, b: *mut u8) {
+ unsafe {
+ core::intrinsics::copy(a, b, 1);
+ //~^ std_instead_of_core
+ }
}
+
+#[clippy::msrv = "1.76"]
+fn msrv_1_76(_: std::net::IpAddr) {}
+
+#[clippy::msrv = "1.77"]
+fn msrv_1_77(_: core::net::IpAddr) {}
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs
index e22b4f61..01bb78d 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.rs
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs
@@ -75,8 +75,17 @@ mod std_in_proc_macro_derive {
struct B {}
}
-fn main() {
- std_instead_of_core();
- std_instead_of_alloc();
- alloc_instead_of_core();
+// Some intrinsics are usable on stable but live in an unstable module, but should still suggest
+// replacing std -> core
+fn intrinsic(a: *mut u8, b: *mut u8) {
+ unsafe {
+ std::intrinsics::copy(a, b, 1);
+ //~^ std_instead_of_core
+ }
}
+
+#[clippy::msrv = "1.76"]
+fn msrv_1_76(_: std::net::IpAddr) {}
+
+#[clippy::msrv = "1.77"]
+fn msrv_1_77(_: std::net::IpAddr) {}
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
index 22cb9db..45d60d23 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
@@ -85,5 +85,17 @@
= note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]`
-error: aborting due to 13 previous errors
+error: used import from `std` instead of `core`
+ --> tests/ui/std_instead_of_core.rs:82:9
+ |
+LL | std::intrinsics::copy(a, b, 1);
+ | ^^^ help: consider importing the item from `core`: `core`
+
+error: used import from `std` instead of `core`
+ --> tests/ui/std_instead_of_core.rs:91:17
+ |
+LL | fn msrv_1_77(_: std::net::IpAddr) {}
+ | ^^^ help: consider importing the item from `core`: `core`
+
+error: aborting due to 15 previous errors
diff --git a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
index 4faf023..43b0367 100644
--- a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr
@@ -2,51 +2,84 @@
--> tests/ui/suspicious_xor_used_as_pow.rs:19:13
|
LL | let _ = 2 ^ 5;
- | ^^^^^ help: did you mean to write: `2.pow(5)`
+ | ^^^^^
|
= note: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::suspicious_xor_used_as_pow)]`
+help: did you mean to write
+ |
+LL | let _ = 2.pow(5);
+ | ~~~~~~~~
error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:22:13
|
LL | let _ = 2i32 ^ 9i32;
- | ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(9i32)`
+ | ^^^^^^^^^^^
+ |
+help: did you mean to write
+ |
+LL | let _ = 2i32.pow(9i32);
+ | ~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:24:13
|
LL | let _ = 2i32 ^ 2i32;
- | ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(2i32)`
+ | ^^^^^^^^^^^
+ |
+help: did you mean to write
+ |
+LL | let _ = 2i32.pow(2i32);
+ | ~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:26:13
|
LL | let _ = 50i32 ^ 3i32;
- | ^^^^^^^^^^^^ help: did you mean to write: `50i32.pow(3i32)`
+ | ^^^^^^^^^^^^
+ |
+help: did you mean to write
+ |
+LL | let _ = 50i32.pow(3i32);
+ | ~~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:28:13
|
LL | let _ = 5i32 ^ 8i32;
- | ^^^^^^^^^^^ help: did you mean to write: `5i32.pow(8i32)`
+ | ^^^^^^^^^^^
+ |
+help: did you mean to write
+ |
+LL | let _ = 5i32.pow(8i32);
+ | ~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:30:13
|
LL | let _ = 2i32 ^ 32i32;
- | ^^^^^^^^^^^^ help: did you mean to write: `2i32.pow(32i32)`
+ | ^^^^^^^^^^^^
+ |
+help: did you mean to write
+ |
+LL | let _ = 2i32.pow(32i32);
+ | ~~~~~~~~~~~~~~~
error: `^` is not the exponentiation operator
--> tests/ui/suspicious_xor_used_as_pow.rs:13:9
|
LL | 1 ^ 2 // should warn even if inside macro
- | ^^^^^ help: did you mean to write: `1.pow(2)`
+ | ^^^^^
...
LL | macro_test_inside!();
| -------------------- in this macro invocation
|
= note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: did you mean to write
+ |
+LL | 1.pow(2) // should warn even if inside macro
+ | ~~~~~~~~
error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/try_err.fixed b/src/tools/clippy/tests/ui/try_err.fixed
index aae4f8a..f149bfb 100644
--- a/src/tools/clippy/tests/ui/try_err.fixed
+++ b/src/tools/clippy/tests/ui/try_err.fixed
@@ -1,5 +1,5 @@
//@aux-build:proc_macros.rs
-
+#![feature(try_blocks)]
#![deny(clippy::try_err)]
#![allow(
clippy::unnecessary_wraps,
@@ -152,3 +152,11 @@
}
Ok(0)
}
+
+// Test that the lint is suppressed in try block.
+pub fn try_block() -> Result<(), i32> {
+ let _: Result<_, i32> = try {
+ Err(1)?;
+ };
+ Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/try_err.rs b/src/tools/clippy/tests/ui/try_err.rs
index 927eccf..841ec6b 100644
--- a/src/tools/clippy/tests/ui/try_err.rs
+++ b/src/tools/clippy/tests/ui/try_err.rs
@@ -1,5 +1,5 @@
//@aux-build:proc_macros.rs
-
+#![feature(try_blocks)]
#![deny(clippy::try_err)]
#![allow(
clippy::unnecessary_wraps,
@@ -152,3 +152,11 @@ pub fn try_return(x: bool) -> Result<i32, i32> {
}
Ok(0)
}
+
+// Test that the lint is suppressed in try block.
+pub fn try_block() -> Result<(), i32> {
+ let _: Result<_, i32> = try {
+ Err(1)?;
+ };
+ Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/uninit_vec.rs b/src/tools/clippy/tests/ui/uninit_vec.rs
index c069b9a..0cc77a8 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.rs
+++ b/src/tools/clippy/tests/ui/uninit_vec.rs
@@ -1,5 +1,6 @@
#![warn(clippy::uninit_vec)]
+use std::cell::UnsafeCell;
use std::mem::MaybeUninit;
#[derive(Default)]
@@ -12,6 +13,12 @@ union MyOwnMaybeUninit {
uninit: (),
}
+// https://github.com/rust-lang/rust/issues/119620
+unsafe fn requires_paramenv<S>() {
+ let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
+ vec.set_len(1);
+}
+
fn main() {
// with_capacity() -> set_len() should be detected
let mut vec: Vec<u8> = Vec::with_capacity(1000);
diff --git a/src/tools/clippy/tests/ui/uninit_vec.stderr b/src/tools/clippy/tests/ui/uninit_vec.stderr
index 8e93466..e8b77d6 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.stderr
+++ b/src/tools/clippy/tests/ui/uninit_vec.stderr
@@ -1,5 +1,17 @@
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:17:5
+ --> tests/ui/uninit_vec.rs:18:5
+ |
+LL | let mut vec = Vec::<UnsafeCell<*mut S>>::with_capacity(1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | vec.set_len(1);
+ | ^^^^^^^^^^^^^^
+ |
+ = help: initialize the buffer or wrap the content in `MaybeUninit`
+ = note: `-D clippy::uninit-vec` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::uninit_vec)]`
+
+error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
+ --> tests/ui/uninit_vec.rs:24:5
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,11 +20,9 @@
| ^^^^^^^^^^^^^^^^
|
= help: initialize the buffer or wrap the content in `MaybeUninit`
- = note: `-D clippy::uninit-vec` implied by `-D warnings`
- = help: to override `-D warnings` add `#[allow(clippy::uninit_vec)]`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:24:5
+ --> tests/ui/uninit_vec.rs:31:5
|
LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^
@@ -23,7 +33,7 @@
= help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` on empty `Vec` creates out-of-bound values
- --> tests/ui/uninit_vec.rs:31:5
+ --> tests/ui/uninit_vec.rs:38:5
|
LL | let mut vec: Vec<u8> = Vec::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,7 +42,7 @@
| ^^^^^^^^^^^^^^^^
error: calling `set_len()` on empty `Vec` creates out-of-bound values
- --> tests/ui/uninit_vec.rs:38:5
+ --> tests/ui/uninit_vec.rs:45:5
|
LL | let mut vec: Vec<u8> = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -41,7 +51,7 @@
| ^^^^^^^^^^^^^^^^
error: calling `set_len()` on empty `Vec` creates out-of-bound values
- --> tests/ui/uninit_vec.rs:44:5
+ --> tests/ui/uninit_vec.rs:51:5
|
LL | let mut vec: Vec<u8> = Vec::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +60,7 @@
| ^^^^^^^^^^^^^^^^
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:61:5
+ --> tests/ui/uninit_vec.rs:68:5
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +71,7 @@
= help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:71:5
+ --> tests/ui/uninit_vec.rs:78:5
|
LL | my_vec.vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +82,7 @@
= help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:77:5
+ --> tests/ui/uninit_vec.rs:84:5
|
LL | my_vec.vec = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -83,7 +93,7 @@
= help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:52:9
+ --> tests/ui/uninit_vec.rs:59:9
|
LL | let mut vec: Vec<u8> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -94,7 +104,7 @@
= help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:56:9
+ --> tests/ui/uninit_vec.rs:63:9
|
LL | vec.reserve(1000);
| ^^^^^^^^^^^^^^^^^^
@@ -105,7 +115,7 @@
= help: initialize the buffer or wrap the content in `MaybeUninit`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
- --> tests/ui/uninit_vec.rs:132:9
+ --> tests/ui/uninit_vec.rs:139:9
|
LL | let mut vec: Vec<T> = Vec::with_capacity(1000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -115,5 +125,5 @@
|
= help: initialize the buffer or wrap the content in `MaybeUninit`
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
index 1570809..37ee919 100644
--- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr
@@ -63,7 +63,7 @@
help: remove the `None` and `expect()`
|
LL | let _val = panic!("this always happens");
- | ~~~~~~~ ~
+ | ~~~~~~~
error: used `unwrap_or_default()` on `None` value
--> tests/ui/unnecessary_literal_unwrap.rs:22:24
@@ -134,7 +134,7 @@
help: remove the `None` and `expect()`
|
LL | panic!("this always happens");
- | ~~~~~~~ ~
+ | ~~~~~~~
error: used `unwrap_or_default()` on `None` value
--> tests/ui/unnecessary_literal_unwrap.rs:30:5
diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
index a55a23d..59986d8 100644
--- a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr
@@ -118,8 +118,8 @@
|
help: remove the return type...
|
-LL | fn issue_6640_1(a: bool, b: bool) -> Option<()> {
- | ~~~~~~~~~~
+LL | fn issue_6640_1(a: bool, b: bool) -> () {
+ | ~~
help: ...and then remove returned values
|
LL ~ return ;
@@ -145,8 +145,8 @@
|
help: remove the return type...
|
-LL | fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> {
- | ~~~~~~~~~~~~~~~
+LL | fn issue_6640_2(a: bool, b: bool) -> () {
+ | ~~
help: ...and then remove returned values
|
LL ~ return ;
diff --git a/src/tools/clippy/tests/ui/unneeded_field_pattern.rs b/src/tools/clippy/tests/ui/unneeded_field_pattern.rs
index 0dc21f4..1d42f81 100644
--- a/src/tools/clippy/tests/ui/unneeded_field_pattern.rs
+++ b/src/tools/clippy/tests/ui/unneeded_field_pattern.rs
@@ -1,6 +1,6 @@
//@aux-build:proc_macros.rs
#![warn(clippy::unneeded_field_pattern)]
-#![allow(dead_code, unused)]
+#![allow(dead_code, unused, clippy::single_match)]
#[macro_use]
extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/unused_result_ok.fixed b/src/tools/clippy/tests/ui/unused_result_ok.fixed
new file mode 100644
index 0000000..e78fde5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_result_ok.fixed
@@ -0,0 +1,40 @@
+//@aux-build:proc_macros.rs
+#![warn(clippy::unused_result_ok)]
+#![allow(dead_code)]
+
+#[macro_use]
+extern crate proc_macros;
+
+fn bad_style(x: &str) {
+ let _ = x.parse::<u32>();
+}
+
+fn good_style(x: &str) -> Option<u32> {
+ x.parse::<u32>().ok()
+}
+
+#[rustfmt::skip]
+fn strange_parse(x: &str) {
+ let _ = x . parse::<i32>();
+}
+
+macro_rules! v {
+ () => {
+ Ok::<(), ()>(())
+ };
+}
+
+macro_rules! w {
+ () => {
+ let _ = Ok::<(), ()>(());
+ };
+}
+
+fn main() {
+ let _ = v!();
+ w!();
+
+ external! {
+ Ok::<(),()>(()).ok();
+ };
+}
diff --git a/src/tools/clippy/tests/ui/unused_result_ok.rs b/src/tools/clippy/tests/ui/unused_result_ok.rs
new file mode 100644
index 0000000..117d64c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_result_ok.rs
@@ -0,0 +1,40 @@
+//@aux-build:proc_macros.rs
+#![warn(clippy::unused_result_ok)]
+#![allow(dead_code)]
+
+#[macro_use]
+extern crate proc_macros;
+
+fn bad_style(x: &str) {
+ x.parse::<u32>().ok();
+}
+
+fn good_style(x: &str) -> Option<u32> {
+ x.parse::<u32>().ok()
+}
+
+#[rustfmt::skip]
+fn strange_parse(x: &str) {
+ x . parse::<i32>() . ok ();
+}
+
+macro_rules! v {
+ () => {
+ Ok::<(), ()>(())
+ };
+}
+
+macro_rules! w {
+ () => {
+ Ok::<(), ()>(()).ok();
+ };
+}
+
+fn main() {
+ v!().ok();
+ w!();
+
+ external! {
+ Ok::<(),()>(()).ok();
+ };
+}
diff --git a/src/tools/clippy/tests/ui/unused_result_ok.stderr b/src/tools/clippy/tests/ui/unused_result_ok.stderr
new file mode 100644
index 0000000..241e0c7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_result_ok.stderr
@@ -0,0 +1,52 @@
+error: ignoring a result with `.ok()` is misleading
+ --> tests/ui/unused_result_ok.rs:9:5
+ |
+LL | x.parse::<u32>().ok();
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::unused-result-ok` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::unused_result_ok)]`
+help: consider using `let _ =` and removing the call to `.ok()` instead
+ |
+LL | let _ = x.parse::<u32>();
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: ignoring a result with `.ok()` is misleading
+ --> tests/ui/unused_result_ok.rs:18:5
+ |
+LL | x . parse::<i32>() . ok ();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider using `let _ =` and removing the call to `.ok()` instead
+ |
+LL | let _ = x . parse::<i32>();
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: ignoring a result with `.ok()` is misleading
+ --> tests/ui/unused_result_ok.rs:34:5
+ |
+LL | v!().ok();
+ | ^^^^^^^^^
+ |
+help: consider using `let _ =` and removing the call to `.ok()` instead
+ |
+LL | let _ = v!();
+ | ~~~~~~~~~~~~
+
+error: ignoring a result with `.ok()` is misleading
+ --> tests/ui/unused_result_ok.rs:29:9
+ |
+LL | Ok::<(), ()>(()).ok();
+ | ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | w!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `w` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider using `let _ =` and removing the call to `.ok()` instead
+ |
+LL | let _ = Ok::<(), ()>(());
+ | ~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.rs b/src/tools/clippy/tests/ui/unwrap_expect_used.rs
index 96368a0..a56bd0a 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.rs
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.rs
@@ -31,7 +31,7 @@ fn main() {
// Don't trigger on unwrap_err on an option
Some(3).unwrap_err();
- Some(3).expect_err("Hellow none!");
+ Some(3).expect_err("Hello none!");
// Issue #11245: The `Err` variant can never be constructed so do not lint this.
let x: Result<(), !> = Ok(());
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
index 59b5c85..b8087c6 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
@@ -456,6 +456,15 @@
});
}
+fn issue13123() {
+ let mut it = 0..20;
+ 'label: for n in it {
+ if n % 25 == 0 {
+ break 'label;
+ }
+ }
+}
+
fn main() {
let mut it = 0..20;
for _ in it {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
index 559513d..8e02f59 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
@@ -456,6 +456,15 @@ fn f4(_: impl MySpecialFnMut) {}
});
}
+fn issue13123() {
+ let mut it = 0..20;
+ 'label: while let Some(n) = it.next() {
+ if n % 25 == 0 {
+ break 'label;
+ }
+ }
+}
+
fn main() {
let mut it = 0..20;
while let Some(..) = it.next() {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
index 8ff1f23..d96b26a 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
@@ -160,8 +160,14 @@
error: this loop could be written as a `for` loop
--> tests/ui/while_let_on_iterator.rs:461:5
|
+LL | 'label: while let Some(n) = it.next() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `'label: for n in it`
+
+error: this loop could be written as a `for` loop
+ --> tests/ui/while_let_on_iterator.rs:470:5
+ |
LL | while let Some(..) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
-error: aborting due to 27 previous errors
+error: aborting due to 28 previous errors
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index eba5405..6832833 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(clippy::single_match_else)]
diff --git a/src/tools/clippy/tests/workspace_test/path_dep/Cargo.toml b/src/tools/clippy/tests/workspace_test/path_dep/Cargo.toml
index 85a91cd..98b4fb7a 100644
--- a/src/tools/clippy/tests/workspace_test/path_dep/Cargo.toml
+++ b/src/tools/clippy/tests/workspace_test/path_dep/Cargo.toml
@@ -1,3 +1,6 @@
[package]
name = "path_dep"
version = "0.1.0"
+
+[features]
+primary_package_test = []
diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html
index 0c0f28e..300c9de 100644
--- a/src/tools/clippy/util/gh-pages/index.html
+++ b/src/tools/clippy/util/gh-pages/index.html
@@ -541,7 +541,7 @@
<div class="col-12 col-md-5 search-control">
<div class="input-group">
<label class="input-group-addon" id="filter-label" for="search-input">Filter:</label>
- <input type="text" class="form-control filter-input" placeholder="Keywords or search string" id="search-input"
+ <input type="text" class="form-control filter-input" placeholder="Keywords or search string (`S` or `/` to focus)" id="search-input"
ng-model="search" ng-blur="updatePath()" ng-keyup="$event.keyCode == 13 && updatePath()"
ng-model-options="{debounce: 50}" />
<span class="input-group-btn">
@@ -605,7 +605,7 @@
<a href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+{{lint.id}}">Related Issues</a>
</div>
<!-- Jump to source -->
- <div class="lint-additional-info-item">
+ <div class="lint-additional-info-item" ng-if="lint.id_span">
<a href="https://github.com/rust-lang/rust-clippy/blob/{{docVersion}}/clippy_lints/{{lint.id_span.path}}#L{{lint.id_span.line}}">View Source</a>
</div>
</div>
diff --git a/src/tools/clippy/util/gh-pages/script.js b/src/tools/clippy/util/gh-pages/script.js
index 661f80a..ed1e090 100644
--- a/src/tools/clippy/util/gh-pages/script.js
+++ b/src/tools/clippy/util/gh-pages/script.js
@@ -1,5 +1,5 @@
(function () {
- var md = window.markdownit({
+ const md = window.markdownit({
html: true,
linkify: true,
typographer: true,
@@ -17,7 +17,7 @@
});
function scrollToLint(lintId) {
- var target = document.getElementById(lintId);
+ const target = document.getElementById(lintId);
if (!target) {
return;
}
@@ -25,21 +25,17 @@
}
function scrollToLintByURL($scope, $location) {
- var removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
+ const removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
scrollToLint($location.path().substring(1));
removeListener();
});
}
function selectGroup($scope, selectedGroup) {
- var groups = $scope.groups;
- for (var group in groups) {
+ const groups = $scope.groups;
+ for (const group in groups) {
if (groups.hasOwnProperty(group)) {
- if (group === selectedGroup) {
- groups[group] = true;
- } else {
- groups[group] = false;
- }
+ groups[group] = group === selectedGroup;
}
}
}
@@ -108,7 +104,7 @@
})
.controller("lintList", function ($scope, $http, $location, $timeout) {
// Level filter
- var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
+ const LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
$scope.levels = { ...LEVEL_FILTERS_DEFAULT };
$scope.byLevels = function (lint) {
return $scope.levels[lint.level];
@@ -367,7 +363,7 @@
}
$scope.clearVersionFilters = function () {
- for (let filter in $scope.versionFilters) {
+ for (const filter in $scope.versionFilters) {
$scope.versionFilters[filter] = { enabled: false, minorVersion: null };
}
}
@@ -378,7 +374,7 @@
$scope.updateVersionFilters = function() {
for (const filter in $scope.versionFilters) {
- let minorVersion = $scope.versionFilters[filter].minorVersion;
+ const minorVersion = $scope.versionFilters[filter].minorVersion;
// 1.29.0 and greater
if (minorVersion && minorVersion > 28) {
@@ -391,14 +387,14 @@
}
$scope.byVersion = function(lint) {
- let filters = $scope.versionFilters;
+ const filters = $scope.versionFilters;
for (const filter in filters) {
if (filters[filter].enabled) {
- let minorVersion = filters[filter].minorVersion;
+ const minorVersion = filters[filter].minorVersion;
// Strip the "pre " prefix for pre 1.29.0 lints
- let lintVersion = lint.version.startsWith("pre ") ? lint.version.substring(4, lint.version.length) : lint.version;
- let lintMinorVersion = lintVersion.substring(2, 4);
+ const lintVersion = lint.version.startsWith("pre ") ? lint.version.substring(4, lint.version.length) : lint.version;
+ const lintMinorVersion = lintVersion.substring(2, 4);
switch (filter) {
// "=" gets the highest priority, since all filters are inclusive
@@ -441,8 +437,8 @@
// Search the description
// The use of `for`-loops instead of `foreach` enables us to return early
- let terms = searchStr.split(" ");
- let docsLowerCase = lint.docs.toLowerCase();
+ const terms = searchStr.split(" ");
+ const docsLowerCase = lint.docs.toLowerCase();
for (index = 0; index < terms.length; index++) {
// This is more likely and will therefore be checked first
if (docsLowerCase.indexOf(terms[index]) !== -1) {
@@ -479,7 +475,7 @@
const clipboard = document.getElementById("clipboard-" + lint.id);
if (clipboard) {
let resetClipboardTimeout = null;
- let resetClipboardIcon = clipboard.innerHTML;
+ const resetClipboardIcon = clipboard.innerHTML;
function resetClipboard() {
resetClipboardTimeout = null;
@@ -511,7 +507,7 @@
$scope.data = data;
$scope.loading = false;
- var selectedGroup = getQueryVariable("sel");
+ const selectedGroup = getQueryVariable("sel");
if (selectedGroup) {
selectGroup($scope, selectedGroup.toLowerCase());
}
@@ -519,7 +515,7 @@
scrollToLintByURL($scope, $location);
setTimeout(function () {
- var el = document.getElementById('filter-input');
+ const el = document.getElementById('filter-input');
if (el) { el.focus() }
}, 0);
})
@@ -531,10 +527,10 @@
})();
function getQueryVariable(variable) {
- var query = window.location.search.substring(1);
- var vars = query.split('&');
- for (var i = 0; i < vars.length; i++) {
- var pair = vars[i].split('=');
+ const query = window.location.search.substring(1);
+ const vars = query.split('&');
+ for (const entry of vars) {
+ const pair = entry.split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
@@ -579,6 +575,32 @@
}
}
+function handleShortcut(ev) {
+ if (ev.ctrlKey || ev.altKey || ev.metaKey) {
+ return;
+ }
+
+ if (document.activeElement.tagName === "INPUT") {
+ if (ev.key === "Escape") {
+ document.activeElement.blur();
+ }
+ } else {
+ switch (ev.key) {
+ case "s":
+ case "S":
+ case "/":
+ ev.preventDefault(); // To prevent the key to be put into the input.
+ document.getElementById("search-input").focus();
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+document.addEventListener("keypress", handleShortcut);
+document.addEventListener("keydown", handleShortcut);
+
// loading the theme after the initial load
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)");
const theme = localStorage.getItem('clippy-lint-list-theme');
diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml
index d0820cf..edf9e5c 100644
--- a/src/tools/collect-license-metadata/Cargo.toml
+++ b/src/tools/collect-license-metadata/Cargo.toml
@@ -2,6 +2,8 @@
name = "collect-license-metadata"
version = "0.1.0"
edition = "2021"
+description = "Runs the reuse tool and caches the output, so rust toolchain devs don't need to have reuse installed"
+license = "MIT OR Apache-2.0"
[dependencies]
anyhow = "1.0.65"
diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs
index ca2a6f4..dce36bb 100644
--- a/src/tools/collect-license-metadata/src/main.rs
+++ b/src/tools/collect-license-metadata/src/main.rs
@@ -2,10 +2,17 @@
mod path_tree;
mod reuse;
-use crate::licenses::LicensesInterner;
-use anyhow::Error;
use std::path::PathBuf;
+use anyhow::Error;
+
+use crate::licenses::LicensesInterner;
+
+/// The entry point to the binary.
+///
+/// You should probably let `bootstrap` execute this program instead of running it directly.
+///
+/// Run `x.py run collect-license-metadata`
fn main() -> Result<(), Error> {
let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into();
let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into();
diff --git a/src/tools/collect-license-metadata/src/path_tree.rs b/src/tools/collect-license-metadata/src/path_tree.rs
index b27fb7f..866a4e4 100644
--- a/src/tools/collect-license-metadata/src/path_tree.rs
+++ b/src/tools/collect-license-metadata/src/path_tree.rs
@@ -3,10 +3,11 @@
//! responsible for that, by turning the list of paths into a tree and executing simplification
//! passes over the tree to remove redundant information.
-use crate::licenses::{License, LicenseId, LicensesInterner};
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
+use crate::licenses::{License, LicenseId, LicensesInterner};
+
#[derive(serde::Serialize)]
#[serde(rename_all = "kebab-case", tag = "type")]
pub(crate) enum Node<L> {
diff --git a/src/tools/collect-license-metadata/src/reuse.rs b/src/tools/collect-license-metadata/src/reuse.rs
index a5d0193..e5ee8f0 100644
--- a/src/tools/collect-license-metadata/src/reuse.rs
+++ b/src/tools/collect-license-metadata/src/reuse.rs
@@ -1,9 +1,11 @@
-use crate::licenses::{License, LicenseId, LicensesInterner};
-use anyhow::Error;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::Instant;
+use anyhow::Error;
+
+use crate::licenses::{License, LicenseId, LicensesInterner};
+
pub(crate) fn collect(
reuse_exe: &Path,
interner: &mut LicensesInterner,
diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs
index c356f42..50c9097 100644
--- a/src/tools/compiletest/src/command-list.rs
+++ b/src/tools/compiletest/src/command-list.rs
@@ -18,6 +18,7 @@
"check-test-line-numbers-match",
"compare-output-lines-by-subset",
"compile-flags",
+ "doc-flags",
"dont-check-compiler-stderr",
"dont-check-compiler-stdout",
"dont-check-failure-status",
@@ -117,6 +118,7 @@
"ignore-watchos",
"ignore-windows",
"ignore-windows-gnu",
+ "ignore-windows-msvc",
"ignore-x32",
"ignore-x86",
"ignore-x86_64",
@@ -168,6 +170,7 @@
"only-32bit",
"only-64bit",
"only-aarch64",
+ "only-aarch64-unknown-linux-gnu",
"only-apple",
"only-arm",
"only-avr",
@@ -202,6 +205,7 @@
"only-watchos",
"only-windows",
"only-windows-gnu",
+ "only-windows-msvc",
"only-x86",
"only-x86_64",
"only-x86_64-fortanix-unknown-sgx",
@@ -225,6 +229,7 @@
"should-ice",
"stderr-per-bitwidth",
"test-mir-pass",
+ "unique-doc-out-dir",
"unset-exec-env",
"unset-rustc-env",
// Used by the tidy check `unknown_revision`.
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index bc66dcb..70ebefe 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -1,19 +1,18 @@
-pub use self::Mode::*;
-
+use std::collections::{HashMap, HashSet};
use std::ffi::OsString;
-use std::fmt;
-use std::iter;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::sync::OnceLock;
+use std::{fmt, iter};
-use crate::util::{add_dylib_path, PathBufExt};
use build_helper::git::GitConfig;
use serde::de::{Deserialize, Deserializer, Error as _};
-use std::collections::{HashMap, HashSet};
use test::{ColorConfig, OutputFormat};
+pub use self::Mode::*;
+use crate::util::{add_dylib_path, PathBufExt};
+
macro_rules! string_enum {
($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => {
$(#[$meta])*
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 7a5abc5..4ca9f02 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -1,5 +1,3 @@
-use self::WhichLine::*;
-
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
@@ -11,6 +9,8 @@
use regex::Regex;
use tracing::*;
+use self::WhichLine::*;
+
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ErrorKind {
Help,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 3afb5e2..1fc2430 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -11,8 +11,7 @@
use tracing::*;
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
-use crate::header::cfg::parse_cfg_name_directive;
-use crate::header::cfg::MatchOutcome;
+use crate::header::cfg::{parse_cfg_name_directive, MatchOutcome};
use crate::header::needs::CachedNeedsConditions;
use crate::util::static_regex;
use crate::{extract_cdb_version, extract_gdb_version};
@@ -96,6 +95,8 @@ pub struct TestProps {
pub compile_flags: Vec<String>,
// Extra flags to pass when the compiled code is run (such as --bench)
pub run_flags: Vec<String>,
+ /// Extra flags to pass to rustdoc but not the compiler.
+ pub doc_flags: Vec<String>,
// If present, the name of a file that this test should match when
// pretty-printed
pub pp_exact: Option<PathBuf>,
@@ -123,6 +124,9 @@ pub struct TestProps {
pub unset_exec_env: Vec<String>,
// Build documentation for all specified aux-builds as well
pub build_aux_docs: bool,
+ /// Build the documentation for each crate in a unique output directory.
+ /// Uses <root output directory>/docs/<test name>/doc
+ pub unique_doc_out_dir: bool,
// Flag to force a crate to be built with the host architecture
pub force_host: bool,
// Check stdout for error-pattern output as well as stderr
@@ -221,8 +225,10 @@ mod directives {
pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern";
pub const COMPILE_FLAGS: &'static str = "compile-flags";
pub const RUN_FLAGS: &'static str = "run-flags";
+ pub const DOC_FLAGS: &'static str = "doc-flags";
pub const SHOULD_ICE: &'static str = "should-ice";
pub const BUILD_AUX_DOCS: &'static str = "build-aux-docs";
+ pub const UNIQUE_DOC_OUT_DIR: &'static str = "unique-doc-out-dir";
pub const FORCE_HOST: &'static str = "force-host";
pub const CHECK_STDOUT: &'static str = "check-stdout";
pub const CHECK_RUN_RESULTS: &'static str = "check-run-results";
@@ -268,6 +274,7 @@ pub fn new() -> Self {
regex_error_patterns: vec![],
compile_flags: vec![],
run_flags: vec![],
+ doc_flags: vec![],
pp_exact: None,
aux_builds: vec![],
aux_bins: vec![],
@@ -282,6 +289,7 @@ pub fn new() -> Self {
exec_env: vec![],
unset_exec_env: vec![],
build_aux_docs: false,
+ unique_doc_out_dir: false,
force_host: false,
check_stdout: false,
check_run_results: false,
@@ -331,6 +339,7 @@ pub fn from_aux_file(&self, testfile: &Path, revision: Option<&str>, config: &Co
pub fn from_file(testfile: &Path, revision: Option<&str>, config: &Config) -> Self {
let mut props = TestProps::new();
props.load_from(testfile, revision, config);
+ props.exec_env.push(("RUSTC".to_string(), config.rustc_path.display().to_string()));
match (props.pass_mode, props.fail_mode) {
(None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check),
@@ -378,6 +387,8 @@ fn load_from(&mut self, testfile: &Path, test_revision: Option<&str>, config: &C
|r| r,
);
+ config.push_name_value_directive(ln, DOC_FLAGS, &mut self.doc_flags, |r| r);
+
fn split_flags(flags: &str) -> Vec<String> {
// Individual flags can be single-quoted to preserve spaces; see
// <https://github.com/rust-lang/rust/pull/115948/commits/957c5db6>.
@@ -415,6 +426,8 @@ fn split_flags(flags: &str) -> Vec<String> {
config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
+ config.set_name_directive(ln, UNIQUE_DOC_OUT_DIR, &mut self.unique_doc_out_dir);
+
config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index 522c52b..948568e 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -1,6 +1,7 @@
+use std::collections::HashSet;
+
use crate::common::{CompareMode, Config, Debugger, Mode};
use crate::header::IgnoreDecision;
-use std::collections::HashSet;
const EXTRA_ARCHS: &[&str] = &["spirv"];
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c790eb1..29e11e7 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -2,11 +2,10 @@
use std::path::Path;
use std::str::FromStr;
+use super::iter_header;
use crate::common::{Config, Debugger, Mode};
use crate::header::{parse_normalize_rule, EarlyProps, HeadersCache};
-use super::iter_header;
-
fn make_test_description<R: Read>(
config: &Config,
name: test::TestName,
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 29e8809..76b83f0 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -1,12 +1,14 @@
//! These structs are a subset of the ones found in `rustc_errors::json`.
//! They are only used for deserialization of JSON output provided by libtest.
-use crate::errors::{Error, ErrorKind};
-use crate::runtest::ProcRes;
-use serde::Deserialize;
use std::path::{Path, PathBuf};
use std::str::FromStr;
+use serde::Deserialize;
+
+use crate::errors::{Error, ErrorKind};
+use crate::runtest::ProcRes;
+
#[derive(Deserialize)]
struct Diagnostic {
message: String,
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 81a5acb..6acf46f 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -18,27 +18,29 @@
pub mod runtest;
pub mod util;
-use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
-use crate::common::{Config, Debugger, Mode, PassMode, TestPaths};
-use crate::util::logv;
-use build_helper::git::{get_git_modified_files, get_git_untracked_files};
use core::panic;
-use getopts::Options;
use std::collections::HashSet;
use std::ffi::{OsStr, OsString};
-use std::fs;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::sync::{Arc, OnceLock};
use std::time::SystemTime;
-use std::{env, vec};
+use std::{env, fs, vec};
+
+use build_helper::git::{get_git_modified_files, get_git_untracked_files};
+use getopts::Options;
use test::ColorConfig;
use tracing::*;
use walkdir::WalkDir;
use self::header::{make_test_description, EarlyProps};
+use crate::common::{
+ expected_output_path, output_base_dir, output_relative_path, Config, Debugger, Mode, PassMode,
+ TestPaths, UI_EXTENSIONS,
+};
use crate::header::HeadersCache;
+use crate::util::logv;
pub fn parse_config(args: Vec<String>) -> Config {
let mut opts = Options::new();
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 1ec3f0a0..7b85e6f 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -1,6 +1,9 @@
-use std::{env, io::IsTerminal, sync::Arc};
+use std::env;
+use std::io::IsTerminal;
+use std::sync::Arc;
-use compiletest::{common::Mode, log_config, parse_config, run_tests};
+use compiletest::common::Mode;
+use compiletest::{log_config, parse_config, run_tests};
fn main() {
tracing_subscriber::fmt::init();
diff --git a/src/tools/compiletest/src/raise_fd_limit.rs b/src/tools/compiletest/src/raise_fd_limit.rs
index 218bea6..4445ecb 100644
--- a/src/tools/compiletest/src/raise_fd_limit.rs
+++ b/src/tools/compiletest/src/raise_fd_limit.rs
@@ -7,10 +7,9 @@
#[cfg(target_vendor = "apple")]
#[allow(non_camel_case_types)]
pub unsafe fn raise_fd_limit() {
- use std::cmp;
- use std::io;
use std::mem::size_of_val;
use std::ptr::null_mut;
+ use std::{cmp, io};
static CTL_KERN: libc::c_int = 1;
static KERN_MAXFILESPERPROC: libc::c_int = 29;
diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs
index 8c06339..b2d068e 100644
--- a/src/tools/compiletest/src/read2.rs
+++ b/src/tools/compiletest/src/read2.rs
@@ -4,10 +4,11 @@
#[cfg(test)]
mod tests;
-pub use self::imp::read2;
use std::io::{self, Write};
use std::process::{Child, Output};
+pub use self::imp::read2;
+
#[derive(Copy, Clone, Debug)]
pub enum Truncated {
Yes,
@@ -154,11 +155,10 @@ pub fn read2(
#[cfg(unix)]
mod imp {
- use std::io;
use std::io::prelude::*;
- use std::mem;
use std::os::unix::prelude::*;
use std::process::{ChildStderr, ChildStdout};
+ use std::{io, mem};
pub fn read2(
mut out_pipe: ChildStdout,
@@ -228,10 +228,9 @@ pub fn read2(
#[cfg(windows)]
mod imp {
- use std::io;
use std::os::windows::prelude::*;
use std::process::{ChildStderr, ChildStdout};
- use std::slice;
+ use std::{io, slice};
use miow::iocp::{CompletionPort, CompletionStatus};
use miow::pipe::NamedPipe;
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 78c0655..59fce44 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,45 +1,38 @@
// ignore-tidy-filelength
-use crate::common::{
- expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG,
-};
-use crate::common::{incremental_dir, output_base_dir, output_base_name, output_testname_unique};
-use crate::common::{Assembly, Crashes, Incremental, JsDocTest, MirOpt, RunMake, RustdocJson, Ui};
-use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
-use crate::common::{CompareMode, FailMode, PassMode};
-use crate::common::{Config, TestPaths};
-use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind};
-use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
-use crate::compute_diff::{write_diff, write_filtered_diff};
-use crate::errors::{self, Error, ErrorKind};
-use crate::header::TestProps;
-use crate::json;
-use crate::read2::{read2_abbreviated, Truncated};
-use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
-use crate::ColorConfig;
-use colored::Colorize;
-use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
-use regex::{Captures, Regex};
-use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
+use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
-use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::{self, create_dir_all, File, OpenOptions};
use std::hash::{DefaultHasher, Hash, Hasher};
use std::io::prelude::*;
use std::io::{self, BufReader};
-use std::iter;
use std::path::{Path, PathBuf};
use std::process::{Child, Command, ExitStatus, Output, Stdio};
-use std::str;
use std::sync::Arc;
+use std::{env, iter, str};
use anyhow::Context;
+use colored::Colorize;
use glob::glob;
+use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
+use regex::{Captures, Regex};
+use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
use tracing::*;
-use crate::extract_gdb_version;
-use crate::is_android_gdb_target;
+use crate::common::{
+ expected_output_path, incremental_dir, output_base_dir, output_base_name,
+ output_testname_unique, Assembly, Codegen, CodegenUnits, CompareMode, Config, CoverageMap,
+ CoverageRun, Crashes, DebugInfo, Debugger, FailMode, Incremental, JsDocTest, MirOpt, PassMode,
+ Pretty, RunMake, RunPassValgrind, Rustdoc, RustdocJson, TestPaths, Ui, UI_EXTENSIONS, UI_FIXED,
+ UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG,
+};
+use crate::compute_diff::{write_diff, write_filtered_diff};
+use crate::errors::{self, Error, ErrorKind};
+use crate::header::TestProps;
+use crate::read2::{read2_abbreviated, Truncated};
+use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
+use crate::{extract_gdb_version, is_android_gdb_target, json, ColorConfig};
mod coverage;
mod debugger;
@@ -731,7 +724,7 @@ fn typecheck_source(&self, src: String) -> ProcRes {
self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
rustc.args(&self.props.compile_flags);
- self.compose_and_run_compiler(rustc, Some(src))
+ self.compose_and_run_compiler(rustc, Some(src), self.testpaths)
}
fn run_debuginfo_test(&self) {
@@ -1587,13 +1580,15 @@ fn compile_test_general(
passes,
);
- self.compose_and_run_compiler(rustc, None)
+ self.compose_and_run_compiler(rustc, None, self.testpaths)
}
- fn document(&self, out_dir: &Path) -> ProcRes {
+ /// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run.
+ /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths.
+ fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
if self.props.build_aux_docs {
for rel_ab in &self.props.aux_builds {
- let aux_testpaths = self.compute_aux_test_paths(&self.testpaths, rel_ab);
+ let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab);
let aux_props =
self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
let aux_cx = TestCx {
@@ -1604,7 +1599,9 @@ fn document(&self, out_dir: &Path) -> ProcRes {
};
// Create the directory for the stdout/stderr files.
create_dir_all(aux_cx.output_base_dir()).unwrap();
- let auxres = aux_cx.document(out_dir);
+ // use root_testpaths here, because aux-builds should have the
+ // same --out-dir and auxiliary directory.
+ let auxres = aux_cx.document(&root_out_dir, root_testpaths);
if !auxres.status.success() {
return auxres;
}
@@ -1614,21 +1611,40 @@ fn document(&self, out_dir: &Path) -> ProcRes {
let aux_dir = self.aux_output_dir_name();
let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed");
- let mut rustdoc = Command::new(rustdoc_path);
+ // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire
+ // test
+ let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir {
+ let file_name = self.testpaths.file.file_stem().expect("file name should not be empty");
+ let out_dir = PathBuf::from_iter([
+ root_out_dir,
+ Path::new("docs"),
+ Path::new(file_name),
+ Path::new("doc"),
+ ]);
+ create_dir_all(&out_dir).unwrap();
+ Cow::Owned(out_dir)
+ } else {
+ Cow::Borrowed(root_out_dir)
+ };
+
+ let mut rustdoc = Command::new(rustdoc_path);
+ let current_dir = output_base_dir(self.config, root_testpaths, self.safe_revision());
+ rustdoc.current_dir(current_dir);
rustdoc
.arg("-L")
.arg(self.config.run_lib_path.to_str().unwrap())
.arg("-L")
.arg(aux_dir)
.arg("-o")
- .arg(out_dir)
+ .arg(out_dir.as_ref())
.arg("--deny")
.arg("warnings")
.arg(&self.testpaths.file)
.arg("-A")
.arg("internal_features")
- .args(&self.props.compile_flags);
+ .args(&self.props.compile_flags)
+ .args(&self.props.doc_flags);
if self.config.mode == RustdocJson {
rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options");
@@ -1638,7 +1654,7 @@ fn document(&self, out_dir: &Path) -> ProcRes {
rustdoc.arg(format!("-Clinker={}", linker));
}
- self.compose_and_run_compiler(rustdoc, None)
+ self.compose_and_run_compiler(rustdoc, None, root_testpaths)
}
fn exec_compiled_test(&self) -> ProcRes {
@@ -1836,9 +1852,16 @@ fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Comman
}
}
- fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
+ /// `root_testpaths` refers to the path of the original test.
+ /// the auxiliary and the test with an aux-build have the same `root_testpaths`.
+ fn compose_and_run_compiler(
+ &self,
+ mut rustc: Command,
+ input: Option<String>,
+ root_testpaths: &TestPaths,
+ ) -> ProcRes {
let aux_dir = self.aux_output_dir();
- self.build_all_auxiliary(&self.testpaths, &aux_dir, &mut rustc);
+ self.build_all_auxiliary(root_testpaths, &aux_dir, &mut rustc);
rustc.envs(self.props.rustc_env.clone());
self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
@@ -2553,7 +2576,7 @@ fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) {
Vec::new(),
);
- let proc_res = self.compose_and_run_compiler(rustc, None);
+ let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
let output_path = self.get_filecheck_file("ll");
(proc_res, output_path)
}
@@ -2589,7 +2612,7 @@ fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
Vec::new(),
);
- let proc_res = self.compose_and_run_compiler(rustc, None);
+ let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
let output_path = self.get_filecheck_file("s");
(proc_res, output_path)
}
@@ -2672,7 +2695,7 @@ fn run_rustdoc_test(&self) {
let out_dir = self.output_base_dir();
remove_and_create_dir_all(&out_dir);
- let proc_res = self.document(&out_dir);
+ let proc_res = self.document(&out_dir, &self.testpaths);
if !proc_res.status.success() {
self.fatal_proc_rec("rustdoc failed!", &proc_res);
}
@@ -2731,7 +2754,7 @@ fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
let aux_dir = new_rustdoc.aux_output_dir();
new_rustdoc.build_all_auxiliary(&new_rustdoc.testpaths, &aux_dir, &mut rustc);
- let proc_res = new_rustdoc.document(&compare_dir);
+ let proc_res = new_rustdoc.document(&compare_dir, &new_rustdoc.testpaths);
if !proc_res.status.success() {
eprintln!("failed to run nightly rustdoc");
return;
@@ -2739,6 +2762,7 @@ fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
#[rustfmt::skip]
let tidy_args = [
+ "--new-blocklevel-tags", "rustdoc-search",
"--indent", "yes",
"--indent-spaces", "2",
"--wrap", "0",
@@ -2854,7 +2878,7 @@ fn run_rustdoc_json_test(&self) {
let out_dir = self.output_base_dir();
remove_and_create_dir_all(&out_dir);
- let proc_res = self.document(&out_dir);
+ let proc_res = self.document(&out_dir, &self.testpaths);
if !proc_res.status.success() {
self.fatal_proc_rec("rustdoc failed!", &proc_res);
}
@@ -2930,31 +2954,24 @@ fn get_lines<P: AsRef<Path>>(
fn check_rustdoc_test_option(&self, res: ProcRes) {
let mut other_files = Vec::new();
let mut files: HashMap<String, Vec<usize>> = HashMap::new();
- let cwd = env::current_dir().unwrap();
- files.insert(
- self.testpaths
- .file
- .strip_prefix(&cwd)
- .unwrap_or(&self.testpaths.file)
- .to_str()
- .unwrap()
- .replace('\\', "/"),
- self.get_lines(&self.testpaths.file, Some(&mut other_files)),
- );
+ let normalized = fs::canonicalize(&self.testpaths.file).expect("failed to canonicalize");
+ let normalized = normalized.to_str().unwrap().replace('\\', "/");
+ files.insert(normalized, self.get_lines(&self.testpaths.file, Some(&mut other_files)));
for other_file in other_files {
let mut path = self.testpaths.file.clone();
path.set_file_name(&format!("{}.rs", other_file));
- files.insert(
- path.strip_prefix(&cwd).unwrap_or(&path).to_str().unwrap().replace('\\', "/"),
- self.get_lines(&path, None),
- );
+ let path = fs::canonicalize(path).expect("failed to canonicalize");
+ let normalized = path.to_str().unwrap().replace('\\', "/");
+ files.insert(normalized, self.get_lines(&path, None));
}
let mut tested = 0;
for _ in res.stdout.split('\n').filter(|s| s.starts_with("test ")).inspect(|s| {
if let Some((left, right)) = s.split_once(" - ") {
let path = left.rsplit("test ").next().unwrap();
- if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) {
+ let path = fs::canonicalize(&path).expect("failed to canonicalize");
+ let path = path.to_str().unwrap().replace('\\', "/");
+ if let Some(ref mut v) = files.get_mut(&path) {
tested += 1;
let mut iter = right.split("(line ");
iter.next();
@@ -3010,11 +3027,17 @@ fn run_codegen_units_test(&self) {
const PREFIX: &str = "MONO_ITEM ";
const CGU_MARKER: &str = "@@";
+ // Some MonoItems can contain {closure@/path/to/checkout/tests/codgen-units/test.rs}
+ // To prevent the current dir from leaking, we just replace the entire path to the test
+ // file with TEST_PATH.
let actual: Vec<MonoItem> = proc_res
.stdout
.lines()
.filter(|line| line.starts_with(PREFIX))
- .map(|line| str_to_mono_item(line, true))
+ .map(|line| {
+ line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string()
+ })
+ .map(|line| str_to_mono_item(&line, true))
.collect();
let expected: Vec<MonoItem> = errors::load_errors(&self.testpaths.file, None)
@@ -3712,15 +3735,14 @@ fn run_rmake_v2_test(&self) {
}
if self.config.bless {
- cmd.env("RUSTC_BLESS_TEST", "--bless");
- // Assume this option is active if the environment variable is "defined", with _any_ value.
- // As an example, a `Makefile` can use this option by:
+ // If we're running in `--bless` mode, set an environment variable to tell
+ // `run_make_support` to bless snapshot files instead of checking them.
//
- // ifdef RUSTC_BLESS_TEST
- // cp "$(TMPDIR)"/actual_something.ext expected_something.ext
- // else
- // $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext
- // endif
+ // The value is this test's source directory, because the support code
+ // will need that path in order to bless the _original_ snapshot files,
+ // not the copies in `rmake_out`.
+ // (See <https://github.com/rust-lang/rust/issues/129038>.)
+ cmd.env("RUSTC_BLESS_TEST", &self.testpaths.file);
}
if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
@@ -3786,7 +3808,7 @@ fn run_js_doc_test(&self) {
if let Some(nodejs) = &self.config.nodejs {
let out_dir = self.output_base_dir();
- self.document(&out_dir);
+ self.document(&out_dir, &self.testpaths);
let root = self.config.find_rust_src_root().unwrap();
let file_stem =
@@ -4102,7 +4124,7 @@ fn run_ui_test(&self) {
rustc.arg(crate_name);
}
- let res = self.compose_and_run_compiler(rustc, None);
+ let res = self.compose_and_run_compiler(rustc, None, self.testpaths);
if !res.status.success() {
self.fatal_proc_rec("failed to compile fixed code", &res);
}
diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs
index 6ee147da..05191a1 100644
--- a/src/tools/compiletest/src/runtest/coverage.rs
+++ b/src/tools/compiletest/src/runtest/coverage.rs
@@ -191,7 +191,7 @@ fn run_doctests_for_coverage(
rustdoc_cmd.arg(&self.testpaths.file);
- let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None);
+ let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None, self.testpaths);
if !proc_res.status.success() {
self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
}
diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs
index ed6cc97..985fe63 100644
--- a/src/tools/compiletest/src/runtest/debugger.rs
+++ b/src/tools/compiletest/src/runtest/debugger.rs
@@ -1,12 +1,12 @@
-use crate::common::Config;
-use crate::header::line_directive;
-use crate::runtest::ProcRes;
-
use std::fmt::Write;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
+use crate::common::Config;
+use crate::header::line_directive;
+use crate::runtest::ProcRes;
+
/// Representation of information to invoke a debugger and check its output
pub(super) struct DebuggerCommands {
/// Commands for the debuuger
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index cdec49a..bff02f1 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -1,4 +1,3 @@
-use crate::common::Config;
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
@@ -6,6 +5,8 @@
use tracing::*;
+use crate::common::Config;
+
#[cfg(test)]
mod tests;
diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs
index b308c8d..4729b32 100644
--- a/src/tools/coverage-dump/src/covfun.rs
+++ b/src/tools/coverage-dump/src/covfun.rs
@@ -1,10 +1,12 @@
-use crate::parser::{unescape_llvm_string_contents, Parser};
-use anyhow::{anyhow, Context};
-use regex::Regex;
use std::collections::HashMap;
use std::fmt::{self, Debug, Write as _};
use std::sync::OnceLock;
+use anyhow::{anyhow, Context};
+use regex::Regex;
+
+use crate::parser::{unescape_llvm_string_contents, Parser};
+
pub(crate) fn dump_covfun_mappings(
llvm_ir: &str,
function_names: &HashMap<u64, String>,
diff --git a/src/tools/coverage-dump/src/parser.rs b/src/tools/coverage-dump/src/parser.rs
index eefac1a..0bd4abd 100644
--- a/src/tools/coverage-dump/src/parser.rs
+++ b/src/tools/coverage-dump/src/parser.rs
@@ -1,9 +1,10 @@
#[cfg(test)]
mod tests;
+use std::sync::OnceLock;
+
use anyhow::ensure;
use regex::bytes;
-use std::sync::OnceLock;
/// Given the raw contents of a string literal in LLVM IR assembly, decodes any
/// backslash escapes and returns a vector containing the resulting byte string.
diff --git a/src/tools/coverage-dump/src/prf_names.rs b/src/tools/coverage-dump/src/prf_names.rs
index d3f7b81..c5f9c4c 100644
--- a/src/tools/coverage-dump/src/prf_names.rs
+++ b/src/tools/coverage-dump/src/prf_names.rs
@@ -1,9 +1,11 @@
-use crate::parser::{unescape_llvm_string_contents, Parser};
-use anyhow::{anyhow, ensure};
-use regex::Regex;
use std::collections::HashMap;
use std::sync::OnceLock;
+use anyhow::{anyhow, ensure};
+use regex::Regex;
+
+use crate::parser::{unescape_llvm_string_contents, Parser};
+
/// Scans through the contents of an LLVM IR assembly file to find `__llvm_prf_names`
/// entries, decodes them, and creates a table that maps name hash values to
/// (demangled) function names.
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 2de2d95..53a2611 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -5,18 +5,16 @@
extern crate rustc_session;
extern crate rustc_errors;
-use rustc_errors::codes::DIAGNOSTICS;
-
use std::env;
use std::error::Error;
use std::fs::{self, File};
use std::io::Write;
-use std::path::Path;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::str::FromStr;
use mdbook::book::{parse_summary, BookItem, Chapter};
use mdbook::{Config, MDBook};
+use rustc_errors::codes::DIAGNOSTICS;
enum OutputFormat {
HTML,
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
index 899ef0f..404101a 100644
--- a/src/tools/generate-copyright/Cargo.toml
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -2,10 +2,14 @@
name = "generate-copyright"
version = "0.1.0"
edition = "2021"
+description = "Produces a manifest of all the copyrighted materials in the Rust Toolchain"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.65"
+cargo_metadata = "0.18.1"
+rinja = "0.3.0"
serde = { version = "1.0.147", features = ["derive"] }
serde_json = "1.0.85"
+thiserror = "1"
diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs
new file mode 100644
index 0000000..c85e4aa
--- /dev/null
+++ b/src/tools/generate-copyright/src/cargo_metadata.rs
@@ -0,0 +1,191 @@
+//! Gets metadata about a workspace from Cargo
+
+use std::collections::BTreeMap;
+use std::ffi::OsStr;
+use std::path::{Path, PathBuf};
+
+/// Describes how this module can fail
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+ #[error("I/O Error: {0:?}")]
+ Io(#[from] std::io::Error),
+ #[error("Failed get output from cargo-metadata: {0:?}")]
+ GettingMetadata(#[from] cargo_metadata::Error),
+ #[error("Failed to run cargo vendor: {0:?}")]
+ LaunchingVendor(std::io::Error),
+ #[error("Failed to complete cargo vendor")]
+ RunningVendor,
+ #[error("Bad path {0:?} whilst scraping files")]
+ Scraping(PathBuf),
+}
+
+/// Uniquely describes a package on crates.io
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Package {
+ /// The name of the package
+ pub name: String,
+ /// The version number
+ pub version: String,
+}
+
+/// Extra data about a package
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct PackageMetadata {
+ /// The license it is under
+ pub license: String,
+ /// The list of authors from the package metadata
+ pub authors: Vec<String>,
+ /// A list of important files from the package, with their contents.
+ ///
+ /// This includes *COPYRIGHT*, *NOTICE*, *AUTHOR*, *LICENSE*, and *LICENCE* files, case-insensitive.
+ pub notices: BTreeMap<String, String>,
+ /// If this is true, this dep is in the Rust Standard Library
+ pub is_in_libstd: Option<bool>,
+}
+
+/// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data.
+///
+/// This will involve running `cargo vendor` into `${BUILD}/vendor` so we can
+/// grab the license files.
+///
+/// Any dependency with a path beginning with `root_path` is ignored, as we
+/// assume `reuse` has covered it already.
+pub fn get_metadata_and_notices(
+ cargo: &Path,
+ dest: &Path,
+ root_path: &Path,
+ manifest_paths: &[&Path],
+) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
+ let mut output = get_metadata(cargo, root_path, manifest_paths)?;
+
+ // Now do a cargo-vendor and grab everything
+ let vendor_path = dest.join("vendor");
+ println!("Vendoring deps into {}...", vendor_path.display());
+ run_cargo_vendor(cargo, &vendor_path, manifest_paths)?;
+
+ // Now for each dependency we found, go and grab any important looking files
+ for (package, metadata) in output.iter_mut() {
+ load_important_files(package, metadata, &vendor_path)?;
+ }
+
+ Ok(output)
+}
+
+/// Use `cargo metadata` to get a list of dependencies and their license data.
+///
+/// Any dependency with a path beginning with `root_path` is ignored, as we
+/// assume `reuse` has covered it already.
+pub fn get_metadata(
+ cargo: &Path,
+ root_path: &Path,
+ manifest_paths: &[&Path],
+) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
+ let mut output = BTreeMap::new();
+ // Look at the metadata for each manifest
+ for manifest_path in manifest_paths {
+ if manifest_path.file_name() != Some(OsStr::new("Cargo.toml")) {
+ panic!("cargo_manifest::get requires a path to a Cargo.toml file");
+ }
+ let metadata = cargo_metadata::MetadataCommand::new()
+ .cargo_path(cargo)
+ .env("RUSTC_BOOTSTRAP", "1")
+ .manifest_path(manifest_path)
+ .exec()?;
+ for package in metadata.packages {
+ let manifest_path = package.manifest_path.as_path();
+ if manifest_path.starts_with(root_path) {
+ // it's an in-tree dependency and reuse covers it
+ continue;
+ }
+ // otherwise it's an out-of-tree dependency
+ let package_id = Package { name: package.name, version: package.version.to_string() };
+ output.insert(
+ package_id,
+ PackageMetadata {
+ license: package.license.unwrap_or_else(|| String::from("Unspecified")),
+ authors: package.authors,
+ notices: BTreeMap::new(),
+ is_in_libstd: None,
+ },
+ );
+ }
+ }
+
+ Ok(output)
+}
+
+/// Run cargo-vendor, fetching into the given dir
+fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> {
+ let mut vendor_command = std::process::Command::new(cargo);
+ vendor_command.env("RUSTC_BOOTSTRAP", "1");
+ vendor_command.arg("vendor");
+ vendor_command.arg("--quiet");
+ vendor_command.arg("--versioned-dirs");
+ for manifest_path in manifest_paths {
+ vendor_command.arg("-s");
+ vendor_command.arg(manifest_path);
+ }
+ vendor_command.arg(dest);
+
+ let vendor_status = vendor_command.status().map_err(Error::LaunchingVendor)?;
+
+ if !vendor_status.success() {
+ return Err(Error::RunningVendor);
+ }
+
+ Ok(())
+}
+
+/// Add important files off disk into this dependency.
+///
+/// Maybe one-day Cargo.toml will contain enough information that we don't need
+/// to do this manual scraping.
+fn load_important_files(
+ package: &Package,
+ dep: &mut PackageMetadata,
+ vendor_root: &Path,
+) -> Result<(), Error> {
+ let name_version = format!("{}-{}", package.name, package.version);
+ println!("Scraping notices for {}...", name_version);
+ let dep_vendor_path = vendor_root.join(name_version);
+ for entry in std::fs::read_dir(dep_vendor_path)? {
+ let entry = entry?;
+ let metadata = entry.metadata()?;
+ let path = entry.path();
+ let Some(filename) = path.file_name() else {
+ return Err(Error::Scraping(path));
+ };
+ let lc_filename = filename.to_ascii_lowercase();
+ let lc_filename_str = lc_filename.to_string_lossy();
+ let mut keep = false;
+ for m in ["copyright", "licence", "license", "author", "notice"] {
+ if lc_filename_str.contains(m) {
+ keep = true;
+ break;
+ }
+ }
+ if keep {
+ if metadata.is_dir() {
+ for inner_entry in std::fs::read_dir(entry.path())? {
+ let inner_entry = inner_entry?;
+ if inner_entry.metadata()?.is_file() {
+ let inner_filename = inner_entry.file_name();
+ let inner_filename_str = inner_filename.to_string_lossy();
+ let qualified_filename =
+ format!("{}/{}", lc_filename_str, inner_filename_str);
+ println!("Scraping {}", qualified_filename);
+ dep.notices.insert(
+ qualified_filename.to_string(),
+ std::fs::read_to_string(inner_entry.path())?,
+ );
+ }
+ }
+ } else if metadata.is_file() {
+ let filename = filename.to_string_lossy();
+ println!("Scraping {}", filename);
+ dep.notices.insert(filename.to_string(), std::fs::read_to_string(path)?);
+ }
+ }
+ }
+ Ok(())
+}
diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs
index d91b258..afa75d0 100644
--- a/src/tools/generate-copyright/src/main.rs
+++ b/src/tools/generate-copyright/src/main.rs
@@ -1,78 +1,70 @@
-use anyhow::Error;
-use std::io::Write;
-use std::path::PathBuf;
+use std::collections::BTreeMap;
+use std::path::{Path, PathBuf};
+use anyhow::Error;
+use rinja::Template;
+
+mod cargo_metadata;
+
+#[derive(Template)]
+#[template(path = "COPYRIGHT.html")]
+struct CopyrightTemplate {
+ in_tree: Node,
+ dependencies: BTreeMap<cargo_metadata::Package, cargo_metadata::PackageMetadata>,
+}
+
+/// The entry point to the binary.
+///
+/// You should probably let `bootstrap` execute this program instead of running it directly.
+///
+/// Run `x.py run generate-copyright`
fn main() -> Result<(), Error> {
- let dest = env_path("DEST")?;
+ let dest_file = env_path("DEST")?;
+ let out_dir = env_path("OUT_DIR")?;
+ let cargo = env_path("CARGO")?;
let license_metadata = env_path("LICENSE_METADATA")?;
- let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
+ let collected_tree_metadata: Metadata =
+ serde_json::from_slice(&std::fs::read(&license_metadata)?)?;
- let mut buffer = Vec::new();
- render_recursive(&metadata.files, &mut buffer, 0)?;
+ let root_path = std::path::absolute(".")?;
+ let workspace_paths = [
+ Path::new("./Cargo.toml"),
+ Path::new("./src/tools/cargo/Cargo.toml"),
+ Path::new("./library/Cargo.toml"),
+ ];
+ let mut collected_cargo_metadata =
+ cargo_metadata::get_metadata_and_notices(&cargo, &out_dir, &root_path, &workspace_paths)?;
- std::fs::write(&dest, &buffer)?;
+ let stdlib_set =
+ cargo_metadata::get_metadata(&cargo, &root_path, &[Path::new("./library/std/Cargo.toml")])?;
+
+ for (key, value) in collected_cargo_metadata.iter_mut() {
+ value.is_in_libstd = Some(stdlib_set.contains_key(key));
+ }
+
+ let template = CopyrightTemplate {
+ in_tree: collected_tree_metadata.files,
+ dependencies: collected_cargo_metadata,
+ };
+
+ let output = template.render()?;
+
+ std::fs::write(&dest_file, output)?;
Ok(())
}
-fn render_recursive(node: &Node, buffer: &mut Vec<u8>, depth: usize) -> Result<(), Error> {
- let prefix = std::iter::repeat("> ").take(depth + 1).collect::<String>();
-
- match node {
- Node::Root { children } => {
- for child in children {
- render_recursive(child, buffer, depth)?;
- }
- }
- Node::Directory { name, children, license } => {
- render_license(&prefix, std::iter::once(name), license.as_ref(), buffer)?;
- if !children.is_empty() {
- writeln!(buffer, "{prefix}")?;
- writeln!(buffer, "{prefix}*Exceptions:*")?;
- for child in children {
- writeln!(buffer, "{prefix}")?;
- render_recursive(child, buffer, depth + 1)?;
- }
- }
- }
- Node::Group { files, directories, license } => {
- render_license(&prefix, directories.iter().chain(files.iter()), Some(license), buffer)?;
- }
- Node::File { name, license } => {
- render_license(&prefix, std::iter::once(name), Some(license), buffer)?;
- }
- }
-
- Ok(())
-}
-
-fn render_license<'a>(
- prefix: &str,
- names: impl Iterator<Item = &'a String>,
- license: Option<&License>,
- buffer: &mut Vec<u8>,
-) -> Result<(), Error> {
- for name in names {
- writeln!(buffer, "{prefix}**`{name}`** ")?;
- }
- if let Some(license) = license {
- writeln!(buffer, "{prefix}License: `{}`", license.spdx)?;
- for copyright in license.copyright.iter() {
- writeln!(buffer, "{prefix}Copyright: {copyright}")?;
- }
- }
-
- Ok(())
-}
-
+/// Describes a tree of metadata for our filesystem tree
#[derive(serde::Deserialize)]
struct Metadata {
files: Node,
}
-#[derive(serde::Deserialize)]
+/// Describes one node in our metadata tree
+#[derive(serde::Deserialize, rinja::Template)]
#[serde(rename_all = "kebab-case", tag = "type")]
+#[template(path = "Node.html")]
pub(crate) enum Node {
Root { children: Vec<Node> },
Directory { name: String, children: Vec<Node>, license: Option<License> },
@@ -80,12 +72,14 @@ pub(crate) enum Node {
Group { files: Vec<String>, directories: Vec<String>, license: License },
}
+/// A License has an SPDX license name and a list of copyright holders.
#[derive(serde::Deserialize)]
struct License {
spdx: String,
copyright: Vec<String>,
}
+/// Grab an environment variable as a PathBuf, or fail nicely.
fn env_path(var: &str) -> Result<PathBuf, Error> {
if let Some(var) = std::env::var_os(var) {
Ok(var.into())
diff --git a/src/tools/generate-copyright/templates/COPYRIGHT.html b/src/tools/generate-copyright/templates/COPYRIGHT.html
new file mode 100644
index 0000000..ccb177a
--- /dev/null
+++ b/src/tools/generate-copyright/templates/COPYRIGHT.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Copyright notices for The Rust Toolchain</title>
+</head>
+<body>
+
+<h1>Copyright notices for The Rust Toolchain</h1>
+
+<p>This file describes the copyright and licensing information for the source
+code within The Rust Project git tree, and the third-party dependencies used
+when building the Rust toolchain (including the Rust Standard Library).</p>
+
+<h2>Table of Contents</h2>
+<ul>
+ <li><a href="#in-tree-files">In-tree files</a></li>
+ <li><a href="#out-of-tree-dependencies">Out-of-tree dependencies</a></li>
+</ul>
+
+<h2 id="in-tree-files">In-tree files</h2>
+
+<p>The following licenses cover the in-tree source files that were used in this
+release:</p>
+
+{{ in_tree|safe }}
+
+<h2 id="out-of-tree-dependencies">Out-of-tree dependencies</h2>
+
+<p>The following licenses cover the out-of-tree crates that were used in this
+release:</p>
+
+{% for (key, value) in dependencies %}
+ <h3>📦 {{key.name}}-{{key.version}}</h3>
+ <p><b>URL:</b> <a href="https://crates.io/crates/{{ key.name }}/{{ key.version }}">https://crates.io/crates/{{ key.name }}/{{ key.version }}</a></p>
+ <p><b>In libstd:</b> {% if value.is_in_libstd.unwrap() %} Yes {% else %} No {% endif %}</p>
+ <p><b>Authors:</b> {{ value.authors|join(", ") }}</p>
+ <p><b>License:</b> {{ value.license }}</p>
+ {% let len = value.notices.len() %}
+ {% if len > 0 %}
+ <p><b>Notices:</b>
+ {% for (notice_name, notice_text) in value.notices %}
+ <details>
+ <summary><code>{{ notice_name }}</code></summary>
+ <pre>
+{{ notice_text }}
+ </pre>
+ </details>
+ {% endfor %}
+ </p>
+ {% endif %}
+{% endfor %}
+</body>
+</html>
\ No newline at end of file
diff --git a/src/tools/generate-copyright/templates/Node.html b/src/tools/generate-copyright/templates/Node.html
new file mode 100644
index 0000000..a71a1bf
--- /dev/null
+++ b/src/tools/generate-copyright/templates/Node.html
@@ -0,0 +1,71 @@
+{% match self %}
+
+{% when Node::Root { children } %}
+
+{% for child in children %}
+{{ child|safe }}
+{% endfor %}
+
+{% when Node::Directory { name, children, license } %}
+
+<div style="border:1px solid black; padding: 5px;">
+
+ <p>
+ <b>File/Directory:</b> <code>{{ name }}</code>
+ </p>
+
+ {% if let Some(license) = license %}
+
+ <p><b>License:</b> {{ license.spdx }}</p>
+ {% for copyright in license.copyright.iter() %}
+ <p><b>Copyright:</b> {{ copyright }}</p>
+ {% endfor %}
+
+ {% endif %}
+
+ {% if !children.is_empty() %}
+
+ <p><b>Exceptions:</b></p>
+ {% for child in children %}
+ {{ child|safe }}
+ {% endfor %}
+
+ {% endif %}
+
+</div>
+
+{% when Node::File { name, license } %}
+
+<div style="border:1px solid black; padding: 5px;">
+ <p>
+ <b>File/Directory:</b> <code>{{ name }}</code>
+ </p>
+
+ <p><b>License:</b> {{ license.spdx }}</p>
+ {% for copyright in license.copyright.iter() %}
+ <p><b>Copyright:</b> {{ copyright }}</p>
+ {% endfor %}
+</div>
+
+{% when Node::Group { files, directories, license } %}
+
+<div style="border:1px solid black; padding: 5px;">
+
+ <p>
+ <b>File/Directory:</b>
+ {% for name in files %}
+ <code>{{ name }}</code>
+ {% endfor %}
+ {% for name in directories %}
+ <code>{{ name }}</code>
+ {% endfor %}
+ </p>
+
+ <p><b>License:</b> {{ license.spdx }}</p>
+ {% for copyright in license.copyright.iter() %}
+ <p><b>Copyright:</b> {{ copyright }}</p>
+ {% endfor %}
+
+</div>
+
+{% endmatch %}
diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs
index 90fce2b..fe1b1bd 100644
--- a/src/tools/generate-windows-sys/src/main.rs
+++ b/src/tools/generate-windows-sys/src/main.rs
@@ -1,8 +1,7 @@
-use std::env;
use std::error::Error;
-use std::fs;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::PathBuf;
+use std::{env, fs};
/// 32-bit ARM is not supported by Microsoft so ARM types are not generated.
/// Therefore we need to inject a few types to make the bindings work.
diff --git a/src/tools/html-checker/main.rs b/src/tools/html-checker/main.rs
index e74f726..ecfbb195 100644
--- a/src/tools/html-checker/main.rs
+++ b/src/tools/html-checker/main.rs
@@ -1,8 +1,9 @@
-use rayon::iter::{ParallelBridge, ParallelIterator};
use std::env;
use std::path::Path;
use std::process::{Command, Output};
+use rayon::iter::{ParallelBridge, ParallelIterator};
+
fn check_html_file(file: &Path) -> usize {
let to_mute = &[
// "disabled" on <link> or "autocomplete" on <select> emit this warning
diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs
index 5f72bd1..9f95f9f 100644
--- a/src/tools/jsondocck/src/cache.rs
+++ b/src/tools/jsondocck/src/cache.rs
@@ -1,9 +1,10 @@
-use crate::config::Config;
-use serde_json::Value;
use std::collections::HashMap;
use std::path::Path;
use fs_err as fs;
+use serde_json::Value;
+
+use crate::config::Config;
#[derive(Debug)]
pub struct Cache {
diff --git a/src/tools/jsondocck/src/error.rs b/src/tools/jsondocck/src/error.rs
index 53b9af2..c4cd79a 100644
--- a/src/tools/jsondocck/src/error.rs
+++ b/src/tools/jsondocck/src/error.rs
@@ -1,7 +1,8 @@
-use crate::Command;
use std::error::Error;
use std::fmt;
+use crate::Command;
+
#[derive(Debug)]
pub enum CkError {
/// A check failed. File didn't exist or failed to match the command
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index de94990..b264405 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -1,10 +1,11 @@
-use jsonpath_lib::select;
-use regex::{Regex, RegexBuilder};
-use serde_json::Value;
use std::borrow::Cow;
use std::sync::OnceLock;
use std::{env, fmt, fs};
+use jsonpath_lib::select;
+use regex::{Regex, RegexBuilder};
+use serde_json::Value;
+
mod cache;
mod config;
mod error;
diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs
index 525de03..7d6ec47 100644
--- a/src/tools/jsondoclint/src/item_kind.rs
+++ b/src/tools/jsondoclint/src/item_kind.rs
@@ -13,7 +13,6 @@ pub(crate) enum Kind {
Variant,
Function,
TypeAlias,
- OpaqueTy,
Constant,
Trait,
TraitAlias,
@@ -55,7 +54,6 @@ pub fn can_appear_in_mod(self) -> bool {
// FIXME(adotinthevoid): I'm not sure if these are correct
Keyword => false,
- OpaqueTy => false,
ProcAttribute => false,
ProcDerive => false,
@@ -99,7 +97,6 @@ pub fn can_appear_in_trait(self) -> bool {
Kind::Enum => false,
Kind::Variant => false,
Kind::TypeAlias => false,
- Kind::OpaqueTy => false,
Kind::Constant => false,
Kind::Trait => false,
Kind::TraitAlias => false,
@@ -149,7 +146,6 @@ pub fn from_item(i: &Item) -> Self {
ItemEnum::TraitAlias(_) => TraitAlias,
ItemEnum::Impl(_) => Impl,
ItemEnum::TypeAlias(_) => TypeAlias,
- ItemEnum::OpaqueTy(_) => OpaqueTy,
ItemEnum::Constant { .. } => Constant,
ItemEnum::Static(_) => Static,
ItemEnum::Macro(_) => Macro,
@@ -177,7 +173,6 @@ pub fn from_summary(s: &ItemSummary) -> Self {
ItemKind::Keyword => Keyword,
ItemKind::Macro => Macro,
ItemKind::Module => Module,
- ItemKind::OpaqueTy => OpaqueTy,
ItemKind::Primitive => Primitive,
ItemKind::ProcAttribute => ProcAttribute,
ItemKind::ProcDerive => ProcDerive,
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index ea1e573..0ffb96b 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -3,13 +3,14 @@
use rustdoc_json_types::{
Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
- GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module,
- OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias,
- Type, TypeAlias, TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate,
+ GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, Path,
+ Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeAlias,
+ TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate,
};
use serde_json::Value;
-use crate::{item_kind::Kind, json_find, Error, ErrorKind};
+use crate::item_kind::Kind;
+use crate::{json_find, Error, ErrorKind};
// This is a rustc implementation detail that we rely on here
const LOCAL_CRATE_ID: u32 = 0;
@@ -100,7 +101,6 @@ fn check_item(&mut self, id: &'a Id) {
ItemEnum::TraitAlias(x) => self.check_trait_alias(x),
ItemEnum::Impl(x) => self.check_impl(x, id),
ItemEnum::TypeAlias(x) => self.check_type_alias(x),
- ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x),
ItemEnum::Constant { type_, const_ } => {
self.check_type(type_);
self.check_constant(const_);
@@ -229,11 +229,6 @@ fn check_type_alias(&mut self, x: &'a TypeAlias) {
self.check_type(&x.type_);
}
- fn check_opaque_ty(&mut self, x: &'a OpaqueTy) {
- x.bounds.iter().for_each(|b| self.check_generic_bound(b));
- self.check_generics(&x.generics);
- }
-
fn check_constant(&mut self, _x: &'a Constant) {
// nop
}
diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs
index ba0fe11..f28702d 100644
--- a/src/tools/jsondoclint/src/validator/tests.rs
+++ b/src/tools/jsondoclint/src/validator/tests.rs
@@ -1,9 +1,8 @@
use rustc_hash::FxHashMap;
use rustdoc_json_types::{Item, ItemKind, Visibility, FORMAT_VERSION};
-use crate::json_find::SelectorPart;
-
use super::*;
+use crate::json_find::SelectorPart;
#[track_caller]
fn check(krate: &Crate, errs: &[Error]) {
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 72ae3ed..72448c1 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -14,18 +14,18 @@
//! A few exceptions are allowed as there's known bugs in rustdoc, but this
//! should catch the majority of "broken link" cases.
-use html5ever::tendril::ByteTendril;
-use html5ever::tokenizer::{
- BufferQueue, TagToken, Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts,
-};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
-use std::env;
-use std::fs;
use std::io::ErrorKind;
use std::path::{Component, Path, PathBuf};
use std::rc::Rc;
use std::time::Instant;
+use std::{env, fs};
+
+use html5ever::tendril::ByteTendril;
+use html5ever::tokenizer::{
+ BufferQueue, TagToken, Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts,
+};
// Add linkcheck exceptions here
// If at all possible you should use intra-doc links to avoid linkcheck issues. These
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 0d827ab..78d4f87 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -1,10 +1,11 @@
-use crate::{Lint, LintExtractor};
use std::collections::{BTreeMap, BTreeSet};
use std::error::Error;
use std::fmt::Write;
use std::fs;
use std::process::Command;
+use crate::{Lint, LintExtractor};
+
/// Descriptions of rustc lint groups.
static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
("unused", "Lints that detect things being declared but not used, or excess syntax"),
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index 48e2dd0..e0aef13 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -3,6 +3,7 @@
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
+
use walkdir::WalkDir;
mod groups;
diff --git a/src/tools/lld-wrapper/src/main.rs b/src/tools/lld-wrapper/src/main.rs
index 79e279a..2f756ae 100644
--- a/src/tools/lld-wrapper/src/main.rs
+++ b/src/tools/lld-wrapper/src/main.rs
@@ -11,7 +11,8 @@
//! obtained from the wrapper's name as the first two arguments.
//! On Windows it spawns a `..\rust-lld.exe` child process.
-use std::env::{self, consts::EXE_SUFFIX};
+use std::env::consts::EXE_SUFFIX;
+use std::env::{self};
use std::fmt::Display;
use std::path::{Path, PathBuf};
use std::process;
diff --git a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
index a92af71..fdbf617 100644
--- a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
+++ b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
@@ -1,7 +1,6 @@
use std::path::PathBuf;
use clap::Parser;
-
use llvm_bitcode_linker::{Optimization, Session, Target};
#[derive(Debug, Parser)]
diff --git a/src/tools/llvm-bitcode-linker/src/linker.rs b/src/tools/llvm-bitcode-linker/src/linker.rs
index 40572f2..9f579d1 100644
--- a/src/tools/llvm-bitcode-linker/src/linker.rs
+++ b/src/tools/llvm-bitcode-linker/src/linker.rs
@@ -2,8 +2,7 @@
use anyhow::Context;
-use crate::Optimization;
-use crate::Target;
+use crate::{Optimization, Target};
#[derive(Debug)]
pub struct Session {
diff --git a/src/tools/llvm-bitcode-linker/src/opt.rs b/src/tools/llvm-bitcode-linker/src/opt.rs
index 93f0ec7..12692c4 100644
--- a/src/tools/llvm-bitcode-linker/src/opt.rs
+++ b/src/tools/llvm-bitcode-linker/src/opt.rs
@@ -1,5 +1,4 @@
-use std::fmt::Display;
-use std::fmt::Formatter;
+use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, Copy, Default, Hash, Eq, PartialEq, clap::ValueEnum)]
pub enum Optimization {
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 417ecb0..e4bfd9b 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -58,9 +58,9 @@
[[package]]
name = "anyhow"
-version = "1.0.82"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "autocfg"
@@ -85,15 +85,15 @@
[[package]]
name = "bitflags"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bstr"
-version = "1.9.1"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
dependencies = [
"memchr",
"regex-automata",
@@ -101,10 +101,16 @@
]
[[package]]
-name = "camino"
-version = "1.1.6"
+name = "byteorder"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
+[[package]]
+name = "camino"
+version = "1.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
dependencies = [
"serde",
]
@@ -134,9 +140,9 @@
[[package]]
name = "cc"
-version = "1.0.96"
+version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
+checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
[[package]]
name = "cfg-if"
@@ -258,18 +264,18 @@
[[package]]
name = "crossbeam-channel"
-version = "0.5.12"
+version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.19"
+version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crypto-common"
@@ -320,9 +326,9 @@
[[package]]
name = "errno"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
@@ -356,9 +362,9 @@
[[package]]
name = "getrandom"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
@@ -401,9 +407,9 @@
[[package]]
name = "instant"
-version = "0.1.12"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
]
@@ -426,9 +432,9 @@
[[package]]
name = "lazy_static"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "levenshtein"
@@ -438,9 +444,9 @@
[[package]]
name = "libc"
-version = "0.2.154"
+version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libffi"
@@ -463,12 +469,12 @@
[[package]]
name = "libloading"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
+checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
- "windows-targets 0.52.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -483,9 +489,9 @@
[[package]]
name = "linux-raw-sys"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "lock_api"
@@ -499,9 +505,9 @@
[[package]]
name = "log"
-version = "0.4.21"
+version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "measureme"
@@ -519,9 +525,9 @@
[[package]]
name = "memchr"
-version = "2.7.2"
+version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "memmap2"
@@ -534,9 +540,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.7.2"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
]
@@ -563,6 +569,7 @@
"smallvec",
"tempfile",
"ui_test",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -630,9 +637,9 @@
[[package]]
name = "parking_lot"
-version = "0.12.2"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -648,7 +655,7 @@
"libc",
"redox_syscall",
"smallvec",
- "windows-targets 0.52.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -715,15 +722,18 @@
[[package]]
name = "portable-atomic"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
+checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
[[package]]
name = "ppv-lite86"
-version = "0.2.17"
+version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
[[package]]
name = "prettydiff"
@@ -737,9 +747,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.81"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
@@ -785,9 +795,9 @@
[[package]]
name = "redox_syscall"
-version = "0.5.1"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
+checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
dependencies = [
"bitflags",
]
@@ -805,9 +815,9 @@
[[package]]
name = "regex"
-version = "1.10.4"
+version = "1.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
dependencies = [
"aho-corasick",
"memchr",
@@ -817,9 +827,9 @@
[[package]]
name = "regex-automata"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
@@ -828,15 +838,15 @@
[[package]]
name = "regex-syntax"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rustc-demangle"
-version = "0.1.23"
+version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc-hash"
@@ -880,9 +890,9 @@
[[package]]
name = "ryu"
-version = "1.0.17"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
@@ -892,27 +902,27 @@
[[package]]
name = "semver"
-version = "1.0.22"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
dependencies = [
"serde",
]
[[package]]
name = "serde"
-version = "1.0.200"
+version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
+checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.200"
+version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
+checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote",
@@ -921,11 +931,12 @@
[[package]]
name = "serde_json"
-version = "1.0.116"
+version = "1.0.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
+checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
dependencies = [
"itoa",
+ "memchr",
"ryu",
"serde",
]
@@ -953,9 +964,9 @@
[[package]]
name = "syn"
-version = "2.0.60"
+version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [
"proc-macro2",
"quote",
@@ -964,30 +975,31 @@
[[package]]
name = "tempfile"
-version = "3.10.1"
+version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53"
dependencies = [
"cfg-if",
"fastrand",
+ "once_cell",
"rustix",
"windows-sys 0.52.0",
]
[[package]]
name = "thiserror"
-version = "1.0.59"
+version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
+checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.59"
+version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
+checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
@@ -1086,9 +1098,9 @@
[[package]]
name = "unicode-width"
-version = "0.1.12"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
+checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]]
name = "valuable"
@@ -1098,9 +1110,9 @@
[[package]]
name = "version_check"
-version = "0.9.4"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
@@ -1145,7 +1157,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.52.5",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -1165,18 +1177,18 @@
[[package]]
name = "windows-targets"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm 0.52.5",
- "windows_aarch64_msvc 0.52.5",
- "windows_i686_gnu 0.52.5",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
- "windows_i686_msvc 0.52.5",
- "windows_x86_64_gnu 0.52.5",
- "windows_x86_64_gnullvm 0.52.5",
- "windows_x86_64_msvc 0.52.5",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
]
[[package]]
@@ -1187,9 +1199,9 @@
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
@@ -1199,9 +1211,9 @@
[[package]]
name = "windows_aarch64_msvc"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
@@ -1211,15 +1223,15 @@
[[package]]
name = "windows_i686_gnu"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
@@ -1229,9 +1241,9 @@
[[package]]
name = "windows_i686_msvc"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
@@ -1241,9 +1253,9 @@
[[package]]
name = "windows_x86_64_gnu"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -1253,9 +1265,9 @@
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
@@ -1265,9 +1277,9 @@
[[package]]
name = "windows_x86_64_msvc"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "yansi-term"
@@ -1277,3 +1289,24 @@
dependencies = [
"winapi",
]
+
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 976bd08..e12f3f9 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -9,12 +9,12 @@
edition = "2021"
[lib]
-test = true # we have unit tests
+test = true # we have unit tests
doctest = false # but no doc tests
[[bin]]
name = "miri"
-test = false # we have no unit tests
+test = false # we have no unit tests
doctest = false # and no doc tests
[dependencies]
@@ -42,6 +42,13 @@
libffi = "3.2.0"
libloading = "0.8"
+[target.'cfg(target_family = "windows")'.dependencies]
+windows-sys = { version = "0.52", features = [
+ "Win32_Foundation",
+ "Win32_System_IO",
+ "Win32_Storage_FileSystem",
+] }
+
[dev-dependencies]
colored = "2"
ui_test = "0.21.1"
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index b1be596..a0bff38 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -212,7 +212,6 @@
- All Rust [Tier 1 targets](https://doc.rust-lang.org/rustc/platform-support.html) are supported by
Miri. They are all checked on Miri's CI, and some (at least one per OS) are even checked on every
Rust PR, so the shipped Miri should always work on these targets.
-- `aarch64-apple-darwin` is supported.
- `s390x-unknown-linux-gnu` is supported as our "big-endian target of choice".
- For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we
make no promises and we don't run tests for such targets.
@@ -398,6 +397,8 @@
application instead of raising an error within the context of Miri (and halting
execution). Note that code might not expect these operations to ever panic, so
this flag can lead to strange (mis)behavior.
+* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking
+ recurse below references.
* `-Zmiri-retag-fields[=<all|none|scalar>]` controls when Stacked Borrows retagging recurses into
fields. `all` means it always recurses (the default, and equivalent to `-Zmiri-retag-fields`
without an explicit value), `none` means it never recurses, `scalar` means it only recurses for
@@ -474,6 +475,19 @@
Miri-specific functionality. They are declared in
[/tests/utils/miri\_extern.rs](/tests/utils/miri_extern.rs).
+## Entry point for no-std binaries
+
+Binaries that do not use the standard library are expected to declare a function like this so that
+Miri knows where it is supposed to start execution:
+
+```rust
+#[cfg(miri)]
+#[no_mangle]
+fn miri_start(argc: isize, argv: *const *const u8) -> isize {
+ // Call the actual start function that your project implements, based on your target's conventions.
+}
+```
+
## Contributing and getting help
If you want to contribute to Miri, great! Please check out our
diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock
index 8bd8f10..7369a3f 100644
--- a/src/tools/miri/cargo-miri/Cargo.lock
+++ b/src/tools/miri/cargo-miri/Cargo.lock
@@ -4,21 +4,21 @@
[[package]]
name = "anyhow"
-version = "1.0.82"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "bitflags"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "camino"
-version = "1.1.6"
+version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
+checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
dependencies = [
"serde",
]
@@ -88,9 +88,9 @@
[[package]]
name = "errno"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
@@ -104,9 +104,9 @@
[[package]]
name = "getrandom"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
@@ -121,9 +121,9 @@
[[package]]
name = "libc"
-version = "0.2.154"
+version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libredox"
@@ -137,9 +137,21 @@
[[package]]
name = "linux-raw-sys"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "option-ext"
@@ -149,9 +161,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.81"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
@@ -178,9 +190,9 @@
[[package]]
name = "rustc-build-sysroot"
-version = "0.5.2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa3ca63cc537c1cb69e4c2c0afc5fda2ccd36ac84c97d5a4ae05e69b1c834afb"
+checksum = "2471f8f296262437d7e848e527b4210b44a96e53a3b4435b890227ce3e6da106"
dependencies = [
"anyhow",
"rustc_version",
@@ -218,9 +230,9 @@
[[package]]
name = "ryu"
-version = "1.0.17"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
@@ -233,27 +245,27 @@
[[package]]
name = "semver"
-version = "1.0.22"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
+checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
dependencies = [
"serde",
]
[[package]]
name = "serde"
-version = "1.0.200"
+version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
+checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.200"
+version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
+checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote",
@@ -262,20 +274,21 @@
[[package]]
name = "serde_json"
-version = "1.0.116"
+version = "1.0.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813"
+checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
dependencies = [
"itoa",
+ "memchr",
"ryu",
"serde",
]
[[package]]
name = "syn"
-version = "2.0.60"
+version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [
"proc-macro2",
"quote",
@@ -284,30 +297,31 @@
[[package]]
name = "tempfile"
-version = "3.10.1"
+version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53"
dependencies = [
"cfg-if",
"fastrand",
+ "once_cell",
"rustix",
"windows-sys 0.52.0",
]
[[package]]
name = "thiserror"
-version = "1.0.59"
+version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
+checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.59"
+version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
+checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
@@ -338,11 +352,11 @@
[[package]]
name = "winapi-util"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
+checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -360,7 +374,16 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.52.5",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets 0.52.6",
]
[[package]]
@@ -380,18 +403,18 @@
[[package]]
name = "windows-targets"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm 0.52.5",
- "windows_aarch64_msvc 0.52.5",
- "windows_i686_gnu 0.52.5",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
- "windows_i686_msvc 0.52.5",
- "windows_x86_64_gnu 0.52.5",
- "windows_x86_64_gnullvm 0.52.5",
- "windows_x86_64_msvc 0.52.5",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
]
[[package]]
@@ -402,9 +425,9 @@
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
@@ -414,9 +437,9 @@
[[package]]
name = "windows_aarch64_msvc"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
@@ -426,15 +449,15 @@
[[package]]
name = "windows_i686_gnu"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
@@ -444,9 +467,9 @@
[[package]]
name = "windows_i686_msvc"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
@@ -456,9 +479,9 @@
[[package]]
name = "windows_x86_64_gnu"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -468,9 +491,9 @@
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
@@ -480,6 +503,6 @@
[[package]]
name = "windows_x86_64_msvc"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml
index 6acdbc4..477c60d 100644
--- a/src/tools/miri/cargo-miri/Cargo.toml
+++ b/src/tools/miri/cargo-miri/Cargo.toml
@@ -18,7 +18,7 @@
rustc_version = "0.4"
serde_json = "1.0.40"
cargo_metadata = "0.18.0"
-rustc-build-sysroot = "0.5.2"
+rustc-build-sysroot = "0.5.3"
# Enable some feature flags that dev-dependencies need but dependencies
# do not. This makes `./miri install` after `./miri build` faster.
diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs
index fe67aad..0cf6f1a 100644
--- a/src/tools/miri/cargo-miri/src/setup.rs
+++ b/src/tools/miri/cargo-miri/src/setup.rs
@@ -100,7 +100,10 @@ pub fn setup(
// for target crates.
let cargo_miri_path = std::env::current_exe().expect("current executable path invalid");
if env::var_os("RUSTC_STAGE").is_some() {
- assert!(env::var_os("RUSTC").is_some());
+ assert!(
+ env::var_os("RUSTC").is_some() && env::var_os("RUSTC_WRAPPER").is_some(),
+ "cargo-miri setup is running inside rustc bootstrap but RUSTC or RUST_WRAPPER is not set"
+ );
command.env("RUSTC_REAL", &cargo_miri_path);
} else {
command.env("RUSTC", &cargo_miri_path);
diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh
index 5e75638..3e90ecc 100755
--- a/src/tools/miri/ci/ci.sh
+++ b/src/tools/miri/ci/ci.sh
@@ -137,7 +137,7 @@
MANY_SEEDS=16 TEST_TARGET=x86_64-pc-windows-gnu run_tests
;;
aarch64-apple-darwin)
- # Host (tier 2)
+ # Host
GC_STRESS=1 MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests
# Extra tier 1
MANY_SEEDS=64 TEST_TARGET=i686-pc-windows-gnu run_tests
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index 62a3ab2..fc20504 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -355,7 +355,10 @@ fn rustc_push(github_user: String, branch: String) -> Result<()> {
let head = cmd!(sh, "git rev-parse HEAD").read()?;
let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?;
if head != fetch_head {
- bail!("Josh created a non-roundtrip push! Do NOT merge this into rustc!");
+ bail!(
+ "Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\
+ Expected {head}, got {fetch_head}."
+ );
}
println!(
"Confirmed that the push round-trips back to Miri properly. Please create a rustc PR:"
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index e90d373..b74f975 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-99b7134389e9766462601a2fc4013840b9d31745
+29e924841f06bb181d87494eba2783761bc1ddec
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index d0f977f..ed955e7 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -11,7 +11,7 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_span::Span;
-use rustc_target::abi::{Align, HasDataLayout, Size};
+use rustc_target::abi::{Align, Size};
use crate::{concurrency::VClock, *};
@@ -105,15 +105,17 @@ impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Returns the exposed `AllocId` that corresponds to the specified addr,
// or `None` if the addr is out of bounds
- fn alloc_id_from_addr(&self, addr: u64) -> Option<AllocId> {
+ fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option<AllocId> {
let ecx = self.eval_context_ref();
let global_state = ecx.machine.alloc_addresses.borrow();
assert!(global_state.provenance_mode != ProvenanceMode::Strict);
+ // We always search the allocation to the right of this address. So if the size is structly
+ // negative, we have to search for `addr-1` instead.
+ let addr = if size >= 0 { addr } else { addr.saturating_sub(1) };
let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr);
// Determine the in-bounds provenance for this pointer.
- // (This is only called on an actual access, so in-bounds is the only possible kind of provenance.)
let alloc_id = match pos {
Ok(pos) => Some(global_state.int_to_ptr_map[pos].1),
Err(0) => None,
@@ -305,20 +307,24 @@ fn adjust_alloc_root_pointer(
let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
let alloc_id = prov.alloc_id();
- let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?;
- // Add offset with the right kind of pointer-overflowing arithmetic.
- let dl = ecx.data_layout();
- let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0;
- Ok(interpret::Pointer::new(
+ // Get a pointer to the beginning of this allocation.
+ let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?;
+ let base_ptr = interpret::Pointer::new(
Provenance::Concrete { alloc_id, tag },
- Size::from_bytes(absolute_addr),
- ))
+ Size::from_bytes(base_addr),
+ );
+ // Add offset with the right kind of pointer-overflowing arithmetic.
+ Ok(base_ptr.wrapping_offset(offset, ecx))
}
/// When a pointer is used for a memory access, this computes where in which allocation the
/// access is going.
- fn ptr_get_alloc(&self, ptr: interpret::Pointer<Provenance>) -> Option<(AllocId, Size)> {
+ fn ptr_get_alloc(
+ &self,
+ ptr: interpret::Pointer<Provenance>,
+ size: i64,
+ ) -> Option<(AllocId, Size)> {
let ecx = self.eval_context_ref();
let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
@@ -327,7 +333,7 @@ fn ptr_get_alloc(&self, ptr: interpret::Pointer<Provenance>) -> Option<(AllocId,
alloc_id
} else {
// A wildcard pointer.
- ecx.alloc_id_from_addr(addr.bytes())?
+ ecx.alloc_id_from_addr(addr.bytes(), size)?
};
// This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
@@ -335,12 +341,8 @@ fn ptr_get_alloc(&self, ptr: interpret::Pointer<Provenance>) -> Option<(AllocId,
let base_addr = *ecx.machine.alloc_addresses.borrow().base_addr.get(&alloc_id).unwrap();
// Wrapping "addr - base_addr"
- #[allow(clippy::cast_possible_wrap)] // we want to wrap here
- let neg_base_addr = (base_addr as i64).wrapping_neg();
- Some((
- alloc_id,
- Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0),
- ))
+ let rel_offset = ecx.truncate_to_target_usize(addr.bytes().wrapping_sub(base_addr));
+ Some((alloc_id, Size::from_bytes(rel_offset)))
}
}
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 9f3fa07..e13e54c 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -14,11 +14,14 @@
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_hir;
+extern crate rustc_hir_analysis;
extern crate rustc_interface;
extern crate rustc_log;
extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_session;
+extern crate rustc_span;
+extern crate rustc_target;
use std::env::{self, VarError};
use std::num::NonZero;
@@ -29,7 +32,9 @@
use rustc_data_structures::sync::Lrc;
use rustc_driver::Compilation;
+use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::{self as hir, Node};
+use rustc_hir_analysis::check::check_function_signature;
use rustc_interface::interface::Config;
use rustc_middle::{
middle::{
@@ -37,14 +42,17 @@
exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel},
},
query::LocalCrate,
- ty::TyCtxt,
+ traits::{ObligationCause, ObligationCauseCode},
+ ty::{self, Ty, TyCtxt},
util::Providers,
};
-use rustc_session::config::{CrateType, ErrorOutputType, OptLevel};
+use rustc_session::config::{CrateType, EntryFnType, ErrorOutputType, OptLevel};
use rustc_session::search_paths::PathKind;
use rustc_session::{CtfeBacktrace, EarlyDiagCtxt};
+use rustc_span::def_id::DefId;
+use rustc_target::spec::abi::Abi;
-use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields};
+use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields, ValidationMode};
struct MiriCompilerCalls {
miri_config: miri::MiriConfig,
@@ -82,11 +90,7 @@ fn after_analysis<'tcx>(
tcx.dcx().fatal("miri only makes sense on bin crates");
}
- let (entry_def_id, entry_type) = if let Some(entry_def) = tcx.entry_fn(()) {
- entry_def
- } else {
- tcx.dcx().fatal("miri can only run programs that have a main function");
- };
+ let (entry_def_id, entry_type) = entry_fn(tcx);
let mut config = self.miri_config.clone();
// Add filename to `miri` arguments.
@@ -351,6 +355,56 @@ fn jemalloc_magic() {
}
}
+fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, EntryFnType) {
+ if let Some(entry_def) = tcx.entry_fn(()) {
+ return entry_def;
+ }
+ // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point.
+ let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
+ if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None }
+ });
+ if let Some(ExportedSymbol::NonGeneric(id)) = sym {
+ let start_def_id = id.expect_local();
+ let start_span = tcx.def_span(start_def_id);
+
+ let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
+ [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
+ tcx.types.isize,
+ false,
+ hir::Safety::Safe,
+ Abi::Rust,
+ ));
+
+ let correct_func_sig = check_function_signature(
+ tcx,
+ ObligationCause::new(start_span, start_def_id, ObligationCauseCode::Misc),
+ *id,
+ expected_sig,
+ )
+ .is_ok();
+
+ if correct_func_sig {
+ (*id, EntryFnType::Start)
+ } else {
+ tcx.dcx().fatal(
+ "`miri_start` must have the following signature:\n\
+ fn miri_start(argc: isize, argv: *const *const u8) -> isize",
+ );
+ }
+ } else {
+ tcx.dcx().fatal(
+ "Miri can only run programs that have a main function.\n\
+ Alternatively, you can export a `miri_start` function:\n\
+ \n\
+ #[cfg(miri)]\n\
+ #[no_mangle]\n\
+ fn miri_start(argc: isize, argv: *const *const u8) -> isize {\
+ \n // Call the actual start function that your project implements, based on your target's conventions.\n\
+ }"
+ );
+ }
+}
+
fn main() {
#[cfg(any(target_os = "linux", target_os = "macos"))]
jemalloc_magic();
@@ -421,7 +475,9 @@ fn main() {
} else if arg == "--" {
after_dashdash = true;
} else if arg == "-Zmiri-disable-validation" {
- miri_config.validate = false;
+ miri_config.validation = ValidationMode::No;
+ } else if arg == "-Zmiri-recursive-validation" {
+ miri_config.validation = ValidationMode::Deep;
} else if arg == "-Zmiri-disable-stacked-borrows" {
miri_config.borrow_tracker = None;
} else if arg == "-Zmiri-tree-borrows" {
@@ -620,6 +676,14 @@ fn main() {
"-Zmiri-unique-is-unique only has an effect when -Zmiri-tree-borrows is also used"
);
}
+ // Tree Borrows + permissive provenance does not work.
+ if miri_config.provenance_mode == ProvenanceMode::Permissive
+ && matches!(miri_config.borrow_tracker, Some(BorrowTrackerMethod::TreeBorrows))
+ {
+ show_error!(
+ "Tree Borrows does not support integer-to-pointer casts, and is hence not compatible with permissive provenance"
+ );
+ }
debug!("rustc arguments: {:?}", rustc_args);
debug!("crate arguments: {:?}", miri_config.args);
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index c9e7e30..d537a7f 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -232,6 +232,10 @@ pub fn root_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_>) -> BorTag
pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_>) {
self.root_ptr_tags.retain(|id, _| allocs.is_live(*id));
}
+
+ pub fn borrow_tracker_method(&self) -> BorrowTrackerMethod {
+ self.borrow_tracker_method
+ }
}
/// Which borrow tracking method to use
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 603733f..fc2b3f9 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -5,6 +5,7 @@
mod item;
mod stack;
+use std::cell::RefCell;
use std::cmp;
use std::fmt::Write;
use std::mem;
@@ -672,7 +673,8 @@ fn sb_reborrow(
// attempt to use it for a non-zero-sized access.
// Dangling slices are a common case here; it's valid to get their length but with raw
// pointer tagging for example all calls to get_unchecked on them are invalid.
- if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr()) {
+ if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr(), 0)
+ {
log_creation(this, Some((alloc_id, base_offset, orig_tag)))?;
// Still give it the new provenance, it got retagged after all.
return Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag }));
@@ -684,7 +686,7 @@ fn sb_reborrow(
}
}
- let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr())?;
+ let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr(), 0)?;
log_creation(this, Some((alloc_id, base_offset, orig_tag)))?;
trace!(
@@ -820,7 +822,19 @@ fn sb_retag_place(
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/276.
let size = match size {
Some(size) => size,
- None => return Ok(place.clone()),
+ None => {
+ // The first time this happens, show a warning.
+ thread_local! { static WARNING_SHOWN: RefCell<bool> = const { RefCell::new(false) }; }
+ WARNING_SHOWN.with_borrow_mut(|shown| {
+ if *shown {
+ return;
+ }
+ // Not yet shown. Show it!
+ *shown = true;
+ this.emit_diagnostic(NonHaltingDiagnostic::ExternTypeReborrow);
+ });
+ return Ok(place.clone());
+ }
};
// Compute new borrow.
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 8607438..44f42d5 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -141,8 +141,15 @@ fn from_ref_ty(
) -> Option<Self> {
let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env());
let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env());
+ let is_protected = kind == RetagKind::FnEntry;
+ // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`,
+ // interior mutability and protectors interact poorly.
+ // To eliminate the case of Protected Reserved IM we override interior mutability
+ // in the case of a protected reference: protected references are always considered
+ // "freeze".
let initial_state = match mutability {
- Mutability::Mut if ty_is_unpin => Permission::new_reserved(ty_is_freeze),
+ Mutability::Mut if ty_is_unpin =>
+ Permission::new_reserved(ty_is_freeze || is_protected),
Mutability::Not if ty_is_freeze => Permission::new_frozen(),
// Raw pointers never enter this function so they are not handled.
// However raw pointers are not the only pointers that take the parent
@@ -151,7 +158,7 @@ fn from_ref_ty(
_ => return None,
};
- let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
+ let protector = is_protected.then_some(ProtectorKind::StrongProtector);
Some(Self { zero_size: false, initial_state, protector })
}
@@ -216,7 +223,7 @@ fn tb_reborrow(
};
trace!("Reborrow of size {:?}", ptr_size);
- let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr()) {
+ let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr(), 0) {
Ok(data) => {
// Unlike SB, we *do* a proper retag for size 0 if can identify the allocation.
// After all, the pointer may be lazily initialized outside this initial range.
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
index 7aa9c3e..8e23257 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
@@ -22,6 +22,11 @@ enum PermissionPriv {
/// - foreign-read then child-write is UB due to `conflicted`,
/// - child-write then foreign-read is UB since child-write will activate and then
/// foreign-read disables a protected `Active`, which is UB.
+ ///
+ /// Note: since the discovery of `tests/fail/tree_borrows/reservedim_spurious_write.rs`,
+ /// `ty_is_freeze` does not strictly mean that the type has no interior mutability,
+ /// it could be an interior mutable type that lost its interior mutability privileges
+ /// when retagged with a protector.
Reserved { ty_is_freeze: bool, conflicted: bool },
/// represents: a unique pointer;
/// allows: child reads, child writes;
@@ -141,6 +146,12 @@ fn child_write(state: PermissionPriv, protected: bool) -> Option<PermissionPriv>
/// non-protected interior mutable `Reserved` which stay the same.
fn foreign_write(state: PermissionPriv, protected: bool) -> Option<PermissionPriv> {
Some(match state {
+ // FIXME: since the fix related to reservedim_spurious_write, it is now possible
+ // to express these transitions of the state machine without an explicit dependency
+ // on `protected`: because `ty_is_freeze: false` implies `!protected` then
+ // the line handling `Reserved { .. } if protected` could be deleted.
+ // This will however require optimizations to the exhaustive tests because
+ // fewer initial conditions are valid.
Reserved { .. } if protected => Disabled,
res @ Reserved { ty_is_freeze: false, .. } => res,
_ => Disabled,
diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs
index 2baa09b..9df0d95 100644
--- a/src/tools/miri/src/concurrency/data_race.rs
+++ b/src/tools/miri/src/concurrency/data_race.rs
@@ -1180,7 +1180,7 @@ fn atomic_access_check(
// We avoid `get_ptr_alloc` since we do *not* want to run the access hooks -- the actual
// access will happen later.
let (alloc_id, _offset, _prov) = this
- .ptr_try_get_alloc_id(place.ptr())
+ .ptr_try_get_alloc_id(place.ptr(), 0)
.expect("there are no zero-sized atomic accesses");
if this.get_alloc_mutability(alloc_id)? == Mutability::Not {
// See if this is fine.
@@ -1307,7 +1307,7 @@ fn validate_atomic_op<A: Debug + Copy>(
if let Some(data_race) = &this.machine.data_race {
if data_race.race_detecting() {
let size = place.layout.size;
- let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr())?;
+ let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr(), 0)?;
// Load and log the atomic operation.
// Note that atomic loads are possible even from read-only allocations, so `get_alloc_extra_mut` is not an option.
let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap();
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index a53dd7e..f72591f 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -256,7 +256,7 @@ pub struct Thread<'tcx> {
/// which then forwards it to 'Resume'. However this argument is implicit in MIR,
/// so we have to store it out-of-band. When there are multiple active unwinds,
/// the innermost one is always caught first, so we can store them as a stack.
- pub(crate) panic_payloads: Vec<Scalar>,
+ pub(crate) panic_payloads: Vec<ImmTy<'tcx>>,
/// Last OS error location in memory. It is a 32-bit integer.
pub(crate) last_error: Option<MPlaceTy<'tcx>>,
@@ -377,10 +377,6 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
return_place,
locals,
extra,
- body: _,
- instance: _,
- return_to_block: _,
- loc: _,
// There are some private fields we cannot access; they contain no tags.
..
} = self;
@@ -952,7 +948,7 @@ fn start_regular_thread(
this.call_function(
instance,
start_abi,
- &[*func_arg],
+ &[func_arg],
Some(&ret_place),
StackPopCleanup::Root { cleanup: true },
)?;
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index e92eaa8..6f41715 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -468,7 +468,7 @@ fn buffered_atomic_rmw(
init: Scalar,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
- let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
+ let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?;
if let (
crate::AllocExtra { weak_memory: Some(alloc_buffers), .. },
crate::MiriMachine { data_race: Some(global), threads, .. },
@@ -495,7 +495,7 @@ fn buffered_atomic_read(
) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_ref();
if let Some(global) = &this.machine.data_race {
- let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
+ let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?;
if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() {
if atomic == AtomicReadOrd::SeqCst {
global.sc_read(&this.machine.threads);
@@ -535,7 +535,7 @@ fn buffered_atomic_write(
init: Scalar,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
- let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr())?;
+ let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr(), 0)?;
if let (
crate::AllocExtra { weak_memory: Some(alloc_buffers), .. },
crate::MiriMachine { data_race: Some(global), threads, .. },
@@ -585,7 +585,7 @@ fn perform_read_on_buffered_latest(
global.sc_read(&this.machine.threads);
}
let size = place.layout.size;
- let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?;
+ let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?;
if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() {
let buffer = alloc_buffers
.get_or_create_store_buffer(alloc_range(base_offset, size), init)?;
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 647d7d4..1bed557 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -130,6 +130,7 @@ pub enum NonHaltingDiagnostic {
WeakMemoryOutdatedLoad {
ptr: Pointer,
},
+ ExternTypeReborrow,
}
/// Level of Miri specific diagnostics
@@ -139,6 +140,15 @@ pub enum DiagLevel {
Note,
}
+/// Generate a note/help text without a span.
+macro_rules! note {
+ ($($tt:tt)*) => { (None, format!($($tt)*)) };
+}
+/// Generate a note/help text with a span.
+macro_rules! note_span {
+ ($span:expr, $($tt:tt)*) => { (Some($span), format!($($tt)*)) };
+}
+
/// Attempts to prune a stacktrace to omit the Rust runtime, and returns a bool indicating if any
/// frames were pruned. If the stacktrace does not have any local frames, we conclude that it must
/// be pointing to a problem in the Rust runtime itself, and do not prune it at all.
@@ -227,38 +237,38 @@ pub fn report_error<'tcx>(
let helps = match info {
UnsupportedInIsolation(_) =>
vec![
- (None, format!("set `MIRIFLAGS=-Zmiri-disable-isolation` to disable isolation;")),
- (None, format!("or set `MIRIFLAGS=-Zmiri-isolation-error=warn` to make Miri return an error code from isolated operations (if supported for that operation) and continue with a warning")),
+ note!("set `MIRIFLAGS=-Zmiri-disable-isolation` to disable isolation;"),
+ note!("or set `MIRIFLAGS=-Zmiri-isolation-error=warn` to make Miri return an error code from isolated operations (if supported for that operation) and continue with a warning"),
],
UnsupportedForeignItem(_) => {
vec![
- (None, format!("if this is a basic API commonly used on this target, please report an issue with Miri")),
- (None, format!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases")),
+ note!("if this is a basic API commonly used on this target, please report an issue with Miri"),
+ note!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases"),
]
}
StackedBorrowsUb { help, history, .. } => {
msg.extend(help.clone());
let mut helps = vec![
- (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental")),
- (None, format!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information")),
+ note!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental"),
+ note!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information"),
];
if let Some(TagHistory {created, invalidated, protected}) = history.clone() {
helps.push((Some(created.1), created.0));
if let Some((msg, span)) = invalidated {
- helps.push((Some(span), msg));
+ helps.push(note_span!(span, "{msg}"));
}
if let Some((protector_msg, protector_span)) = protected {
- helps.push((Some(protector_span), protector_msg));
+ helps.push(note_span!(protector_span, "{protector_msg}"));
}
}
helps
},
TreeBorrowsUb { title: _, details, history } => {
let mut helps = vec![
- (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental"))
+ note!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental")
];
for m in details {
- helps.push((None, m.clone()));
+ helps.push(note!("{m}"));
}
for event in history.events.clone() {
helps.push(event);
@@ -267,26 +277,26 @@ pub fn report_error<'tcx>(
}
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
vec![
- (Some(*first), format!("it's first defined here, in crate `{first_crate}`")),
- (Some(*second), format!("then it's defined here again, in crate `{second_crate}`")),
+ note_span!(*first, "it's first defined here, in crate `{first_crate}`"),
+ note_span!(*second, "then it's defined here again, in crate `{second_crate}`"),
],
SymbolShimClashing { link_name, span } =>
- vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
+ vec![note_span!(*span, "the `{link_name}` symbol is defined here")],
Int2PtrWithStrictProvenance =>
- vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
+ vec![note!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead")],
DataRace { op1, extra, retag_explain, .. } => {
- let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))];
+ let mut helps = vec![note_span!(op1.span, "and (1) occurred earlier here")];
if let Some(extra) = extra {
- helps.push((None, format!("{extra}")));
- helps.push((None, format!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model")));
+ helps.push(note!("{extra}"));
+ helps.push(note!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model"));
}
if *retag_explain {
- helps.push((None, "retags occur on all (re)borrows and as well as when references are copied or moved".to_owned()));
- helps.push((None, "retags permit optimizations that insert speculative reads or writes".to_owned()));
- helps.push((None, "therefore from the perspective of data races, a retag has the same implications as a read or write".to_owned()));
+ helps.push(note!("retags occur on all (re)borrows and as well as when references are copied or moved"));
+ helps.push(note!("retags permit optimizations that insert speculative reads or writes"));
+ helps.push(note!("therefore from the perspective of data races, a retag has the same implications as a read or write"));
}
- helps.push((None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")));
- helps.push((None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")));
+ helps.push(note!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"));
+ helps.push(note!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"));
helps
}
,
@@ -331,32 +341,32 @@ pub fn report_error<'tcx>(
let helps = match e.kind() {
Unsupported(_) =>
vec![
- (None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support")),
+ note!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support"),
],
UndefinedBehavior(AlignmentCheckFailed { .. })
if ecx.machine.check_alignment == AlignmentCheck::Symbolic
=>
vec![
- (None, format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior")),
- (None, format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives")),
+ note!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
+ note!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives"),
],
UndefinedBehavior(info) => {
let mut helps = vec![
- (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
- (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
+ note!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
+ note!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
];
match info {
PointerUseAfterFree(alloc_id, _) | PointerOutOfBounds { alloc_id, .. } => {
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
- helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
+ helps.push(note_span!(span, "{:?} was allocated here:", alloc_id));
}
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
- helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
+ helps.push(note_span!(span, "{:?} was deallocated here:", alloc_id));
}
}
AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => {
- helps.push((None, format!("this means these two types are not *guaranteed* to be ABI-compatible across all targets")));
- helps.push((None, format!("if you think this code should be accepted anyway, please report an issue with Miri")));
+ helps.push(note!("this means these two types are not *guaranteed* to be ABI-compatible across all targets"));
+ helps.push(note!("if you think this code should be accepted anyway, please report an issue with Miri"));
}
_ => {},
}
@@ -593,6 +603,8 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
RejectedIsolatedOp(_) =>
("operation rejected by isolation".to_string(), DiagLevel::Warning),
Int2Ptr { .. } => ("integer-to-pointer cast".to_string(), DiagLevel::Warning),
+ ExternTypeReborrow =>
+ ("reborrow of reference to `extern type`".to_string(), DiagLevel::Warning),
CreatedPointerTag(..)
| PoppedPointerTag(..)
| CreatedCallId(..)
@@ -630,51 +642,56 @@ pub fn emit_diagnostic(&self, e: NonHaltingDiagnostic) {
Int2Ptr { .. } => format!("integer-to-pointer cast"),
WeakMemoryOutdatedLoad { ptr } =>
format!("weak memory emulation: outdated value returned from load at {ptr}"),
+ ExternTypeReborrow =>
+ format!("reborrow of a reference to `extern type` is not properly supported"),
};
let notes = match &e {
ProgressReport { block_count } => {
- // It is important that each progress report is slightly different, since
- // identical diagnostics are being deduplicated.
- vec![(None, format!("so far, {block_count} basic blocks have been executed"))]
+ vec![note!("so far, {block_count} basic blocks have been executed")]
}
_ => vec![],
};
let helps = match &e {
- Int2Ptr { details: true } =>
+ Int2Ptr { details: true } => {
+ let mut v = vec![
+ note!(
+ "this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program"
+ ),
+ note!(
+ "see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation"
+ ),
+ note!(
+ "to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"
+ ),
+ note!(
+ "you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics"
+ ),
+ ];
+ if self.borrow_tracker.as_ref().is_some_and(|b| {
+ matches!(b.borrow().borrow_tracker_method(), BorrowTrackerMethod::TreeBorrows)
+ }) {
+ v.push(
+ note!("Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used")
+ );
+ } else {
+ v.push(
+ note!("alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning")
+ );
+ }
+ v
+ }
+ ExternTypeReborrow => {
vec![
- (
- None,
- format!(
- "This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program."
- ),
+ note!(
+ "`extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code"
),
- (
- None,
- format!(
- "See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation."
- ),
+ note!(
+ "try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead"
),
- (
- None,
- format!(
- "To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead."
- ),
- ),
- (
- None,
- format!(
- "You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics."
- ),
- ),
- (
- None,
- format!(
- "Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning."
- ),
- ),
- ],
+ ]
+ }
_ => vec![],
};
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 2184a44..d781188 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -68,7 +68,7 @@ pub enum IsolatedOp {
Allow,
}
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BacktraceStyle {
/// Prints a terser backtrace which ideally only contains relevant information.
Short,
@@ -78,6 +78,16 @@ pub enum BacktraceStyle {
Off,
}
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum ValidationMode {
+ /// Do not perform any kind of validation.
+ No,
+ /// Validate the interior of the value, but not things behind references.
+ Shallow,
+ /// Fully recursively validate references.
+ Deep,
+}
+
/// Configuration needed to spawn a Miri instance.
#[derive(Clone)]
pub struct MiriConfig {
@@ -85,7 +95,7 @@ pub struct MiriConfig {
/// (This is still subject to isolation as well as `forwarded_env_vars`.)
pub env: Vec<(OsString, OsString)>,
/// Determine if validity checking is enabled.
- pub validate: bool,
+ pub validation: ValidationMode,
/// Determines if Stacked Borrows or Tree Borrows is enabled.
pub borrow_tracker: Option<BorrowTrackerMethod>,
/// Whether `core::ptr::Unique` receives special treatment.
@@ -162,7 +172,7 @@ impl Default for MiriConfig {
fn default() -> MiriConfig {
MiriConfig {
env: vec![],
- validate: true,
+ validation: ValidationMode::Shallow,
borrow_tracker: Some(BorrowTrackerMethod::StackedBorrows),
unique_is_unique: false,
check_alignment: AlignmentCheck::Int,
@@ -297,7 +307,8 @@ pub fn create_ecx<'tcx>(
// First argument is constructed later, because it's skipped if the entry function uses #[start].
// Second argument (argc): length of `config.args`.
- let argc = Scalar::from_target_usize(u64::try_from(config.args.len()).unwrap(), &ecx);
+ let argc =
+ ImmTy::from_int(i64::try_from(config.args.len()).unwrap(), ecx.machine.layouts.isize);
// Third argument (`argv`): created from `config.args`.
let argv = {
// Put each argument in memory, collect pointers.
@@ -324,13 +335,11 @@ pub fn create_ecx<'tcx>(
ecx.write_immediate(arg, &place)?;
}
ecx.mark_immutable(&argvs_place);
- // A pointer to that place is the 3rd argument for main.
- let argv = argvs_place.to_ref(&ecx);
// Store `argc` and `argv` for macOS `_NSGetArg{c,v}`.
{
let argc_place =
ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into())?;
- ecx.write_scalar(argc, &argc_place)?;
+ ecx.write_immediate(*argc, &argc_place)?;
ecx.mark_immutable(&argc_place);
ecx.machine.argc = Some(argc_place.ptr());
@@ -338,7 +347,7 @@ pub fn create_ecx<'tcx>(
ecx.layout_of(Ty::new_imm_ptr(tcx, tcx.types.unit))?,
MiriMemoryKind::Machine.into(),
)?;
- ecx.write_immediate(argv, &argv_place)?;
+ ecx.write_pointer(argvs_place.ptr(), &argv_place)?;
ecx.mark_immutable(&argv_place);
ecx.machine.argv = Some(argv_place.ptr());
}
@@ -359,7 +368,7 @@ pub fn create_ecx<'tcx>(
}
ecx.mark_immutable(&cmd_place);
}
- argv
+ ecx.mplace_to_ref(&argvs_place)?
};
// Return place (in static memory so that it does not count as leak).
@@ -395,10 +404,14 @@ pub fn create_ecx<'tcx>(
start_instance,
Abi::Rust,
&[
- Scalar::from_pointer(main_ptr, &ecx).into(),
- argc.into(),
+ ImmTy::from_scalar(
+ Scalar::from_pointer(main_ptr, &ecx),
+ // FIXME use a proper fn ptr type
+ ecx.machine.layouts.const_raw_ptr,
+ ),
+ argc,
argv,
- Scalar::from_u8(sigpipe).into(),
+ ImmTy::from_uint(sigpipe, ecx.machine.layouts.u8),
],
Some(&ret_place),
StackPopCleanup::Root { cleanup: true },
@@ -408,7 +421,7 @@ pub fn create_ecx<'tcx>(
ecx.call_function(
entry_instance,
Abi::Rust,
- &[argc.into(), argv],
+ &[argc, argv],
Some(&ret_place),
StackPopCleanup::Root { cleanup: true },
)?;
@@ -450,6 +463,7 @@ pub fn eval_entry<'tcx>(
let res = match res {
Err(res) => res,
// `Ok` can never happen
+ #[cfg(bootstrap)]
Ok(never) => match never {},
};
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index ba094c9..1bdf9f0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -12,13 +12,14 @@
use rustc_hir::{
def::{DefKind, Namespace},
def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE},
+ Safety,
};
use rustc_index::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::ExportedSymbol;
use rustc_middle::mir;
-use rustc_middle::ty::layout::MaybeResult;
+use rustc_middle::ty::layout::{FnAbiOf, MaybeResult};
use rustc_middle::ty::{
self,
layout::{LayoutOf, TyAndLayout},
@@ -492,48 +493,38 @@ fn call_function(
&mut self,
f: ty::Instance<'tcx>,
caller_abi: Abi,
- args: &[Immediate<Provenance>],
+ args: &[ImmTy<'tcx>],
dest: Option<&MPlaceTy<'tcx>>,
stack_pop: StackPopCleanup,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
- let param_env = ty::ParamEnv::reveal_all(); // in Miri this is always the param_env we use... and this.param_env is private.
- let callee_abi = f.ty(*this.tcx, param_env).fn_sig(*this.tcx).abi();
- if callee_abi != caller_abi {
- throw_ub_format!(
- "calling a function with ABI {} using caller ABI {}",
- callee_abi.name(),
- caller_abi.name()
- )
- }
- // Push frame.
+ // Get MIR.
let mir = this.load_mir(f.def, None)?;
let dest = match dest {
Some(dest) => dest.clone(),
None => MPlaceTy::fake_alloc_zst(this.layout_of(mir.return_ty())?),
};
- this.push_stack_frame(f, mir, &dest, stack_pop)?;
- // Initialize arguments.
- let mut callee_args = this.frame().body.args_iter();
- for arg in args {
- let local = callee_args
- .next()
- .ok_or_else(|| err_ub_format!("callee has fewer arguments than expected"))?;
- // Make the local live, and insert the initial value.
- this.storage_live(local)?;
- let callee_arg = this.local_to_place(local)?;
- this.write_immediate(*arg, &callee_arg)?;
- }
- if callee_args.next().is_some() {
- throw_ub_format!("callee has more arguments than expected");
- }
+ // Construct a function pointer type representing the caller perspective.
+ let sig = this.tcx.mk_fn_sig(
+ args.iter().map(|a| a.layout.ty),
+ dest.layout.ty,
+ /*c_variadic*/ false,
+ Safety::Safe,
+ caller_abi,
+ );
+ let caller_fn_abi = this.fn_abi_of_fn_ptr(ty::Binder::dummy(sig), ty::List::empty())?;
- // Initialize remaining locals.
- this.storage_live_for_always_live_locals()?;
-
- Ok(())
+ this.init_stack_frame(
+ f,
+ mir,
+ caller_fn_abi,
+ &args.iter().map(|a| FnArg::Copy(a.clone().into())).collect::<Vec<_>>(),
+ /*with_caller_location*/ false,
+ &dest,
+ stack_pop,
+ )
}
/// Visits the memory covered by `place`, sensitive to freezing: the 2nd parameter
@@ -606,7 +597,7 @@ fn visit_freeze_sensitive(
}
// The part between the end_ptr and the end of the place is also frozen.
// So pretend there is a 0-sized `UnsafeCell` at the end.
- unsafe_cell_action(&place.ptr().offset(size, this)?, Size::ZERO)?;
+ unsafe_cell_action(&place.ptr().wrapping_offset(size, this), Size::ZERO)?;
// Done!
return Ok(());
@@ -975,7 +966,7 @@ fn read_c_str<'a>(&'a self, ptr: Pointer) -> InterpResult<'tcx, &'a [u8]>
loop {
// FIXME: We are re-getting the allocation each time around the loop.
// Would be nice if we could somehow "extend" an existing AllocRange.
- let alloc = this.get_ptr_alloc(ptr.offset(len, this)?, size1)?.unwrap(); // not a ZST, so we will get a result
+ let alloc = this.get_ptr_alloc(ptr.wrapping_offset(len, this), size1)?.unwrap(); // not a ZST, so we will get a result
let byte = alloc.read_integer(alloc_range(Size::ZERO, size1))?.to_u8()?;
if byte == 0 {
break;
@@ -1039,7 +1030,7 @@ fn read_c_str_with_char_size<T>(
break;
} else {
wchars.push(wchar_int.try_into().unwrap());
- ptr = ptr.offset(size, this)?;
+ ptr = ptr.wrapping_offset(size, this);
}
}
@@ -1114,12 +1105,12 @@ fn frame_in_std(&self) -> bool {
// Make an attempt to get at the instance of the function this is inlined from.
let instance: Option<_> = try {
let scope = frame.current_source_info()?.scope;
- let inlined_parent = frame.body.source_scopes[scope].inlined_parent_scope?;
- let source = &frame.body.source_scopes[inlined_parent];
+ let inlined_parent = frame.body().source_scopes[scope].inlined_parent_scope?;
+ let source = &frame.body().source_scopes[inlined_parent];
source.inlined.expect("inlined_parent_scope points to scope without inline info").0
};
// Fall back to the instance of the function itself.
- let instance = instance.unwrap_or(frame.instance);
+ let instance = instance.unwrap_or(frame.instance());
// Now check the crate it is in. We could try to be clever here and e.g. check if this is
// the same crate as `start_fn`, but that would not work for running std tests in Miri, so
// we'd need some more hacks anyway. So we just check the name of the crate. If someone
@@ -1359,9 +1350,9 @@ fn top_user_relevant_frame(&self) -> Option<usize> {
/// This is the source of truth for the `is_user_relevant` flag in our `FrameExtra`.
pub fn is_user_relevant(&self, frame: &Frame<'tcx, Provenance>) -> bool {
- let def_id = frame.instance.def_id();
+ let def_id = frame.instance().def_id();
(def_id.is_local() || self.local_crates.contains(&def_id.krate))
- && !frame.instance.def.requires_caller_location(self.tcx)
+ && !frame.instance().def.requires_caller_location(self.tcx)
}
}
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index 9cd776c..18b2282 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -33,7 +33,7 @@ fn call_intrinsic(
let this = self.eval_context_mut();
// See if the core engine can handle this intrinsic.
- if this.emulate_intrinsic(instance, args, dest, ret)? {
+ if this.eval_intrinsic(instance, args, dest, ret)? {
return Ok(None);
}
let intrinsic_name = this.tcx.item_name(instance.def_id());
@@ -153,7 +153,7 @@ fn emulate_intrinsic_by_name(
// Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
"is_val_statically_known" => {
let [arg] = check_arg_count(args)?;
- this.validate_operand(arg)?;
+ this.validate_operand(arg, /*recursive*/ false)?;
let branch: bool = this.machine.rng.get_mut().gen();
this.write_scalar(Scalar::from_bool(branch), dest)?;
}
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 7fb68d7..966d385 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -10,7 +10,6 @@
#![feature(yeet_expr)]
#![feature(nonzero_ops)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
#![feature(trait_upcasting)]
#![feature(strict_overflow_ops)]
#![feature(is_none_or)]
@@ -57,6 +56,7 @@
extern crate tracing;
// The rustc crates we need
+extern crate rustc_attr;
extern crate rustc_apfloat;
extern crate rustc_ast;
extern crate rustc_const_eval;
@@ -143,6 +143,7 @@
};
pub use crate::eval::{
create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
+ ValidationMode,
};
pub use crate::helpers::{AccessKind, EvalContextExt as _};
pub use crate::machine::{
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index adb8459..754f8cf 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -11,6 +11,7 @@
use rand::Rng;
use rand::SeedableRng;
+use rustc_attr::InlineAttr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
#[allow(unused)]
use rustc_data_structures::static_assert_size;
@@ -23,6 +24,7 @@
Instance, Ty, TyCtxt,
},
};
+use rustc_session::config::InliningThreshold;
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::{Span, SpanData, Symbol};
use rustc_target::abi::{Align, Size};
@@ -47,10 +49,10 @@
/// `SIGRTMAX` - `SIGRTMIN` >= 8 (which is the value of `_POSIX_RTSIG_MAX`)
pub const SIGRTMAX: i32 = 42;
-/// Each const has multiple addresses, but only this many. Since const allocations are never
-/// deallocated, choosing a new [`AllocId`] and thus base address for each evaluation would
-/// produce unbounded memory usage.
-const ADDRS_PER_CONST: usize = 16;
+/// Each anonymous global (constant, vtable, function pointer, ...) has multiple addresses, but only
+/// this many. Since const allocations are never deallocated, choosing a new [`AllocId`] and thus
+/// base address for each evaluation would produce unbounded memory usage.
+const ADDRS_PER_ANON_GLOBAL: usize = 32;
/// Extra data stored with each stack frame
pub struct FrameExtra<'tcx> {
@@ -187,7 +189,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
pub type MemoryKind = interpret::MemoryKind<MiriMemoryKind>;
/// Pointer provenance.
-#[derive(Clone, Copy)]
+// This needs to be `Eq`+`Hash` because the `Machine` trait needs that because validity checking
+// *might* be recursive and then it has to track which places have already been visited.
+// These implementations are a bit questionable, and it means we may check the same place multiple
+// times with different provenance, but that is in general not wrong.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum Provenance {
/// For pointers with concrete provenance. we exactly know which allocation they are attached to
/// and what their borrow tag is.
@@ -215,24 +221,6 @@ pub enum Provenance {
Wildcard,
}
-// This needs to be `Eq`+`Hash` because the `Machine` trait needs that because validity checking
-// *might* be recursive and then it has to track which places have already been visited.
-// However, comparing provenance is meaningless, since `Wildcard` might be any provenance -- and of
-// course we don't actually do recursive checking.
-// We could change `RefTracking` to strip provenance for its `seen` set but that type is generic so that is quite annoying.
-// Instead owe add the required instances but make them panic.
-impl PartialEq for Provenance {
- fn eq(&self, _other: &Self) -> bool {
- panic!("Provenance must not be compared")
- }
-}
-impl Eq for Provenance {}
-impl std::hash::Hash for Provenance {
- fn hash<H: std::hash::Hasher>(&self, _state: &mut H) {
- panic!("Provenance must not be hashed")
- }
-}
-
/// The "extra" information a pointer has over a regular AllocId.
#[derive(Copy, Clone, PartialEq)]
pub enum ProvenanceExtra {
@@ -460,7 +448,7 @@ pub struct MiriMachine<'tcx> {
pub(crate) isolated_op: IsolatedOp,
/// Whether to enforce the validity invariant.
- pub(crate) validate: bool,
+ pub(crate) validation: ValidationMode,
/// The table of file descriptors.
pub(crate) fds: shims::FdTable,
@@ -659,8 +647,8 @@ pub(crate) fn new(config: &MiriConfig, layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>)
cmd_line: None,
tls: TlsData::default(),
isolated_op: config.isolated_op,
- validate: config.validate,
- fds: shims::FdTable::new(config.mute_stdout_stderr),
+ validation: config.validation,
+ fds: shims::FdTable::init(config.mute_stdout_stderr),
dirs: Default::default(),
layouts,
threads,
@@ -801,7 +789,7 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
fds,
tcx: _,
isolated_op: _,
- validate: _,
+ validation: _,
clock: _,
layouts: _,
static_roots: _,
@@ -943,7 +931,14 @@ fn alignment_check(
#[inline(always)]
fn enforce_validity(ecx: &MiriInterpCx<'tcx>, _layout: TyAndLayout<'tcx>) -> bool {
- ecx.machine.validate
+ ecx.machine.validation != ValidationMode::No
+ }
+ #[inline(always)]
+ fn enforce_validity_recursively(
+ ecx: &InterpCx<'tcx, Self>,
+ _layout: TyAndLayout<'tcx>,
+ ) -> bool {
+ ecx.machine.validation == ValidationMode::Deep
}
#[inline(always)]
@@ -1198,19 +1193,23 @@ fn expose_ptr(ecx: &mut InterpCx<'tcx, Self>, ptr: StrictPointer) -> InterpResul
}
}
- /// Convert a pointer with provenance into an allocation-offset pair,
- /// or a `None` with an absolute address if that conversion is not possible.
+ /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info.
+ /// `size` says how many bytes of memory are expected at that pointer. The *sign* of `size` can
+ /// be used to disambiguate situations where a wildcard pointer sits right in between two
+ /// allocations.
///
- /// This is called when a pointer is about to be used for memory access,
- /// an in-bounds check, or anything else that requires knowing which allocation it points to.
+ /// If `ptr.provenance.get_alloc_id()` is `Some(p)`, the returned `AllocId` must be `p`.
/// The resulting `AllocId` will just be used for that one step and the forgotten again
/// (i.e., we'll never turn the data returned here back into a `Pointer` that might be
/// stored in machine state).
+ ///
+ /// When this fails, that means the pointer does not point to a live allocation.
fn ptr_get_alloc(
ecx: &MiriInterpCx<'tcx>,
ptr: StrictPointer,
+ size: i64,
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
- let rel = ecx.ptr_get_alloc(ptr);
+ let rel = ecx.ptr_get_alloc(ptr, size);
rel.map(|(alloc_id, size)| {
let tag = match ptr.provenance {
@@ -1355,7 +1354,7 @@ fn init_frame(
) -> InterpResult<'tcx, Frame<'tcx, Provenance, FrameExtra<'tcx>>> {
// Start recording our event before doing anything else
let timing = if let Some(profiler) = ecx.machine.profiler.as_ref() {
- let fn_name = frame.instance.to_string();
+ let fn_name = frame.instance().to_string();
let entry = ecx.machine.string_cache.entry(fn_name.clone());
let name = entry.or_insert_with(|| profiler.alloc_string(&*fn_name));
@@ -1375,7 +1374,7 @@ fn init_frame(
catch_unwind: None,
timing,
is_user_relevant: ecx.machine.is_user_relevant(&frame),
- salt: ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_CONST,
+ salt: ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_ANON_GLOBAL,
};
Ok(frame.with_extra(extra))
@@ -1446,7 +1445,7 @@ fn before_stack_pop(
// tracing-tree can autoamtically annotate scope changes, but it gets very confused by our
// concurrency and what it prints is just plain wrong. So we print our own information
// instead. (Cc https://github.com/rust-lang/miri/issues/2266)
- info!("Leaving {}", ecx.frame().instance);
+ info!("Leaving {}", ecx.frame().instance());
Ok(())
}
@@ -1476,7 +1475,7 @@ fn after_stack_pop(
// Needs to be done after dropping frame to show up on the right nesting level.
// (Cc https://github.com/rust-lang/miri/issues/2266)
if !ecx.active_thread_stack().is_empty() {
- info!("Continuing in {}", ecx.frame().instance);
+ info!("Continuing in {}", ecx.frame().instance());
}
res
}
@@ -1489,7 +1488,7 @@ fn after_local_allocated(
let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr().provenance else {
panic!("after_local_allocated should only be called on fresh allocations");
};
- let local_decl = &ecx.frame().body.local_decls[local];
+ let local_decl = &ecx.frame().body().local_decls[local];
let span = local_decl.source_info.span;
ecx.machine.allocation_spans.borrow_mut().insert(alloc_id, (span, None));
Ok(())
@@ -1521,4 +1520,45 @@ fn eval_mir_constant<F>(
Entry::Occupied(oe) => Ok(oe.get().clone()),
}
}
+
+ fn get_global_alloc_salt(
+ ecx: &InterpCx<'tcx, Self>,
+ instance: Option<ty::Instance<'tcx>>,
+ ) -> usize {
+ let unique = if let Some(instance) = instance {
+ // Functions cannot be identified by pointers, as asm-equal functions can get
+ // deduplicated by the linker (we set the "unnamed_addr" attribute for LLVM) and
+ // functions can be duplicated across crates. We thus generate a new `AllocId` for every
+ // mention of a function. This means that `main as fn() == main as fn()` is false, while
+ // `let x = main as fn(); x == x` is true. However, as a quality-of-life feature it can
+ // be useful to identify certain functions uniquely, e.g. for backtraces. So we identify
+ // whether codegen will actually emit duplicate functions. It does that when they have
+ // non-lifetime generics, or when they can be inlined. All other functions are given a
+ // unique address. This is not a stable guarantee! The `inline` attribute is a hint and
+ // cannot be relied upon for anything. But if we don't do this, the
+ // `__rust_begin_short_backtrace`/`__rust_end_short_backtrace` logic breaks and panic
+ // backtraces look terrible.
+ let is_generic = instance
+ .args
+ .into_iter()
+ .any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_)));
+ let can_be_inlined = matches!(
+ ecx.tcx.sess.opts.unstable_opts.cross_crate_inline_threshold,
+ InliningThreshold::Always
+ ) || !matches!(
+ ecx.tcx.codegen_fn_attrs(instance.def_id()).inline,
+ InlineAttr::Never
+ );
+ !is_generic && !can_be_inlined
+ } else {
+ // Non-functions are never unique.
+ false
+ };
+ // Always use the same salt if the allocation is unique.
+ if unique {
+ CTFE_ALLOC_SALT
+ } else {
+ ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_ANON_GLOBAL
+ }
+ }
}
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 24a4b5f..9bb6777 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -46,8 +46,8 @@ fn handle_miri_get_backtrace(
let mut data = Vec::new();
for frame in this.active_thread_stack().iter().rev() {
// Match behavior of debuginfo (`FunctionCx::adjusted_span_and_dbg_scope`).
- let span = hygiene::walk_chain_collapsed(frame.current_span(), frame.body.span);
- data.push((frame.instance, span.lo()));
+ let span = hygiene::walk_chain_collapsed(frame.current_span(), frame.body().span);
+ data.push((frame.instance(), span.lo()));
}
let ptrs: Vec<_> = data
@@ -116,7 +116,7 @@ fn resolve_frame_pointer(
let ptr = this.read_pointer(ptr)?;
// Take apart the pointer, we need its pieces. The offset encodes the span.
- let (alloc_id, offset, _prov) = this.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _prov) = this.ptr_get_alloc_id(ptr, 0)?;
// This has to be an actual global fn ptr, not a dlsym function.
let fn_instance = if let Some(GlobalAlloc::Function { instance, .. }) =
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 7ad395c..6586ea8 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -108,4 +108,9 @@ fn get_env_var(&mut self, name: &OsStr) -> InterpResult<'tcx, Option<OsString>>
EnvVars::Windows(vars) => vars.get(name),
}
}
+
+ fn get_pid(&self) -> u32 {
+ let this = self.eval_context_ref();
+ if this.machine.communicate() { std::process::id() } else { 1000 }
+ }
}
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 9004f7e..7f6f63f 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -278,7 +278,7 @@ fn emulate_foreign_item_inner(
"miri_get_alloc_id" => {
let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
- let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| {
+ let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err(|_e| {
err_machine_stop!(TerminationInfo::Abort(format!(
"pointer passed to `miri_get_alloc_id` must not be dangling, got {ptr:?}"
)))
@@ -311,7 +311,7 @@ fn emulate_foreign_item_inner(
"miri_static_root" => {
let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
- let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr)?;
+ let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?;
if offset != Size::ZERO {
throw_unsup_format!(
"pointer passed to `miri_static_root` must point to beginning of an allocated block"
@@ -392,7 +392,7 @@ fn emulate_foreign_item_inner(
"`miri_promise_symbolic_alignment`: pointer is not actually aligned"
);
}
- if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr) {
+ if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr, 0) {
let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id);
// If the newly promised alignment is bigger than the native alignment of this
// allocation, and bigger than the previously promised alignment, then set it.
@@ -584,8 +584,8 @@ fn emulate_foreign_item_inner(
let n = Size::from_bytes(this.read_target_usize(n)?);
// C requires that this must always be a valid pointer (C18 §7.1.4).
- this.ptr_get_alloc_id(left)?;
- this.ptr_get_alloc_id(right)?;
+ this.ptr_get_alloc_id(left, 0)?;
+ this.ptr_get_alloc_id(right, 0)?;
let result = {
let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?;
@@ -612,7 +612,7 @@ fn emulate_foreign_item_inner(
let val = val as u8;
// C requires that this must always be a valid pointer (C18 §7.1.4).
- this.ptr_get_alloc_id(ptr)?;
+ this.ptr_get_alloc_id(ptr, 0)?;
if let Some(idx) = this
.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))?
@@ -622,7 +622,7 @@ fn emulate_foreign_item_inner(
{
let idx = u64::try_from(idx).unwrap();
#[allow(clippy::arithmetic_side_effects)] // idx < num, so this never wraps
- let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?;
+ let new_ptr = ptr.wrapping_offset(Size::from_bytes(num - idx - 1), this);
this.write_pointer(new_ptr, dest)?;
} else {
this.write_null(dest)?;
@@ -639,14 +639,14 @@ fn emulate_foreign_item_inner(
let val = val as u8;
// C requires that this must always be a valid pointer (C18 §7.1.4).
- this.ptr_get_alloc_id(ptr)?;
+ this.ptr_get_alloc_id(ptr, 0)?;
let idx = this
.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))?
.iter()
.position(|&c| c == val);
if let Some(idx) = idx {
- let new_ptr = ptr.offset(Size::from_bytes(idx as u64), this)?;
+ let new_ptr = ptr.wrapping_offset(Size::from_bytes(idx as u64), this);
this.write_pointer(new_ptr, dest)?;
} else {
this.write_null(dest)?;
@@ -681,8 +681,8 @@ fn emulate_foreign_item_inner(
// C requires that this must always be a valid pointer, even if `n` is zero, so we better check that.
// (This is more than Rust requires, so `mem_copy` is not sufficient.)
- this.ptr_get_alloc_id(ptr_dest)?;
- this.ptr_get_alloc_id(ptr_src)?;
+ this.ptr_get_alloc_id(ptr_dest, 0)?;
+ this.ptr_get_alloc_id(ptr_src, 0)?;
this.mem_copy(ptr_src, ptr_dest, Size::from_bytes(n), true)?;
this.write_pointer(ptr_dest, dest)?;
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 306dce5..ab705dd 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -25,7 +25,7 @@ pub struct CatchUnwindData<'tcx> {
/// The `catch_fn` callback to call in case of a panic.
catch_fn: Pointer,
/// The `data` argument for that callback.
- data: Scalar,
+ data: ImmTy<'tcx>,
/// The return place from the original call to `try`.
dest: MPlaceTy<'tcx>,
/// The return block from the original call to `try`.
@@ -48,9 +48,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn handle_miri_start_unwind(&mut self, payload: &OpTy<'tcx>) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
- trace!("miri_start_unwind: {:?}", this.frame().instance);
+ trace!("miri_start_unwind: {:?}", this.frame().instance());
- let payload = this.read_scalar(payload)?;
+ let payload = this.read_immediate(payload)?;
let thread = this.active_thread_mut();
thread.panic_payloads.push(payload);
@@ -80,7 +80,7 @@ fn handle_catch_unwind(
// Get all the arguments.
let [try_fn, data, catch_fn] = check_arg_count(args)?;
let try_fn = this.read_pointer(try_fn)?;
- let data = this.read_scalar(data)?;
+ let data = this.read_immediate(data)?;
let catch_fn = this.read_pointer(catch_fn)?;
// Now we make a function call, and pass `data` as first and only argument.
@@ -89,7 +89,7 @@ fn handle_catch_unwind(
this.call_function(
f_instance,
Abi::Rust,
- &[data.into()],
+ &[data.clone()],
None,
// Directly return to caller.
StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Continue },
@@ -124,7 +124,7 @@ fn handle_stack_pop_unwind(
// and we are unwinding, so we should catch that.
trace!(
"unwinding: found catch_panic frame during unwinding: {:?}",
- this.frame().instance
+ this.frame().instance()
);
// We set the return value of `try` to 1, since there was a panic.
@@ -140,7 +140,7 @@ fn handle_stack_pop_unwind(
this.call_function(
f_instance,
Abi::Rust,
- &[catch_unwind.data.into(), payload.into()],
+ &[catch_unwind.data, payload],
None,
// Directly return to caller of `try`.
StackPopCleanup::Goto {
@@ -169,7 +169,7 @@ fn start_panic(&mut self, msg: &str, unwind: mir::UnwindAction) -> InterpResult<
this.call_function(
panic,
Abi::Rust,
- &[msg.to_ref(this)],
+ &[this.mplace_to_ref(&msg)?],
None,
StackPopCleanup::Goto { ret: None, unwind },
)
@@ -188,7 +188,7 @@ fn start_panic_nounwind(&mut self, msg: &str) -> InterpResult<'tcx> {
this.call_function(
panic,
Abi::Rust,
- &[msg.to_ref(this)],
+ &[this.mplace_to_ref(&msg)?],
None,
StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
)
@@ -207,9 +207,9 @@ fn assert_panic(
// Forward to `panic_bounds_check` lang item.
// First arg: index.
- let index = this.read_scalar(&this.eval_operand(index, None)?)?;
+ let index = this.read_immediate(&this.eval_operand(index, None)?)?;
// Second arg: len.
- let len = this.read_scalar(&this.eval_operand(len, None)?)?;
+ let len = this.read_immediate(&this.eval_operand(len, None)?)?;
// Call the lang item.
let panic_bounds_check = this.tcx.lang_items().panic_bounds_check_fn().unwrap();
@@ -217,7 +217,7 @@ fn assert_panic(
this.call_function(
panic_bounds_check,
Abi::Rust,
- &[index.into(), len.into()],
+ &[index, len],
None,
StackPopCleanup::Goto { ret: None, unwind },
)?;
@@ -226,9 +226,9 @@ fn assert_panic(
// Forward to `panic_misaligned_pointer_dereference` lang item.
// First arg: required.
- let required = this.read_scalar(&this.eval_operand(required, None)?)?;
+ let required = this.read_immediate(&this.eval_operand(required, None)?)?;
// Second arg: found.
- let found = this.read_scalar(&this.eval_operand(found, None)?)?;
+ let found = this.read_immediate(&this.eval_operand(found, None)?)?;
// Call the lang item.
let panic_misaligned_pointer_dereference =
@@ -238,7 +238,7 @@ fn assert_panic(
this.call_function(
panic_misaligned_pointer_dereference,
Abi::Rust,
- &[required.into(), found.into()],
+ &[required, found],
None,
StackPopCleanup::Goto { ret: None, unwind },
)?;
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index e8f906d..ebec1a7 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -93,7 +93,11 @@ fn clock_gettime(
Ok(Scalar::from_i32(0))
}
- fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn gettimeofday(
+ &mut self,
+ tv_op: &OpTy<'tcx>,
+ tz_op: &OpTy<'tcx>,
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os_is_unix("gettimeofday");
@@ -106,7 +110,7 @@ fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResu
if !this.ptr_is_null(tz)? {
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let duration = system_time_to_duration(&SystemTime::now())?;
@@ -115,7 +119,7 @@ fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResu
this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &tv)?;
- Ok(0)
+ Ok(Scalar::from_i32(0))
}
// The localtime() function shall convert the time in seconds since the Epoch pointed to by
@@ -308,7 +312,7 @@ fn nanosleep(
&mut self,
req_op: &OpTy<'tcx>,
_rem: &OpTy<'tcx>, // Signal handlers are not supported, so rem will never be written to.
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os_is_unix("nanosleep");
@@ -320,7 +324,7 @@ fn nanosleep(
None => {
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
};
@@ -333,7 +337,7 @@ fn nanosleep(
@timeout = |_this| { Ok(()) }
),
);
- Ok(0)
+ Ok(Scalar::from_i32(0))
}
#[allow(non_snake_case)]
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index 8707446..52d83cd 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -315,6 +315,8 @@ fn schedule_windows_tls_dtor(&mut self, dtor: ImmTy<'tcx>) -> InterpResult<'tcx>
// FIXME: Technically, the reason should be `DLL_PROCESS_DETACH` when the main thread exits
// but std treats both the same.
let reason = this.eval_windows("c", "DLL_THREAD_DETACH");
+ let null_ptr =
+ ImmTy::from_scalar(Scalar::null_ptr(this), this.machine.layouts.const_raw_ptr);
// The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`.
// FIXME: `h` should be a handle to the current module and what `pv` should be is unknown
@@ -322,7 +324,7 @@ fn schedule_windows_tls_dtor(&mut self, dtor: ImmTy<'tcx>) -> InterpResult<'tcx>
this.call_function(
thread_callback,
Abi::System { unwind: false },
- &[Scalar::null_ptr(this).into(), reason.into(), Scalar::null_ptr(this).into()],
+ &[null_ptr.clone(), ImmTy::from_scalar(reason, this.machine.layouts.u32), null_ptr],
None,
StackPopCleanup::Root { cleanup: true },
)?;
@@ -343,7 +345,7 @@ fn schedule_macos_tls_dtor(&mut self) -> InterpResult<'tcx, Poll<()>> {
this.call_function(
instance,
Abi::C { unwind: false },
- &[data.into()],
+ &[ImmTy::from_scalar(data, this.machine.layouts.mut_raw_ptr)],
None,
StackPopCleanup::Root { cleanup: true },
)?;
@@ -380,7 +382,7 @@ fn schedule_next_pthread_tls_dtor(
this.call_function(
instance,
Abi::C { unwind: false },
- &[ptr.into()],
+ &[ImmTy::from_scalar(ptr, this.machine.layouts.mut_raw_ptr)],
None,
StackPopCleanup::Root { cleanup: true },
)?;
diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs
index 405431f..54bf3a3 100644
--- a/src/tools/miri/src/shims/unix/env.rs
+++ b/src/tools/miri/src/shims/unix/env.rs
@@ -81,8 +81,10 @@ fn get_ptr(
return Ok(None);
};
// The offset is used to strip the "{name}=" part of the string.
- let var_ptr = var_ptr
- .offset(Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), ecx)?;
+ let var_ptr = var_ptr.wrapping_offset(
+ Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)),
+ ecx,
+ );
Ok(Some(var_ptr))
}
@@ -148,7 +150,11 @@ fn getenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Pointer> {
Ok(var_ptr.unwrap_or_else(Pointer::null))
}
- fn setenv(&mut self, name_op: &OpTy<'tcx>, value_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn setenv(
+ &mut self,
+ name_op: &OpTy<'tcx>,
+ value_op: &OpTy<'tcx>,
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os_is_unix("setenv");
@@ -169,16 +175,16 @@ fn setenv(&mut self, name_op: &OpTy<'tcx>, value_op: &OpTy<'tcx>) -> InterpResul
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
}
this.update_environ()?;
- Ok(0) // return zero on success
+ Ok(Scalar::from_i32(0)) // return zero on success
} else {
// name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- Ok(-1)
+ Ok(Scalar::from_i32(-1))
}
}
- fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os_is_unix("unsetenv");
@@ -195,12 +201,12 @@ fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
}
this.update_environ()?;
- Ok(0)
+ Ok(Scalar::from_i32(0))
} else {
// name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- Ok(-1)
+ Ok(Scalar::from_i32(-1))
}
}
@@ -232,7 +238,7 @@ fn getcwd(&mut self, buf_op: &OpTy<'tcx>, size_op: &OpTy<'tcx>) -> InterpResult<
Ok(Pointer::null())
}
- fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os_is_unix("chdir");
@@ -242,16 +248,11 @@ fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
this.reject_in_isolation("`chdir`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
- match env::set_current_dir(path) {
- Ok(()) => Ok(0),
- Err(e) => {
- this.set_last_error_from_io_error(e)?;
- Ok(-1)
- }
- }
+ let result = env::set_current_dir(path).map(|()| 0);
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
}
/// Updates the `environ` static.
@@ -270,16 +271,26 @@ fn update_environ(&mut self) -> InterpResult<'tcx> {
Ok(())
}
- fn getpid(&mut self) -> InterpResult<'tcx, i32> {
+ fn getpid(&mut self) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os_is_unix("getpid");
- this.check_no_isolation("`getpid`")?;
-
// The reason we need to do this wacky of a conversion is because
// `libc::getpid` returns an i32, however, `std::process::id()` return an u32.
// So we un-do the conversion that stdlib does and turn it back into an i32.
- #[allow(clippy::cast_possible_wrap)]
- Ok(std::process::id() as i32)
+ // In `Scalar` representation, these are the same, so we don't need to anything else.
+ Ok(Scalar::from_u32(this.get_pid()))
+ }
+
+ fn linux_gettid(&mut self) -> InterpResult<'tcx, Scalar> {
+ let this = self.eval_context_ref();
+ this.assert_target_os("linux", "gettid");
+
+ let index = this.machine.threads.active_thread().to_u32();
+
+ // Compute a TID for this thread, ensuring that the main thread has PID == TID.
+ let tid = this.get_pid().strict_add(index);
+
+ Ok(Scalar::from_u32(tid))
}
}
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 8fb046b..1b25ef0 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -12,6 +12,13 @@
use crate::shims::unix::*;
use crate::*;
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) enum FlockOp {
+ SharedLock { nonblocking: bool },
+ ExclusiveLock { nonblocking: bool },
+ Unlock,
+}
+
/// Represents an open file descriptor.
pub trait FileDescription: std::fmt::Debug + Any {
fn name(&self) -> &'static str;
@@ -36,6 +43,30 @@ fn write<'tcx>(
throw_unsup_format!("cannot write to {}", self.name());
}
+ /// Reads as much as possible into the given buffer from a given offset,
+ /// and returns the number of bytes read.
+ fn pread<'tcx>(
+ &mut self,
+ _communicate_allowed: bool,
+ _bytes: &mut [u8],
+ _offset: u64,
+ _ecx: &mut MiriInterpCx<'tcx>,
+ ) -> InterpResult<'tcx, io::Result<usize>> {
+ throw_unsup_format!("cannot pread from {}", self.name());
+ }
+
+ /// Writes as much as possible from the given buffer starting at a given offset,
+ /// and returns the number of bytes written.
+ fn pwrite<'tcx>(
+ &mut self,
+ _communicate_allowed: bool,
+ _bytes: &[u8],
+ _offset: u64,
+ _ecx: &mut MiriInterpCx<'tcx>,
+ ) -> InterpResult<'tcx, io::Result<usize>> {
+ throw_unsup_format!("cannot pwrite to {}", self.name());
+ }
+
/// Seeks to the given offset (which can be relative to the beginning, end, or current position).
/// Returns the new position from the start of the stream.
fn seek<'tcx>(
@@ -53,6 +84,14 @@ fn close<'tcx>(
throw_unsup_format!("cannot close {}", self.name());
}
+ fn flock<'tcx>(
+ &self,
+ _communicate_allowed: bool,
+ _op: FlockOp,
+ ) -> InterpResult<'tcx, io::Result<()>> {
+ throw_unsup_format!("cannot flock {}", self.name());
+ }
+
fn is_tty(&self, _communicate_allowed: bool) -> bool {
// Most FDs are not tty's and the consequence of a wrong `false` are minor,
// so we use a default impl here.
@@ -165,11 +204,11 @@ fn write<'tcx>(
}
#[derive(Clone, Debug)]
-pub struct FileDescriptor(Rc<RefCell<Box<dyn FileDescription>>>);
+pub struct FileDescriptionRef(Rc<RefCell<Box<dyn FileDescription>>>);
-impl FileDescriptor {
- pub fn new<T: FileDescription>(fd: T) -> Self {
- FileDescriptor(Rc::new(RefCell::new(Box::new(fd))))
+impl FileDescriptionRef {
+ fn new(fd: impl FileDescription) -> Self {
+ FileDescriptionRef(Rc::new(RefCell::new(Box::new(fd))))
}
pub fn borrow(&self) -> Ref<'_, dyn FileDescription> {
@@ -193,7 +232,7 @@ pub fn close<'ctx>(self, communicate_allowed: bool) -> InterpResult<'ctx, io::Re
/// The file descriptor table
#[derive(Debug)]
pub struct FdTable {
- pub fds: BTreeMap<i32, FileDescriptor>,
+ fds: BTreeMap<i32, FileDescriptionRef>,
}
impl VisitProvenance for FdTable {
@@ -203,25 +242,30 @@ fn visit_provenance(&self, _visit: &mut VisitWith<'_>) {
}
impl FdTable {
- pub(crate) fn new(mute_stdout_stderr: bool) -> FdTable {
- let mut fds: BTreeMap<_, FileDescriptor> = BTreeMap::new();
- fds.insert(0i32, FileDescriptor::new(io::stdin()));
+ fn new() -> Self {
+ FdTable { fds: BTreeMap::new() }
+ }
+ pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable {
+ let mut fds = FdTable::new();
+ fds.insert_new(io::stdin());
if mute_stdout_stderr {
- fds.insert(1i32, FileDescriptor::new(NullOutput));
- fds.insert(2i32, FileDescriptor::new(NullOutput));
+ assert_eq!(fds.insert_new(NullOutput), 1);
+ assert_eq!(fds.insert_new(NullOutput), 2);
} else {
- fds.insert(1i32, FileDescriptor::new(io::stdout()));
- fds.insert(2i32, FileDescriptor::new(io::stderr()));
+ assert_eq!(fds.insert_new(io::stdout()), 1);
+ assert_eq!(fds.insert_new(io::stderr()), 2);
}
- FdTable { fds }
+ fds
}
- pub fn insert_fd(&mut self, file_handle: FileDescriptor) -> i32 {
- self.insert_fd_with_min_fd(file_handle, 0)
+ /// Insert a new file description to the FdTable.
+ pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 {
+ let file_handle = FileDescriptionRef::new(fd);
+ self.insert_ref_with_min_fd(file_handle, 0)
}
- /// Insert a new FD that is at least `min_fd`.
- pub fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptor, min_fd: i32) -> i32 {
+ /// Insert a file description, giving it a file descriptor that is at least `min_fd`.
+ fn insert_ref_with_min_fd(&mut self, file_handle: FileDescriptionRef, min_fd: i32) -> i32 {
// Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
// between used FDs, the find_map combinator will return it. If the first such unused FD
// is after all other used FDs, the find_map combinator will return None, and we will use
@@ -257,12 +301,12 @@ pub fn get_mut(&self, fd: i32) -> Option<RefMut<'_, dyn FileDescription>> {
Some(fd.borrow_mut())
}
- pub fn dup(&self, fd: i32) -> Option<FileDescriptor> {
+ pub fn get_ref(&self, fd: i32) -> Option<FileDescriptionRef> {
let fd = self.fds.get(&fd)?;
Some(fd.clone())
}
- pub fn remove(&mut self, fd: i32) -> Option<FileDescriptor> {
+ pub fn remove(&mut self, fd: i32) -> Option<FileDescriptionRef> {
self.fds.remove(&fd)
}
@@ -273,33 +317,67 @@ pub fn is_fd(&self, fd: i32) -> bool {
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
- fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, i32> {
+ fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
- let Some(dup_fd) = this.machine.fds.dup(old_fd) else {
- return this.fd_not_found();
+ let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else {
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
};
- Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0))
+ Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, 0)))
}
- fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, i32> {
+ fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
- let Some(dup_fd) = this.machine.fds.dup(old_fd) else {
- return this.fd_not_found();
+ let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else {
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
};
if new_fd != old_fd {
// Close new_fd if it is previously opened.
// If old_fd and new_fd point to the same description, then `dup_fd` ensures we keep the underlying file description alive.
- if let Some(file_descriptor) = this.machine.fds.fds.insert(new_fd, dup_fd) {
+ if let Some(file_description) = this.machine.fds.fds.insert(new_fd, dup_fd) {
// Ignore close error (not interpreter's) according to dup2() doc.
- file_descriptor.close(this.machine.communicate())?.ok();
+ file_description.close(this.machine.communicate())?.ok();
}
}
- Ok(new_fd)
+ Ok(Scalar::from_i32(new_fd))
}
- fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
+ fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> {
+ let this = self.eval_context_mut();
+ let Some(file_descriptor) = this.machine.fds.get(fd) else {
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
+ };
+
+ // We need to check that there aren't unsupported options in `op`.
+ let lock_sh = this.eval_libc_i32("LOCK_SH");
+ let lock_ex = this.eval_libc_i32("LOCK_EX");
+ let lock_nb = this.eval_libc_i32("LOCK_NB");
+ let lock_un = this.eval_libc_i32("LOCK_UN");
+
+ use FlockOp::*;
+ let parsed_op = if op == lock_sh {
+ SharedLock { nonblocking: false }
+ } else if op == lock_sh | lock_nb {
+ SharedLock { nonblocking: true }
+ } else if op == lock_ex {
+ ExclusiveLock { nonblocking: false }
+ } else if op == lock_ex | lock_nb {
+ ExclusiveLock { nonblocking: true }
+ } else if op == lock_un {
+ Unlock
+ } else {
+ throw_unsup_format!("unsupported flags {:#x}", op);
+ };
+
+ let result = file_descriptor.flock(this.machine.communicate(), parsed_op)?;
+ drop(file_descriptor);
+ // return `0` if flock is successful
+ let result = result.map(|()| 0i32);
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
+ }
+
+ fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
if args.len() < 2 {
@@ -317,11 +395,11 @@ fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
// `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
// always sets this flag when opening a file. However we still need to check that the
// file itself is open.
- if this.machine.fds.is_fd(fd) {
- Ok(this.eval_libc_i32("FD_CLOEXEC"))
+ Ok(Scalar::from_i32(if this.machine.fds.is_fd(fd) {
+ this.eval_libc_i32("FD_CLOEXEC")
} else {
- this.fd_not_found()
- }
+ this.fd_not_found()?
+ }))
} else if cmd == this.eval_libc_i32("F_DUPFD")
|| cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")
{
@@ -337,16 +415,17 @@ fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
}
let start = this.read_scalar(&args[2])?.to_i32()?;
- match this.machine.fds.dup(fd) {
- Some(dup_fd) => Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, start)),
- None => this.fd_not_found(),
+ match this.machine.fds.get_ref(fd) {
+ Some(dup_fd) =>
+ Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, start))),
+ None => Ok(Scalar::from_i32(this.fd_not_found()?)),
}
} else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`fcntl`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
this.ffullsync_fd(fd)
@@ -360,10 +439,10 @@ fn close(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let fd = this.read_scalar(fd_op)?.to_i32()?;
- let Some(file_descriptor) = this.machine.fds.remove(fd) else {
+ let Some(file_description) = this.machine.fds.remove(fd) else {
return Ok(Scalar::from_i32(this.fd_not_found()?));
};
- let result = file_descriptor.close(this.machine.communicate())?;
+ let result = file_description.close(this.machine.communicate())?;
// return `0` if close is successful
let result = result.map(|()| 0i32);
Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
@@ -380,7 +459,18 @@ fn fd_not_found<T: From<i32>>(&mut self) -> InterpResult<'tcx, T> {
Ok((-1).into())
}
- fn read(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64> {
+ /// Read data from `fd` into buffer specified by `buf` and `count`.
+ ///
+ /// If `offset` is `None`, reads data from current cursor position associated with `fd`
+ /// and updates cursor position on completion. Otherwise, reads from the specified offset
+ /// and keeps the cursor unchanged.
+ fn read(
+ &mut self,
+ fd: i32,
+ buf: Pointer,
+ count: u64,
+ offset: Option<i128>,
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
// Isolation check is done via `FileDescriptor` trait.
@@ -398,25 +488,31 @@ fn read(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64>
let communicate = this.machine.communicate();
// We temporarily dup the FD to be able to retain mutable access to `this`.
- let Some(file_descriptor) = this.machine.fds.dup(fd) else {
+ let Some(fd) = this.machine.fds.get_ref(fd) else {
trace!("read: FD not found");
- return this.fd_not_found();
+ return Ok(Scalar::from_target_isize(this.fd_not_found()?, this));
};
- trace!("read: FD mapped to {:?}", file_descriptor);
+ trace!("read: FD mapped to {fd:?}");
// We want to read at most `count` bytes. We are sure that `count` is not negative
// because it was a target's `usize`. Also we are sure that its smaller than
// `usize::MAX` because it is bounded by the host's `isize`.
let mut bytes = vec![0; usize::try_from(count).unwrap()];
- // `File::read` never returns a value larger than `count`,
- // so this cannot fail.
- let result = file_descriptor
- .borrow_mut()
- .read(communicate, &mut bytes, this)?
- .map(|c| i64::try_from(c).unwrap());
- drop(file_descriptor);
+ let result = match offset {
+ None => fd.borrow_mut().read(communicate, &mut bytes, this),
+ Some(offset) => {
+ let Ok(offset) = u64::try_from(offset) else {
+ let einval = this.eval_libc("EINVAL");
+ this.set_last_error(einval)?;
+ return Ok(Scalar::from_target_isize(-1, this));
+ };
+ fd.borrow_mut().pread(communicate, &mut bytes, offset, this)
+ }
+ };
+ drop(fd);
- match result {
+ // `File::read` never returns a value larger than `count`, so this cannot fail.
+ match result?.map(|c| i64::try_from(c).unwrap()) {
Ok(read_bytes) => {
// If reading to `bytes` did not fail, we write those bytes to the buffer.
// Crucially, if fewer than `bytes.len()` bytes were read, only write
@@ -425,16 +521,22 @@ fn read(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64>
buf,
bytes[..usize::try_from(read_bytes).unwrap()].iter().copied(),
)?;
- Ok(read_bytes)
+ Ok(Scalar::from_target_isize(read_bytes, this))
}
Err(e) => {
this.set_last_error_from_io_error(e)?;
- Ok(-1)
+ Ok(Scalar::from_target_isize(-1, this))
}
}
}
- fn write(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64> {
+ fn write(
+ &mut self,
+ fd: i32,
+ buf: Pointer,
+ count: u64,
+ offset: Option<i128>,
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
// Isolation check is done via `FileDescriptor` trait.
@@ -451,16 +553,24 @@ fn write(&mut self, fd: i32, buf: Pointer, count: u64) -> InterpResult<'tcx, i64
let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned();
// We temporarily dup the FD to be able to retain mutable access to `this`.
- let Some(file_descriptor) = this.machine.fds.dup(fd) else {
- return this.fd_not_found();
+ let Some(fd) = this.machine.fds.get_ref(fd) else {
+ return Ok(Scalar::from_target_isize(this.fd_not_found()?, this));
};
- let result = file_descriptor
- .borrow_mut()
- .write(communicate, &bytes, this)?
- .map(|c| i64::try_from(c).unwrap());
- drop(file_descriptor);
+ let result = match offset {
+ None => fd.borrow_mut().write(communicate, &bytes, this),
+ Some(offset) => {
+ let Ok(offset) = u64::try_from(offset) else {
+ let einval = this.eval_libc("EINVAL");
+ this.set_last_error(einval)?;
+ return Ok(Scalar::from_target_isize(-1, this));
+ };
+ fd.borrow_mut().pwrite(communicate, &bytes, offset, this)
+ }
+ };
+ drop(fd);
- this.try_unwrap_io_result(result)
+ let result = result?.map(|c| i64::try_from(c).unwrap());
+ Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this))
}
}
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 3a18d62..57930f9 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -62,13 +62,13 @@ fn emulate_foreign_item_inner(
"unsetenv" => {
let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.unsetenv(name)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"setenv" => {
let [name, value, overwrite] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.read_scalar(overwrite)?.to_i32()?;
let result = this.setenv(name, value)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"getcwd" => {
let [buf, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -78,12 +78,12 @@ fn emulate_foreign_item_inner(
"chdir" => {
let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.chdir(path)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"getpid" => {
let [] = this.check_shim(abi, Abi::C { unwind: false}, link_name, args)?;
let result = this.getpid()?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
// File descriptors
@@ -92,8 +92,8 @@ fn emulate_foreign_item_inner(
let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(count)?;
- let result = this.read(fd, buf, count)?;
- this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
+ let result = this.read(fd, buf, count, None)?;
+ this.write_scalar(result, dest)?;
}
"write" => {
let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -101,9 +101,49 @@ fn emulate_foreign_item_inner(
let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(n)?;
trace!("Called write({:?}, {:?}, {:?})", fd, buf, count);
- let result = this.write(fd, buf, count)?;
+ let result = this.write(fd, buf, count, None)?;
// Now, `result` is the value we return back to the program.
- this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
+ this.write_scalar(result, dest)?;
+ }
+ "pread" => {
+ let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let fd = this.read_scalar(fd)?.to_i32()?;
+ let buf = this.read_pointer(buf)?;
+ let count = this.read_target_usize(count)?;
+ let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
+ let result = this.read(fd, buf, count, Some(offset))?;
+ this.write_scalar(result, dest)?;
+ }
+ "pwrite" => {
+ let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let fd = this.read_scalar(fd)?.to_i32()?;
+ let buf = this.read_pointer(buf)?;
+ let count = this.read_target_usize(n)?;
+ let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
+ trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
+ let result = this.write(fd, buf, count, Some(offset))?;
+ // Now, `result` is the value we return back to the program.
+ this.write_scalar(result, dest)?;
+ }
+ "pread64" => {
+ let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let fd = this.read_scalar(fd)?.to_i32()?;
+ let buf = this.read_pointer(buf)?;
+ let count = this.read_target_usize(count)?;
+ let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
+ let result = this.read(fd, buf, count, Some(offset))?;
+ this.write_scalar(result, dest)?;
+ }
+ "pwrite64" => {
+ let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let fd = this.read_scalar(fd)?.to_i32()?;
+ let buf = this.read_pointer(buf)?;
+ let count = this.read_target_usize(n)?;
+ let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
+ trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
+ let result = this.write(fd, buf, count, Some(offset))?;
+ // Now, `result` is the value we return back to the program.
+ this.write_scalar(result, dest)?;
}
"close" => {
let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -115,20 +155,27 @@ fn emulate_foreign_item_inner(
// in `this.fcntl()`, so we do not use `check_shim` here.
this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?;
let result = this.fcntl(args)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"dup" => {
let [old_fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let old_fd = this.read_scalar(old_fd)?.to_i32()?;
let new_fd = this.dup(old_fd)?;
- this.write_scalar(Scalar::from_i32(new_fd), dest)?;
+ this.write_scalar(new_fd, dest)?;
}
"dup2" => {
let [old_fd, new_fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let old_fd = this.read_scalar(old_fd)?.to_i32()?;
let new_fd = this.read_scalar(new_fd)?.to_i32()?;
let result = this.dup2(old_fd, new_fd)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
+ }
+ "flock" => {
+ let [fd, op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let fd = this.read_scalar(fd)?.to_i32()?;
+ let op = this.read_scalar(op)?.to_i32()?;
+ let result = this.flock(fd, op)?;
+ this.write_scalar(result, dest)?;
}
// File and file system access
@@ -136,32 +183,32 @@ fn emulate_foreign_item_inner(
// `open` is variadic, the third argument is only present when the second argument has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set
this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?;
let result = this.open(args)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"unlink" => {
let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.unlink(path)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"symlink" => {
let [target, linkpath] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.symlink(target, linkpath)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"rename" => {
let [oldpath, newpath] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.rename(oldpath, newpath)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"mkdir" => {
let [path, mode] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.mkdir(path, mode)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"rmdir" => {
let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.rmdir(path)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"opendir" => {
let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -171,7 +218,7 @@ fn emulate_foreign_item_inner(
"closedir" => {
let [dirp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.closedir(dirp)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"lseek64" => {
let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -208,12 +255,12 @@ fn emulate_foreign_item_inner(
"fsync" => {
let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.fsync(fd)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"fdatasync" => {
let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.fdatasync(fd)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"readlink" => {
let [pathname, buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -238,7 +285,7 @@ fn emulate_foreign_item_inner(
"mkstemp" => {
let [template] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.mkstemp(template)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
// Sockets
@@ -254,7 +301,7 @@ fn emulate_foreign_item_inner(
"gettimeofday" => {
let [tv, tz] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.gettimeofday(tv, tz)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"localtime_r" => {
let [timep, result_op] = this.check_shim(abi, Abi::C {unwind: false}, link_name, args)?;
@@ -426,23 +473,23 @@ fn emulate_foreign_item_inner(
// Synchronization primitives
"pthread_mutexattr_init" => {
let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_mutexattr_init(attr)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_mutexattr_init(attr)?;
+ this.write_null(dest)?;
}
"pthread_mutexattr_settype" => {
let [attr, kind] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_mutexattr_settype(attr, kind)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"pthread_mutexattr_destroy" => {
let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_mutexattr_destroy(attr)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_mutexattr_destroy(attr)?;
+ this.write_null(dest)?;
}
"pthread_mutex_init" => {
let [mutex, attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_mutex_init(mutex, attr)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_mutex_init(mutex, attr)?;
+ this.write_null(dest)?;
}
"pthread_mutex_lock" => {
let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -451,17 +498,17 @@ fn emulate_foreign_item_inner(
"pthread_mutex_trylock" => {
let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_mutex_trylock(mutex)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"pthread_mutex_unlock" => {
let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_mutex_unlock(mutex)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"pthread_mutex_destroy" => {
let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_mutex_destroy(mutex)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_mutex_destroy(mutex)?;
+ this.write_int(0, dest)?;
}
"pthread_rwlock_rdlock" => {
let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -470,7 +517,7 @@ fn emulate_foreign_item_inner(
"pthread_rwlock_tryrdlock" => {
let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_rwlock_tryrdlock(rwlock)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"pthread_rwlock_wrlock" => {
let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -479,22 +526,22 @@ fn emulate_foreign_item_inner(
"pthread_rwlock_trywrlock" => {
let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.pthread_rwlock_trywrlock(rwlock)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"pthread_rwlock_unlock" => {
let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_rwlock_unlock(rwlock)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_rwlock_unlock(rwlock)?;
+ this.write_null(dest)?;
}
"pthread_rwlock_destroy" => {
let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_rwlock_destroy(rwlock)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_rwlock_destroy(rwlock)?;
+ this.write_null(dest)?;
}
"pthread_condattr_init" => {
let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_condattr_init(attr)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_condattr_init(attr)?;
+ this.write_null(dest)?;
}
"pthread_condattr_setclock" => {
let [attr, clock_id] =
@@ -505,28 +552,28 @@ fn emulate_foreign_item_inner(
"pthread_condattr_getclock" => {
let [attr, clock_id] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_condattr_getclock(attr, clock_id)?;
- this.write_scalar(result, dest)?;
+ this.pthread_condattr_getclock(attr, clock_id)?;
+ this.write_null(dest)?;
}
"pthread_condattr_destroy" => {
let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_condattr_destroy(attr)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_condattr_destroy(attr)?;
+ this.write_null(dest)?;
}
"pthread_cond_init" => {
let [cond, attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_cond_init(cond, attr)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_cond_init(cond, attr)?;
+ this.write_null(dest)?;
}
"pthread_cond_signal" => {
let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_cond_signal(cond)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_cond_signal(cond)?;
+ this.write_null(dest)?;
}
"pthread_cond_broadcast" => {
let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_cond_broadcast(cond)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_cond_broadcast(cond)?;
+ this.write_null(dest)?;
}
"pthread_cond_wait" => {
let [cond, mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -538,25 +585,25 @@ fn emulate_foreign_item_inner(
}
"pthread_cond_destroy" => {
let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_cond_destroy(cond)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_cond_destroy(cond)?;
+ this.write_null(dest)?;
}
// Threading
"pthread_create" => {
let [thread, attr, start, arg] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_create(thread, attr, start, arg)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_create(thread, attr, start, arg)?;
+ this.write_null(dest)?;
}
"pthread_join" => {
let [thread, retval] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_join(thread, retval)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_join(thread, retval)?;
+ this.write_null(dest)?;
}
"pthread_detach" => {
let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.pthread_detach(thread)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.pthread_detach(thread)?;
+ this.write_null(dest)?;
}
"pthread_self" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -565,13 +612,13 @@ fn emulate_foreign_item_inner(
}
"sched_yield" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- let result = this.sched_yield()?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.sched_yield()?;
+ this.write_null(dest)?;
}
"nanosleep" => {
let [req, rem] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.nanosleep(req, rem)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
"sched_getaffinity" => {
// Currently this function does not exist on all Unixes, e.g. on macOS.
@@ -600,23 +647,23 @@ fn emulate_foreign_item_inner(
if this.ptr_is_null(mask)? {
let einval = this.eval_libc("EFAULT");
this.set_last_error(einval)?;
- this.write_scalar(Scalar::from_i32(-1), dest)?;
+ this.write_int(-1, dest)?;
} else if cpusetsize == 0 || cpusetsize.checked_rem(chunk_size).unwrap() != 0 {
// we only copy whole chunks of size_of::<c_ulong>()
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- this.write_scalar(Scalar::from_i32(-1), dest)?;
+ this.write_int(-1, dest)?;
} else if let Some(cpuset) = this.machine.thread_cpu_affinity.get(&thread_id) {
let cpuset = cpuset.clone();
// we only copy whole chunks of size_of::<c_ulong>()
let byte_count = Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap());
this.write_bytes_ptr(mask, cpuset.as_slice()[..byte_count].iter().copied())?;
- this.write_scalar(Scalar::from_i32(0), dest)?;
+ this.write_null(dest)?;
} else {
// The thread whose ID is pid could not be found
let einval = this.eval_libc("ESRCH");
this.set_last_error(einval)?;
- this.write_scalar(Scalar::from_i32(-1), dest)?;
+ this.write_int(-1, dest)?;
}
}
"sched_setaffinity" => {
@@ -643,7 +690,7 @@ fn emulate_foreign_item_inner(
if this.ptr_is_null(mask)? {
let einval = this.eval_libc("EFAULT");
this.set_last_error(einval)?;
- this.write_scalar(Scalar::from_i32(-1), dest)?;
+ this.write_int(-1, dest)?;
} else {
// NOTE: cpusetsize might be smaller than `CpuAffinityMask::CPU_MASK_BYTES`.
// Any unspecified bytes are treated as zero here (none of the CPUs are configured).
@@ -655,13 +702,13 @@ fn emulate_foreign_item_inner(
match CpuAffinityMask::from_array(this, this.machine.num_cpus, bits_array) {
Some(cpuset) => {
this.machine.thread_cpu_affinity.insert(thread_id, cpuset);
- this.write_scalar(Scalar::from_i32(0), dest)?;
+ this.write_null(dest)?;
}
None => {
// The intersection between the mask and the available CPUs was empty.
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- this.write_scalar(Scalar::from_i32(-1), dest)?;
+ this.write_int(-1, dest)?;
}
}
}
@@ -719,10 +766,10 @@ fn emulate_foreign_item_inner(
if bufsize > 256 {
let err = this.eval_libc("EIO");
this.set_last_error(err)?;
- this.write_scalar(Scalar::from_i32(-1), dest)?;
+ this.write_int(-1, dest)?;
} else {
this.gen_random(buf, bufsize)?;
- this.write_scalar(Scalar::from_i32(0), dest)?;
+ this.write_null(dest)?;
}
}
"getrandom" => {
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index e34aa5c..d93374d 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -16,7 +16,7 @@
use crate::*;
use shims::time::system_time_to_duration;
-use self::fd::FileDescriptor;
+use self::fd::FlockOp;
#[derive(Debug)]
struct FileHandle {
@@ -49,6 +49,54 @@ fn write<'tcx>(
Ok(self.file.write(bytes))
}
+ fn pread<'tcx>(
+ &mut self,
+ communicate_allowed: bool,
+ bytes: &mut [u8],
+ offset: u64,
+ _ecx: &mut MiriInterpCx<'tcx>,
+ ) -> InterpResult<'tcx, io::Result<usize>> {
+ assert!(communicate_allowed, "isolation should have prevented even opening a file");
+ // Emulates pread using seek + read + seek to restore cursor position.
+ // Correctness of this emulation relies on sequential nature of Miri execution.
+ // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`.
+ let mut f = || {
+ let cursor_pos = self.file.stream_position()?;
+ self.file.seek(SeekFrom::Start(offset))?;
+ let res = self.file.read(bytes);
+ // Attempt to restore cursor position even if the read has failed
+ self.file
+ .seek(SeekFrom::Start(cursor_pos))
+ .expect("failed to restore file position, this shouldn't be possible");
+ res
+ };
+ Ok(f())
+ }
+
+ fn pwrite<'tcx>(
+ &mut self,
+ communicate_allowed: bool,
+ bytes: &[u8],
+ offset: u64,
+ _ecx: &mut MiriInterpCx<'tcx>,
+ ) -> InterpResult<'tcx, io::Result<usize>> {
+ assert!(communicate_allowed, "isolation should have prevented even opening a file");
+ // Emulates pwrite using seek + write + seek to restore cursor position.
+ // Correctness of this emulation relies on sequential nature of Miri execution.
+ // The closure is used to emulate `try` block, since we "bubble" `io::Error` using `?`.
+ let mut f = || {
+ let cursor_pos = self.file.stream_position()?;
+ self.file.seek(SeekFrom::Start(offset))?;
+ let res = self.file.write(bytes);
+ // Attempt to restore cursor position even if the write has failed
+ self.file
+ .seek(SeekFrom::Start(cursor_pos))
+ .expect("failed to restore file position, this shouldn't be possible");
+ res
+ };
+ Ok(f())
+ }
+
fn seek<'tcx>(
&mut self,
communicate_allowed: bool,
@@ -81,6 +129,97 @@ fn close<'tcx>(
}
}
+ fn flock<'tcx>(
+ &self,
+ communicate_allowed: bool,
+ op: FlockOp,
+ ) -> InterpResult<'tcx, io::Result<()>> {
+ assert!(communicate_allowed, "isolation should have prevented even opening a file");
+ #[cfg(target_family = "unix")]
+ {
+ use std::os::fd::AsRawFd;
+
+ use FlockOp::*;
+ // We always use non-blocking call to prevent interpreter from being blocked
+ let (host_op, lock_nb) = match op {
+ SharedLock { nonblocking } => (libc::LOCK_SH | libc::LOCK_NB, nonblocking),
+ ExclusiveLock { nonblocking } => (libc::LOCK_EX | libc::LOCK_NB, nonblocking),
+ Unlock => (libc::LOCK_UN, false),
+ };
+
+ let fd = self.file.as_raw_fd();
+ let ret = unsafe { libc::flock(fd, host_op) };
+ let res = match ret {
+ 0 => Ok(()),
+ -1 => {
+ let err = io::Error::last_os_error();
+ if !lock_nb && err.kind() == io::ErrorKind::WouldBlock {
+ throw_unsup_format!("blocking `flock` is not currently supported");
+ }
+ Err(err)
+ }
+ ret => panic!("Unexpected return value from flock: {ret}"),
+ };
+ Ok(res)
+ }
+
+ #[cfg(target_family = "windows")]
+ {
+ use std::os::windows::io::AsRawHandle;
+ use windows_sys::Win32::{
+ Foundation::{ERROR_IO_PENDING, ERROR_LOCK_VIOLATION, FALSE, HANDLE, TRUE},
+ Storage::FileSystem::{
+ LockFileEx, UnlockFile, LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY,
+ },
+ };
+ let fh = self.file.as_raw_handle() as HANDLE;
+
+ use FlockOp::*;
+ let (ret, lock_nb) = match op {
+ SharedLock { nonblocking } | ExclusiveLock { nonblocking } => {
+ // We always use non-blocking call to prevent interpreter from being blocked
+ let mut flags = LOCKFILE_FAIL_IMMEDIATELY;
+ if matches!(op, ExclusiveLock { .. }) {
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ let ret = unsafe { LockFileEx(fh, flags, 0, !0, !0, &mut std::mem::zeroed()) };
+ (ret, nonblocking)
+ }
+ Unlock => {
+ let ret = unsafe { UnlockFile(fh, 0, 0, !0, !0) };
+ (ret, false)
+ }
+ };
+
+ let res = match ret {
+ TRUE => Ok(()),
+ FALSE => {
+ let mut err = io::Error::last_os_error();
+ let code: u32 = err.raw_os_error().unwrap().try_into().unwrap();
+ if matches!(code, ERROR_IO_PENDING | ERROR_LOCK_VIOLATION) {
+ if lock_nb {
+ // The io error mapping does not know about these error codes,
+ // so we translate it to `WouldBlock` manually.
+ let desc = format!("LockFileEx wouldblock error: {err}");
+ err = io::Error::new(io::ErrorKind::WouldBlock, desc);
+ } else {
+ throw_unsup_format!("blocking `flock` is not currently supported");
+ }
+ }
+ Err(err)
+ }
+ _ => panic!("Unexpected return value: {ret}"),
+ };
+ Ok(res)
+ }
+
+ #[cfg(not(any(target_family = "unix", target_family = "windows")))]
+ {
+ let _ = op;
+ compile_error!("flock is supported only on UNIX and Windows hosts");
+ }
+ }
+
fn is_tty(&self, communicate_allowed: bool) -> bool {
communicate_allowed && self.file.is_terminal()
}
@@ -256,7 +395,7 @@ fn maybe_sync_file(
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
- fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
+ fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
if args.len() < 2 {
throw_ub_format!(
"incorrect number of arguments for `open`: got {}, expected at least 2",
@@ -266,7 +405,8 @@ fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut();
- let path = this.read_pointer(&args[0])?;
+ let path_raw = this.read_pointer(&args[0])?;
+ let path = this.read_path_from_c_str(path_raw)?;
let flag = this.read_scalar(&args[1])?.to_i32()?;
let mut options = OpenOptions::new();
@@ -363,30 +503,51 @@ fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
// if the flag contains `O_TMPFILE` then we return a graceful error
let eopnotsupp = this.eval_libc("EOPNOTSUPP");
this.set_last_error(eopnotsupp)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
}
+
+ let o_nofollow = this.eval_libc_i32("O_NOFOLLOW");
+ if flag & o_nofollow == o_nofollow {
+ #[cfg(unix)]
+ {
+ use std::os::unix::fs::OpenOptionsExt;
+ options.custom_flags(libc::O_NOFOLLOW);
+ }
+ // Strictly speaking, this emulation is not equivalent to the O_NOFOLLOW flag behavior:
+ // the path could change between us checking it here and the later call to `open`.
+ // But it's good enough for Miri purposes.
+ #[cfg(not(unix))]
+ {
+ // O_NOFOLLOW only fails when the trailing component is a symlink;
+ // the entire rest of the path can still contain symlinks.
+ if path.is_symlink() {
+ let eloop = this.eval_libc("ELOOP");
+ this.set_last_error(eloop)?;
+ return Ok(Scalar::from_i32(-1));
+ }
+ }
+ mirror |= o_nofollow;
+ }
+
// If `flag` is not equal to `mirror`, there is an unsupported option enabled in `flag`,
// then we throw an error.
if flag != mirror {
throw_unsup_format!("unsupported flags {:#x}", flag & !mirror);
}
- let path = this.read_path_from_c_str(path)?;
-
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`open`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
- let fd = options.open(path).map(|file| {
- let fh = &mut this.machine.fds;
- fh.insert_fd(FileDescriptor::new(FileHandle { file, writable }))
- });
+ let fd = options
+ .open(path)
+ .map(|file| this.machine.fds.insert_new(FileHandle { file, writable }));
- this.try_unwrap_io_result(fd)
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?))
}
fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> {
@@ -415,19 +576,19 @@ fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx,
let communicate = this.machine.communicate();
- let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else {
+ let Some(mut file_description) = this.machine.fds.get_mut(fd) else {
return Ok(Scalar::from_i64(this.fd_not_found()?));
};
- let result = file_descriptor
+ let result = file_description
.seek(communicate, seek_from)?
.map(|offset| i64::try_from(offset).unwrap());
- drop(file_descriptor);
+ drop(file_description);
let result = this.try_unwrap_io_result(result)?;
Ok(Scalar::from_i64(result))
}
- fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
@@ -436,18 +597,18 @@ fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`unlink`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let result = remove_file(path).map(|_| 0);
- this.try_unwrap_io_result(result)
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
}
fn symlink(
&mut self,
target_op: &OpTy<'tcx>,
linkpath_op: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, Scalar> {
#[cfg(unix)]
fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
std::os::unix::fs::symlink(src, dst)
@@ -467,11 +628,11 @@ fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`symlink`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let result = create_link(&target, &linkpath).map(|_| 0);
- this.try_unwrap_io_result(result)
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
}
fn macos_fbsd_stat(
@@ -570,7 +731,7 @@ fn linux_statx(
flags_op: &OpTy<'tcx>, // Should be an `int`
mask_op: &OpTy<'tcx>, // Should be an `unsigned int`
statxbuf_op: &OpTy<'tcx>, // Should be a `struct statx *`
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os("linux", "statx");
@@ -585,7 +746,7 @@ fn linux_statx(
if this.ptr_is_null(statxbuf_ptr)? || this.ptr_is_null(pathname_ptr)? {
let efault = this.eval_libc("EFAULT");
this.set_last_error(efault)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let statxbuf = this.deref_pointer_as(statxbuf_op, this.libc_ty_layout("statx"))?;
@@ -627,7 +788,7 @@ fn linux_statx(
this.eval_libc("EBADF")
};
this.set_last_error(ecode)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
// the `_mask_op` parameter specifies the file information that the caller requested.
@@ -649,7 +810,7 @@ fn linux_statx(
};
let metadata = match metadata {
Some(metadata) => metadata,
- None => return Ok(-1),
+ None => return Ok(Scalar::from_i32(-1)),
};
// The `mode` field specifies the type of the file and the permissions over the file for
@@ -742,14 +903,14 @@ fn linux_statx(
&this.project_field_named(&statxbuf, "stx_mtime")?,
)?;
- Ok(0)
+ Ok(Scalar::from_i32(0))
}
fn rename(
&mut self,
oldpath_op: &OpTy<'tcx>,
newpath_op: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let oldpath_ptr = this.read_pointer(oldpath_op)?;
@@ -758,7 +919,7 @@ fn rename(
if this.ptr_is_null(oldpath_ptr)? || this.ptr_is_null(newpath_ptr)? {
let efault = this.eval_libc("EFAULT");
this.set_last_error(efault)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let oldpath = this.read_path_from_c_str(oldpath_ptr)?;
@@ -768,15 +929,15 @@ fn rename(
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`rename`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let result = rename(oldpath, newpath).map(|_| 0);
- this.try_unwrap_io_result(result)
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
}
- fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
#[cfg_attr(not(unix), allow(unused_variables))]
@@ -792,7 +953,7 @@ fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`mkdir`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
#[cfg_attr(not(unix), allow(unused_mut))]
@@ -808,10 +969,10 @@ fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<
let result = builder.create(path).map(|_| 0i32);
- this.try_unwrap_io_result(result)
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
}
- fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
@@ -820,12 +981,12 @@ fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`rmdir`", reject_with)?;
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
let result = remove_dir(path).map(|_| 0i32);
- this.try_unwrap_io_result(result)
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
}
fn opendir(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
@@ -928,7 +1089,7 @@ fn linux_readdir64(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar
&this.ptr_to_mplace(entry, dirent64_layout),
)?;
- let name_ptr = entry.offset(Size::from_bytes(d_name_offset), this)?;
+ let name_ptr = entry.wrapping_offset(Size::from_bytes(d_name_offset), this);
this.write_bytes_ptr(name_ptr, name_bytes.iter().copied())?;
Some(entry)
@@ -1075,27 +1236,24 @@ fn macos_fbsd_readdir_r(
}))
}
- fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let dirp = this.read_target_usize(dirp_op)?;
// Reject if isolation is enabled.
- if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+ Ok(Scalar::from_i32(if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`closedir`", reject_with)?;
- // Set error code as "EBADF" (bad fd)
- return this.fd_not_found();
- }
-
- if let Some(open_dir) = this.machine.dirs.streams.remove(&dirp) {
+ this.fd_not_found()?
+ } else if let Some(open_dir) = this.machine.dirs.streams.remove(&dirp) {
if let Some(entry) = open_dir.entry {
this.deallocate_ptr(entry, None, MiriMemoryKind::Runtime.into())?;
}
drop(open_dir);
- Ok(0)
+ 0
} else {
- this.fd_not_found()
- }
+ this.fd_not_found()?
+ }))
}
fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> {
@@ -1108,30 +1266,30 @@ fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> {
return Ok(Scalar::from_i32(this.fd_not_found()?));
}
- let Some(file_descriptor) = this.machine.fds.get(fd) else {
+ let Some(file_description) = this.machine.fds.get(fd) else {
return Ok(Scalar::from_i32(this.fd_not_found()?));
};
// FIXME: Support ftruncate64 for all FDs
let FileHandle { file, writable } =
- file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
+ file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors")
})?;
if *writable {
if let Ok(length) = length.try_into() {
let result = file.set_len(length);
- drop(file_descriptor);
+ drop(file_description);
let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
Ok(Scalar::from_i32(result))
} else {
- drop(file_descriptor);
+ drop(file_description);
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
Ok(Scalar::from_i32(-1))
}
} else {
- drop(file_descriptor);
+ drop(file_description);
// The file is not writable
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
@@ -1139,7 +1297,7 @@ fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> {
}
}
- fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
// On macOS, `fsync` (unlike `fcntl(F_FULLFSYNC)`) does not wait for the
// underlying disk to finish writing. In the interest of host compatibility,
// we conservatively implement this with `sync_all`, which
@@ -1153,28 +1311,28 @@ fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`fsync`", reject_with)?;
// Set error code as "EBADF" (bad fd)
- return this.fd_not_found();
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
}
- return self.ffullsync_fd(fd);
+ self.ffullsync_fd(fd)
}
- fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, i32> {
+ fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
- let Some(file_descriptor) = this.machine.fds.get(fd) else {
- return Ok(this.fd_not_found()?);
+ let Some(file_description) = this.machine.fds.get(fd) else {
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
};
// Only regular files support synchronization.
let FileHandle { file, writable } =
- file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
+ file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
})?;
let io_result = maybe_sync_file(file, *writable, File::sync_all);
- drop(file_descriptor);
- this.try_unwrap_io_result(io_result)
+ drop(file_description);
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
}
- fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -1183,20 +1341,20 @@ fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`fdatasync`", reject_with)?;
// Set error code as "EBADF" (bad fd)
- return this.fd_not_found();
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
}
- let Some(file_descriptor) = this.machine.fds.get(fd) else {
- return Ok(this.fd_not_found()?);
+ let Some(file_description) = this.machine.fds.get(fd) else {
+ return Ok(Scalar::from_i32(this.fd_not_found()?));
};
// Only regular files support synchronization.
let FileHandle { file, writable } =
- file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
+ file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors")
})?;
let io_result = maybe_sync_file(file, *writable, File::sync_data);
- drop(file_descriptor);
- this.try_unwrap_io_result(io_result)
+ drop(file_description);
+ Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
}
fn sync_file_range(
@@ -1234,18 +1392,18 @@ fn sync_file_range(
return Ok(Scalar::from_i32(this.fd_not_found()?));
}
- let Some(file_descriptor) = this.machine.fds.get(fd) else {
+ let Some(file_description) = this.machine.fds.get(fd) else {
return Ok(Scalar::from_i32(this.fd_not_found()?));
};
// Only regular files support synchronization.
let FileHandle { file, writable } =
- file_descriptor.downcast_ref::<FileHandle>().ok_or_else(|| {
+ file_description.downcast_ref::<FileHandle>().ok_or_else(|| {
err_unsup_format!(
"`sync_data_range` is only supported on file-backed file descriptors"
)
})?;
let io_result = maybe_sync_file(file, *writable, File::sync_data);
- drop(file_descriptor);
+ drop(file_description);
Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
}
@@ -1373,7 +1531,7 @@ fn realpath(
}
}
}
- fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
use rand::seq::SliceRandom;
// POSIX defines the template string.
@@ -1404,7 +1562,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
this.reject_in_isolation("`mkstemp`", reject_with)?;
let eacc = this.eval_libc("EACCES");
this.set_last_error(eacc)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
// Get the bytes of the suffix we expect in _target_ encoding.
@@ -1422,7 +1580,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
if last_six_char_bytes != suffix_bytes {
let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
// At this point we know we have 6 ASCII 'X' characters as a suffix.
@@ -1476,10 +1634,8 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
match file {
Ok(f) => {
- let fh = &mut this.machine.fds;
- let fd =
- fh.insert_fd(FileDescriptor::new(FileHandle { file: f, writable: true }));
- return Ok(fd);
+ let fd = this.machine.fds.insert_new(FileHandle { file: f, writable: true });
+ return Ok(Scalar::from_i32(fd));
}
Err(e) =>
match e.kind() {
@@ -1490,7 +1646,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
// "On error, -1 is returned, and errno is set to
// indicate the error"
this.set_last_error_from_io_error(e)?;
- return Ok(-1);
+ return Ok(Scalar::from_i32(-1));
}
},
}
@@ -1499,7 +1655,7 @@ fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
// We ran out of attempts to create the file, return an error.
let eexist = this.eval_libc("EEXIST");
this.set_last_error(eexist)?;
- Ok(-1)
+ Ok(Scalar::from_i32(-1))
}
}
@@ -1543,11 +1699,11 @@ fn from_fd<'tcx>(
ecx: &mut MiriInterpCx<'tcx>,
fd: i32,
) -> InterpResult<'tcx, Option<FileMetadata>> {
- let Some(file_descriptor) = ecx.machine.fds.get(fd) else {
+ let Some(file_description) = ecx.machine.fds.get(fd) else {
return ecx.fd_not_found().map(|_: i32| None);
};
- let file = &file_descriptor
+ let file = &file_description
.downcast_ref::<FileHandle>()
.ok_or_else(|| {
err_unsup_format!(
@@ -1557,7 +1713,7 @@ fn from_fd<'tcx>(
.file;
let metadata = file.metadata();
- drop(file_descriptor);
+ drop(file_description);
FileMetadata::from_meta(ecx, metadata)
}
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index a566146..9127db3 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -5,8 +5,6 @@
use crate::shims::unix::*;
use crate::*;
-use self::shims::unix::fd::FileDescriptor;
-
/// An `Epoll` file descriptor connects file handles and epoll events
#[derive(Clone, Debug, Default)]
struct Epoll {
@@ -66,7 +64,7 @@ fn epoll_create1(&mut self, flags: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
);
}
- let fd = this.machine.fds.insert_fd(FileDescriptor::new(Epoll::default()));
+ let fd = this.machine.fds.insert_new(Epoll::default());
Ok(Scalar::from_i32(fd))
}
diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs
index cae5abc..4ab8760 100644
--- a/src/tools/miri/src/shims/unix/linux/eventfd.rs
+++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs
@@ -8,8 +8,6 @@
use crate::shims::unix::*;
use crate::{concurrency::VClock, *};
-use self::shims::unix::fd::FileDescriptor;
-
// We'll only do reads and writes in chunks of size u64.
const U64_ARRAY_SIZE: usize = mem::size_of::<u64>();
@@ -180,11 +178,11 @@ fn eventfd(&mut self, val: &OpTy<'tcx>, flags: &OpTy<'tcx>) -> InterpResult<'tcx
throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags);
}
- let fd = this.machine.fds.insert_fd(FileDescriptor::new(Event {
+ let fd = this.machine.fds.insert_new(Event {
counter: val.into(),
is_nonblock,
clock: VClock::default(),
- }));
+ });
Ok(Scalar::from_i32(fd))
}
}
diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
index 95bee38..581f0db 100644
--- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs
@@ -44,7 +44,7 @@ fn emulate_foreign_item_inner(
let [dirfd, pathname, flags, mask, statxbuf] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
- this.write_scalar(Scalar::from_i32(result), dest)?;
+ this.write_scalar(result, dest)?;
}
// epoll, eventfd
@@ -94,6 +94,11 @@ fn emulate_foreign_item_inner(
)?;
this.write_scalar(res, dest)?;
}
+ "gettid" => {
+ let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+ let result = this.linux_gettid()?;
+ this.write_scalar(result, dest)?;
+ }
// Dynamically invoked syscalls
"syscall" => {
@@ -171,12 +176,12 @@ fn emulate_foreign_item_inner(
"__libc_current_sigrtmin" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- this.write_scalar(Scalar::from_i32(SIGRTMIN), dest)?;
+ this.write_int(SIGRTMIN, dest)?;
}
"__libc_current_sigrtmax" => {
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
- this.write_scalar(Scalar::from_i32(SIGRTMAX), dest)?;
+ this.write_int(SIGRTMAX, dest)?;
}
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs
index c430eff0..3b32612 100644
--- a/src/tools/miri/src/shims/unix/linux/mem.rs
+++ b/src/tools/miri/src/shims/unix/linux/mem.rs
@@ -53,7 +53,7 @@ fn mremap(
// We just allocated this, the access is definitely in-bounds and fits into our address space.
// mmap guarantees new mappings are zero-init.
this.write_bytes_ptr(
- ptr.offset(Size::from_bytes(old_size), this).unwrap().into(),
+ ptr.wrapping_offset(Size::from_bytes(old_size), this).into(),
std::iter::repeat(0u8).take(usize::try_from(increase).unwrap()),
)
.unwrap();
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index 6d3d63b..455820a 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -7,8 +7,6 @@
use crate::shims::unix::*;
use crate::{concurrency::VClock, *};
-use self::fd::FileDescriptor;
-
/// The maximum capacity of the socketpair buffer in bytes.
/// This number is arbitrary as the value can always
/// be configured in the real system.
@@ -221,9 +219,9 @@ fn socketpair(
};
let fds = &mut this.machine.fds;
- let sv0 = fds.insert_fd(FileDescriptor::new(socketpair_0));
+ let sv0 = fds.insert_new(socketpair_0);
+ let sv1 = fds.insert_new(socketpair_1);
let sv0 = Scalar::from_int(sv0, sv.layout.size);
- let sv1 = fds.insert_fd(FileDescriptor::new(socketpair_1));
let sv1 = Scalar::from_int(sv1, sv.layout.size);
this.write_scalar(sv0, &sv)?;
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index e865311..0b889b1 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -363,20 +363,20 @@ fn cond_set_clock_id<'tcx>(
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
- fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT");
mutexattr_set_kind(this, attr_op, default_kind)?;
- Ok(0)
+ Ok(())
}
fn pthread_mutexattr_settype(
&mut self,
attr_op: &OpTy<'tcx>,
kind_op: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let kind = this.read_scalar(kind_op)?.to_i32()?;
@@ -407,13 +407,13 @@ fn pthread_mutexattr_settype(
mutexattr_set_kind(this, attr_op, kind)?;
} else {
let einval = this.eval_libc_i32("EINVAL");
- return Ok(einval);
+ return Ok(Scalar::from_i32(einval));
}
- Ok(0)
+ Ok(Scalar::from_i32(0))
}
- fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
// Destroying an uninit pthread_mutexattr is UB, so check to make sure it's not uninit.
@@ -435,14 +435,14 @@ fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'t
&this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t"))?,
)?;
- Ok(0)
+ Ok(())
}
fn pthread_mutex_init(
&mut self,
mutex_op: &OpTy<'tcx>,
attr_op: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let attr = this.read_pointer(attr_op)?;
@@ -457,7 +457,7 @@ fn pthread_mutex_init(
mutex_set_kind(this, mutex_op, kind)?;
- Ok(0)
+ Ok(())
}
fn pthread_mutex_lock(
@@ -501,25 +501,25 @@ fn pthread_mutex_lock(
Ok(())
}
- fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let kind = mutex_get_kind(this, mutex_op)?;
let id = mutex_get_id(this, mutex_op)?;
- if this.mutex_is_locked(id) {
+ Ok(Scalar::from_i32(if this.mutex_is_locked(id) {
let owner_thread = this.mutex_get_owner(id);
if owner_thread != this.active_thread() {
- Ok(this.eval_libc_i32("EBUSY"))
+ this.eval_libc_i32("EBUSY")
} else {
if is_mutex_kind_default(this, kind)?
|| is_mutex_kind_normal(this, kind)?
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
{
- Ok(this.eval_libc_i32("EBUSY"))
+ this.eval_libc_i32("EBUSY")
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
this.mutex_lock(id);
- Ok(0)
+ 0
} else {
throw_unsup_format!(
"called pthread_mutex_trylock on an unsupported type of mutex"
@@ -529,11 +529,11 @@ fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
} else {
// The mutex is unlocked. Let's lock it.
this.mutex_lock(id);
- Ok(0)
- }
+ 0
+ }))
}
- fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let kind = mutex_get_kind(this, mutex_op)?;
@@ -541,7 +541,7 @@ fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
if let Some(_old_locked_count) = this.mutex_unlock(id)? {
// The mutex was locked by the current thread.
- Ok(0)
+ Ok(Scalar::from_i32(0))
} else {
// The mutex was locked by another thread or not locked at all. See
// the “Unlock When Not Owner” column in
@@ -557,14 +557,14 @@ fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
{
- Ok(this.eval_libc_i32("EPERM"))
+ Ok(Scalar::from_i32(this.eval_libc_i32("EPERM")))
} else {
throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex");
}
}
}
- fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let id = mutex_get_id(this, mutex_op)?;
@@ -583,7 +583,7 @@ fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx,
)?;
// FIXME: delete interpreter state associated with this mutex.
- Ok(0)
+ Ok(())
}
fn pthread_rwlock_rdlock(
@@ -605,16 +605,16 @@ fn pthread_rwlock_rdlock(
Ok(())
}
- fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let id = rwlock_get_id(this, rwlock_op)?;
if this.rwlock_is_write_locked(id) {
- Ok(this.eval_libc_i32("EBUSY"))
+ Ok(Scalar::from_i32(this.eval_libc_i32("EBUSY")))
} else {
this.rwlock_reader_lock(id);
- Ok(0)
+ Ok(Scalar::from_i32(0))
}
}
@@ -649,35 +649,33 @@ fn pthread_rwlock_wrlock(
Ok(())
}
- fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
let id = rwlock_get_id(this, rwlock_op)?;
if this.rwlock_is_locked(id) {
- Ok(this.eval_libc_i32("EBUSY"))
+ Ok(Scalar::from_i32(this.eval_libc_i32("EBUSY")))
} else {
this.rwlock_writer_lock(id);
- Ok(0)
+ Ok(Scalar::from_i32(0))
}
}
- fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let id = rwlock_get_id(this, rwlock_op)?;
#[allow(clippy::if_same_then_else)]
- if this.rwlock_reader_unlock(id)? {
- Ok(0)
- } else if this.rwlock_writer_unlock(id)? {
- Ok(0)
+ if this.rwlock_reader_unlock(id)? || this.rwlock_writer_unlock(id)? {
+ Ok(())
} else {
throw_ub_format!("unlocked an rwlock that was not locked by the active thread");
}
}
- fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let id = rwlock_get_id(this, rwlock_op)?;
@@ -695,10 +693,10 @@ fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tc
)?;
// FIXME: delete interpreter state associated with this rwlock.
- Ok(0)
+ Ok(())
}
- fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
// no clock attribute on macOS
@@ -710,7 +708,7 @@ fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx,
condattr_set_clock_id(this, attr_op, default_clock_id)?;
}
- Ok(0)
+ Ok(())
}
fn pthread_condattr_setclock(
@@ -737,16 +735,16 @@ fn pthread_condattr_getclock(
&mut self,
attr_op: &OpTy<'tcx>,
clk_id_op: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, Scalar> {
+ ) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let clock_id = condattr_get_clock_id(this, attr_op)?;
this.write_scalar(Scalar::from_i32(clock_id), &this.deref_pointer(clk_id_op)?)?;
- Ok(Scalar::from_i32(0))
+ Ok(())
}
- fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
// Destroying an uninit pthread_condattr is UB, so check to make sure it's not uninit.
@@ -761,14 +759,14 @@ fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tc
&this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?,
)?;
- Ok(0)
+ Ok(())
}
fn pthread_cond_init(
&mut self,
cond_op: &OpTy<'tcx>,
attr_op: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let attr = this.read_pointer(attr_op)?;
@@ -784,21 +782,21 @@ fn pthread_cond_init(
cond_set_clock_id(this, cond_op, clock_id)?;
- Ok(0)
+ Ok(())
}
- fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let id = cond_get_id(this, cond_op)?;
this.condvar_signal(id)?;
- Ok(0)
+ Ok(())
}
- fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let id = cond_get_id(this, cond_op)?;
while this.condvar_signal(id)? {}
- Ok(0)
+ Ok(())
}
fn pthread_cond_wait(
@@ -869,7 +867,7 @@ fn pthread_cond_timedwait(
Ok(())
}
- fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let id = cond_get_id(this, cond_op)?;
@@ -885,6 +883,6 @@ fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i
this.write_uninit(&this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?;
// FIXME: delete interpreter state associated with this condvar.
- Ok(0)
+ Ok(())
}
}
diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs
index 6fe331b..56e8270 100644
--- a/src/tools/miri/src/shims/unix/thread.rs
+++ b/src/tools/miri/src/shims/unix/thread.rs
@@ -1,5 +1,4 @@
use crate::*;
-use rustc_middle::ty::layout::LayoutOf;
use rustc_target::spec::abi::Abi;
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -10,7 +9,7 @@ fn pthread_create(
_attr: &OpTy<'tcx>,
start_routine: &OpTy<'tcx>,
arg: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ ) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let thread_info_place = this.deref_pointer_as(thread, this.libc_ty_layout("pthread_t"))?;
@@ -24,17 +23,13 @@ fn pthread_create(
start_routine,
Abi::C { unwind: false },
func_arg,
- this.layout_of(this.tcx.types.usize)?,
+ this.machine.layouts.mut_raw_ptr,
)?;
- Ok(0)
+ Ok(())
}
- fn pthread_join(
- &mut self,
- thread: &OpTy<'tcx>,
- retval: &OpTy<'tcx>,
- ) -> InterpResult<'tcx, i32> {
+ fn pthread_join(&mut self, thread: &OpTy<'tcx>, retval: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
if !this.ptr_is_null(this.read_pointer(retval)?)? {
@@ -45,10 +40,10 @@ fn pthread_join(
let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?;
this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?;
- Ok(0)
+ Ok(())
}
- fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
+ fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?;
@@ -57,7 +52,7 @@ fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
/*allow_terminated_joined*/ false,
)?;
- Ok(0)
+ Ok(())
}
fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar> {
@@ -113,11 +108,11 @@ fn pthread_getname_np(
Ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") })
}
- fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
+ fn sched_yield(&mut self) -> InterpResult<'tcx, ()> {
let this = self.eval_context_mut();
this.yield_active_thread();
- Ok(0)
+ Ok(())
}
}
diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs
index ed3eb69..495df18 100644
--- a/src/tools/miri/src/shims/windows/env.rs
+++ b/src/tools/miri/src/shims/windows/env.rs
@@ -197,12 +197,11 @@ fn SetCurrentDirectoryW(
}
#[allow(non_snake_case)]
- fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> {
+ fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, Scalar> {
let this = self.eval_context_mut();
this.assert_target_os("windows", "GetCurrentProcessId");
- this.check_no_isolation("`GetCurrentProcessId`")?;
- Ok(std::process::id())
+ Ok(Scalar::from_u32(this.get_pid()))
}
#[allow(non_snake_case)]
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 71f6a2b..f840ba1 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -141,7 +141,7 @@ fn emulate_foreign_item_inner(
"GetCurrentProcessId" => {
let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
let result = this.GetCurrentProcessId()?;
- this.write_int(result, dest)?;
+ this.write_scalar(result, dest)?;
}
// File related shims
@@ -372,7 +372,7 @@ fn emulate_foreign_item_inner(
this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?;
// Return success (`1`).
- this.write_scalar(Scalar::from_i32(1), dest)?;
+ this.write_int(1, dest)?;
}
// Access to command-line arguments
@@ -563,7 +563,7 @@ fn emulate_foreign_item_inner(
let ptr = this.read_pointer(ptr)?;
let len = this.read_target_usize(len)?;
this.gen_random(ptr, len)?;
- this.write_scalar(Scalar::from_i32(1), dest)?;
+ this.write_int(1, dest)?;
}
"BCryptGenRandom" => {
// used by getrandom 0.2
@@ -627,7 +627,7 @@ fn emulate_foreign_item_inner(
this.CloseHandle(handle)?;
- this.write_scalar(Scalar::from_u32(1), dest)?;
+ this.write_int(1, dest)?;
}
"GetModuleFileNameW" => {
let [handle, filename, size] =
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 0bbf2a8..1bd32fc 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -1178,7 +1178,7 @@ fn pclmulqdq<'tcx>(
// if the i-th bit in right is set
if (right & (1 << i)) != 0 {
// xor result with `left` shifted to the left by i positions
- result ^= (left as u128) << i;
+ result ^= u128::from(left) << i;
}
}
diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock
index d534fda..e94bef5 100644
--- a/src/tools/miri/test_dependencies/Cargo.lock
+++ b/src/tools/miri/test_dependencies/Cargo.lock
@@ -4,9 +4,9 @@
[[package]]
name = "addr2line"
-version = "0.21.0"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
"gimli",
]
@@ -19,9 +19,9 @@
[[package]]
name = "backtrace"
-version = "0.3.71"
+version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
+checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
@@ -34,9 +34,9 @@
[[package]]
name = "bitflags"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
@@ -46,9 +46,9 @@
[[package]]
name = "cc"
-version = "1.0.96"
+version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
+checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
[[package]]
name = "cfg-if"
@@ -58,12 +58,12 @@
[[package]]
name = "errno"
-version = "0.3.8"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys",
]
[[package]]
@@ -85,9 +85,9 @@
[[package]]
name = "getrandom"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"js-sys",
@@ -98,9 +98,9 @@
[[package]]
name = "gimli"
-version = "0.28.1"
+version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
name = "hermit-abi"
@@ -119,46 +119,47 @@
[[package]]
name = "libc"
-version = "0.2.154"
+version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "linux-raw-sys"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
-version = "0.4.21"
+version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
-version = "2.7.2"
+version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
-version = "0.7.2"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
"adler",
]
[[package]]
name = "mio"
-version = "0.8.11"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
+checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
dependencies = [
+ "hermit-abi",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
@@ -166,13 +167,13 @@
version = "0.1.0"
dependencies = [
"getrandom 0.1.16",
- "getrandom 0.2.14",
+ "getrandom 0.2.15",
"libc",
"num_cpus",
"page_size",
"tempfile",
"tokio",
- "windows-sys 0.52.0",
+ "windows-sys",
]
[[package]]
@@ -187,9 +188,9 @@
[[package]]
name = "object"
-version = "0.32.2"
+version = "0.36.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
dependencies = [
"memchr",
]
@@ -218,9 +219,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.81"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
@@ -236,9 +237,9 @@
[[package]]
name = "rustc-demangle"
-version = "0.1.23"
+version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustix"
@@ -250,7 +251,7 @@
"errno",
"libc",
"linux-raw-sys",
- "windows-sys 0.52.0",
+ "windows-sys",
]
[[package]]
@@ -269,14 +270,14 @@
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys",
]
[[package]]
name = "syn"
-version = "2.0.60"
+version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [
"proc-macro2",
"quote",
@@ -285,38 +286,38 @@
[[package]]
name = "tempfile"
-version = "3.10.1"
+version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53"
dependencies = [
"cfg-if",
"fastrand",
+ "once_cell",
"rustix",
- "windows-sys 0.52.0",
+ "windows-sys",
]
[[package]]
name = "tokio"
-version = "1.37.0"
+version = "1.39.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
+checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
dependencies = [
"backtrace",
"libc",
"mio",
- "num_cpus",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
- "windows-sys 0.48.0",
+ "windows-sys",
]
[[package]]
name = "tokio-macros"
-version = "2.2.0"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
+checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
@@ -419,139 +420,73 @@
[[package]]
name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
-]
-
-[[package]]
-name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.52.5",
+ "windows-targets",
]
[[package]]
name = "windows-targets"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
-dependencies = [
- "windows_aarch64_gnullvm 0.52.5",
- "windows_aarch64_msvc 0.52.5",
- "windows_i686_gnu 0.52.5",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
"windows_i686_gnullvm",
- "windows_i686_msvc 0.52.5",
- "windows_x86_64_gnu 0.52.5",
- "windows_x86_64_gnullvm 0.52.5",
- "windows_x86_64_msvc 0.52.5",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
-version = "0.52.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.5"
+version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs
index 96dd99e..39b1c30 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.rs
@@ -1,11 +1,12 @@
//@ignore-target-windows: No pthreads on Windows
+//~^ERROR: calling a function with more arguments than it expected
//! The thread function must have exactly one argument.
use std::{mem, ptr};
extern "C" fn thread_start() -> *mut libc::c_void {
- panic!() //~ ERROR: callee has fewer arguments than expected
+ panic!()
}
fn main() {
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr
index ca6a05a..aa67420 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_few_args.stderr
@@ -1,14 +1,10 @@
-error: Undefined Behavior: callee has fewer arguments than expected
- --> $DIR/libc_pthread_create_too_few_args.rs:LL:CC
+error: Undefined Behavior: calling a function with more arguments than it expected
|
-LL | panic!()
- | ^^^^^^^^ callee has fewer arguments than expected
- |
+ = note: calling a function with more arguments than it expected
+ = note: (no span available)
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE on thread `unnamed-ID`:
- = note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC
- = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs
index d8fbc68..fc2ab71 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.rs
@@ -1,11 +1,12 @@
//@ignore-target-windows: No pthreads on Windows
+//~^ERROR: calling a function with fewer arguments than it requires
//! The thread function must have exactly one argument.
use std::{mem, ptr};
extern "C" fn thread_start(_null: *mut libc::c_void, _x: i32) -> *mut libc::c_void {
- panic!() //~ ERROR: callee has more arguments than expected
+ panic!()
}
fn main() {
diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr
index 6ab48a7..4de947b 100644
--- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_create_too_many_args.stderr
@@ -1,14 +1,10 @@
-error: Undefined Behavior: callee has more arguments than expected
- --> $DIR/libc_pthread_create_too_many_args.rs:LL:CC
+error: Undefined Behavior: calling a function with fewer arguments than it requires
|
-LL | panic!()
- | ^^^^^^^^ callee has more arguments than expected
- |
+ = note: calling a function with fewer arguments than it requires
+ = note: (no span available)
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE on thread `unnamed-ID`:
- = note: inside `thread_start` at RUSTLIB/core/src/panic.rs:LL:CC
- = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail-dep/libc/affinity.stderr b/src/tools/miri/tests/fail-dep/libc/affinity.stderr
index c01f158..3841462 100644
--- a/src/tools/miri/tests/fail-dep/libc/affinity.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/affinity.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 128, so pointer to 129 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC which is only 128 bytes from the end of the allocation
--> $DIR/affinity.rs:LL:CC
|
LL | let err = unsafe { sched_setaffinity(PID, size_of::<cpu_set_t>() + 1, &cpuset) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 128, so pointer to 129 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC which is only 128 bytes from the end of the allocation
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memchr_null.rs b/src/tools/miri/tests/fail-dep/libc/memchr_null.rs
index 672cc10..b6b4b62 100644
--- a/src/tools/miri/tests/fail-dep/libc/memchr_null.rs
+++ b/src/tools/miri/tests/fail-dep/libc/memchr_null.rs
@@ -3,6 +3,6 @@
// null is explicitly called out as UB in the C docs.
fn main() {
unsafe {
- libc::memchr(ptr::null(), 0, 0); //~ERROR: dangling
+ libc::memchr(ptr::null(), 0, 0); //~ERROR: null pointer
}
}
diff --git a/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr b/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
index b76722f..f03ae33 100644
--- a/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/memchr_null.rs:LL:CC
|
LL | libc::memchr(ptr::null(), 0, 0);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs b/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
index 066af4a..0e204aa 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
+++ b/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
@@ -3,6 +3,6 @@
// null is explicitly called out as UB in the C docs.
fn main() {
unsafe {
- libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: dangling
+ libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: null pointer
}
}
diff --git a/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr b/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
index 5c6ba4f..4bca5a3 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/memcmp_null.rs:LL:CC
|
LL | libc::memcmp(ptr::null(), ptr::null(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr b/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
index 4ab37ab..6adaaeb 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/memcmp_zero.rs:LL:CC
|
LL | libc::memcmp(ptr.cast(), ptr.cast(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr b/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
index 3e1ee7b..b2da332 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x17[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/memcpy_zero.rs:LL:CC
|
LL | libc::memcpy(to.cast(), from.cast(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x17[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs b/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
index f06336b..1fe637d 100644
--- a/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
+++ b/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
@@ -6,6 +6,6 @@
// null is explicitly called out as UB in the C docs.
fn main() {
unsafe {
- libc::memrchr(ptr::null(), 0, 0); //~ERROR: dangling
+ libc::memrchr(ptr::null(), 0, 0); //~ERROR: null pointer
}
}
diff --git a/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr b/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
index 0cc7ac1..a9ed58d 100644
--- a/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/memrchr_null.rs:LL:CC
|
LL | libc::memrchr(ptr::null(), 0, 0);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr
index 4b12729..6d19faa 100644
--- a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr
+++ b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr
@@ -2,7 +2,7 @@
--> CARGO_REGISTRY/.../epoll.rs:LL:CC
|
LL | / syscall!(epoll_wait(
-LL | | self.ep,
+LL | | self.ep.as_raw_fd(),
LL | | events.as_mut_ptr(),
LL | | events.capacity() as i32,
LL | | timeout,
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
index 424aace..49de3dd 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
@@ -1,6 +1,6 @@
//@revisions: stack tree
//@[tree]compile-flags: -Zmiri-tree-borrows
-//@error-in-other-file: pointer to 4 bytes starting at offset 0 is out-of-bounds
+//@error-in-other-file: expected a pointer to 4 bytes of memory
fn main() {
unsafe {
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
index be01c5c..64bbbfc 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
index be01c5c..64bbbfc 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr
index e96e641..04494b5 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr
index e96e641..04494b5 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
--> RUSTLIB/alloc/src/boxed.rs:LL:CC
|
LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
index 37f2bb3..a5c031b 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/dangling_pointer_to_raw_pointer.rs:LL:CC
|
LL | unsafe { &(*x).0 as *const i32 }
- | ^^^^^^^ out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr
index 377022f..d989bff 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/deref-invalid-ptr.rs:LL:CC
|
LL | let _y = unsafe { &*x as *const u32 };
- | ^^^ out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs
index a0773c6..dee0595 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs
@@ -1,5 +1,5 @@
#[allow(deref_nullptr)]
fn main() {
- let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: null pointer is a dangling pointer
+ let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: null pointer
panic!("this should never print: {}", x);
}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr
index a18f0f2..1b97265 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
--> $DIR/null_pointer_deref.rs:LL:CC
|
LL | let x: i32 = unsafe { *std::ptr::null() };
- | ^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs
index 954596f..61f5ef5 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs
@@ -1,4 +1,4 @@
#[allow(deref_nullptr)]
fn main() {
- unsafe { *std::ptr::null_mut() = 0i32 }; //~ ERROR: null pointer is a dangling pointer
+ unsafe { *std::ptr::null_mut() = 0i32 }; //~ ERROR: null pointer
}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr
index 01d4d12..3d75e7a 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
--> $DIR/null_pointer_write.rs:LL:CC
|
LL | unsafe { *std::ptr::null_mut() = 0i32 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr
index 4195c68..4bfac8f 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation
--> $DIR/out_of_bounds_project.rs:LL:CC
|
LL | let _field = addr_of!((*ptr).2);
- | ^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs
index 658fbd1..595a229b 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs
@@ -1,6 +1,6 @@
fn main() {
let v: Vec<u16> = vec![1, 2];
// This read is also misaligned. We make sure that the OOB message has priority.
- let x = unsafe { *v.as_ptr().wrapping_byte_add(5) }; //~ ERROR: out-of-bounds
+ let x = unsafe { *v.as_ptr().wrapping_byte_add(5) }; //~ ERROR: expected a pointer to 2 bytes of memory
panic!("this should never print: {}", x);
}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr
index 37dbea3..8a774c2 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
--> $DIR/out_of_bounds_read.rs:LL:CC
|
LL | let x = unsafe { *v.as_ptr().wrapping_byte_add(5) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs
index 2ff537b..054e1c6 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs
@@ -1,5 +1,5 @@
fn main() {
let mut v: Vec<u16> = vec![1, 2];
// This read is also misaligned. We make sure that the OOB message has priority.
- unsafe { *v.as_mut_ptr().wrapping_byte_add(5) = 0 }; //~ ERROR: out-of-bounds
+ unsafe { *v.as_mut_ptr().wrapping_byte_add(5) = 0 }; //~ ERROR: expected a pointer to 2 bytes of memory
}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr
index 97b3f3e..6ae9f05 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
--> $DIR/out_of_bounds_write.rs:LL:CC
|
LL | unsafe { *v.as_mut_ptr().wrapping_byte_add(5) = 0 };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
index 73c3ff1..2d4fbaf 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/storage_dead_dangling.rs:LL:CC
|
LL | let _ref = unsafe { &mut *(LEAK as *mut i32) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr
index b7492a0..1d8eed3 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: 0x2c[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got 0x2c[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/wild_pointer_deref.rs:LL:CC
|
LL | let x = unsafe { *p };
- | ^^ memory access failed: 0x2c[noalloc] is a dangling pointer (it has no provenance)
+ | ^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x2c[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/extern-type-field-offset.stderr b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
index 3ed5732..c07b63e 100644
--- a/src/tools/miri/tests/fail/extern-type-field-offset.stderr
+++ b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
@@ -1,3 +1,14 @@
+warning: reborrow of reference to `extern type`
+ --> $DIR/extern-type-field-offset.rs:LL:CC
+ |
+LL | let x: &Newtype = unsafe { &*(&buf as *const _ as *const Newtype) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported
+ |
+ = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code
+ = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/extern-type-field-offset.rs:LL:CC
+
error: unsupported operation: `extern type` field does not have a known offset
--> $DIR/extern-type-field-offset.rs:LL:CC
|
@@ -10,5 +21,5 @@
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-error: aborting due to 1 previous error
+error: aborting due to 1 previous error; 1 warning emitted
diff --git a/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs b/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs
index fd667fb..6a7a267 100644
--- a/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs
+++ b/src/tools/miri/tests/fail/function_calls/check_callback_abi.rs
@@ -9,7 +9,7 @@ fn main() {
// Make sure we check the ABI when Miri itself invokes a function
// as part of a shim implementation.
std::intrinsics::catch_unwind(
- //~^ ERROR: calling a function with ABI C using caller ABI Rust
+ //~^ ERROR: calling a function with calling convention C using calling convention Rust
std::mem::transmute::<extern "C" fn(*mut u8), _>(try_fn),
std::ptr::null_mut(),
|_, _| unreachable!(),
diff --git a/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr b/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr
index 501f17c..890fed0 100644
--- a/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr
+++ b/src/tools/miri/tests/fail/function_calls/check_callback_abi.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: calling a function with ABI C using caller ABI Rust
+error: Undefined Behavior: calling a function with calling convention C using calling convention Rust
--> $DIR/check_callback_abi.rs:LL:CC
|
LL | / std::intrinsics::catch_unwind(
@@ -7,7 +7,7 @@
LL | | std::ptr::null_mut(),
LL | | |_, _| unreachable!(),
LL | | );
- | |_________^ calling a function with ABI C using caller ABI Rust
+ | |_________^ calling a function with calling convention C using calling convention Rust
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr b/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr
index 7274f62..347afa7 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/cast_int_to_fn_ptr.rs:LL:CC
|
LL | g(42)
- | ^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs
deleted file mode 100644
index b6a110e..0000000
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
- let v = [0i8; 4];
- let x = &v as *const i8;
- // The error is inside another function, so we cannot match it by line
- let x = unsafe { x.offset(5) }; //~ERROR: pointer to 5 bytes starting at offset 0 is out-of-bounds
- panic!("this should never print: {:?}", x);
-}
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
deleted file mode 100644
index cc8cca7..0000000
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 5 bytes starting at offset 0 is out-of-bounds
- --> $DIR/out_of_bounds_ptr_1.rs:LL:CC
- |
-LL | let x = unsafe { x.offset(5) };
- | ^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 5 bytes starting at offset 0 is out-of-bounds
- |
- = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
- = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-help: ALLOC was allocated here:
- --> $DIR/out_of_bounds_ptr_1.rs:LL:CC
- |
-LL | let v = [0i8; 4];
- | ^
- = note: BACKTRACE (of the first span):
- = note: inside `main` at $DIR/out_of_bounds_ptr_1.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs
deleted file mode 100644
index 0d4eea9..0000000
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
- let v = [0i8; 4];
- let x = &v as *const i8;
- let x = unsafe { x.offset(isize::MIN) }; //~ERROR: overflowing in-bounds pointer arithmetic
- panic!("this should never print: {:?}", x);
-}
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr
deleted file mode 100644
index 97fa1f1..0000000
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: Undefined Behavior: overflowing in-bounds pointer arithmetic
- --> $DIR/out_of_bounds_ptr_2.rs:LL:CC
- |
-LL | let x = unsafe { x.offset(isize::MIN) };
- | ^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
- |
- = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
- = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
- = note: BACKTRACE:
- = note: inside `main` at $DIR/out_of_bounds_ptr_2.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs
deleted file mode 100644
index 701bc33..0000000
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
- let v = [0i8; 4];
- let x = &v as *const i8;
- let x = unsafe { x.offset(-1) }; //~ERROR: pointer to 1 byte starting at offset -1 is out-of-bounds
- panic!("this should never print: {:?}", x);
-}
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
deleted file mode 100644
index 236b51e..0000000
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 1 byte starting at offset -1 is out-of-bounds
- --> $DIR/out_of_bounds_ptr_3.rs:LL:CC
- |
-LL | let x = unsafe { x.offset(-1) };
- | ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 1 byte starting at offset -1 is out-of-bounds
- |
- = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
- = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-help: ALLOC was allocated here:
- --> $DIR/out_of_bounds_ptr_3.rs:LL:CC
- |
-LL | let v = [0i8; 4];
- | ^
- = note: BACKTRACE (of the first span):
- = note: inside `main` at $DIR/out_of_bounds_ptr_3.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
index 217bc82..84023cf 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
@@ -4,11 +4,11 @@
LL | (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
|
- = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
- = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
- = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
- = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
- = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+ = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+ = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+ = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+ = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+ = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
= note: BACKTRACE:
= note: inside `main` at $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
index 57b4fd0..c307dfd 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
@@ -16,6 +16,6 @@ fn main() {
let _ = p1.byte_offset_from(p1);
// UB because different pointers.
- let _ = p1.byte_offset_from(p2); //~ERROR: different pointers without provenance
+ let _ = p1.byte_offset_from(p2); //~ERROR: no provenance
}
}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
index 6e9e563..bf36c54 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+error: Undefined Behavior: out-of-bounds `offset_from` origin: expected a pointer to the end of 1 byte of memory, but got 0xb[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/ptr_offset_from_different_ints.rs:LL:CC
|
LL | let _ = p1.byte_offset_from(p2);
- | ^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+ | ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of 1 byte of memory, but got 0xb[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs
index 06d13d9..13eb5bf 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs
@@ -1,8 +1,9 @@
+//@normalize-stderr-test: "\d+ < \d+" -> "$$ADDR < $$ADDR"
#![feature(ptr_sub_ptr)]
fn main() {
let arr = [0u8; 8];
let ptr1 = arr.as_ptr();
let ptr2 = ptr1.wrapping_add(4);
- let _val = unsafe { ptr1.sub_ptr(ptr2) }; //~ERROR: first pointer has smaller offset than second: 0 < 4
+ let _val = unsafe { ptr1.sub_ptr(ptr2) }; //~ERROR: first pointer has smaller address than second
}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr
index 0b4a9fa..e436f90 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 4
+error: Undefined Behavior: `ptr_offset_from_unsigned` called when first pointer has smaller address than second: $ADDR < $ADDR
--> $DIR/ptr_offset_from_unsigned_neg.rs:LL:CC
|
LL | let _val = unsafe { ptr1.sub_ptr(ptr2) };
- | ^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 4
+ | ^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller address than second: $ADDR < $ADDR
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr
index e03abfb..8d37da6 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/ptr_offset_int_plus_int.rs:LL:CC
|
LL | let _val = (1 as *mut u8).offset(1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs
index fd3c9b4..29bf61e 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs
@@ -1,4 +1,5 @@
//@compile-flags: -Zmiri-permissive-provenance
+//@normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes"
fn main() {
let ptr = Box::into_raw(Box::new(0u32));
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr
index 03ae9bd..2cd02be 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/ptr_offset_int_plus_ptr.rs:LL:CC
|
LL | let _val = (1 as *mut u8).offset(ptr as isize);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.rs
new file mode 100644
index 0000000..905fc67
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let v = [0i8; 4];
+ let x = &v as *const i8;
+ let x = unsafe { x.offset(5) }; //~ERROR: expected a pointer to 5 bytes of memory
+ panic!("this should never print: {:?}", x);
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.stderr
new file mode 100644
index 0000000..c454820
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation
+ --> $DIR/ptr_offset_out_of_bounds.rs:LL:CC
+ |
+LL | let x = unsafe { x.offset(5) };
+ | ^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+help: ALLOC was allocated here:
+ --> $DIR/ptr_offset_out_of_bounds.rs:LL:CC
+ |
+LL | let v = [0i8; 4];
+ | ^
+ = note: BACKTRACE (of the first span):
+ = note: inside `main` at $DIR/ptr_offset_out_of_bounds.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.rs
new file mode 100644
index 0000000..bd1d5c0
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.rs
@@ -0,0 +1,6 @@
+fn main() {
+ let v = [0i8; 4];
+ let x = &v as *const i8;
+ let x = unsafe { x.offset(-1) }; //~ERROR: expected a pointer to the end of 1 byte of memory
+ panic!("this should never print: {:?}", x);
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.stderr
new file mode 100644
index 0000000..8041e15
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC which is at the beginning of the allocation
+ --> $DIR/ptr_offset_out_of_bounds_neg.rs:LL:CC
+ |
+LL | let x = unsafe { x.offset(-1) };
+ | ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC which is at the beginning of the allocation
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+help: ALLOC was allocated here:
+ --> $DIR/ptr_offset_out_of_bounds_neg.rs:LL:CC
+ |
+LL | let v = [0i8; 4];
+ | ^
+ = note: BACKTRACE (of the first span):
+ = note: inside `main` at $DIR/ptr_offset_out_of_bounds_neg.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs
index c3db1e2..6839431 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs
@@ -1,5 +1,8 @@
+//@normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes"
+
fn main() {
- let v = [1i8, 2];
- let x = &v[1] as *const i8;
- let _val = unsafe { x.offset(isize::MIN) }; //~ERROR: overflowing in-bounds pointer arithmetic
+ let v = [0i8; 4];
+ let x = &v as *const i8;
+ let x = unsafe { x.offset(isize::MIN) }; //~ERROR: out-of-bounds pointer arithmetic
+ panic!("this should never print: {:?}", x);
}
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr
index 122529c..ee5aebc 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr
@@ -1,12 +1,17 @@
-error: Undefined Behavior: overflowing in-bounds pointer arithmetic
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC which is at the beginning of the allocation
--> $DIR/ptr_offset_overflow.rs:LL:CC
|
-LL | let _val = unsafe { x.offset(isize::MIN) };
- | ^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+LL | let x = unsafe { x.offset(isize::MIN) };
+ | ^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC which is at the beginning of the allocation
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
- = note: BACKTRACE:
+help: ALLOC was allocated here:
+ --> $DIR/ptr_offset_overflow.rs:LL:CC
+ |
+LL | let v = [0i8; 4];
+ | ^
+ = note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/ptr_offset_overflow.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs
deleted file mode 100644
index c14f861..0000000
--- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![feature(intrinsics)]
-
-extern "rust-intrinsic" {
- fn raw_eq<T>(a: &T, b: &T) -> bool;
-}
-
-fn main() {
- let x = &0;
- unsafe { raw_eq(&x, &x) }; //~ERROR: `raw_eq` on bytes with provenance
-}
diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr
deleted file mode 100644
index 83f81fa..0000000
--- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: Undefined Behavior: `raw_eq` on bytes with provenance
- --> $DIR/raw_eq_on_ptr.rs:LL:CC
- |
-LL | unsafe { raw_eq(&x, &x) };
- | ^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance
- |
- = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
- = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
- = note: BACKTRACE:
- = note: inside `main` at $DIR/raw_eq_on_ptr.rs:LL:CC
-
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.rs b/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
index ceb7bee..b837395 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
@@ -5,6 +5,7 @@ fn main() {
unsafe {
let vec: &[i8] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
let idxs = Simd::from_array([9, 3, 0, 17]);
- let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0)); //~ERROR: pointer to 1 byte starting at offset 9 is out-of-bounds
+ let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
+ //~^ERROR: expected a pointer to 1 byte of memory
}
}
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
index d111644..bc8d0b0 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
--> $DIR/simd-gather.rs:LL:CC
|
LL | let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
index 98b6749..bb8c9db 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
@@ -6,7 +6,7 @@ fn main() {
let mut vec: Vec<i8> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
let idxs = Simd::from_array([9, 3, 0, 17]);
Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
- //~^ERROR: pointer to 1 byte starting at offset 9 is out-of-bounds
+ //~^ERROR: expected a pointer to 1 byte of memory
&mut vec,
Mask::splat(true),
idxs,
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
index 8b517b6..aae77ed 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
--> $DIR/simd-scatter.rs:LL:CC
|
LL | / Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
@@ -7,7 +7,7 @@
LL | | Mask::splat(true),
LL | | idxs,
LL | | );
- | |_________^ memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+ | |_________^ memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/miri_start_wrong_sig.rs b/src/tools/miri/tests/fail/miri_start_wrong_sig.rs
new file mode 100644
index 0000000..dac83d8
--- /dev/null
+++ b/src/tools/miri/tests/fail/miri_start_wrong_sig.rs
@@ -0,0 +1,21 @@
+//@compile-flags: -Cpanic=abort
+//@error-in-other-file: `miri_start` must have the following signature:
+#![no_main]
+#![no_std]
+
+use core::fmt::Write;
+
+#[path = "../utils/mod.no_std.rs"]
+mod utils;
+
+#[no_mangle]
+fn miri_start() -> isize {
+ //~^ ERROR: mismatched types
+ writeln!(utils::MiriStdout, "Hello from miri_start!").unwrap();
+ 0
+}
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/src/tools/miri/tests/fail/miri_start_wrong_sig.stderr b/src/tools/miri/tests/fail/miri_start_wrong_sig.stderr
new file mode 100644
index 0000000..6217191
--- /dev/null
+++ b/src/tools/miri/tests/fail/miri_start_wrong_sig.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> $DIR/miri_start_wrong_sig.rs:LL:CC
+ |
+LL | fn miri_start() -> isize {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+ |
+ = note: expected signature `fn(isize, *const *const u8) -> _`
+ found signature `fn() -> _`
+
+error: `miri_start` must have the following signature:
+ fn miri_start(argc: isize, argv: *const *const u8) -> isize
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/tools/miri/tests/fail/no_main.rs b/src/tools/miri/tests/fail/no_main.rs
index 01b8c7b..4bbd820 100644
--- a/src/tools/miri/tests/fail/no_main.rs
+++ b/src/tools/miri/tests/fail/no_main.rs
@@ -1,2 +1,2 @@
-//@error-in-other-file: miri can only run programs that have a main function
+//@error-in-other-file: Miri can only run programs that have a main function.
#![no_main]
diff --git a/src/tools/miri/tests/fail/no_main.stderr b/src/tools/miri/tests/fail/no_main.stderr
index 1c4fc88..e9b9e5d 100644
--- a/src/tools/miri/tests/fail/no_main.stderr
+++ b/src/tools/miri/tests/fail/no_main.stderr
@@ -1,4 +1,11 @@
-error: miri can only run programs that have a main function
+error: Miri can only run programs that have a main function.
+ Alternatively, you can export a `miri_start` function:
+
+ #[cfg(miri)]
+ #[no_mangle]
+ fn miri_start(argc: isize, argv: *const *const u8) -> isize {
+ // Call the actual start function that your project implements, based on your target's conventions.
+ }
error: aborting due to 1 previous error
diff --git a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr
index 50bff22..1ca35be 100644
--- a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr
+++ b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/pointer_partial_overwrite.rs:LL:CC
|
LL | let x = *p;
- | ^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
index 6b1c294..8a1d39e 100644
--- a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
+++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/provenance_transmute.rs:LL:CC
|
LL | let _val = *left_ptr;
- | ^^^^^^^^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr
index 92ccec5..e218722 100644
--- a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr
+++ b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/ptr_int_unexposed.rs:LL:CC
|
LL | assert_eq!(unsafe { *ptr }, 3);
- | ^^^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr b/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr
index 8b8033b..bd0a9eb 100644
--- a/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr
+++ b/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/ptr_invalid.rs:LL:CC
|
LL | let _val = unsafe { *xptr_invalid };
- | ^^^^^^^^^^^^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr
index 8ae140e..35e5c08 100644
--- a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr
+++ b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/ptr_invalid_offset.rs:LL:CC
|
LL | let _ = unsafe { roundtrip.offset(1) };
- | ^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.stderr b/src/tools/miri/tests/fail/reading_half_a_pointer.stderr
index 03f9351..cba8a9f 100644
--- a/src/tools/miri/tests/fail/reading_half_a_pointer.stderr
+++ b/src/tools/miri/tests/fail/reading_half_a_pointer.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
--> $DIR/reading_half_a_pointer.rs:LL:CC
|
LL | let _val = *x;
- | ^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+ | ^^ memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs
index 843d0d1..75f7aae 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs
@@ -4,6 +4,6 @@
fn main() {
unsafe {
- miri_resolve_frame(std::ptr::null_mut(), 0); //~ ERROR: null pointer is a dangling pointer
+ miri_resolve_frame(std::ptr::null_mut(), 0); //~ ERROR: got a null pointer
}
}
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr
index 04dbd65..523c935 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
--> $DIR/bad-backtrace-ptr.rs:LL:CC
|
LL | miri_resolve_frame(std::ptr::null_mut(), 0);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr
index 7d000ba..ce9a5b7 100644
--- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr
+++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr
@@ -5,7 +5,7 @@
| RsM | └─┬──<TAG=base>
| RsM | ├─┬──<TAG=x>
| RsM | │ └─┬──<TAG=caller:x>
-| RsM | │ └────<TAG=callee:x> Strongly protected
+| Rs | │ └────<TAG=callee:x> Strongly protected
| RsM | └────<TAG=y, callee:y, caller:y>
──────────────────────────────────────────────────
error: Undefined Behavior: write access through <TAG> (y, callee:y, caller:y) at ALLOC[0x0] is forbidden
@@ -16,14 +16,14 @@
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> (y, callee:y, caller:y) is foreign to the protected tag <TAG> (callee:x) (i.e., it is not a child)
- = help: this foreign write access would cause the protected tag <TAG> (callee:x) (currently Reserved (interior mutable)) to become Disabled
+ = help: this foreign write access would cause the protected tag <TAG> (callee:x) (currently Reserved) to become Disabled
= help: protected tags must never be Disabled
help: the accessed tag <TAG> was created here
--> $DIR/cell-protected-write.rs:LL:CC
|
LL | let y = (&mut *n).get();
| ^^^^^^^^^
-help: the protected tag <TAG> was created here, in the initial state Reserved (interior mutable)
+help: the protected tag <TAG> was created here, in the initial state Reserved
--> $DIR/cell-protected-write.rs:LL:CC
|
LL | unsafe fn write_second(x: &mut UnsafeCell<u8>, y: *mut u8) {
diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs
new file mode 100644
index 0000000..73f227f
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs
@@ -0,0 +1,107 @@
+// Illustrating a problematic interaction between Reserved, interior mutability,
+// and protectors, that makes spurious writes fail in the previous model of Tree Borrows.
+// As for all similar tests, we disable preemption so that the error message is deterministic.
+//@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0
+//
+// One revision without spurious read (default source code) and one with spurious read.
+// Both are expected to be UB. Both revisions are expected to have the *same* error
+// because we are aligning the behavior of `without` to that of `with` so that the
+// spurious write is effectively a noop in the long term.
+//@revisions: without with
+
+use std::cell::Cell;
+use std::sync::{Arc, Barrier};
+use std::thread;
+
+// Here is the problematic interleaving:
+// - thread 1: retag and activate `x` (protected)
+// - thread 2: retag but do not initialize (lazy) `y` as Reserved with interior mutability
+// - thread 1: spurious write through `x` would go here
+// - thread 2: function exit (noop due to lazyness)
+// - thread 1: function exit (no permanent effect on `y` because it is now Reserved IM unprotected)
+// - thread 2: write through `y`
+// In the source code nothing happens to `y`
+
+// `Send`able raw pointer wrapper.
+#[derive(Copy, Clone)]
+struct SendPtr(*mut u8);
+unsafe impl Send for SendPtr {}
+
+type IdxBarrier = (usize, Arc<Barrier>);
+
+// Barriers to enforce the interleaving.
+// This macro expects `synchronized!(thread, msg)` where `thread` is a `IdxBarrier`,
+// and `msg` is the message to be displayed when the thread reaches this point in the execution.
+macro_rules! synchronized {
+ ($thread:expr, $msg:expr) => {{
+ let (thread_id, barrier) = &$thread;
+ eprintln!("Thread {} executing: {}", thread_id, $msg);
+ barrier.wait();
+ }};
+}
+
+fn main() {
+ // The conflict occurs on one single location but the example involves
+ // lazily initialized permissions. We will use `&mut Cell<()>` references
+ // to `data` to achieve this.
+ let mut data = 0u8;
+ let ptr = SendPtr(std::ptr::addr_of_mut!(data));
+ let barrier = Arc::new(Barrier::new(2));
+ let bx = Arc::clone(&barrier);
+ let by = Arc::clone(&barrier);
+
+ // Retag and activate `x`, wait until the other thread creates a lazy permission.
+ // Then do a spurious write. Finally exit the function after the other thread.
+ let thread_1 = thread::spawn(move || {
+ let b = (1, bx);
+ synchronized!(b, "start");
+ let ptr = ptr;
+ synchronized!(b, "retag x (&mut, protect)");
+ fn inner(x: &mut u8, b: IdxBarrier) {
+ *x = 42; // activate immediately
+ synchronized!(b, "[lazy] retag y (&mut, protect, IM)");
+ // A spurious write should be valid here because `x` is
+ // `Active` and protected.
+ if cfg!(with) {
+ synchronized!(b, "spurious write x (executed)");
+ *x = 64;
+ } else {
+ synchronized!(b, "spurious write x (skipped)");
+ }
+ synchronized!(b, "ret y");
+ synchronized!(b, "ret x");
+ }
+ inner(unsafe { &mut *ptr.0 }, b.clone());
+ synchronized!(b, "write y");
+ synchronized!(b, "end");
+ });
+
+ // Create a lazy Reserved with interior mutability.
+ // Wait for the other thread's spurious write then observe the side effects
+ // of that write.
+ let thread_2 = thread::spawn(move || {
+ let b = (2, by);
+ synchronized!(b, "start");
+ let ptr = ptr;
+ synchronized!(b, "retag x (&mut, protect)");
+ synchronized!(b, "[lazy] retag y (&mut, protect, IM)");
+ fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 {
+ synchronized!(b, "spurious write x");
+ synchronized!(b, "ret y");
+ // `y` is not retagged for any bytes, so the pointer we return
+ // has its permission lazily initialized.
+ y as *mut Cell<()> as *mut u8
+ }
+ // Currently `ptr` points to `data`.
+ // We do a zero-sized retag so that its permission is lazy.
+ let y_zst = unsafe { &mut *(ptr.0 as *mut Cell<()>) };
+ let y = inner(y_zst, b.clone());
+ synchronized!(b, "ret x");
+ synchronized!(b, "write y");
+ unsafe { *y = 13 } //~ERROR: /write access through .* is forbidden/
+ synchronized!(b, "end");
+ });
+
+ thread_1.join().unwrap();
+ thread_2.join().unwrap();
+}
diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr
new file mode 100644
index 0000000..0e4517e
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr
@@ -0,0 +1,40 @@
+Thread 1 executing: start
+Thread 2 executing: start
+Thread 2 executing: retag x (&mut, protect)
+Thread 1 executing: retag x (&mut, protect)
+Thread 1 executing: [lazy] retag y (&mut, protect, IM)
+Thread 2 executing: [lazy] retag y (&mut, protect, IM)
+Thread 2 executing: spurious write x
+Thread 1 executing: spurious write x (executed)
+Thread 1 executing: ret y
+Thread 2 executing: ret y
+Thread 2 executing: ret x
+Thread 1 executing: ret x
+Thread 1 executing: write y
+Thread 2 executing: write y
+error: Undefined Behavior: write access through <TAG> at ALLOC[0x0] is forbidden
+ --> $DIR/reservedim_spurious_write.rs:LL:CC
+ |
+LL | unsafe { *y = 13 }
+ | ^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
+ |
+ = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+ = help: the accessed tag <TAG> has state Disabled which forbids this child write access
+help: the accessed tag <TAG> was created here, in the initial state Reserved
+ --> $DIR/reservedim_spurious_write.rs:LL:CC
+ |
+LL | fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 {
+ | ^
+help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x1]
+ --> $DIR/reservedim_spurious_write.rs:LL:CC
+ |
+LL | *x = 64;
+ | ^^^^^^^
+ = help: this transition corresponds to a loss of read and write permissions
+ = note: BACKTRACE (of the first span) on thread `unnamed-ID`:
+ = note: inside closure at $DIR/reservedim_spurious_write.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr
new file mode 100644
index 0000000..cbeef90
--- /dev/null
+++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr
@@ -0,0 +1,40 @@
+Thread 1 executing: start
+Thread 2 executing: start
+Thread 2 executing: retag x (&mut, protect)
+Thread 1 executing: retag x (&mut, protect)
+Thread 1 executing: [lazy] retag y (&mut, protect, IM)
+Thread 2 executing: [lazy] retag y (&mut, protect, IM)
+Thread 2 executing: spurious write x
+Thread 1 executing: spurious write x (skipped)
+Thread 1 executing: ret y
+Thread 2 executing: ret y
+Thread 2 executing: ret x
+Thread 1 executing: ret x
+Thread 1 executing: write y
+Thread 2 executing: write y
+error: Undefined Behavior: write access through <TAG> at ALLOC[0x0] is forbidden
+ --> $DIR/reservedim_spurious_write.rs:LL:CC
+ |
+LL | unsafe { *y = 13 }
+ | ^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
+ |
+ = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+ = help: the accessed tag <TAG> has state Disabled which forbids this child write access
+help: the accessed tag <TAG> was created here, in the initial state Reserved
+ --> $DIR/reservedim_spurious_write.rs:LL:CC
+ |
+LL | fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 {
+ | ^
+help: the accessed tag <TAG> later transitioned to Disabled due to a protector release (acting as a foreign write access) on every location previously accessed by this tag
+ --> $DIR/reservedim_spurious_write.rs:LL:CC
+ |
+LL | }
+ | ^
+ = help: this transition corresponds to a loss of read and write permissions
+ = note: BACKTRACE (of the first span) on thread `unnamed-ID`:
+ = note: inside closure at $DIR/reservedim_spurious_write.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs
new file mode 100644
index 0000000..17b81f2
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs
@@ -0,0 +1,8 @@
+//@compile-flags: -Zmiri-recursive-validation
+
+fn main() {
+ let x = 3u8;
+ let xref = &x;
+ let xref_wrong_type: &bool = unsafe { std::mem::transmute(xref) }; //~ERROR: encountered 0x03, but expected a boolean
+ let _val = *xref_wrong_type;
+}
diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr
new file mode 100644
index 0000000..2b2fa9b
--- /dev/null
+++ b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: constructing invalid value at .<deref>: encountered 0x03, but expected a boolean
+ --> $DIR/recursive-validity-ref-bool.rs:LL:CC
+ |
+LL | let xref_wrong_type: &bool = unsafe { std::mem::transmute(xref) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered 0x03, but expected a boolean
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at $DIR/recursive-validity-ref-bool.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/zst_local_oob.rs b/src/tools/miri/tests/fail/zst_local_oob.rs
index cc81481..ab48b7d 100644
--- a/src/tools/miri/tests/fail/zst_local_oob.rs
+++ b/src/tools/miri/tests/fail/zst_local_oob.rs
@@ -1,5 +1,5 @@
fn main() {
// make sure ZST locals cannot be accessed
let x = &() as *const () as *const i8;
- let _val = unsafe { *x }; //~ ERROR: out-of-bounds
+ let _val = unsafe { *x }; //~ ERROR: expected a pointer to 1 byte of memory
}
diff --git a/src/tools/miri/tests/fail/zst_local_oob.stderr b/src/tools/miri/tests/fail/zst_local_oob.stderr
index ba1ccaa..39ac2c9 100644
--- a/src/tools/miri/tests/fail/zst_local_oob.stderr
+++ b/src/tools/miri/tests/fail/zst_local_oob.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got ALLOC which is at or beyond the end of the allocation of size 0 bytes
--> $DIR/zst_local_oob.rs:LL:CC
|
LL | let _val = unsafe { *x };
- | ^^ memory access failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+ | ^^ memory access failed: expected a pointer to 1 byte of memory, but got ALLOC which is at or beyond the end of the allocation of size 0 bytes
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass-dep/libc/gettid.rs b/src/tools/miri/tests/pass-dep/libc/gettid.rs
new file mode 100644
index 0000000..87405b0
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/gettid.rs
@@ -0,0 +1,22 @@
+//@only-target-linux
+//@revisions: with_isolation without_isolation
+//@[without_isolation] compile-flags: -Zmiri-disable-isolation
+
+use libc::{getpid, gettid};
+use std::thread;
+
+fn main() {
+ thread::spawn(|| {
+ // Test that in isolation mode a deterministic value will be returned.
+ // The value 1001 is not important, we only care that whatever the value
+ // is, won't change from execution to execution.
+ #[cfg(with_isolation)]
+ assert_eq!(unsafe { gettid() }, 1001);
+
+ assert_ne!(unsafe { gettid() }, unsafe { getpid() });
+ });
+
+ // Test that the thread ID of the main thread is the same as the process
+ // ID.
+ assert_eq!(unsafe { gettid() }, unsafe { getpid() });
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
new file mode 100644
index 0000000..3f7f9b1
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
@@ -0,0 +1,70 @@
+//@ignore-target-windows: File handling is not implemented yet
+//@compile-flags: -Zmiri-disable-isolation
+
+use std::{fs::File, io::Error, os::fd::AsRawFd};
+
+#[path = "../../utils/mod.rs"]
+mod utils;
+
+fn main() {
+ let bytes = b"Hello, World!\n";
+ let path = utils::prepare_with_content("miri_test_fs_shared_lock.txt", bytes);
+
+ let files: Vec<File> = (0..3).map(|_| File::open(&path).unwrap()).collect();
+
+ // Test that we can apply many shared locks
+ for file in files.iter() {
+ let fd = file.as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_SH) };
+ if ret != 0 {
+ panic!("flock error: {}", Error::last_os_error());
+ }
+ }
+
+ // Test that shared lock prevents exclusive lock
+ {
+ let fd = files[0].as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) };
+ assert_eq!(ret, -1);
+ let err = Error::last_os_error().raw_os_error().unwrap();
+ assert_eq!(err, libc::EWOULDBLOCK);
+ }
+
+ // Unlock shared lock
+ for file in files.iter() {
+ let fd = file.as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_UN) };
+ if ret != 0 {
+ panic!("flock error: {}", Error::last_os_error());
+ }
+ }
+
+ // Take exclusive lock
+ {
+ let fd = files[0].as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_EX) };
+ assert_eq!(ret, 0);
+ }
+
+ // Test that shared lock prevents exclusive and shared locks
+ {
+ let fd = files[1].as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) };
+ assert_eq!(ret, -1);
+ let err = Error::last_os_error().raw_os_error().unwrap();
+ assert_eq!(err, libc::EWOULDBLOCK);
+
+ let fd = files[2].as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB) };
+ assert_eq!(ret, -1);
+ let err = Error::last_os_error().raw_os_error().unwrap();
+ assert_eq!(err, libc::EWOULDBLOCK);
+ }
+
+ // Unlock exclusive lock
+ {
+ let fd = files[0].as_raw_fd();
+ let ret = unsafe { libc::flock(fd, libc::LOCK_UN) };
+ assert_eq!(ret, 0);
+ }
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-readlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
similarity index 76%
rename from src/tools/miri/tests/pass-dep/libc/libc-fs-readlink.rs
rename to src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
index d72edd7..619c6db 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs-readlink.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs
@@ -11,6 +11,11 @@
mod utils;
fn main() {
+ test_readlink();
+ test_nofollow_symlink();
+}
+
+fn test_readlink() {
let bytes = b"Hello, World!\n";
let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes);
let expected_path = path.as_os_str().as_bytes();
@@ -49,3 +54,18 @@ fn main() {
assert_eq!(res, -1);
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
}
+
+fn test_nofollow_symlink() {
+ let bytes = b"Hello, World!\n";
+ let path = utils::prepare_with_content("test_nofollow_symlink_target.txt", bytes);
+
+ let symlink_path = utils::prepare("test_nofollow_symlink.txt");
+ std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
+
+ let symlink_cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap();
+
+ let ret = unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) };
+ assert_eq!(ret, -1);
+ let err = Error::last_os_error().raw_os_error().unwrap();
+ assert_eq!(err, libc::ELOOP);
+}
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs
index eddea92..5b2bbfb 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs
@@ -37,6 +37,7 @@ fn main() {
test_sync_file_range();
test_isatty();
test_read_and_uninit();
+ test_nofollow_not_symlink();
}
fn test_file_open_unix_allow_two_args() {
@@ -423,3 +424,11 @@ fn test_read_and_uninit() {
remove_file(&path).unwrap();
}
}
+
+fn test_nofollow_not_symlink() {
+ let bytes = b"Hello, World!\n";
+ let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes);
+ let cpath = CString::new(path.as_os_str().as_bytes()).unwrap();
+ let ret = unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) };
+ assert!(ret >= 0);
+}
diff --git a/src/tools/miri/tests/pass/adjacent-allocs.rs b/src/tools/miri/tests/pass/adjacent-allocs.rs
index 8be4bda..711c54f 100644
--- a/src/tools/miri/tests/pass/adjacent-allocs.rs
+++ b/src/tools/miri/tests/pass/adjacent-allocs.rs
@@ -1,5 +1,3 @@
-//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows
//@compile-flags: -Zmiri-permissive-provenance
fn ensure_allocs_can_be_adjacent() {
diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs
index a226783..40b8e23 100644
--- a/src/tools/miri/tests/pass/alloc-access-tracking.rs
+++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs
@@ -1,7 +1,7 @@
#![feature(start)]
#![no_std]
-//@compile-flags: -Zmiri-track-alloc-id=20 -Zmiri-track-alloc-accesses -Cpanic=abort
-//@normalize-stderr-test: "id 20" -> "id $$ALLOC"
+//@compile-flags: -Zmiri-track-alloc-id=21 -Zmiri-track-alloc-accesses -Cpanic=abort
+//@normalize-stderr-test: "id 21" -> "id $$ALLOC"
//@only-target-linux: alloc IDs differ between OSes (due to extern static allocations)
extern "Rust" {
diff --git a/src/tools/miri/tests/pass/async-fn.rs b/src/tools/miri/tests/pass/async-fn.rs
index 13400c8..67ec2e2 100644
--- a/src/tools/miri/tests/pass/async-fn.rs
+++ b/src/tools/miri/tests/pass/async-fn.rs
@@ -59,6 +59,7 @@ async fn hello_world() {
}
// This example comes from https://github.com/rust-lang/rust/issues/115145
+#[allow(unreachable_patterns)]
async fn uninhabited_variant() {
async fn unreachable(_: Never) {}
diff --git a/src/tools/miri/tests/pass/box.rs b/src/tools/miri/tests/pass/box.rs
index 174bf8b..693209c 100644
--- a/src/tools/miri/tests/pass/box.rs
+++ b/src/tools/miri/tests/pass/box.rs
@@ -1,5 +1,4 @@
-//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance
+//@compile-flags: -Zmiri-permissive-provenance
#![feature(ptr_internals)]
fn main() {
diff --git a/src/tools/miri/tests/pass/box.stack.stderr b/src/tools/miri/tests/pass/box.stack.stderr
deleted file mode 100644
index 341f84c..0000000
--- a/src/tools/miri/tests/pass/box.stack.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-warning: integer-to-pointer cast
- --> $DIR/box.rs:LL:CC
- |
-LL | let r2 = ((r as usize) + 0) as *mut i32;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
- |
- = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
- = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
- = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
- = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
- = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
- = note: BACKTRACE:
- = note: inside `into_raw` at $DIR/box.rs:LL:CC
-note: inside `main`
- --> $DIR/box.rs:LL:CC
- |
-LL | into_raw();
- | ^^^^^^^^^^
-
-warning: integer-to-pointer cast
- --> $DIR/box.rs:LL:CC
- |
-LL | let r = ((u.as_ptr() as usize) + 0) as *mut i32;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
- |
- = note: BACKTRACE:
- = note: inside `into_unique` at $DIR/box.rs:LL:CC
-note: inside `main`
- --> $DIR/box.rs:LL:CC
- |
-LL | into_unique();
- | ^^^^^^^^^^^^^
-
diff --git a/src/tools/miri/tests/pass/box.stack.stdout b/src/tools/miri/tests/pass/box.stack.stdout
deleted file mode 100644
index 230ef36..0000000
--- a/src/tools/miri/tests/pass/box.stack.stdout
+++ /dev/null
@@ -1,3 +0,0 @@
-pair_foo = PairFoo { fst: Foo(42), snd: Foo(1337) }
-foo #0 = Foo(42)
-foo #1 = Foo(1337)
diff --git a/src/tools/miri/tests/pass/box.tree.stdout b/src/tools/miri/tests/pass/box.stdout
similarity index 100%
rename from src/tools/miri/tests/pass/box.tree.stdout
rename to src/tools/miri/tests/pass/box.stdout
diff --git a/src/tools/miri/tests/pass/dyn-traits.rs b/src/tools/miri/tests/pass/dyn-traits.rs
index 908d521..f622012 100644
--- a/src/tools/miri/tests/pass/dyn-traits.rs
+++ b/src/tools/miri/tests/pass/dyn-traits.rs
@@ -141,7 +141,17 @@ fn foo(mut self) -> String {
}
*/
+fn vtable_ptr_eq() {
+ use std::{fmt, ptr};
+
+ // We don't always get the same vtable when casting this to a wide pointer.
+ let x = &2;
+ let x_wide = x as &dyn fmt::Display;
+ assert!((0..256).any(|_| !ptr::eq(x as &dyn fmt::Display, x_wide)));
+}
+
fn main() {
ref_box_dyn();
box_box_trait();
+ vtable_ptr_eq();
}
diff --git a/src/tools/miri/tests/pass/enums.rs b/src/tools/miri/tests/pass/enums.rs
index ac7aafc..1dafef0 100644
--- a/src/tools/miri/tests/pass/enums.rs
+++ b/src/tools/miri/tests/pass/enums.rs
@@ -43,6 +43,7 @@ enum Foo {
}
}
+#[allow(unreachable_patterns)]
fn more_discriminant_overflow() {
pub enum Infallible {}
diff --git a/src/tools/miri/tests/pass/extern_types.rs b/src/tools/miri/tests/pass/extern_types.rs
index 7ac9357..eade5c6 100644
--- a/src/tools/miri/tests/pass/extern_types.rs
+++ b/src/tools/miri/tests/pass/extern_types.rs
@@ -1,12 +1,14 @@
//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance
-#![feature(extern_types)]
+//@[tree]compile-flags: -Zmiri-tree-borrows
+#![feature(extern_types, strict_provenance)]
+
+use std::ptr;
extern "C" {
type Foo;
}
fn main() {
- let x: &Foo = unsafe { &*(16 as *const Foo) };
+ let x: &Foo = unsafe { &*(ptr::without_provenance::<()>(16) as *const Foo) };
let _y: &Foo = &*x;
}
diff --git a/src/tools/miri/tests/pass/extern_types.stack.stderr b/src/tools/miri/tests/pass/extern_types.stack.stderr
index 03a9167..2c9fc01 100644
--- a/src/tools/miri/tests/pass/extern_types.stack.stderr
+++ b/src/tools/miri/tests/pass/extern_types.stack.stderr
@@ -1,14 +1,11 @@
-warning: integer-to-pointer cast
+warning: reborrow of reference to `extern type`
--> $DIR/extern_types.rs:LL:CC
|
-LL | let x: &Foo = unsafe { &*(16 as *const Foo) };
- | ^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+LL | let x: &Foo = unsafe { &*(ptr::without_provenance::<()>(16) as *const Foo) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported
|
- = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
- = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
- = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
- = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
- = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+ = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code
+ = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead
= note: BACKTRACE:
= note: inside `main` at $DIR/extern_types.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs
index 2aa3ebf..a5c4bc5 100644
--- a/src/tools/miri/tests/pass/function_pointers.rs
+++ b/src/tools/miri/tests/pass/function_pointers.rs
@@ -82,7 +82,8 @@ fn main() {
assert!(return_fn_ptr(i) == i);
assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32);
// Miri gives different addresses to different reifications of a generic function.
- assert!(return_fn_ptr(f) != f);
+ // at least if we try often enough.
+ assert!((0..256).any(|_| return_fn_ptr(f) != f));
// However, if we only turn `f` into a function pointer and use that pointer,
// it is equal to itself.
let f2 = f as fn() -> i32;
diff --git a/src/tools/miri/tests/pass/getpid.rs b/src/tools/miri/tests/pass/getpid.rs
index 7335454..f350faf 100644
--- a/src/tools/miri/tests/pass/getpid.rs
+++ b/src/tools/miri/tests/pass/getpid.rs
@@ -1,9 +1,20 @@
-//@compile-flags: -Zmiri-disable-isolation
+//@revisions: with_isolation without_isolation
+//@[without_isolation] compile-flags: -Zmiri-disable-isolation
fn getpid() -> u32 {
std::process::id()
}
fn main() {
- getpid();
+ let pid = getpid();
+
+ std::thread::spawn(move || {
+ assert_eq!(getpid(), pid);
+ });
+
+ // Test that in isolation mode a deterministic value will be returned.
+ // The value 1000 is not important, we only care that whatever the value
+ // is, won't change from execution to execution.
+ #[cfg(with_isolation)]
+ assert_eq!(pid, 1000);
}
diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs
index fb1a1df..a304f27 100644
--- a/src/tools/miri/tests/pass/intptrcast.rs
+++ b/src/tools/miri/tests/pass/intptrcast.rs
@@ -1,5 +1,3 @@
-//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows
//@compile-flags: -Zmiri-permissive-provenance
use std::mem;
diff --git a/src/tools/miri/tests/pass/miri_start.rs b/src/tools/miri/tests/pass/miri_start.rs
new file mode 100644
index 0000000..756a1f60
--- /dev/null
+++ b/src/tools/miri/tests/pass/miri_start.rs
@@ -0,0 +1,19 @@
+//@compile-flags: -Cpanic=abort
+#![no_main]
+#![no_std]
+
+use core::fmt::Write;
+
+#[path = "../utils/mod.no_std.rs"]
+mod utils;
+
+#[no_mangle]
+fn miri_start(_argc: isize, _argv: *const *const u8) -> isize {
+ writeln!(utils::MiriStdout, "Hello from miri_start!").unwrap();
+ 0
+}
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
diff --git a/src/tools/miri/tests/pass/miri_start.stdout b/src/tools/miri/tests/pass/miri_start.stdout
new file mode 100644
index 0000000..1c9e848
--- /dev/null
+++ b/src/tools/miri/tests/pass/miri_start.stdout
@@ -0,0 +1 @@
+Hello from miri_start!
diff --git a/src/tools/miri/tests/pass/pointers.rs b/src/tools/miri/tests/pass/pointers.rs
index c7b720d..280a815 100644
--- a/src/tools/miri/tests/pass/pointers.rs
+++ b/src/tools/miri/tests/pass/pointers.rs
@@ -1,5 +1,3 @@
-//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows
//@compile-flags: -Zmiri-permissive-provenance
#![feature(ptr_metadata, const_raw_ptr_comparison)]
#![allow(ambiguous_wide_pointer_comparisons)]
diff --git a/src/tools/miri/tests/pass/ptr_int_casts.rs b/src/tools/miri/tests/pass/ptr_int_casts.rs
index a2fcd09..684e8f6 100644
--- a/src/tools/miri/tests/pass/ptr_int_casts.rs
+++ b/src/tools/miri/tests/pass/ptr_int_casts.rs
@@ -1,6 +1,7 @@
//@revisions: stack tree
+// Tree Borrows doesn't support int2ptr casts, but let's make sure we don't immediately crash either.
//@[tree]compile-flags: -Zmiri-tree-borrows
-//@compile-flags: -Zmiri-permissive-provenance
+//@[stack]compile-flags: -Zmiri-permissive-provenance
use std::mem;
use std::ptr;
diff --git a/src/tools/miri/tests/pass/ptr_int_casts.tree.stderr b/src/tools/miri/tests/pass/ptr_int_casts.tree.stderr
new file mode 100644
index 0000000..a34474e
--- /dev/null
+++ b/src/tools/miri/tests/pass/ptr_int_casts.tree.stderr
@@ -0,0 +1,89 @@
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | assert_eq!(1 as *const i32 as usize, 1);
+ | ^^^^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+ = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+ = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+ = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+ = help: Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used
+ = note: BACKTRACE:
+ = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | ptr_int_casts();
+ | ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | assert_eq!((1 as *const i32).wrapping_offset(4) as usize, 1 + 4 * 4);
+ | ^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = note: BACKTRACE:
+ = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | ptr_int_casts();
+ | ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | *val = (1 as *const u8).wrapping_offset(-4);
+ | ^^^^^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = note: BACKTRACE:
+ = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | ptr_int_casts();
+ | ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | let y = y as *const _;
+ | ^^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = note: BACKTRACE:
+ = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | ptr_int_casts();
+ | ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | let x: fn() -> i32 = unsafe { mem::transmute(y as *mut u8) };
+ | ^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = note: BACKTRACE:
+ = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | ptr_int_casts();
+ | ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | assert_eq!((-1i32) as usize as *const i32 as usize, (-1i32) as usize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = note: BACKTRACE:
+ = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_casts.rs:LL:CC
+ |
+LL | ptr_int_casts();
+ | ^^^^^^^^^^^^^^^
+
diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
index 5690d78..ade5f53 100644
--- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
+++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
@@ -1,6 +1,7 @@
//@revisions: stack tree
+// Tree Borrows doesn't support int2ptr casts, but let's make sure we don't immediately crash either.
//@[tree]compile-flags: -Zmiri-tree-borrows
-//@compile-flags: -Zmiri-permissive-provenance
+//@[stack]compile-flags: -Zmiri-permissive-provenance
#![feature(strict_provenance, exposed_provenance)]
use std::ptr;
@@ -56,9 +57,18 @@ fn ptr_roundtrip_null() {
assert_eq!(unsafe { *x_ptr_copy }, 42);
}
+fn ptr_roundtrip_offset_from() {
+ let arr = [0; 5];
+ let begin = arr.as_ptr();
+ let end = begin.wrapping_add(arr.len());
+ let end_roundtrip = ptr::with_exposed_provenance::<i32>(end.expose_provenance());
+ unsafe { end_roundtrip.offset_from(begin) };
+}
+
fn main() {
ptr_roundtrip_out_of_bounds();
ptr_roundtrip_confusion();
ptr_roundtrip_imperfect();
ptr_roundtrip_null();
+ ptr_roundtrip_offset_from();
}
diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.tree.stderr b/src/tools/miri/tests/pass/ptr_int_from_exposed.tree.stderr
new file mode 100644
index 0000000..614b0d2
--- /dev/null
+++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.tree.stderr
@@ -0,0 +1,19 @@
+warning: integer-to-pointer cast
+ --> $DIR/ptr_int_from_exposed.rs:LL:CC
+ |
+LL | let ptr = ptr::with_exposed_provenance::<i32>(x_usize).wrapping_offset(-128);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+ |
+ = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+ = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+ = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+ = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+ = help: Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used
+ = note: BACKTRACE:
+ = note: inside `ptr_roundtrip_out_of_bounds` at $DIR/ptr_int_from_exposed.rs:LL:CC
+note: inside `main`
+ --> $DIR/ptr_int_from_exposed.rs:LL:CC
+ |
+LL | ptr_roundtrip_out_of_bounds();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs
index 6dd1b3a..b1470da 100644
--- a/src/tools/miri/tests/pass/rc.rs
+++ b/src/tools/miri/tests/pass/rc.rs
@@ -75,7 +75,8 @@ fn rc_fat_ptr_eq() {
let p = Rc::new(1) as Rc<dyn Debug>;
let a: *const dyn Debug = &*p;
let r = Rc::into_raw(p);
- assert!(a == r);
+ // Only compare the pointer parts, as the vtable might differ.
+ assert!(a as *const () == r as *const ());
drop(unsafe { Rc::from_raw(r) });
}
diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs
index 16d3e8c..70e375b 100644
--- a/src/tools/miri/tests/pass/shims/fs.rs
+++ b/src/tools/miri/tests/pass/shims/fs.rs
@@ -30,6 +30,8 @@ fn main() {
test_directory();
test_canonicalize();
test_from_raw_os_error();
+ #[cfg(unix)]
+ test_pread_pwrite();
}
fn test_path_conversion() {
@@ -303,3 +305,42 @@ fn test_from_raw_os_error() {
// Make sure we can also format this.
let _ = format!("{error:?}");
}
+
+#[cfg(unix)]
+fn test_pread_pwrite() {
+ use std::os::unix::fs::FileExt;
+
+ let bytes = b"hello world";
+ let path = utils::prepare_with_content("miri_test_fs_pread_pwrite.txt", bytes);
+ let mut f = OpenOptions::new().read(true).write(true).open(path).unwrap();
+
+ let mut buf1 = [0u8; 3];
+ f.seek(SeekFrom::Start(5)).unwrap();
+
+ // Check that we get expected result after seek
+ f.read_exact(&mut buf1).unwrap();
+ assert_eq!(&buf1, b" wo");
+ f.seek(SeekFrom::Start(5)).unwrap();
+
+ // Check pread
+ f.read_exact_at(&mut buf1, 2).unwrap();
+ assert_eq!(&buf1, b"llo");
+ f.read_exact_at(&mut buf1, 6).unwrap();
+ assert_eq!(&buf1, b"wor");
+
+ // Ensure that cursor position is not changed
+ f.read_exact(&mut buf1).unwrap();
+ assert_eq!(&buf1, b" wo");
+ f.seek(SeekFrom::Start(5)).unwrap();
+
+ // Check pwrite
+ f.write_all_at(b" mo", 6).unwrap();
+
+ let mut buf2 = [0u8; 11];
+ f.read_exact_at(&mut buf2, 0).unwrap();
+ assert_eq!(&buf2, b"hello mold");
+
+ // Ensure that cursor position is not changed
+ f.read_exact(&mut buf1).unwrap();
+ assert_eq!(&buf1, b" m");
+}
diff --git a/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr b/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr
index b0e1adf..216bb6c 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr
+++ b/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr
@@ -4,11 +4,11 @@
LL | let wildcard = &root0 as *const Cell<i32> as usize as *const Cell<i32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
|
- = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
- = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
- = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
- = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
- = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+ = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+ = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+ = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+ = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+ = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
= note: BACKTRACE:
= note: inside `main` at $DIR/issue-miri-2389.rs:LL:CC
diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr
index 0d0d52c..d149a40 100644
--- a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr
+++ b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr
@@ -6,7 +6,7 @@
| RsM | └─┬──<TAG=base>
| RsM | ├─┬──<TAG=x>
| RsM | │ └─┬──<TAG=caller:x>
-| RsCM| │ └────<TAG=callee:x>
+| RsC | │ └────<TAG=callee:x>
| RsM | └────<TAG=y, caller:y, callee:y>
──────────────────────────────────────────────────
[interior mut] Foreign Read: Re* -> Re*
diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs
index 05090d6..9debe22 100644
--- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs
+++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.rs
@@ -1,3 +1,5 @@
+// FIXME: This test is broken since https://github.com/rust-lang/rust/pull/126793,
+// possibly related to the additional struct between Vec and Unique.
//@revisions: default uniq
// We disable the GC for this test because it would change what is printed.
//@compile-flags: -Zmiri-tree-borrows -Zmiri-provenance-gc=0
diff --git a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr
index 7942e98..e3796a7 100644
--- a/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr
+++ b/src/tools/miri/tests/pass/tree_borrows/vec_unique.uniq.stderr
@@ -2,7 +2,9 @@
Warning: this tree is indicative only. Some tags may have been hidden.
0.. 2
| Act | └─┬──<TAG=root of the allocation>
-|-----| └─┬──<TAG=base.as_ptr(), base.as_ptr()>
-|-----| └─┬──<TAG=raw_parts.0>
-|-----| └────<TAG=reconstructed.as_ptr(), reconstructed.as_ptr()>
+|-----| ├────<TAG=base.as_ptr()>
+|-----| ├────<TAG=base.as_ptr()>
+|-----| └─┬──<TAG=raw_parts.0>
+|-----| ├────<TAG=reconstructed.as_ptr()>
+|-----| └────<TAG=reconstructed.as_ptr()>
──────────────────────────────────────────────────
diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs
index 3a8b098..95f8b05 100644
--- a/src/tools/miri/tests/ui.rs
+++ b/src/tools/miri/tests/ui.rs
@@ -73,7 +73,7 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
stdout_filters: stdout_filters().into(),
mode,
program,
- out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"),
+ out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("miri_ui"),
edition: Some("2021".into()), // keep in sync with `./miri run`
threads: std::env::var("MIRI_TEST_THREADS")
.ok()
diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml
index 88e8640..d34f8ad 100644
--- a/src/tools/opt-dist/Cargo.toml
+++ b/src/tools/opt-dist/Cargo.toml
@@ -10,7 +10,7 @@
anyhow = { version = "1", features = ["backtrace"] }
humantime = "2"
humansize = "2"
-sysinfo = { version = "0.30", default-features = false }
+sysinfo = { version = "0.31.2", default-features = false, features = ["disk"] }
fs_extra = "1"
camino = "1"
tar = "0.4"
diff --git a/src/tools/opt-dist/src/bolt.rs b/src/tools/opt-dist/src/bolt.rs
index eb10426..d9efbb8 100644
--- a/src/tools/opt-dist/src/bolt.rs
+++ b/src/tools/opt-dist/src/bolt.rs
@@ -1,9 +1,8 @@
use anyhow::Context;
+use camino::{Utf8Path, Utf8PathBuf};
use crate::exec::cmd;
use crate::training::BoltProfile;
-use camino::{Utf8Path, Utf8PathBuf};
-
use crate::utils::io::copy_file;
/// Instruments an artifact at the given `path` (in-place) with BOLT and then calls `func`.
diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs
index 90a045e..e50f260 100644
--- a/src/tools/opt-dist/src/exec.rs
+++ b/src/tools/opt-dist/src/exec.rs
@@ -1,11 +1,13 @@
+use std::collections::BTreeMap;
+use std::fs::File;
+use std::process::{Command, Stdio};
+
+use camino::{Utf8Path, Utf8PathBuf};
+
use crate::environment::Environment;
use crate::metrics::{load_metrics, record_metrics};
use crate::timer::TimerSection;
use crate::training::{BoltProfile, LlvmPGOProfile, RustcPGOProfile};
-use camino::{Utf8Path, Utf8PathBuf};
-use std::collections::BTreeMap;
-use std::fs::File;
-use std::process::{Command, Stdio};
#[derive(Default)]
pub struct CmdBuilder {
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index e4271a6..73389f9 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -1,10 +1,10 @@
-use crate::bolt::{bolt_optimize, with_bolt_instrumented};
use anyhow::Context;
use camino::{Utf8Path, Utf8PathBuf};
use clap::Parser;
use log::LevelFilter;
use utils::io;
+use crate::bolt::{bolt_optimize, with_bolt_instrumented};
use crate::environment::{Environment, EnvironmentBuilder};
use crate::exec::{cmd, Bootstrap};
use crate::tests::run_tests;
diff --git a/src/tools/opt-dist/src/metrics.rs b/src/tools/opt-dist/src/metrics.rs
index cabe07e..89c4cb1 100644
--- a/src/tools/opt-dist/src/metrics.rs
+++ b/src/tools/opt-dist/src/metrics.rs
@@ -1,7 +1,9 @@
-use crate::timer::TimerSection;
+use std::time::Duration;
+
use build_helper::metrics::{JsonNode, JsonRoot};
use camino::Utf8Path;
-use std::time::Duration;
+
+use crate::timer::TimerSection;
#[derive(Clone, Debug)]
pub struct BuildStep {
diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs
index d03d193..30c9648 100644
--- a/src/tools/opt-dist/src/tests.rs
+++ b/src/tools/opt-dist/src/tests.rs
@@ -1,8 +1,9 @@
+use anyhow::Context;
+use camino::{Utf8Path, Utf8PathBuf};
+
use crate::environment::{executable_extension, Environment};
use crate::exec::cmd;
use crate::utils::io::{copy_directory, find_file_in_dir, unpack_archive};
-use anyhow::Context;
-use camino::{Utf8Path, Utf8PathBuf};
/// Run tests on optimized dist artifacts.
pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
@@ -59,17 +60,26 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
.join(format!("llvm-config{}", executable_extension()));
assert!(llvm_config.is_file());
- let rustc = format!("build.rustc={}", rustc_path.to_string().replace('\\', "/"));
- let cargo = format!("build.cargo={}", cargo_path.to_string().replace('\\', "/"));
- let llvm_config =
- format!("target.{host_triple}.llvm-config={}", llvm_config.to_string().replace('\\', "/"));
+ let config_content = format!(
+ r#"profile = "user"
+change-id = 115898
- log::info!("Set the following configurations for running tests:");
- log::info!("\t{rustc}");
- log::info!("\t{cargo}");
- log::info!("\t{llvm_config}");
+[build]
+rustc = "{rustc}"
+cargo = "{cargo}"
+
+[target.{host_triple}]
+llvm-config = "{llvm_config}"
+"#,
+ rustc = rustc_path.to_string().replace('\\', "/"),
+ cargo = cargo_path.to_string().replace('\\', "/"),
+ llvm_config = llvm_config.to_string().replace('\\', "/")
+ );
+ log::info!("Using following `config.toml` for running tests:\n{config_content}");
// Simulate a stage 0 compiler with the extracted optimized dist artifacts.
+ std::fs::write("config.toml", config_content)?;
+
let x_py = env.checkout_path().join("x.py");
let mut args = vec![
env.python_binary(),
@@ -88,12 +98,6 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
"tests/run-pass-valgrind",
"tests/ui",
"tests/crashes",
- "--set",
- &rustc,
- "--set",
- &cargo,
- "--set",
- &llvm_config,
];
for test_path in env.skipped_tests() {
args.extend(["--skip", test_path]);
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 1237951..97e8ec5 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -1,12 +1,13 @@
-use crate::environment::{executable_extension, Environment};
-use crate::exec::{cmd, CmdBuilder};
-use crate::utils::io::{count_files, delete_directory};
-use crate::utils::with_log_group;
use anyhow::Context;
use build_helper::{LLVM_PGO_CRATES, RUSTC_PGO_CRATES};
use camino::{Utf8Path, Utf8PathBuf};
use humansize::BINARY;
+use crate::environment::{executable_extension, Environment};
+use crate::exec::{cmd, CmdBuilder};
+use crate::utils::io::{count_files, delete_directory};
+use crate::utils::with_log_group;
+
fn init_compiler_benchmarks(
env: &Environment,
profiles: &[&str],
diff --git a/src/tools/opt-dist/src/utils/artifact_size.rs b/src/tools/opt-dist/src/utils/artifact_size.rs
index b6c453f..e51b5f0 100644
--- a/src/tools/opt-dist/src/utils/artifact_size.rs
+++ b/src/tools/opt-dist/src/utils/artifact_size.rs
@@ -9,10 +9,10 @@
use crate::utils::io::get_files_from_dir;
pub fn print_binary_sizes(env: &Environment) -> anyhow::Result<()> {
- use humansize::format_size;
- use humansize::BINARY;
use std::fmt::Write;
+ use humansize::{format_size, BINARY};
+
let root = env.build_artifacts().join("stage2");
let mut files = get_files_from_dir(&root.join("bin"), None)?;
diff --git a/src/tools/opt-dist/src/utils/io.rs b/src/tools/opt-dist/src/utils/io.rs
index d6bd5cb..ce425bd 100644
--- a/src/tools/opt-dist/src/utils/io.rs
+++ b/src/tools/opt-dist/src/utils/io.rs
@@ -1,8 +1,9 @@
+use std::fs::File;
+use std::path::Path;
+
use anyhow::Context;
use camino::{Utf8Path, Utf8PathBuf};
use fs_extra::dir::CopyOptions;
-use std::fs::File;
-use std::path::Path;
/// Delete and re-create the directory.
pub fn reset_directory(path: &Utf8Path) -> anyhow::Result<()> {
diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs
index 22b0483..32d88a5 100644
--- a/src/tools/opt-dist/src/utils/mod.rs
+++ b/src/tools/opt-dist/src/utils/mod.rs
@@ -1,10 +1,11 @@
+use std::time::Duration;
+
+use humansize::BINARY;
use sysinfo::Disks;
use crate::environment::Environment;
use crate::timer::Timer;
use crate::utils::io::delete_directory;
-use humansize::BINARY;
-use std::time::Duration;
pub mod artifact_size;
pub mod io;
diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs
index 42de3ca..bda0842 100644
--- a/src/tools/remote-test-client/src/main.rs
+++ b/src/tools/remote-test-client/src/main.rs
@@ -5,15 +5,14 @@
//! Here is also where we bake in the support to spawn the QEMU emulator as
//! well.
-use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufWriter};
use std::net::TcpStream;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
-use std::thread;
use std::time::Duration;
+use std::{env, thread};
const REMOTE_ADDR_ENV: &str = "TEST_DEVICE_ADDR";
const DEFAULT_ADDR: &str = "127.0.0.1:12345";
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index 79f96c5..67a7ad6 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -12,22 +12,17 @@
#[cfg(not(windows))]
use std::fs::Permissions;
-use std::net::SocketAddr;
-#[cfg(not(windows))]
-use std::os::unix::prelude::*;
-
-use std::cmp;
-use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::{self, BufReader};
-use std::net::{TcpListener, TcpStream};
+use std::net::{SocketAddr, TcpListener, TcpStream};
+#[cfg(not(windows))]
+use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus, Stdio};
-use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
-use std::thread;
+use std::{cmp, env, str, thread};
macro_rules! t {
($e:expr) => {
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 5c9c18b..247e4e7 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -1,4 +1,5 @@
use std::path::PathBuf;
+
use tidy::{t, walk};
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
diff --git a/src/tools/rls/src/main.rs b/src/tools/rls/src/main.rs
index d7be108..3a95b47 100644
--- a/src/tools/rls/src/main.rs
+++ b/src/tools/rls/src/main.rs
@@ -3,10 +3,10 @@
//! This is a small stub that replaces RLS to alert the user that RLS is no
//! longer available.
-use serde_json::Value;
use std::error::Error;
-use std::io::BufRead;
-use std::io::Write;
+use std::io::{BufRead, Write};
+
+use serde_json::Value;
const ALERT_MSG: &str = "\
RLS is no longer available as of Rust 1.65.
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index b391373..c4d5446 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -5,9 +5,9 @@
[dependencies]
bstr = "1.6.0"
-object = "0.34.0"
+object = "0.36.2"
similar = "2.5.0"
-wasmparser = "0.118.2"
+wasmparser = { version = "0.214", default-features = false, features = ["std"] }
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
gimli = "0.31.0"
build_helper = { path = "../build_helper" }
diff --git a/src/tools/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs
index bc6ec75..0d7b5cb9 100644
--- a/src/tools/run-make-support/src/artifact_names.rs
+++ b/src/tools/run-make-support/src/artifact_names.rs
@@ -38,6 +38,17 @@ pub fn dynamic_lib_name(name: &str) -> String {
format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION)
}
+/// Construct the name of the import library for the dynamic library, exclusive to MSVC and
+/// accepted by link.exe.
+#[track_caller]
+#[must_use]
+pub fn msvc_import_dynamic_lib_name(name: &str) -> String {
+ assert!(is_msvc(), "this function is exclusive to MSVC");
+ assert!(!name.contains(char::is_whitespace), "import library name cannot contain whitespace");
+
+ format!("{name}.dll.lib")
+}
+
/// Construct the dynamic library extension based on the target.
#[must_use]
pub fn dynamic_lib_extension() -> &'static str {
diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs
index 4b5b349..6d256fc 100644
--- a/src/tools/run-make-support/src/assertion_helpers.rs
+++ b/src/tools/run-make-support/src/assertion_helpers.rs
@@ -3,7 +3,7 @@
use std::panic;
use std::path::Path;
-use crate::fs;
+use crate::{fs, regex};
/// Assert that `actual` is equal to `expected`.
#[track_caller]
@@ -47,6 +47,36 @@ pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N)
}
}
+/// Assert that `haystack` contains the regex pattern `needle`.
+#[track_caller]
+pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+ let haystack = haystack.as_ref();
+ let needle = needle.as_ref();
+ let re = regex::Regex::new(needle).unwrap();
+ if !re.is_match(haystack) {
+ eprintln!("=== HAYSTACK ===");
+ eprintln!("{}", haystack);
+ eprintln!("=== NEEDLE ===");
+ eprintln!("{}", needle);
+ panic!("needle was not found in haystack");
+ }
+}
+
+/// Assert that `haystack` does not contain the regex pattern `needle`.
+#[track_caller]
+pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
+ let haystack = haystack.as_ref();
+ let needle = needle.as_ref();
+ let re = regex::Regex::new(needle).unwrap();
+ if re.is_match(haystack) {
+ eprintln!("=== HAYSTACK ===");
+ eprintln!("{}", haystack);
+ eprintln!("=== NEEDLE ===");
+ eprintln!("{}", needle);
+ panic!("needle was unexpectedly found in haystack");
+ }
+}
+
/// Assert that all files in `dir1` exist and have the same content in `dir2`
pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
let dir2 = dir2.as_ref();
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index 47376c4..a0b96e2 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -1,15 +1,17 @@
-use std::ffi;
use std::ffi::OsStr;
use std::io::Write;
-use std::panic;
use std::path::Path;
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
-
-use crate::util::handle_failed_output;
-use crate::{assert_contains, assert_equals, assert_not_contains};
+use std::{ffi, panic};
use build_helper::drop_bomb::DropBomb;
+use crate::util::handle_failed_output;
+use crate::{
+ assert_contains, assert_contains_regex, assert_equals, assert_not_contains,
+ assert_not_contains_regex,
+};
+
/// This is a custom command wrapper that simplifies working with commands and makes it easier to
/// ensure that we check the exit status of executed processes.
///
@@ -164,11 +166,19 @@ pub struct CompletedProcess {
impl CompletedProcess {
#[must_use]
+ #[track_caller]
pub fn stdout_utf8(&self) -> String {
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
}
#[must_use]
+ #[track_caller]
+ pub fn invalid_stdout_utf8(&self) -> String {
+ String::from_utf8_lossy(&self.output.stdout.clone()).to_string()
+ }
+
+ #[must_use]
+ #[track_caller]
pub fn stderr_utf8(&self) -> String {
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
}
@@ -192,6 +202,13 @@ pub fn assert_stdout_not_contains<S: AsRef<str>>(&self, unexpected: S) -> &Self
self
}
+ /// Checks that `stdout` does not contain the regex pattern `unexpected`.
+ #[track_caller]
+ pub fn assert_stdout_not_contains_regex<S: AsRef<str>>(&self, unexpected: S) -> &Self {
+ assert_not_contains_regex(&self.stdout_utf8(), unexpected);
+ self
+ }
+
/// Checks that `stdout` contains `expected`.
#[track_caller]
pub fn assert_stdout_contains<S: AsRef<str>>(&self, expected: S) -> &Self {
@@ -199,6 +216,13 @@ pub fn assert_stdout_contains<S: AsRef<str>>(&self, expected: S) -> &Self {
self
}
+ /// Checks that `stdout` contains the regex pattern `expected`.
+ #[track_caller]
+ pub fn assert_stdout_contains_regex<S: AsRef<str>>(&self, expected: S) -> &Self {
+ assert_contains_regex(&self.stdout_utf8(), expected);
+ self
+ }
+
/// Checks that trimmed `stderr` matches trimmed `expected`.
#[track_caller]
pub fn assert_stderr_equals<S: AsRef<str>>(&self, expected: S) -> &Self {
@@ -213,10 +237,24 @@ pub fn assert_stderr_contains<S: AsRef<str>>(&self, expected: S) -> &Self {
self
}
+ /// Checks that `stderr` contains the regex pattern `expected`.
+ #[track_caller]
+ pub fn assert_stderr_contains_regex<S: AsRef<str>>(&self, expected: S) -> &Self {
+ assert_contains_regex(&self.stderr_utf8(), expected);
+ self
+ }
+
/// Checks that `stderr` does not contain `unexpected`.
#[track_caller]
pub fn assert_stderr_not_contains<S: AsRef<str>>(&self, unexpected: S) -> &Self {
- assert_not_contains(&self.stdout_utf8(), unexpected);
+ assert_not_contains(&self.stderr_utf8(), unexpected);
+ self
+ }
+
+ /// Checks that `stderr` does not contain the regex pattern `unexpected`.
+ #[track_caller]
+ pub fn assert_stderr_not_contains_regex<S: AsRef<str>>(&self, unexpected: S) -> &Self {
+ assert_not_contains_regex(&self.stdout_utf8(), unexpected);
self
}
diff --git a/src/tools/run-make-support/src/diff/mod.rs b/src/tools/run-make-support/src/diff/mod.rs
index ac66233..ee48e37 100644
--- a/src/tools/run-make-support/src/diff/mod.rs
+++ b/src/tools/run-make-support/src/diff/mod.rs
@@ -1,10 +1,9 @@
use std::path::{Path, PathBuf};
+use build_helper::drop_bomb::DropBomb;
use regex::Regex;
use similar::TextDiff;
-use build_helper::drop_bomb::DropBomb;
-
use crate::fs;
#[cfg(test)]
@@ -113,14 +112,8 @@ pub fn run(&mut self) {
let (expected_name, actual_name, output, actual) = self.run_common();
if !output.is_empty() {
- // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
- // environment variable set), then we write into the file and return.
- if let Some(ref expected_file) = self.expected_file {
- if std::env::var("RUSTC_BLESS_TEST").is_ok() {
- println!("Blessing `{}`", expected_file.display());
- fs::write(expected_file, actual);
- return;
- }
+ if self.maybe_bless_expected_file(&actual) {
+ return;
}
panic!(
"test failed: `{}` is different from `{}`\n\n{}",
@@ -135,14 +128,8 @@ pub fn run_fail(&mut self) {
let (expected_name, actual_name, output, actual) = self.run_common();
if output.is_empty() {
- // If we can bless (meaning we have a file to write into and the `RUSTC_BLESS_TEST`
- // environment variable set), then we write into the file and return.
- if let Some(ref expected_file) = self.expected_file {
- if std::env::var("RUSTC_BLESS_TEST").is_ok() {
- println!("Blessing `{}`", expected_file.display());
- fs::write(expected_file, actual);
- return;
- }
+ if self.maybe_bless_expected_file(&actual) {
+ return;
}
panic!(
"test failed: `{}` is not different from `{}`\n\n{}",
@@ -150,4 +137,24 @@ pub fn run_fail(&mut self) {
)
}
}
+
+ /// If we have an expected file to write into, and `RUSTC_BLESS_TEST` is
+ /// set, then write the actual output into the file and return `true`.
+ ///
+ /// We assume that `RUSTC_BLESS_TEST` contains the path to the original test's
+ /// source directory. That lets us bless the original snapshot file in the
+ /// source tree, not the copy in `rmake_out` that we would normally use.
+ fn maybe_bless_expected_file(&self, actual: &str) -> bool {
+ let Some(ref expected_file) = self.expected_file else {
+ return false;
+ };
+ let Ok(bless_dir) = std::env::var("RUSTC_BLESS_TEST") else {
+ return false;
+ };
+
+ let bless_file = Path::new(&bless_dir).join(expected_file);
+ println!("Blessing `{}`", bless_file.display());
+ fs::write(bless_file, actual);
+ true
+ }
}
diff --git a/src/tools/run-make-support/src/env.rs b/src/tools/run-make-support/src/env.rs
index f52524e..e6460fb 100644
--- a/src/tools/run-make-support/src/env.rs
+++ b/src/tools/run-make-support/src/env.rs
@@ -17,3 +17,10 @@ pub fn env_var_os(name: &str) -> OsString {
None => panic!("failed to retrieve environment variable {name:?}"),
}
}
+
+/// Check if `NO_DEBUG_ASSERTIONS` is set (usually this may be set in CI jobs).
+#[track_caller]
+#[must_use]
+pub fn no_debug_assertions() -> bool {
+ std::env::var_os("NO_DEBUG_ASSERTIONS").is_some()
+}
diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs
index 86c9c08..f8d1666 100644
--- a/src/tools/run-make-support/src/external_deps/c_build.rs
+++ b/src/tools/run-make-support/src/external_deps/c_build.rs
@@ -1,8 +1,7 @@
use std::path::PathBuf;
-use super::cygpath::get_windows_path;
use crate::artifact_names::{dynamic_lib_name, static_lib_name};
-use crate::external_deps::cc::cc;
+use crate::external_deps::cc::{cc, cxx};
use crate::external_deps::llvm::llvm_ar;
use crate::path_helpers::path;
use crate::targets::{is_darwin, is_msvc, is_windows};
@@ -10,16 +9,34 @@
// FIXME(Oneirical): These native build functions should take a Path-based generic.
/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
+/// Built from a C file.
#[track_caller]
pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
+ build_native_static_lib_internal(lib_name, false)
+}
+
+/// Builds an optimized static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
+/// Built from a C file.
+#[track_caller]
+pub fn build_native_static_lib_optimized(lib_name: &str) -> PathBuf {
+ build_native_static_lib_internal(lib_name, true)
+}
+
+#[track_caller]
+fn build_native_static_lib_internal(lib_name: &str, optimzed: bool) -> PathBuf {
let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
let src = format!("{lib_name}.c");
let lib_path = static_lib_name(lib_name);
- if is_msvc() {
- cc().arg("-c").out_exe(&obj_file).input(src).run();
- } else {
- cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run();
- };
+
+ let mut cc = cc();
+ if !is_msvc() {
+ cc.arg("-v");
+ }
+ if optimzed {
+ cc.optimize();
+ }
+ cc.arg("-c").out_exe(&obj_file).input(src).optimize().run();
+
let obj_file = if is_msvc() {
PathBuf::from(format!("{lib_name}.obj"))
} else {
@@ -43,8 +60,7 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf {
};
let obj_file = if is_msvc() { format!("{lib_name}.obj") } else { format!("{lib_name}.o") };
if is_msvc() {
- let mut out_arg = "-out:".to_owned();
- out_arg.push_str(&get_windows_path(&lib_path));
+ let out_arg = format!("-out:{lib_path}");
cc().input(&obj_file).args(&["-link", "-dll", &out_arg]).run();
} else if is_darwin() {
cc().out_exe(&lib_path).input(&obj_file).args(&["-dynamiclib", "-Wl,-dylib"]).run();
@@ -58,3 +74,24 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf {
}
path(lib_path)
}
+
+/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
+/// Built from a C++ file.
+#[track_caller]
+pub fn build_native_static_lib_cxx(lib_name: &str) -> PathBuf {
+ let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
+ let src = format!("{lib_name}.cpp");
+ let lib_path = static_lib_name(lib_name);
+ if is_msvc() {
+ cxx().arg("-EHs").arg("-c").out_exe(&obj_file).input(src).run();
+ } else {
+ cxx().arg("-c").out_exe(&obj_file).input(src).run();
+ };
+ let obj_file = if is_msvc() {
+ PathBuf::from(format!("{lib_name}.obj"))
+ } else {
+ PathBuf::from(format!("{lib_name}.o"))
+ };
+ llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
+ path(lib_path)
+}
diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs
index 19a8970..011ad89 100644
--- a/src/tools/run-make-support/src/external_deps/cc.rs
+++ b/src/tools/run-make-support/src/external_deps/cc.rs
@@ -3,9 +3,6 @@
use crate::command::Command;
use crate::{env_var, is_msvc, is_windows, uname};
-// FIXME(jieyouxu): can we get rid of the `cygpath` external dependency?
-use super::cygpath::get_windows_path;
-
/// Construct a new platform-specific C compiler invocation.
///
/// WARNING: This means that what flags are accepted by the underlying C compiler is
@@ -98,12 +95,12 @@ pub fn out_exe(&mut self, name: &str) -> &mut Self {
if is_msvc() {
path.set_extension("exe");
- let fe_path = get_windows_path(&path);
+ let fe_path = path.clone();
path.set_extension("");
path.set_extension("obj");
- let fo_path = get_windows_path(path);
- self.cmd.arg(format!("-Fe:{fe_path}"));
- self.cmd.arg(format!("-Fo:{fo_path}"));
+ let fo_path = path;
+ self.cmd.arg(format!("-Fe:{}", fe_path.to_str().unwrap()));
+ self.cmd.arg(format!("-Fo:{}", fo_path.to_str().unwrap()));
} else {
self.cmd.arg("-o");
self.cmd.arg(name);
@@ -118,6 +115,17 @@ pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg(path.as_ref());
self
}
+
+ /// Optimize the output.
+ /// Equivalent to `-O3` for GNU-compatible linkers or `-O2` for MSVC linkers.
+ pub fn optimize(&mut self) -> &mut Self {
+ if is_msvc() {
+ self.cmd.arg("-O2");
+ } else {
+ self.cmd.arg("-O3");
+ }
+ self
+ }
}
/// `EXTRACFLAGS`
diff --git a/src/tools/run-make-support/src/external_deps/clang.rs b/src/tools/run-make-support/src/external_deps/clang.rs
index 2b07125..2d110c6 100644
--- a/src/tools/run-make-support/src/external_deps/clang.rs
+++ b/src/tools/run-make-support/src/external_deps/clang.rs
@@ -1,7 +1,7 @@
use std::path::Path;
use crate::command::Command;
-use crate::{bin_name, env_var};
+use crate::{bin_name, cwd, env_var};
/// Construct a new `clang` invocation. `clang` is not always available for all targets.
#[track_caller]
@@ -23,7 +23,8 @@ impl Clang {
#[track_caller]
pub fn new() -> Self {
let clang = env_var("CLANG");
- let cmd = Command::new(clang);
+ let mut cmd = Command::new(clang);
+ cmd.arg("-L").arg(cwd());
Self { cmd }
}
diff --git a/src/tools/run-make-support/src/external_deps/cygpath.rs b/src/tools/run-make-support/src/external_deps/cygpath.rs
deleted file mode 100644
index 07d8e84..0000000
--- a/src/tools/run-make-support/src/external_deps/cygpath.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use std::panic;
-use std::path::Path;
-
-use crate::command::Command;
-use crate::util::handle_failed_output;
-
-/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
-/// available on the platform!
-///
-/// # FIXME
-///
-/// FIXME(jieyouxu): we should consider not depending on `cygpath`.
-///
-/// > The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style
-/// > pathnames and vice versa.
-/// >
-/// > [irrelevant entries omitted...]
-/// >
-/// > `-w, --windows print Windows form of NAMEs (C:\WINNT)`
-/// >
-/// > -- *from [cygpath documentation](https://cygwin.com/cygwin-ug-net/cygpath.html)*.
-#[track_caller]
-#[must_use]
-pub fn get_windows_path<P: AsRef<Path>>(path: P) -> String {
- let caller = panic::Location::caller();
- let mut cygpath = Command::new("cygpath");
- cygpath.arg("-w");
- cygpath.arg(path.as_ref());
- let output = cygpath.run();
- if !output.status().success() {
- handle_failed_output(&cygpath, output, caller.line());
- }
- // cygpath -w can attach a newline
- output.stdout_utf8().trim().to_string()
-}
diff --git a/src/tools/run-make-support/src/external_deps/htmldocck.rs b/src/tools/run-make-support/src/external_deps/htmldocck.rs
index afd0711..621d386 100644
--- a/src/tools/run-make-support/src/external_deps/htmldocck.rs
+++ b/src/tools/run-make-support/src/external_deps/htmldocck.rs
@@ -1,8 +1,7 @@
+use super::python::python_command;
use crate::command::Command;
use crate::source_root;
-use super::python::python_command;
-
/// `htmldocck` is a python script which is used for rustdoc test suites, it is assumed to be
/// available at `$SOURCE_ROOT/src/etc/htmldocck.py`.
#[track_caller]
diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs
index b116bd0..dc651fd 100644
--- a/src/tools/run-make-support/src/external_deps/llvm.rs
+++ b/src/tools/run-make-support/src/external_deps/llvm.rs
@@ -36,6 +36,18 @@ pub fn llvm_ar() -> LlvmAr {
LlvmAr::new()
}
+/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
+/// at `$LLVM_BIN_DIR/llvm-nm`.
+pub fn llvm_nm() -> LlvmNm {
+ LlvmNm::new()
+}
+
+/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
+/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
+pub fn llvm_bcanalyzer() -> LlvmBcanalyzer {
+ LlvmBcanalyzer::new()
+}
+
/// A `llvm-readobj` invocation builder.
#[derive(Debug)]
#[must_use]
@@ -71,11 +83,27 @@ pub struct LlvmAr {
cmd: Command,
}
+/// A `llvm-nm` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmNm {
+ cmd: Command,
+}
+
+/// A `llvm-bcanalyzer` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmBcanalyzer {
+ cmd: Command,
+}
+
crate::macros::impl_common_helpers!(LlvmReadobj);
crate::macros::impl_common_helpers!(LlvmProfdata);
crate::macros::impl_common_helpers!(LlvmFilecheck);
crate::macros::impl_common_helpers!(LlvmObjdump);
crate::macros::impl_common_helpers!(LlvmAr);
+crate::macros::impl_common_helpers!(LlvmNm);
+crate::macros::impl_common_helpers!(LlvmBcanalyzer);
/// Generate the path to the bin directory of LLVM.
#[must_use]
@@ -123,7 +151,8 @@ pub fn program_headers(&mut self) -> &mut Self {
self
}
- /// Pass `--symbols` to display the symbol.
+ /// Pass `--symbols` to display the symbol table, including both local
+ /// and global symbols.
pub fn symbols(&mut self) -> &mut Self {
self.cmd.arg("--symbols");
self
@@ -218,6 +247,12 @@ pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg(path.as_ref());
self
}
+
+ /// Disassemble all executable sections found in the input files.
+ pub fn disassemble(&mut self) -> &mut Self {
+ self.cmd.arg("-d");
+ self
+ }
}
impl LlvmAr {
@@ -236,6 +271,12 @@ pub fn obj_to_ar(&mut self) -> &mut Self {
self
}
+ /// Extract archive members back to files.
+ pub fn extract(&mut self) -> &mut Self {
+ self.cmd.arg("x");
+ self
+ }
+
/// Provide an output, then an input file. Bundled in one function, as llvm-ar has
/// no "--output"-style flag.
pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
@@ -244,3 +285,35 @@ pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -
self
}
}
+
+impl LlvmNm {
+ /// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
+ /// at `$LLVM_BIN_DIR/llvm-nm`.
+ pub fn new() -> Self {
+ let llvm_nm = llvm_bin_dir().join("llvm-nm");
+ let cmd = Command::new(llvm_nm);
+ Self { cmd }
+ }
+
+ /// Provide an input file.
+ pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+ self.cmd.arg(path.as_ref());
+ self
+ }
+}
+
+impl LlvmBcanalyzer {
+ /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available
+ /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`.
+ pub fn new() -> Self {
+ let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer");
+ let cmd = Command::new(llvm_bcanalyzer);
+ Self { cmd }
+ }
+
+ /// Provide an input file.
+ pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+ self.cmd.arg(path.as_ref());
+ self
+ }
+}
diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs
index a2dc426..f7c8472 100644
--- a/src/tools/run-make-support/src/external_deps/mod.rs
+++ b/src/tools/run-make-support/src/external_deps/mod.rs
@@ -9,6 +9,3 @@
pub mod python;
pub mod rustc;
pub mod rustdoc;
-
-// Library-internal external dependency.
-mod cygpath;
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index 71d28dd..cece58d 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -5,6 +5,7 @@
use crate::env::env_var;
use crate::path_helpers::cwd;
use crate::util::set_host_rpath;
+use crate::{is_darwin, is_msvc, is_windows, uname};
/// Construct a new `rustc` invocation. This will automatically set the library
/// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
@@ -314,4 +315,62 @@ pub fn linker_flavor(&mut self, linker_flavor: &str) -> &mut Self {
self.cmd.arg(format!("-Clinker-flavor={linker_flavor}"));
self
}
+
+ /// `EXTRARSCXXFLAGS`
+ pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
+ // Adapted from tools.mk (trimmed):
+ //
+ // ```makefile
+ // ifdef IS_WINDOWS
+ // ifdef IS_MSVC
+ // else
+ // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++
+ // endif
+ // else
+ // ifeq ($(UNAME),Darwin)
+ // EXTRARSCXXFLAGS := -lc++
+ // else
+ // ifeq ($(UNAME),FreeBSD)
+ // else
+ // ifeq ($(UNAME),SunOS)
+ // else
+ // ifeq ($(UNAME),OpenBSD)
+ // else
+ // EXTRARSCXXFLAGS := -lstdc++
+ // endif
+ // endif
+ // endif
+ // endif
+ // endif
+ // ```
+ let flag = if is_windows() {
+ // So this is a bit hacky: we can't use the DLL version of libstdc++ because
+ // it pulls in the DLL version of libgcc, which means that we end up with 2
+ // instances of the DW2 unwinding implementation. This is a problem on
+ // i686-pc-windows-gnu because each module (DLL/EXE) needs to register its
+ // unwind information with the unwinding implementation, and libstdc++'s
+ // __cxa_throw won't see the unwinding info we registered with our statically
+ // linked libgcc.
+ //
+ // Now, simply statically linking libstdc++ would fix this problem, except
+ // that it is compiled with the expectation that pthreads is dynamically
+ // linked as a DLL and will fail to link with a statically linked libpthread.
+ //
+ // So we end up with the following hack: we link use static:-bundle to only
+ // link the parts of libstdc++ that we actually use, which doesn't include
+ // the dependency on the pthreads DLL.
+ if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") }
+ } else if is_darwin() {
+ Some("-lc++")
+ } else {
+ match &uname()[..] {
+ "FreeBSD" | "SunOS" | "OpenBSD" => None,
+ _ => Some("-lstdc++"),
+ }
+ };
+ if let Some(flag) = flag {
+ self.cmd.arg(flag);
+ }
+ self
+ }
}
diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs
index 0a79616..2c35ba5 100644
--- a/src/tools/run-make-support/src/fs.rs
+++ b/src/tools/run-make-support/src/fs.rs
@@ -9,11 +9,19 @@ pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) {
if link.as_ref().exists() {
std::fs::remove_dir(link.as_ref()).unwrap();
}
- std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
- "failed to create symlink {:?} for {:?}",
- link.as_ref().display(),
- original.as_ref().display(),
- ));
+ if original.as_ref().is_file() {
+ std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!(
+ "failed to create symlink {:?} for {:?}",
+ link.as_ref().display(),
+ original.as_ref().display(),
+ ));
+ } else {
+ std::os::windows::fs::symlink_dir(original.as_ref(), link.as_ref()).expect(&format!(
+ "failed to create symlink {:?} for {:?}",
+ link.as_ref().display(),
+ original.as_ref().display(),
+ ));
+ }
}
/// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix.
@@ -41,6 +49,8 @@ fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Resul
let ty = entry.file_type()?;
if ty.is_dir() {
copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?;
+ } else if ty.is_symlink() {
+ copy_symlink(entry.path(), dst.join(entry.file_name()))?;
} else {
std::fs::copy(entry.path(), dst.join(entry.file_name()))?;
}
@@ -59,6 +69,12 @@ fn copy_dir_all_inner(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Resul
}
}
+fn copy_symlink<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
+ let target_path = std::fs::read_link(from).unwrap();
+ create_symlink(target_path, to);
+ Ok(())
+}
+
/// Helper for reading entries in a given directory.
pub fn read_dir_entries<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, mut callback: F) {
for entry in read_dir(dir) {
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 0851207..a44dd00 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -21,6 +21,7 @@
pub mod scoped_run;
pub mod string;
pub mod targets;
+pub mod symbols;
// Internally we call our fs-related support module as `fs`, but re-export its content as `rfs`
// to tests to avoid colliding with commonly used `use std::fs;`.
@@ -43,13 +44,13 @@ pub mod rfs {
pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc};
// These rely on external dependencies.
-pub use c_build::{build_native_dynamic_lib, build_native_static_lib};
pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
+pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx};
pub use clang::{clang, Clang};
pub use htmldocck::htmldocck;
pub use llvm::{
- llvm_ar, llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmFilecheck,
- LlvmObjdump, LlvmProfdata, LlvmReadobj,
+ llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj,
+ LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj,
};
pub use python::python_command;
pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
@@ -71,20 +72,22 @@ pub mod rfs {
/// Helpers for building names of output artifacts that are potentially target-specific.
pub use artifact_names::{
- bin_name, dynamic_lib_extension, dynamic_lib_name, rust_lib_name, static_lib_name,
+ bin_name, dynamic_lib_extension, dynamic_lib_name, msvc_import_dynamic_lib_name, rust_lib_name,
+ static_lib_name,
};
/// Path-related helpers.
pub use path_helpers::{
- cwd, filename_not_in_denylist, has_extension, has_prefix, has_suffix, not_contains, path,
- shallow_find_files, source_root,
+ cwd, filename_contains, filename_not_in_denylist, has_extension, has_prefix, has_suffix,
+ not_contains, path, shallow_find_files, source_root,
};
/// Helpers for scoped test execution where certain properties are attempted to be maintained.
pub use scoped_run::{run_in_tmpdir, test_while_readonly};
pub use assertion_helpers::{
- assert_contains, assert_dirs_are_equal, assert_equals, assert_not_contains,
+ assert_contains, assert_contains_regex, assert_dirs_are_equal, assert_equals,
+ assert_not_contains, assert_not_contains_regex,
};
pub use string::{
diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs
index f37ea8d..b788bc6 100644
--- a/src/tools/run-make-support/src/path_helpers.rs
+++ b/src/tools/run-make-support/src/path_helpers.rs
@@ -3,6 +3,7 @@
use std::path::{Path, PathBuf};
use crate::env::env_var;
+use crate::rfs;
/// Return the current working directory.
///
@@ -40,7 +41,7 @@ pub fn shallow_find_files<P: AsRef<Path>, F: Fn(&PathBuf) -> bool>(
filter: F,
) -> Vec<PathBuf> {
let mut matching_files = Vec::new();
- for entry in std::fs::read_dir(path).unwrap() {
+ for entry in rfs::read_dir(path) {
let entry = entry.expect("failed to read directory entry.");
let path = entry.path();
@@ -78,3 +79,8 @@ pub fn has_extension<P: AsRef<Path>>(path: P, extension: &str) -> bool {
pub fn has_suffix<P: AsRef<Path>>(path: P, suffix: &str) -> bool {
path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().ends_with(suffix))
}
+
+/// Returns true if the filename at `path` contains `needle`.
+pub fn filename_contains<P: AsRef<Path>>(path: P, needle: &str) -> bool {
+ path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(needle))
+}
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 17f8ce3..12088e5 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -1,7 +1,6 @@
-use std::env;
use std::ffi::OsStr;
-use std::panic;
use std::path::{Path, PathBuf};
+use std::{env, panic};
use crate::command::{Command, CompletedProcess};
use crate::util::{handle_failed_output, set_host_rpath};
diff --git a/src/tools/run-make-support/src/symbols.rs b/src/tools/run-make-support/src/symbols.rs
new file mode 100644
index 0000000..fd0c866
--- /dev/null
+++ b/src/tools/run-make-support/src/symbols.rs
@@ -0,0 +1,44 @@
+use std::path::Path;
+
+use object::{self, Object, ObjectSymbol, SymbolIterator};
+
+/// Iterate through the symbols in an object file.
+///
+/// Uses a callback because `SymbolIterator` does not own its data.
+///
+/// Panics if `path` is not a valid object file readable by the current user.
+pub fn with_symbol_iter<P, F, R>(path: P, func: F) -> R
+where
+ P: AsRef<Path>,
+ F: FnOnce(&mut SymbolIterator<'_, '_>) -> R,
+{
+ let raw_bytes = crate::fs::read(path);
+ let f = object::File::parse(raw_bytes.as_slice()).expect("unable to parse file");
+ let mut iter = f.symbols();
+ func(&mut iter)
+}
+
+/// Check an object file's symbols for substrings.
+///
+/// Returns `true` if any of the symbols found in the object file at
+/// `path` contain a substring listed in `substrings`.
+///
+/// Panics if `path` is not a valid object file readable by the current user.
+pub fn any_symbol_contains(path: impl AsRef<Path>, substrings: &[&str]) -> bool {
+ with_symbol_iter(path, |syms| {
+ for sym in syms {
+ for substring in substrings {
+ if sym
+ .name_bytes()
+ .unwrap()
+ .windows(substring.len())
+ .any(|x| x == substring.as_bytes())
+ {
+ eprintln!("{:?} contains {}", sym, substring);
+ return true;
+ }
+ }
+ }
+ false
+ })
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index bd43a62..d76f538 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -27,6 +27,7 @@ macro_rules! from_bytes {
($ty:tt, $value:expr) => {
($ty::from_le_bytes(match ($value).try_into() {
Ok(it) => it,
+ #[allow(unreachable_patterns)]
Err(_) => return Err(MirEvalError::InternalError("mismatched size".into())),
}))
};
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 057f553..9aa2eee 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -1161,6 +1161,7 @@ fn lower_expr_to_place_without_adjust(
ProjectionElem::OpaqueCast(it) => {
ProjectionElem::OpaqueCast(it)
}
+ #[allow(unreachable_patterns)]
ProjectionElem::Index(it) => match it {},
})
.collect(),
diff --git a/src/tools/rust-installer/src/combiner.rs b/src/tools/rust-installer/src/combiner.rs
index e702098..66b3d32 100644
--- a/src/tools/rust-installer/src/combiner.rs
+++ b/src/tools/rust-installer/src/combiner.rs
@@ -1,14 +1,13 @@
-use super::Scripter;
-use super::Tarballer;
-use crate::{
- compression::{CompressionFormat, CompressionFormats, CompressionProfile},
- util::*,
-};
-use anyhow::{bail, Context, Result};
use std::io::{Read, Write};
use std::path::Path;
+
+use anyhow::{bail, Context, Result};
use tar::Archive;
+use super::{Scripter, Tarballer};
+use crate::compression::{CompressionFormat, CompressionFormats, CompressionProfile};
+use crate::util::*;
+
actor! {
#[derive(Debug)]
pub struct Combiner {
diff --git a/src/tools/rust-installer/src/compression.rs b/src/tools/rust-installer/src/compression.rs
index 40c7c59..df3a98a 100644
--- a/src/tools/rust-installer/src/compression.rs
+++ b/src/tools/rust-installer/src/compression.rs
@@ -1,8 +1,14 @@
+use std::fmt;
+use std::io::{Read, Write};
+use std::path::Path;
+use std::str::FromStr;
+
use anyhow::{Context, Error};
-use flate2::{read::GzDecoder, write::GzEncoder};
+use flate2::read::GzDecoder;
+use flate2::write::GzEncoder;
use rayon::prelude::*;
-use std::{fmt, io::Read, io::Write, path::Path, str::FromStr};
-use xz2::{read::XzDecoder, write::XzEncoder};
+use xz2::read::XzDecoder;
+use xz2::write::XzEncoder;
#[derive(Default, Debug, Copy, Clone)]
pub enum CompressionProfile {
diff --git a/src/tools/rust-installer/src/generator.rs b/src/tools/rust-installer/src/generator.rs
index 035a394..e122869 100644
--- a/src/tools/rust-installer/src/generator.rs
+++ b/src/tools/rust-installer/src/generator.rs
@@ -1,12 +1,13 @@
-use super::Scripter;
-use super::Tarballer;
-use crate::compression::{CompressionFormats, CompressionProfile};
-use crate::util::*;
-use anyhow::{bail, format_err, Context, Result};
use std::collections::BTreeSet;
use std::io::Write;
use std::path::Path;
+use anyhow::{bail, format_err, Context, Result};
+
+use super::{Scripter, Tarballer};
+use crate::compression::{CompressionFormats, CompressionProfile};
+use crate::util::*;
+
actor! {
#[derive(Debug)]
pub struct Generator {
diff --git a/src/tools/rust-installer/src/scripter.rs b/src/tools/rust-installer/src/scripter.rs
index ff65e81..abac405 100644
--- a/src/tools/rust-installer/src/scripter.rs
+++ b/src/tools/rust-installer/src/scripter.rs
@@ -1,7 +1,9 @@
-use crate::util::*;
-use anyhow::{Context, Result};
use std::io::Write;
+use anyhow::{Context, Result};
+
+use crate::util::*;
+
const TEMPLATE: &str = include_str!("../install-template.sh");
actor! {
diff --git a/src/tools/rust-installer/src/tarballer.rs b/src/tools/rust-installer/src/tarballer.rs
index b5e87a6..a101be8 100644
--- a/src/tools/rust-installer/src/tarballer.rs
+++ b/src/tools/rust-installer/src/tarballer.rs
@@ -1,14 +1,13 @@
-use anyhow::{bail, Context, Result};
use std::fs::{read_link, symlink_metadata};
use std::io::{BufWriter, Write};
use std::path::Path;
+
+use anyhow::{bail, Context, Result};
use tar::{Builder, Header, HeaderMode};
use walkdir::WalkDir;
-use crate::{
- compression::{CombinedEncoder, CompressionFormats, CompressionProfile},
- util::*,
-};
+use crate::compression::{CombinedEncoder, CompressionFormats, CompressionProfile};
+use crate::util::*;
actor! {
#[derive(Debug)]
diff --git a/src/tools/rust-installer/src/util.rs b/src/tools/rust-installer/src/util.rs
index 47ca0cf..51b8c9c 100644
--- a/src/tools/rust-installer/src/util.rs
+++ b/src/tools/rust-installer/src/util.rs
@@ -1,17 +1,16 @@
-use anyhow::{format_err, Context, Result};
use std::fs;
-use std::path::Path;
-use walkdir::WalkDir;
-
+// FIXME: what about Windows? Are default ACLs executable?
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_file;
// Needed to set the script mode to executable.
#[cfg(unix)]
use std::os::unix::fs::OpenOptionsExt;
-// FIXME: what about Windows? Are default ACLs executable?
-
-#[cfg(unix)]
-use std::os::unix::fs::symlink as symlink_file;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
+use std::path::Path;
+
+use anyhow::{format_err, Context, Result};
+use walkdir::WalkDir;
/// Converts a `&Path` to a UTF-8 `&str`.
pub fn path_to_str(path: &Path) -> Result<&str> {
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 75b89a1..df051ed 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -662,6 +662,20 @@
]
[[package]]
+name = "mdbook-spec"
+version = "0.1.2"
+dependencies = [
+ "anyhow",
+ "mdbook",
+ "once_cell",
+ "pathdiff",
+ "regex",
+ "semver",
+ "serde_json",
+ "tempfile",
+]
+
+[[package]]
name = "mdbook-trpl-listing"
version = "0.1.0"
dependencies = [
@@ -795,6 +809,12 @@
]
[[package]]
+name = "pathdiff"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+
+[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1079,6 +1099,7 @@
"env_logger",
"mdbook",
"mdbook-i18n-helpers",
+ "mdbook-spec",
"mdbook-trpl-listing",
"mdbook-trpl-note",
]
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 51ba584..2c29a28 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -12,6 +12,7 @@
mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" }
mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" }
mdbook-i18n-helpers = "0.3.3"
+mdbook-spec = { path = "../../doc/reference/mdbook-spec"}
[dependencies.mdbook]
version = "0.4.37"
diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs
index 31bba56..a4faac0 100644
--- a/src/tools/rustbook/src/main.rs
+++ b/src/tools/rustbook/src/main.rs
@@ -1,14 +1,11 @@
-use clap::crate_version;
-
use std::env;
use std::path::{Path, PathBuf};
-use clap::{arg, ArgMatches, Command};
-
+use clap::{arg, crate_version, ArgMatches, Command};
use mdbook::errors::Result as Result3;
use mdbook::MDBook;
use mdbook_i18n_helpers::preprocessors::Gettext;
-
+use mdbook_spec::Spec;
use mdbook_trpl_listing::TrplListing;
use mdbook_trpl_note::TrplNote;
@@ -83,6 +80,13 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
book.config.build.build_dir = dest_dir.into();
}
+ // NOTE: Replacing preprocessors using this technique causes error
+ // messages to be displayed when the original preprocessor doesn't work
+ // (but it otherwise succeeds).
+ //
+ // This should probably be fixed in mdbook to remove the existing
+ // preprocessor, or this should modify the config and use
+ // MDBook::load_with_config.
if book.config.get_preprocessor("trpl-note").is_some() {
book.with_preprocessor(TrplNote);
}
@@ -91,6 +95,10 @@ pub fn build(args: &ArgMatches) -> Result3<()> {
book.with_preprocessor(TrplListing);
}
+ if book.config.get_preprocessor("spec").is_some() {
+ book.with_preprocessor(Spec::new());
+ }
+
book.build()?;
Ok(())
diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf
index c64bb60..d5055e7 160000
--- a/src/tools/rustc-perf
+++ b/src/tools/rustc-perf
@@ -1 +1 @@
-Subproject commit c64bb60dd1636922b1ccbb82867bed934a99dbcb
+Subproject commit d5055e78042c739deeb3fe0bef83fde0e5cc2594
diff --git a/src/tools/rustc-perf-wrapper/src/main.rs b/src/tools/rustc-perf-wrapper/src/main.rs
index 1c0d174..951d36b 100644
--- a/src/tools/rustc-perf-wrapper/src/main.rs
+++ b/src/tools/rustc-perf-wrapper/src/main.rs
@@ -1,8 +1,11 @@
-use crate::config::{Profile, Scenario};
-use clap::Parser;
+use std::fs::create_dir_all;
use std::path::PathBuf;
use std::process::Command;
+use clap::Parser;
+
+use crate::config::{Profile, Scenario};
+
mod config;
/// Performs profiling or benchmarking with [`rustc-perf`](https://github.com/rust-lang/rustc-perf)
@@ -16,9 +19,6 @@ pub struct Args {
cmd: PerfCommand,
#[clap(flatten)]
- opts: SharedOpts,
-
- #[clap(flatten)]
ctx: BuildContext,
}
@@ -26,22 +26,37 @@ pub struct Args {
enum PerfCommand {
/// Run `profile_local eprintln`.
/// This executes the compiler on the given benchmarks and stores its stderr output.
- Eprintln,
+ Eprintln {
+ #[clap(flatten)]
+ opts: SharedOpts,
+ },
/// Run `profile_local samply`
/// This executes the compiler on the given benchmarks and profiles it with `samply`.
/// You need to install `samply`, e.g. using `cargo install samply`.
- Samply,
+ Samply {
+ #[clap(flatten)]
+ opts: SharedOpts,
+ },
/// Run `profile_local cachegrind`.
/// This executes the compiler on the given benchmarks under `Cachegrind`.
- Cachegrind,
-}
+ Cachegrind {
+ #[clap(flatten)]
+ opts: SharedOpts,
+ },
+ Benchmark {
+ /// Identifier to associate benchmark results with
+ id: String,
-impl PerfCommand {
- fn is_profiling(&self) -> bool {
- match self {
- PerfCommand::Eprintln | PerfCommand::Samply | PerfCommand::Cachegrind => true,
- }
- }
+ #[clap(flatten)]
+ opts: SharedOpts,
+ },
+ Compare {
+ /// The name of the base artifact to be compared.
+ base: String,
+
+ /// The name of the modified artifact to be compared.
+ modified: String,
+ },
}
#[derive(Debug, clap::Parser)]
@@ -50,6 +65,11 @@ struct SharedOpts {
/// If unspecified, all benchmarks will be executed.
#[clap(long, global = true, value_delimiter = ',')]
include: Vec<String>,
+
+ /// Select the benchmarks matching a prefix in this comma-separated list that you don't want to run.
+ #[clap(long, global = true, value_delimiter = ',')]
+ exclude: Vec<String>,
+
/// Select the scenarios that should be benchmarked.
#[clap(
long,
@@ -85,35 +105,67 @@ fn main() {
fn run(args: Args) {
let mut cmd = Command::new(args.ctx.collector);
+ let db_path = args.ctx.results_dir.join("results.db");
+
match &args.cmd {
- PerfCommand::Eprintln => {
- cmd.arg("profile_local").arg("eprintln");
- }
- PerfCommand::Samply => {
- cmd.arg("profile_local").arg("samply");
- }
- PerfCommand::Cachegrind => {
- cmd.arg("profile_local").arg("cachegrind");
- }
- }
- if args.cmd.is_profiling() {
- cmd.arg("--out-dir").arg(&args.ctx.results_dir);
- }
+ PerfCommand::Eprintln { opts }
+ | PerfCommand::Samply { opts }
+ | PerfCommand::Cachegrind { opts } => {
+ cmd.arg("profile_local");
+ cmd.arg(match &args.cmd {
+ PerfCommand::Eprintln { .. } => "eprintln",
+ PerfCommand::Samply { .. } => "samply",
+ PerfCommand::Cachegrind { .. } => "cachegrind",
+ _ => unreachable!(),
+ });
- if !args.opts.include.is_empty() {
- cmd.arg("--include").arg(args.opts.include.join(","));
+ cmd.arg("--out-dir").arg(&args.ctx.results_dir);
+
+ apply_shared_opts(&mut cmd, opts);
+ execute_benchmark(&mut cmd, &args.ctx.compiler);
+
+ println!("You can find the results at `{}`", args.ctx.results_dir.display());
+ }
+ PerfCommand::Benchmark { id, opts } => {
+ cmd.arg("bench_local");
+ cmd.arg("--db").arg(&db_path);
+ cmd.arg("--id").arg(id);
+
+ apply_shared_opts(&mut cmd, opts);
+ create_dir_all(&args.ctx.results_dir).unwrap();
+ execute_benchmark(&mut cmd, &args.ctx.compiler);
+ }
+ PerfCommand::Compare { base, modified } => {
+ cmd.arg("bench_cmp");
+ cmd.arg("--db").arg(&db_path);
+ cmd.arg(base).arg(modified);
+
+ create_dir_all(&args.ctx.results_dir).unwrap();
+ cmd.status().expect("error while running rustc-perf bench_cmp");
+ }
}
- if !args.opts.profiles.is_empty() {
+}
+
+fn apply_shared_opts(cmd: &mut Command, opts: &SharedOpts) {
+ if !opts.include.is_empty() {
+ cmd.arg("--include").arg(opts.include.join(","));
+ }
+ if !opts.exclude.is_empty() {
+ cmd.arg("--exclude").arg(opts.exclude.join(","));
+ }
+ if !opts.profiles.is_empty() {
cmd.arg("--profiles")
- .arg(args.opts.profiles.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
+ .arg(opts.profiles.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
}
- if !args.opts.scenarios.is_empty() {
+ if !opts.scenarios.is_empty() {
cmd.arg("--scenarios")
- .arg(args.opts.scenarios.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
+ .arg(opts.scenarios.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
}
- cmd.arg(&args.ctx.compiler);
+}
- println!("Running `rustc-perf` using `{}`", args.ctx.compiler.display());
+fn execute_benchmark(cmd: &mut Command, compiler: &PathBuf) {
+ cmd.arg(compiler);
+ println!("Running `rustc-perf` using `{}`", compiler.display());
const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");
@@ -123,8 +175,4 @@ fn run(args: Args) {
// with compile-time benchmarks.
let cmd = cmd.current_dir(rustc_perf_dir);
cmd.status().expect("error while running rustc-perf collector");
-
- if args.cmd.is_profiling() {
- println!("You can find the results at `{}`", args.ctx.results_dir.display());
- }
}
diff --git a/src/tools/rustdoc-gui-test/src/config.rs b/src/tools/rustdoc-gui-test/src/config.rs
index dc4c56a..950e2fa 100644
--- a/src/tools/rustdoc-gui-test/src/config.rs
+++ b/src/tools/rustdoc-gui-test/src/config.rs
@@ -1,5 +1,7 @@
+use std::env;
+use std::path::PathBuf;
+
use getopts::Options;
-use std::{env, path::PathBuf};
pub(crate) struct Config {
pub(crate) nodejs: PathBuf,
diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs
index bf58127..5adb525 100644
--- a/src/tools/rustdoc-gui-test/src/main.rs
+++ b/src/tools/rustdoc-gui-test/src/main.rs
@@ -1,11 +1,12 @@
-use build_helper::util::try_run;
-use compiletest::header::TestProps;
-use config::Config;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::Arc;
use std::{env, fs};
+use build_helper::util::try_run;
+use compiletest::header::TestProps;
+use config::Config;
+
mod config;
fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String> {
diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs
index 5b499a1..d4099ca 100644
--- a/src/tools/rustdoc/main.rs
+++ b/src/tools/rustdoc/main.rs
@@ -1,3 +1,6 @@
+// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
+#![feature(rustc_private)]
+
fn main() {
rustdoc::main()
}
diff --git a/src/tools/rustfmt/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs
index 3059d91..5674f40 100644
--- a/src/tools/rustfmt/src/git-rustfmt/main.rs
+++ b/src/tools/rustfmt/src/git-rustfmt/main.rs
@@ -1,3 +1,7 @@
+// We need this feature as it changes `dylib` linking behavior and allows us to link to
+// `rustc_driver`.
+#![feature(rustc_private)]
+
#[macro_use]
extern crate tracing;
diff --git a/src/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
index 7baac24..b6de5f8 100644
--- a/src/tools/rustfmt/src/parse/macros/lazy_static.rs
+++ b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
@@ -33,15 +33,17 @@ macro_rules! parse_or {
}
while parser.token.kind != TokenKind::Eof {
// Parse a `lazy_static!` item.
+ // FIXME: These `eat_*` calls should be converted to `parse_or` to avoid
+ // silently formatting malformed lazy-statics.
let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No);
- parser.eat_keyword(kw::Static);
- parser.eat_keyword(kw::Ref);
+ let _ = parser.eat_keyword(kw::Static);
+ let _ = parser.eat_keyword(kw::Ref);
let id = parse_or!(parse_ident);
- parser.eat(&TokenKind::Colon);
+ let _ = parser.eat(&TokenKind::Colon);
let ty = parse_or!(parse_ty);
- parser.eat(&TokenKind::Eq);
+ let _ = parser.eat(&TokenKind::Eq);
let expr = parse_or!(parse_expr);
- parser.eat(&TokenKind::Semi);
+ let _ = parser.eat(&TokenKind::Semi);
result.push((vis, id, ty, expr));
}
diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs
index 9257b8a..b9adc67 100644
--- a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs
+++ b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs
@@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool {
fn detect_features() -> cache::Initializer {
let mut value = cache::Initializer::default();
- // If the x86 CPU does not support the CPUID instruction then it is too
- // old to support any of the currently-detectable features.
- if !has_cpuid() {
- return value;
- }
-
- // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU
- // has `cpuid` support.
-
// 0. EAX = 0: Basic Information:
// - EAX returns the "Highest Function Parameter", that is, the maximum
// leaf value for subsequent calls of `cpuinfo` in range [0,
diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs
index 2e228aa..944b516 100644
--- a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs
+++ b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs
@@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool {
fn detect_features() -> cache::Initializer {
let mut value = cache::Initializer::default();
- // If the x86 CPU does not support the CPUID instruction then it is too
- // old to support any of the currently-detectable features.
- if !has_cpuid() {
- return value;
- }
-
- // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU
- // has `cpuid` support.
-
// 0. EAX = 0: Basic Information:
// - EAX returns the "Highest Function Parameter", that is, the maximum
// leaf value for subsequent calls of `cpuinfo` in range [0,
diff --git a/src/tools/suggest-tests/src/lib.rs b/src/tools/suggest-tests/src/lib.rs
index 8932403..cc1288c 100644
--- a/src/tools/suggest-tests/src/lib.rs
+++ b/src/tools/suggest-tests/src/lib.rs
@@ -1,7 +1,5 @@
-use std::{
- fmt::{self, Display},
- path::Path,
-};
+use std::fmt::{self, Display};
+use std::path::Path;
use dynamic_suggestions::DYNAMIC_SUGGESTIONS;
use glob::Pattern;
diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs
index a34a4b1..a282fac 100644
--- a/src/tools/suggest-tests/src/static_suggestions.rs
+++ b/src/tools/suggest-tests/src/static_suggestions.rs
@@ -1,6 +1,7 @@
-use crate::{sug, Suggestion};
use std::sync::OnceLock;
+use crate::{sug, Suggestion};
+
// FIXME: perhaps this could use `std::lazy` when it is stablizied
macro_rules! static_suggestions {
($( [ $( $glob:expr ),* $(,)? ] => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => {
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 7284fea..14f0a9c 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,64 +1,26 @@
run-make/branch-protection-check-IBT/Makefile
run-make/cat-and-grep-sanity-check/Makefile
-run-make/cdylib-dylib-linkage/Makefile
-run-make/cross-lang-lto-clang/Makefile
-run-make/cross-lang-lto-pgo-smoketest/Makefile
-run-make/cross-lang-lto-upstream-rlibs/Makefile
-run-make/cross-lang-lto/Makefile
run-make/dep-info-doesnt-run-much/Makefile
run-make/dep-info-spaces/Makefile
run-make/dep-info/Makefile
run-make/emit-to-stdout/Makefile
run-make/extern-fn-reachable/Makefile
-run-make/fmt-write-bloat/Makefile
-run-make/foreign-double-unwind/Makefile
-run-make/foreign-exceptions/Makefile
run-make/incr-add-rust-src-component/Makefile
-run-make/issue-35164/Makefile
-run-make/issue-36710/Makefile
-run-make/issue-47551/Makefile
-run-make/issue-69368/Makefile
run-make/issue-84395-lto-embed-bitcode/Makefile
-run-make/issue-88756-default-output/Makefile
run-make/jobserver-error/Makefile
run-make/libs-through-symlinks/Makefile
run-make/libtest-json/Makefile
run-make/libtest-junit/Makefile
run-make/libtest-thread-limit/Makefile
-run-make/link-cfg/Makefile
-run-make/long-linker-command-lines-cmd-exe/Makefile
-run-make/long-linker-command-lines/Makefile
run-make/macos-deployment-target/Makefile
run-make/min-global-align/Makefile
run-make/native-link-modifier-bundle/Makefile
-run-make/native-link-modifier-whole-archive/Makefile
run-make/no-alloc-shim/Makefile
-run-make/no-builtins-attribute/Makefile
-run-make/pdb-buildinfo-cl-cmd/Makefile
-run-make/pgo-gen-lto/Makefile
-run-make/pgo-indirect-call-promotion/Makefile
-run-make/print-calling-conventions/Makefile
-run-make/print-target-list/Makefile
-run-make/raw-dylib-alt-calling-convention/Makefile
-run-make/raw-dylib-c/Makefile
-run-make/raw-dylib-import-name-type/Makefile
-run-make/raw-dylib-link-ordinal/Makefile
-run-make/raw-dylib-stdcall-ordinal/Makefile
-run-make/redundant-libs/Makefile
run-make/remap-path-prefix-dwarf/Makefile
-run-make/reproducible-build-2/Makefile
run-make/reproducible-build/Makefile
-run-make/rlib-format-packed-bundled-libs-2/Makefile
run-make/rlib-format-packed-bundled-libs/Makefile
-run-make/share-generics-dylib/Makefile
-run-make/simd-ffi/Makefile
run-make/split-debuginfo/Makefile
-run-make/stable-symbol-names/Makefile
-run-make/staticlib-dylib-linkage/Makefile
run-make/symbol-mangling-hashed/Makefile
-run-make/symbol-visibility/Makefile
run-make/sysroot-crates-are-unstable/Makefile
-run-make/thumb-none-cortex-m/Makefile
-run-make/thumb-none-qemu/Makefile
run-make/translation/Makefile
run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
diff --git a/src/tools/tidy/src/alphabetical/tests.rs b/src/tools/tidy/src/alphabetical/tests.rs
index 560e028..29e89a6 100644
--- a/src/tools/tidy/src/alphabetical/tests.rs
+++ b/src/tools/tidy/src/alphabetical/tests.rs
@@ -1,7 +1,8 @@
-use super::*;
use std::io::Write;
use std::str::from_utf8;
+use super::*;
+
fn test(lines: &str, name: &str, expected_msg: &str, expected_bad: bool) {
let mut actual_msg = Vec::new();
let mut actual_bad = false;
diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs
index c82e8b6..d158a8e 100644
--- a/src/tools/tidy/src/bins.rs
+++ b/src/tools/tidy/src/bins.rs
@@ -21,12 +21,13 @@ pub fn check(_path: &Path, _bad: &mut bool) {}
#[cfg(unix)]
mod os_impl {
- use crate::walk::{filter_dirs, walk_no_read};
use std::fs;
use std::os::unix::prelude::*;
use std::path::Path;
use std::process::{Command, Stdio};
+ use crate::walk::{filter_dirs, walk_no_read};
+
enum FilesystemSupport {
Supported,
Unsupported,
diff --git a/src/tools/tidy/src/debug_artifacts.rs b/src/tools/tidy/src/debug_artifacts.rs
index 582014d..645534c 100644
--- a/src/tools/tidy/src/debug_artifacts.rs
+++ b/src/tools/tidy/src/debug_artifacts.rs
@@ -1,8 +1,9 @@
//! Tidy check to prevent creation of unnecessary debug artifacts while running tests.
-use crate::walk::{filter_dirs, filter_not_rust, walk};
use std::path::Path;
+use crate::walk::{filter_dirs, filter_not_rust, walk};
+
const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test";
pub fn check(test_dir: &Path, bad: &mut bool) {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 499e735..89011bb 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,11 +1,12 @@
//! Checks the licenses of third-party dependencies.
-use build_helper::ci::CiEnv;
-use cargo_metadata::{Metadata, Package, PackageId};
use std::collections::HashSet;
use std::fs::read_dir;
use std::path::Path;
+use build_helper::ci::CiEnv;
+use cargo_metadata::{Metadata, Package, PackageId};
+
/// These are licenses that are allowed for all crates, including the runtime,
/// rustc, tools, etc.
#[rustfmt::skip]
@@ -53,6 +54,7 @@
pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, &[&str])] = &[
// The root workspace has to be first for check_rustfix to work.
(".", EXCEPTIONS, Some((&["rustc-main"], PERMITTED_RUSTC_DEPENDENCIES)), &[]),
+ ("library", EXCEPTIONS_STDLIB, Some((&["sysroot"], PERMITTED_STDLIB_DEPENDENCIES)), &[]),
// Outside of the alphabetical section because rustfmt formats it using multiple lines.
(
"compiler/rustc_codegen_cranelift",
@@ -72,7 +74,7 @@
//("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
//("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]),
- ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book"]),
+ ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
("src/tools/x", &[], None, &[]),
// tidy-alphabetical-end
@@ -89,7 +91,6 @@
("colored", "MPL-2.0"), // rustfmt
("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
- ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above.
("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
("mdbook", "MPL-2.0"), // mdbook
("option-ext", "MPL-2.0"), // cargo-miri (via `directories`)
@@ -107,6 +108,17 @@
// tidy-alphabetical-end
];
+/// These are exceptions to Rust's permissive licensing policy, and
+/// should be considered bugs. Exceptions are only allowed in Rust
+/// tooling. It is _crucial_ that no exception crates be dependencies
+/// of the Rust runtime (std/test).
+#[rustfmt::skip]
+const EXCEPTIONS_STDLIB: ExceptionList = &[
+ // tidy-alphabetical-start
+ ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above.
+ // tidy-alphabetical-end
+];
+
// FIXME uncomment once rust-lang/stdarch#1462 lands
/*
const EXCEPTIONS_STDARCH: ExceptionList = &[
@@ -180,6 +192,7 @@
const EXCEPTIONS_CRANELIFT: ExceptionList = &[
// tidy-alphabetical-start
("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
+ ("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"),
("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"),
@@ -227,10 +240,6 @@
"ring",
];
-/// These are the root crates that are part of the runtime. The licenses for
-/// these and all their dependencies *must not* be in the exception list.
-const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
-
const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!());
/// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
@@ -239,7 +248,6 @@
/// rustc. Please check with the compiler team before adding an entry.
const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
// tidy-alphabetical-start
- "addr2line",
"adler",
"ahash",
"aho-corasick",
@@ -255,7 +263,6 @@
"cc",
"cfg-if",
"cfg_aliases",
- "compiler_builtins",
"cpufeatures",
"crc32fast",
"crossbeam-channel",
@@ -275,7 +282,6 @@
"digest",
"displaydoc",
"dissimilar",
- "dlmalloc",
"either",
"elsa",
"ena",
@@ -290,7 +296,6 @@
"fluent-langneg",
"fluent-syntax",
"fnv",
- "fortanix-sgx-abi",
"generic-array",
"getopts",
"getrandom",
@@ -353,12 +358,9 @@
"pulldown-cmark-escape",
"punycode",
"quote",
- "r-efi",
- "r-efi-alloc",
"rand",
"rand_chacha",
"rand_core",
- "rand_xorshift",
"rand_xoshiro",
"redox_syscall",
"regex",
@@ -428,7 +430,6 @@
"unicode-security",
"unicode-width",
"unicode-xid",
- "unwinding",
"valuable",
"version_check",
"wasi",
@@ -462,6 +463,46 @@
// tidy-alphabetical-end
];
+const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
+ // tidy-alphabetical-start
+ "addr2line",
+ "adler",
+ "allocator-api2",
+ "cc",
+ "cfg-if",
+ "compiler_builtins",
+ "dlmalloc",
+ "fortanix-sgx-abi",
+ "getopts",
+ "gimli",
+ "hashbrown",
+ "hermit-abi",
+ "libc",
+ "memchr",
+ "miniz_oxide",
+ "object",
+ "r-efi",
+ "r-efi-alloc",
+ "rand",
+ "rand_core",
+ "rand_xorshift",
+ "rustc-demangle",
+ "unicode-width",
+ "unwinding",
+ "wasi",
+ "windows-sys",
+ "windows-targets",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+ // tidy-alphabetical-end
+];
+
const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
// tidy-alphabetical-start
"ahash",
@@ -471,6 +512,7 @@
"bumpalo",
"cfg-if",
"cranelift-bforest",
+ "cranelift-bitset",
"cranelift-codegen",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
@@ -555,9 +597,8 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad);
}
- if workspace == "." {
- let runtime_ids = compute_runtime_crates(&metadata);
- check_runtime_license_exceptions(&metadata, runtime_ids, bad);
+ if workspace == "library" {
+ check_runtime_license_exceptions(&metadata, bad);
checked_runtime_licenses = true;
}
}
@@ -582,16 +623,8 @@ pub fn has_missing_submodule(root: &Path, submodules: &[&str]) -> bool {
///
/// Unlike for tools we don't allow exceptions to the `LICENSES` list for the runtime with the sole
/// exception of `fortanix-sgx-abi` which is only used on x86_64-fortanix-unknown-sgx.
-fn check_runtime_license_exceptions(
- metadata: &Metadata,
- runtime_ids: HashSet<&PackageId>,
- bad: &mut bool,
-) {
+fn check_runtime_license_exceptions(metadata: &Metadata, bad: &mut bool) {
for pkg in &metadata.packages {
- if !runtime_ids.contains(&pkg.id) {
- // Only checking dependencies of runtime libraries here.
- continue;
- }
if pkg.source.is_none() {
// No need to check local packages.
continue;
@@ -612,20 +645,6 @@ fn check_runtime_license_exceptions(
continue;
}
- // This exception is due to the fact that the feature set of the
- // `object` crate is different between rustc and libstd. In the
- // standard library only a conservative set of features are enabled
- // which notably does not include the `wasm` feature which pulls in
- // this dependency. In the compiler, however, the `wasm` feature is
- // enabled. This exception is intended to be here so long as the
- // `EXCEPTIONS` above contains `wasmparser`, but once that goes away
- // this can be removed.
- if pkg.name == "wasmparser"
- && pkg.license.as_deref() == Some("Apache-2.0 WITH LLVM-exception")
- {
- continue;
- }
-
tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id);
}
}
@@ -757,16 +776,6 @@ fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package {
metadata.packages.iter().find(|p| &p.id == id).unwrap()
}
-/// Finds all the packages that are in the rust runtime.
-fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> {
- let mut result = HashSet::new();
- for name in RUNTIME_CRATES {
- let id = &pkg_from_name(metadata, name).id;
- deps_of(metadata, id, &mut result);
- }
- result
-}
-
/// Recursively find all dependencies.
fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId, result: &mut HashSet<&'a PackageId>) {
if !result.insert(pkg_id) {
diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs
index f28f677..6a58d58 100644
--- a/src/tools/tidy/src/edition.rs
+++ b/src/tools/tidy/src/edition.rs
@@ -1,12 +1,8 @@
//! Tidy check to ensure that crate `edition` is '2018' or '2021'.
-use crate::walk::{filter_dirs, walk};
use std::path::Path;
-fn is_edition_2021(mut line: &str) -> bool {
- line = line.trim();
- line == "edition = \"2021\""
-}
+use crate::walk::{filter_dirs, walk};
pub fn check(path: &Path, bad: &mut bool) {
walk(path, |path, _is_dir| filter_dirs(path), &mut |entry, contents| {
@@ -16,8 +12,15 @@ pub fn check(path: &Path, bad: &mut bool) {
return;
}
- let is_2021 = contents.lines().any(is_edition_2021);
- if !is_2021 {
+ let is_2021 = contents.lines().any(|line| line.trim() == "edition = \"2021\"");
+
+ let is_workspace = contents.lines().any(|line| line.trim() == "[workspace]");
+ let is_package = contents.lines().any(|line| line.trim() == "[package]");
+ assert!(is_workspace || is_package);
+
+ // Check that all packages use the 2021 edition. Virtual workspaces don't allow setting an
+ // edition, so these shouldn't be checked.
+ if is_package && !is_2021 {
tidy_error!(
bad,
"{} doesn't have `edition = \"2021\"` on a separate line",
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index 47e2be7..e2d1b85 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -16,7 +16,9 @@
//! 4. We check that the error code is actually emitted by the compiler.
//! - This is done by searching `compiler/` with a regex.
-use std::{ffi::OsStr, fs, path::Path};
+use std::ffi::OsStr;
+use std::fs;
+use std::path::Path;
use regex::Regex;
@@ -317,7 +319,7 @@ fn check_error_codes_tests(
if !found_code {
verbose_print!(
verbose,
- "warning: Error code {code}`` has a UI test file, but doesn't contain its own error code!"
+ "warning: Error code `{code}` has a UI test file, but doesn't contain its own error code!"
);
}
}
diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs
index 8ce4411..ea9ab01 100644
--- a/src/tools/tidy/src/ext_tool_checks.rs
+++ b/src/tools/tidy/src/ext_tool_checks.rs
@@ -18,11 +18,9 @@
//! is set, rerun the tool to print a suggestion diff (for e.g. CI)
use std::ffi::OsStr;
-use std::fmt;
-use std::fs;
-use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
+use std::{fmt, fs, io};
const MIN_PY_REV: (u32, u32) = (3, 9);
const MIN_PY_REV_STR: &str = "≥3.9";
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index e8dff2d..a4d27d2 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -9,13 +9,13 @@
//! * All unstable lang features have tests to ensure they are actually unstable.
//! * Language features in a group are sorted by feature name.
-use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many};
use std::collections::hash_map::{Entry, HashMap};
use std::ffi::OsStr;
-use std::fmt;
-use std::fs;
use std::num::NonZeroU32;
use std::path::{Path, PathBuf};
+use std::{fmt, fs};
+
+use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many};
#[cfg(test)]
mod tests;
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
index a853679..6f154b9 100644
--- a/src/tools/tidy/src/fluent_alphabetical.rs
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -1,11 +1,14 @@
//! Checks that all Flunt files have messages in alphabetical order
-use crate::walk::{filter_dirs, walk};
use std::collections::HashMap;
-use std::{fs::OpenOptions, io::Write, path::Path};
+use std::fs::OpenOptions;
+use std::io::Write;
+use std::path::Path;
use regex::Regex;
+use crate::walk::{filter_dirs, walk};
+
fn message() -> &'static Regex {
static_regex!(r#"(?m)^([a-zA-Z0-9_]+)\s*=\s*"#)
}
diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs
index 3a1fb6d..8bc404d 100644
--- a/src/tools/tidy/src/fluent_period.rs
+++ b/src/tools/tidy/src/fluent_period.rs
@@ -1,9 +1,10 @@
//! Checks that no Fluent messages or attributes end in periods (except ellipses)
+use std::path::Path;
+
use fluent_syntax::ast::{Entry, PatternElement};
use crate::walk::{filter_dirs, walk};
-use std::path::Path;
fn filter_fluent(path: &Path) -> bool {
if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs
index 8b6c6c1..ab56b5f 100644
--- a/src/tools/tidy/src/fluent_used.rs
+++ b/src/tools/tidy/src/fluent_used.rs
@@ -1,9 +1,10 @@
//! Checks that all Fluent messages appear at least twice
-use crate::walk::{filter_dirs, walk};
use std::collections::HashMap;
use std::path::Path;
+use crate::walk::{filter_dirs, walk};
+
fn filter_used_messages(
contents: &str,
msgs_not_appeared_yet: &mut HashMap<String, String>,
diff --git a/src/tools/tidy/src/known_bug.rs b/src/tools/tidy/src/known_bug.rs
index a62556f..182a81c 100644
--- a/src/tools/tidy/src/known_bug.rs
+++ b/src/tools/tidy/src/known_bug.rs
@@ -1,8 +1,9 @@
//! Tidy check to ensure that tests inside 'tests/crashes' have a '@known-bug' directive.
-use crate::walk::*;
use std::path::Path;
+use crate::walk::*;
+
pub fn check(filepath: &Path, bad: &mut bool) {
walk(filepath, |path, _is_dir| filter_not_rust(path), &mut |entry, contents| {
let file = entry.path();
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index ecd3272..3215896 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -50,6 +50,7 @@ macro_rules! tidy_error_ext {
fn tidy_error(args: &str) -> std::io::Result<()> {
use std::io::Write;
+
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream};
let mut stderr = StandardStream::stdout(ColorChoice::Auto);
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index ec6fc1f..e6d21bf 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -4,16 +4,15 @@
//! etc. This is run by default on `./x.py test` and as part of the auto
//! builders. The tidy checks can be executed with `./x.py test tidy`.
-use tidy::*;
-
use std::collections::VecDeque;
-use std::env;
use std::num::NonZeroUsize;
use std::path::PathBuf;
-use std::process;
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, scope, ScopedJoinHandle};
+use std::{env, process};
+
+use tidy::*;
fn main() {
// Running Cargo will read the libstd Cargo.toml
diff --git a/src/tools/tidy/src/mir_opt_tests.rs b/src/tools/tidy/src/mir_opt_tests.rs
index 76feeb3..bb0d815 100644
--- a/src/tools/tidy/src/mir_opt_tests.rs
+++ b/src/tools/tidy/src/mir_opt_tests.rs
@@ -1,9 +1,10 @@
//! Tidy check to ensure that mir opt directories do not have stale files or dashes in file names
-use miropt_test_tools::PanicStrategy;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
+use miropt_test_tools::PanicStrategy;
+
use crate::walk::walk_no_read;
fn check_unused_files(path: &Path, bless: bool, bad: &mut bool) {
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 2f8abc7..b7ddf47 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -30,9 +30,10 @@
//! platform-specific cfgs are allowed. Not sure yet how to deal with
//! this in the long term.
-use crate::walk::{filter_dirs, walk};
use std::path::Path;
+use crate::walk::{filter_dirs, walk};
+
// Paths that may contain platform-specific code.
const EXCEPTION_PATHS: &[&str] = &[
"library/panic_abort",
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 8d8cc7a..6394a14 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -17,10 +17,14 @@
//! `// ignore-tidy-CHECK-NAME`.
// ignore-tidy-dbg
-use crate::walk::{filter_dirs, walk};
+use std::ffi::OsStr;
+use std::path::Path;
+use std::sync::LazyLock;
+
use regex::RegexSetBuilder;
use rustc_hash::FxHashMap;
-use std::{ffi::OsStr, path::Path, sync::LazyLock};
+
+use crate::walk::{filter_dirs, walk};
#[cfg(test)]
mod tests;
diff --git a/src/tools/tidy/src/target_policy.rs b/src/tools/tidy/src/target_policy.rs
index cb9a0c1..776221d 100644
--- a/src/tools/tidy/src/target_policy.rs
+++ b/src/tools/tidy/src/target_policy.rs
@@ -2,8 +2,10 @@
//!
//! As of writing, only checks that sanity-check assembly test for targets doesn't miss any targets.
+use std::collections::HashSet;
+use std::path::Path;
+
use crate::walk::{filter_not_rust, walk};
-use std::{collections::HashSet, path::Path};
const TARGET_DEFINITIONS_PATH: &str = "compiler/rustc_target/src/spec/targets/";
const ASSEMBLY_TEST_PATH: &str = "tests/assembly/targets/";
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 0ae0356..41f7778 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -2,13 +2,14 @@
//! - the number of entries in each directory must be less than `ENTRY_LIMIT`
//! - there are no stray `.stderr` files
-use ignore::Walk;
use std::collections::{BTreeSet, HashMap};
use std::ffi::OsStr;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
+use ignore::Walk;
+
// FIXME: GitHub's UI truncates file lists that exceed 1000 entries, so these
// should all be 1000 or lower. Limits significantly smaller than 1000 are also
// desirable, because large numbers of files are unwieldy in general. See issue
diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs
index 0a5dad8..708e4ef 100644
--- a/src/tools/tidy/src/unit_tests.rs
+++ b/src/tools/tidy/src/unit_tests.rs
@@ -7,9 +7,10 @@
//! named `tests.rs` or `benches.rs`, or directories named `tests` or `benches` unconfigured
//! during normal build.
-use crate::walk::{filter_dirs, walk};
use std::path::Path;
+use crate::walk::{filter_dirs, walk};
+
pub fn check(root_path: &Path, bad: &mut bool) {
let core = root_path.join("core");
let core_copy = core.clone();
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 7dfb622..8be25b9 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -1,8 +1,9 @@
-use crate::features::{CollectedFeatures, Features, Status};
use std::collections::BTreeSet;
use std::fs;
use std::path::{Path, PathBuf};
+use crate::features::{CollectedFeatures, Features, Status};
+
pub const PATH_STR: &str = "doc/unstable-book";
pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index 1cecf99..d4721b5 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -1,6 +1,9 @@
-use ignore::DirEntry;
+use std::ffi::OsStr;
+use std::fs::File;
+use std::io::Read;
+use std::path::Path;
-use std::{ffi::OsStr, fs::File, io::Read, path::Path};
+use ignore::DirEntry;
/// The default directory filter.
pub fn filter_dirs(path: &Path) -> bool {
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
index 55bfbed8..4893435 100644
--- a/src/tools/tidy/src/x_version.rs
+++ b/src/tools/tidy/src/x_version.rs
@@ -1,7 +1,8 @@
-use semver::Version;
use std::path::Path;
use std::process::{Command, Stdio};
+use semver::Version;
+
pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
let cargo_list = Command::new(cargo).args(["install", "--list"]).stdout(Stdio::piped()).spawn();
diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs
index 02c7542..036f0bd 100644
--- a/src/tools/unicode-table-generator/src/cascading_map.rs
+++ b/src/tools/unicode-table-generator/src/cascading_map.rs
@@ -1,9 +1,10 @@
-use crate::fmt_list;
-use crate::raw_emitter::RawEmitter;
use std::collections::HashMap;
use std::fmt::Write as _;
use std::ops::Range;
+use crate::fmt_list;
+use crate::raw_emitter::RawEmitter;
+
impl RawEmitter {
pub fn emit_cascading_map(&mut self, ranges: &[Range<u32>]) -> bool {
let mut map: [u8; 256] = [
diff --git a/src/tools/unicode-table-generator/src/case_mapping.rs b/src/tools/unicode-table-generator/src/case_mapping.rs
index 7a978db..f28161c 100644
--- a/src/tools/unicode-table-generator/src/case_mapping.rs
+++ b/src/tools/unicode-table-generator/src/case_mapping.rs
@@ -1,9 +1,8 @@
+use std::char;
+use std::collections::BTreeMap;
+use std::fmt::{self, Write};
+
use crate::{fmt_list, UnicodeData};
-use std::{
- char,
- collections::BTreeMap,
- fmt::{self, Write},
-};
const INDEX_MASK: u32 = 1 << 22;
diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs
index 2fe578a..9f89e7c 100644
--- a/src/tools/unicode-table-generator/src/main.rs
+++ b/src/tools/unicode-table-generator/src/main.rs
@@ -73,6 +73,7 @@
use std::collections::{BTreeMap, HashMap};
use std::ops::Range;
+
use ucd_parse::Codepoints;
mod cascading_map;
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index ef5cea1..47120e4 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -1,8 +1,9 @@
-use crate::fmt_list;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt::{self, Write};
use std::ops::Range;
+use crate::fmt_list;
+
#[derive(Clone)]
pub struct RawEmitter {
pub file: String,
diff --git a/src/tools/unicode-table-generator/src/skiplist.rs b/src/tools/unicode-table-generator/src/skiplist.rs
index 8fae828..8ca18dd 100644
--- a/src/tools/unicode-table-generator/src/skiplist.rs
+++ b/src/tools/unicode-table-generator/src/skiplist.rs
@@ -1,8 +1,9 @@
-use crate::fmt_list;
-use crate::raw_emitter::RawEmitter;
use std::fmt::Write as _;
use std::ops::Range;
+use crate::fmt_list;
+use crate::raw_emitter::RawEmitter;
+
/// This will get packed into a single u32 before inserting into the data set.
#[derive(Debug, PartialEq)]
struct ShortOffsetRunHeader {
diff --git a/src/tools/unicode-table-generator/src/unicode_download.rs b/src/tools/unicode-table-generator/src/unicode_download.rs
index 714bb53..c982617 100644
--- a/src/tools/unicode-table-generator/src/unicode_download.rs
+++ b/src/tools/unicode-table-generator/src/unicode_download.rs
@@ -1,7 +1,8 @@
-use crate::UNICODE_DIRECTORY;
use std::path::Path;
use std::process::{Command, Output};
+use crate::UNICODE_DIRECTORY;
+
static URL_PREFIX: &str = "https://www.unicode.org/Public/UCD/latest/ucd/";
static README: &str = "ReadMe.txt";
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index a9830a3..9af8802 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -4,6 +4,7 @@
use std::env;
use std::fs::{self, write};
use std::path::Path;
+
use tidy::features::{collect_lang_features, collect_lib_features, Features};
use tidy::t;
use tidy::unstable_book::{
diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs
index 5da8a28..b288cfc 100644
--- a/src/tools/x/src/main.rs
+++ b/src/tools/x/src/main.rs
@@ -8,12 +8,11 @@
//! the ones that call `x.py`. We use `sh -c` on Unix, because it is a standard.
//! We also don't use `pwsh` on Windows, because it is not installed by default;
-use std::{
- env::{self, consts::EXE_EXTENSION},
- io,
- path::Path,
- process::{self, Command, ExitStatus},
-};
+use std::env::consts::EXE_EXTENSION;
+use std::env::{self};
+use std::io;
+use std::path::Path;
+use std::process::{self, Command, ExitStatus};
const PYTHON: &str = "python";
const PYTHON2: &str = "python2";
diff --git a/tests/assembly/asm/aarch64-outline-atomics.rs b/tests/assembly/asm/aarch64-outline-atomics.rs
index bcf0964..46586f0 100644
--- a/tests/assembly/asm/aarch64-outline-atomics.rs
+++ b/tests/assembly/asm/aarch64-outline-atomics.rs
@@ -7,7 +7,8 @@
#![crate_type = "rlib"]
-use std::sync::atomic::{AtomicI32, Ordering::*};
+use std::sync::atomic::AtomicI32;
+use std::sync::atomic::Ordering::*;
pub fn compare_exchange(a: &AtomicI32) {
// On AArch64 LLVM should outline atomic operations.
diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs
new file mode 100644
index 0000000..9a3540d
--- /dev/null
+++ b/tests/assembly/powerpc64-struct-abi.rs
@@ -0,0 +1,132 @@
+//@ revisions: elfv1-be elfv2-be elfv2-le
+//@ assembly-output: emit-asm
+//@ compile-flags: -O
+//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu
+//@[elfv1-be] needs-llvm-components: powerpc
+//@[elfv2-be] compile-flags: --target powerpc64-unknown-linux-musl
+//@[elfv2-be] needs-llvm-components: powerpc
+//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//@[elfv2-le] needs-llvm-components: powerpc
+//@[elfv1-be] filecheck-flags: --check-prefix be
+//@[elfv2-be] filecheck-flags: --check-prefix be
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "freeze"]
+trait Freeze {}
+
+#[lang = "unpin"]
+trait Unpin {}
+
+impl Copy for u8 {}
+impl Copy for u16 {}
+impl Copy for u32 {}
+impl Copy for FiveU32s {}
+impl Copy for FiveU16s {}
+impl Copy for ThreeU8s {}
+
+#[repr(C)]
+struct FiveU32s(u32, u32, u32, u32, u32);
+
+#[repr(C)]
+struct FiveU16s(u16, u16, u16, u16, u16);
+
+#[repr(C)]
+struct ThreeU8s(u8, u8, u8);
+
+// CHECK-LABEL: read_large
+// be: lwz [[REG1:.*]], 16(4)
+// be-NEXT: stw [[REG1]], 16(3)
+// be-NEXT: ld [[REG2:.*]], 8(4)
+// be-NEXT: ld [[REG3:.*]], 0(4)
+// be-NEXT: std [[REG2]], 8(3)
+// be-NEXT: std [[REG3]], 0(3)
+// elfv2-le: lxvd2x [[REG1:.*]], 0, 4
+// elfv2-le-NEXT: lwz [[REG2:.*]], 16(4)
+// elfv2-le-NEXT: stw [[REG2]], 16(3)
+// elfv2-le-NEXT: stxvd2x [[REG1]], 0, 3
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn read_large(x: &FiveU32s) -> FiveU32s {
+ *x
+}
+
+// CHECK-LABEL: read_medium
+// elfv1-be: lhz [[REG1:.*]], 8(4)
+// elfv1-be-NEXT: ld [[REG2:.*]], 0(4)
+// elfv1-be-NEXT: sth [[REG1]], 8(3)
+// elfv1-be-NEXT: std [[REG2]], 0(3)
+// elfv2-be: lhz [[REG1:.*]], 8(3)
+// elfv2-be-NEXT: ld 3, 0(3)
+// elfv2-be-NEXT: sldi 4, [[REG1]], 48
+// elfv2-le: ld [[REG1:.*]], 0(3)
+// elfv2-le-NEXT: lhz 4, 8(3)
+// elfv2-le-NEXT: mr 3, [[REG1]]
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn read_medium(x: &FiveU16s) -> FiveU16s {
+ *x
+}
+
+// CHECK-LABEL: read_small
+// elfv1-be: lbz [[REG1:.*]], 2(4)
+// elfv1-be-NEXT: lhz [[REG2:.*]], 0(4)
+// elfv1-be-NEXT: stb [[REG1]], 2(3)
+// elfv1-be-NEXT: sth [[REG2]], 0(3)
+// elfv2-be: lhz [[REG1:.*]], 0(3)
+// elfv2-be-NEXT: lbz 3, 2(3)
+// elfv2-be-NEXT: rldimi 3, [[REG1]], 8, 0
+// elfv2-le: lbz [[REG1:.*]], 2(3)
+// elfv2-le-NEXT: lhz 3, 0(3)
+// elfv2-le-NEXT: rldimi 3, [[REG1]], 16, 0
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s {
+ *x
+}
+
+// CHECK-LABEL: write_large
+// CHECK: std 3, 0(6)
+// be-NEXT: rldicl [[REG1:.*]], 5, 32, 32
+// CHECK-NEXT: std 4, 8(6)
+// be-NEXT: stw [[REG1]], 16(6)
+// elfv2-le-NEXT: stw 5, 16(6)
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn write_large(x: FiveU32s, dest: &mut FiveU32s) {
+ *dest = x;
+}
+
+// CHECK-LABEL: write_medium
+// CHECK: std 3, 0(5)
+// be-NEXT: rldicl [[REG1:.*]], 4, 16, 48
+// be-NEXT: sth [[REG1]], 8(5)
+// elfv2-le-NEXT: sth 4, 8(5)
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn write_medium(x: FiveU16s, dest: &mut FiveU16s) {
+ *dest = x;
+}
+
+// CHECK-LABEL: write_small
+// be: stb 3, 2(4)
+// be-NEXT: srwi [[REG1:.*]], 3, 8
+// be-NEXT: sth [[REG1]], 0(4)
+// The order these instructions are emitted in changed in LLVM 18.
+// elfv2-le-DAG: sth 3, 0(4)
+// elfv2-le-DAG: srwi [[REG1:.*]], 3, 16
+// elfv2-le-NEXT: stb [[REG1]], 2(4)
+// CHECK-NEXT: blr
+#[no_mangle]
+extern "C" fn write_small(x: ThreeU8s, dest: &mut ThreeU8s) {
+ *dest = x;
+}
diff --git a/tests/assembly/x86-return-float.rs b/tests/assembly/x86-return-float.rs
index c4a2c1a..f9ebf53 100644
--- a/tests/assembly/x86-return-float.rs
+++ b/tests/assembly/x86-return-float.rs
@@ -8,9 +8,9 @@
// Force frame pointers to make ASM more consistent between targets
//@ compile-flags: -O -C force-frame-pointers
//@ filecheck-flags: --implicit-check-not fld --implicit-check-not fst
-//@ revisions: unix windows
-//@[unix] ignore-windows
-//@[windows] only-windows
+//@ revisions: normal win
+//@[normal] ignore-windows
+//@[win] only-windows
#![crate_type = "lib"]
#![feature(f16, f128)]
@@ -190,10 +190,10 @@ pub unsafe fn call_f64_f64(x: &mut (f64, f64)) {
}
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
// CHECK: calll {{()|_}}get_f64_f64
- // unix: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
- // unix-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
- // windows: movsd (%esp), %[[VAL1:.*]]
- // windows-NEXT: movsd 8(%esp), %[[VAL2:.*]]
+ // normal: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+ // normal-NEXT: movsd [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+ // win: movsd (%esp), %[[VAL1:.*]]
+ // win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
// CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
// CHECK-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
*x = get_f64_f64();
@@ -207,13 +207,13 @@ pub unsafe fn call_f32_f64(x: &mut (f32, f64)) {
}
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
// CHECK: calll {{()|_}}get_f32_f64
- // unix: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
- // unix-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
- // windows: movss (%esp), %[[VAL1:.*]]
- // windows-NEXT: movsd 8(%esp), %[[VAL2:.*]]
+ // normal: movss [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+ // normal-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+ // win: movss (%esp), %[[VAL1:.*]]
+ // win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
// CHECK-NEXT: movss %[[VAL1]], (%[[PTR]])
- // unix-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
- // windows-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
+ // normal-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
+ // win-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
*x = get_f32_f64();
}
@@ -225,10 +225,10 @@ pub unsafe fn call_f64_f32(x: &mut (f64, f32)) {
}
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
// CHECK: calll {{()|_}}get_f64_f32
- // unix: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
- // unix-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
- // windows: movsd (%esp), %[[VAL1:.*]]
- // windows-NEXT: movss 8(%esp), %[[VAL2:.*]]
+ // normal: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+ // normal-NEXT: movss [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+ // win: movsd (%esp), %[[VAL1:.*]]
+ // win-NEXT: movss 8(%esp), %[[VAL2:.*]]
// CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
// CHECK-NEXT: movss %[[VAL2]], 8(%[[PTR]])
*x = get_f64_f32();
@@ -257,10 +257,10 @@ pub unsafe fn call_f64_other(x: &mut (f64, usize)) {
}
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
// CHECK: calll {{()|_}}get_f64_other
- // unix: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
- // unix-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
- // windows: movsd (%esp), %[[VAL1:.*]]
- // windows-NEXT: movl 8(%esp), %[[VAL2:.*]]
+ // normal: movsd [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+ // normal-NEXT: movl [[#%d,OFFSET+8]](%ebp), %[[VAL2:.*]]
+ // win: movsd (%esp), %[[VAL1:.*]]
+ // win-NEXT: movl 8(%esp), %[[VAL2:.*]]
// CHECK-NEXT: movsd %[[VAL1]], (%[[PTR]])
// CHECK-NEXT: movl %[[VAL2]], 8(%[[PTR]])
*x = get_f64_other();
@@ -289,13 +289,13 @@ pub unsafe fn call_other_f64(x: &mut (usize, f64)) {
}
// CHECK: movl {{.*}}(%ebp), %[[PTR:.*]]
// CHECK: calll {{()|_}}get_other_f64
- // unix: movl [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
- // unix-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
- // windows: movl (%esp), %[[VAL1:.*]]
- // windows-NEXT: movsd 8(%esp), %[[VAL2:.*]]
+ // normal: movl [[#%d,OFFSET:]](%ebp), %[[VAL1:.*]]
+ // normal-NEXT: movsd [[#%d,OFFSET+4]](%ebp), %[[VAL2:.*]]
+ // win: movl (%esp), %[[VAL1:.*]]
+ // win-NEXT: movsd 8(%esp), %[[VAL2:.*]]
// CHECK-NEXT: movl %[[VAL1]], (%[[PTR]])
- // unix-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
- // windows-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
+ // normal-NEXT: movsd %[[VAL2]], 4(%[[PTR]])
+ // win-NEXT: movsd %[[VAL2]], 8(%[[PTR]])
*x = get_other_f64();
}
diff --git a/tests/assembly/x86_64-windows-float-abi.rs b/tests/assembly/x86_64-windows-float-abi.rs
new file mode 100644
index 0000000..1381d49
--- /dev/null
+++ b/tests/assembly/x86_64-windows-float-abi.rs
@@ -0,0 +1,39 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: -O
+//@ only-windows
+//@ only-x86_64
+
+#![feature(f16, f128)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: second_f16
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f16(_: f16, x: f16) -> f16 {
+ x
+}
+
+// CHECK-LABEL: second_f32
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f32(_: f32, x: f32) -> f32 {
+ x
+}
+
+// CHECK-LABEL: second_f64
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f64(_: f64, x: f64) -> f64 {
+ x
+}
+
+// CHECK-LABEL: second_f128
+// CHECK: movaps %xmm1, %xmm0
+// CHECK-NEXT: retq
+#[no_mangle]
+pub extern "C" fn second_f128(_: f128, x: f128) -> f128 {
+ x
+}
diff --git a/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs
index 0192a3d..33a32d7 100644
--- a/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs
+++ b/tests/codegen-units/item-collection/auxiliary/cgu_extern_closures.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Zinline-mir=no
+
#![crate_type = "lib"]
#[inline]
diff --git a/tests/codegen-units/item-collection/cross-crate-closures.rs b/tests/codegen-units/item-collection/cross-crate-closures.rs
index 2dab194..cb86cf1 100644
--- a/tests/codegen-units/item-collection/cross-crate-closures.rs
+++ b/tests/codegen-units/item-collection/cross-crate-closures.rs
@@ -1,9 +1,6 @@
-// In the current version of the collector that still has to support
-// legacy-codegen, closures do not generate their own MonoItems, so we are
-// ignoring this test until MIR codegen has taken over completely
-//@ ignore-test
-
-//@ compile-flags:-Zprint-mono-items=eager
+// We need to disable MIR inlining in both this and its aux-build crate. The MIR inliner
+// will just inline everything into our start function if we let it. As it should.
+//@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no
#![deny(dead_code)]
#![feature(start)]
@@ -11,15 +8,15 @@
//@ aux-build:cgu_extern_closures.rs
extern crate cgu_extern_closures;
-//~ MONO_ITEM fn cross_crate_closures::start[0]
+//~ MONO_ITEM fn start @@ cross_crate_closures-cgu.0[Internal]
#[start]
fn start(_: isize, _: *const *const u8) -> isize {
- //~ MONO_ITEM fn cgu_extern_closures::inlined_fn[0]
- //~ MONO_ITEM fn cgu_extern_closures::inlined_fn[0]::{{closure}}[0]
+ //~ MONO_ITEM fn cgu_extern_closures::inlined_fn @@ cross_crate_closures-cgu.0[Internal]
+ //~ MONO_ITEM fn cgu_extern_closures::inlined_fn::{closure#0} @@ cross_crate_closures-cgu.0[Internal]
let _ = cgu_extern_closures::inlined_fn(1, 2);
- //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic[0]<i32>
- //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic[0]::{{closure}}[0]<i32>
+ //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic::<i32> @@ cross_crate_closures-cgu.0[Internal]
+ //~ MONO_ITEM fn cgu_extern_closures::inlined_fn_generic::<i32>::{closure#0} @@ cross_crate_closures-cgu.0[Internal]
let _ = cgu_extern_closures::inlined_fn_generic(3, 4, 5i32);
// Nothing should be generated for this call, we just link to the instance
@@ -28,5 +25,3 @@ fn start(_: isize, _: *const *const u8) -> isize {
0
}
-
-//~ MONO_ITEM drop-glue i8
diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs
index b4cd992..23d09e0 100644
--- a/tests/codegen-units/item-collection/generic-impl.rs
+++ b/tests/codegen-units/item-collection/generic-impl.rs
@@ -22,16 +22,16 @@ fn get<T2>(self, x: T2) -> (T, T2) {
}
}
-pub struct _LifeTimeOnly<'a> {
+pub struct LifeTimeOnly<'a> {
_a: &'a u32,
}
-impl<'a> _LifeTimeOnly<'a> {
- //~ MONO_ITEM fn _LifeTimeOnly::<'_>::foo
+impl<'a> LifeTimeOnly<'a> {
+ //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo
pub fn foo(&self) {}
- //~ MONO_ITEM fn _LifeTimeOnly::<'_>::bar
+ //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar
pub fn bar(&'a self) {}
- //~ MONO_ITEM fn _LifeTimeOnly::<'_>::baz
+ //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz
pub fn baz<'b>(&'b self) {}
pub fn non_instantiated<T>(&self) {}
diff --git a/tests/codegen-units/item-collection/non-generic-closures.rs b/tests/codegen-units/item-collection/non-generic-closures.rs
index 105348e..dc0846f 100644
--- a/tests/codegen-units/item-collection/non-generic-closures.rs
+++ b/tests/codegen-units/item-collection/non-generic-closures.rs
@@ -1,49 +1,45 @@
-// In the current version of the collector that still has to support
-// legacy-codegen, closures do not generate their own MonoItems, so we are
-// ignoring this test until MIR codegen has taken over completely
-//@ ignore-test
-
-//
-//@ compile-flags:-Zprint-mono-items=eager
+//@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no
#![deny(dead_code)]
#![feature(start)]
-//~ MONO_ITEM fn non_generic_closures::temporary[0]
+//~ MONO_ITEM fn temporary @@ non_generic_closures-cgu.0[Internal]
fn temporary() {
- //~ MONO_ITEM fn non_generic_closures::temporary[0]::{{closure}}[0]
+ //~ MONO_ITEM fn temporary::{closure#0} @@ non_generic_closures-cgu.0[Internal]
(|a: u32| {
let _ = a;
})(4);
}
-//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0]
+//~ MONO_ITEM fn assigned_to_variable_but_not_executed @@ non_generic_closures-cgu.0[Internal]
fn assigned_to_variable_but_not_executed() {
- //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_but_not_executed[0]::{{closure}}[0]
let _x = |a: i16| {
let _ = a + 1;
};
}
-//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0]
+//~ MONO_ITEM fn assigned_to_variable_executed_indirectly @@ non_generic_closures-cgu.0[Internal]
fn assigned_to_variable_executed_indirectly() {
- //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_directly[0]::{{closure}}[0]
+ //~ MONO_ITEM fn assigned_to_variable_executed_indirectly::{closure#0} @@ non_generic_closures-cgu.0[Internal]
+ //~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim @@ non_generic_closures-cgu.0[Internal]
+ //~ MONO_ITEM fn <{closure@TEST_PATH:27:13: 27:21} as std::ops::FnOnce<(i32,)>>::call_once - shim(vtable) @@ non_generic_closures-cgu.0[Internal]
+ //~ MONO_ITEM fn std::ptr::drop_in_place::<{closure@TEST_PATH:27:13: 27:21}> - shim(None) @@ non_generic_closures-cgu.0[Internal]
let f = |a: i32| {
let _ = a + 2;
};
run_closure(&f);
}
-//~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0]
+//~ MONO_ITEM fn assigned_to_variable_executed_directly @@ non_generic_closures-cgu.0[Internal]
fn assigned_to_variable_executed_directly() {
- //~ MONO_ITEM fn non_generic_closures::assigned_to_variable_executed_indirectly[0]::{{closure}}[0]
+ //~ MONO_ITEM fn assigned_to_variable_executed_directly::{closure#0} @@ non_generic_closures-cgu.0[Internal]
let f = |a: i64| {
let _ = a + 3;
};
f(4);
}
-//~ MONO_ITEM fn non_generic_closures::start[0]
+//~ MONO_ITEM fn start @@ non_generic_closures-cgu.0[Internal]
#[start]
fn start(_: isize, _: *const *const u8) -> isize {
temporary();
@@ -54,7 +50,7 @@ fn start(_: isize, _: *const *const u8) -> isize {
0
}
-//~ MONO_ITEM fn non_generic_closures::run_closure[0]
+//~ MONO_ITEM fn run_closure @@ non_generic_closures-cgu.0[Internal]
fn run_closure(f: &Fn(i32)) {
f(3);
}
diff --git a/tests/codegen-units/item-collection/overloaded-operators.rs b/tests/codegen-units/item-collection/overloaded-operators.rs
index e00e22d..69b5569 100644
--- a/tests/codegen-units/item-collection/overloaded-operators.rs
+++ b/tests/codegen-units/item-collection/overloaded-operators.rs
@@ -5,44 +5,44 @@
use std::ops::{Add, Deref, Index, IndexMut};
-pub struct _Indexable {
+pub struct Indexable {
data: [u8; 3],
}
-impl Index<usize> for _Indexable {
+impl Index<usize> for Indexable {
type Output = u8;
- //~ MONO_ITEM fn <_Indexable as std::ops::Index<usize>>::index
+ //~ MONO_ITEM fn <Indexable as std::ops::Index<usize>>::index
fn index(&self, index: usize) -> &Self::Output {
if index >= 3 { &self.data[0] } else { &self.data[index] }
}
}
-impl IndexMut<usize> for _Indexable {
- //~ MONO_ITEM fn <_Indexable as std::ops::IndexMut<usize>>::index_mut
+impl IndexMut<usize> for Indexable {
+ //~ MONO_ITEM fn <Indexable as std::ops::IndexMut<usize>>::index_mut
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index >= 3 { &mut self.data[0] } else { &mut self.data[index] }
}
}
-//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::eq
-//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::ne
+//~ MONO_ITEM fn <Equatable as std::cmp::PartialEq>::eq
+//~ MONO_ITEM fn <Equatable as std::cmp::PartialEq>::ne
#[derive(PartialEq)]
-pub struct _Equatable(u32);
+pub struct Equatable(u32);
-impl Add<u32> for _Equatable {
+impl Add<u32> for Equatable {
type Output = u32;
- //~ MONO_ITEM fn <_Equatable as std::ops::Add<u32>>::add
+ //~ MONO_ITEM fn <Equatable as std::ops::Add<u32>>::add
fn add(self, rhs: u32) -> u32 {
self.0 + rhs
}
}
-impl Deref for _Equatable {
+impl Deref for Equatable {
type Target = u32;
- //~ MONO_ITEM fn <_Equatable as std::ops::Deref>::deref
+ //~ MONO_ITEM fn <Equatable as std::ops::Deref>::deref
fn deref(&self) -> &Self::Target {
&self.0
}
diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs
index 901e750..7c9045e 100644
--- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs
+++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs
@@ -1,30 +1,23 @@
-// Currently, all generic functions are instantiated in each codegen unit that
-// uses them, even those not marked with #[inline], so this test does not make
-// much sense at the moment.
-//@ ignore-test
-
// We specify incremental here because we want to test the partitioning for incremental compilation
//@ incremental
//@ compile-flags:-Zprint-mono-items=lazy
-#![allow(dead_code)]
-#![feature(start)]
+#![crate_type = "lib"]
-struct SomeType;
+pub struct SomeType;
struct SomeGenericType<T1, T2>(T1, T2);
-mod mod1 {
+pub mod mod1 {
use super::{SomeGenericType, SomeType};
// Even though the impl is in `mod1`, the methods should end up in the
// parent module, since that is where their self-type is.
impl SomeType {
- //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::method[0] @@ methods_are_with_self_type[External]
- fn method(&self) {}
-
- //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[0]::associated_fn[0] @@ methods_are_with_self_type[External]
- fn associated_fn() {}
+ //~ MONO_ITEM fn mod1::<impl SomeType>::method @@ methods_are_with_self_type[External]
+ pub fn method(&self) {}
+ //~ MONO_ITEM fn mod1::<impl SomeType>::associated_fn @@ methods_are_with_self_type[External]
+ pub fn associated_fn() {}
}
impl<T1, T2> SomeGenericType<T1, T2> {
@@ -52,25 +45,20 @@ mod type2 {
pub struct Struct;
}
-//~ MONO_ITEM fn methods_are_with_self_type::start[0]
-#[start]
-fn start(_: isize, _: *const *const u8) -> isize {
- //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::method[0]<u32, u64> @@ methods_are_with_self_type.volatile[WeakODR]
+//~ MONO_ITEM fn start @@ methods_are_with_self_type[External]
+pub fn start() {
+ //~ MONO_ITEM fn mod1::<impl SomeGenericType<u32, u64>>::method @@ methods_are_with_self_type.volatile[External]
SomeGenericType(0u32, 0u64).method();
- //~ MONO_ITEM fn methods_are_with_self_type::mod1[0]::{{impl}}[1]::associated_fn[0]<char, &str> @@ methods_are_with_self_type.volatile[WeakODR]
+ //~ MONO_ITEM fn mod1::<impl SomeGenericType<char, &str>>::associated_fn @@ methods_are_with_self_type.volatile[External]
SomeGenericType::associated_fn('c', "&str");
- //~ MONO_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0]<methods_are_with_self_type::type1[0]::Struct[0]> @@ methods_are_with_self_type-type1.volatile[WeakODR]
+ //~ MONO_ITEM fn <type1::Struct as Trait>::foo @@ methods_are_with_self_type-type1.volatile[External]
type1::Struct.foo();
- //~ MONO_ITEM fn methods_are_with_self_type::{{impl}}[0]::foo[0]<methods_are_with_self_type::type2[0]::Struct[0]> @@ methods_are_with_self_type-type2.volatile[WeakODR]
+ //~ MONO_ITEM fn <type2::Struct as Trait>::foo @@ methods_are_with_self_type-type2.volatile[External]
type2::Struct.foo();
- //~ MONO_ITEM fn methods_are_with_self_type::Trait[0]::default[0]<methods_are_with_self_type::type1[0]::Struct[0]> @@ methods_are_with_self_type-type1.volatile[WeakODR]
+ //~ MONO_ITEM fn <type1::Struct as Trait>::default @@ methods_are_with_self_type-type1.volatile[External]
type1::Struct.default();
- //~ MONO_ITEM fn methods_are_with_self_type::Trait[0]::default[0]<methods_are_with_self_type::type2[0]::Struct[0]> @@ methods_are_with_self_type-type2.volatile[WeakODR]
+ //~ MONO_ITEM fn <type2::Struct as Trait>::default @@ methods_are_with_self_type-type2.volatile[External]
type2::Struct.default();
-
- 0
}
-
-//~ MONO_ITEM drop-glue i8
diff --git a/tests/codegen/aarch64-struct-align-128.rs b/tests/codegen/aarch64-struct-align-128.rs
index d1b4132..3fed19d 100644
--- a/tests/codegen/aarch64-struct-align-128.rs
+++ b/tests/codegen/aarch64-struct-align-128.rs
@@ -1,12 +1,12 @@
// Test that structs aligned to 128 bits are passed with the correct ABI on aarch64.
-//@ revisions:linux darwin windows
+//@ revisions: linux darwin win
//@[linux] compile-flags: --target aarch64-unknown-linux-gnu
//@[darwin] compile-flags: --target aarch64-apple-darwin
-//@[windows] compile-flags: --target aarch64-pc-windows-msvc
+//@[win] compile-flags: --target aarch64-pc-windows-msvc
//@[linux] needs-llvm-components: aarch64
//@[darwin] needs-llvm-components: aarch64
-//@[windows] needs-llvm-components: aarch64
+//@[win] needs-llvm-components: aarch64
#![feature(no_core, lang_items)]
#![crate_type = "lib"]
@@ -39,9 +39,9 @@ pub struct Wrapped8 {
}
extern "C" {
- // linux: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
- // darwin: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
- // windows: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
+ // linux: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
+ // darwin: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
+ // win: declare void @test_8([2 x i64], [2 x i64], [2 x i64])
fn test_8(a: Align8, b: Transparent8, c: Wrapped8);
}
@@ -69,9 +69,9 @@ pub struct Wrapped16 {
}
extern "C" {
- // linux: declare void @test_16([2 x i64], [2 x i64], i128)
- // darwin: declare void @test_16(i128, i128, i128)
- // windows: declare void @test_16(i128, i128, i128)
+ // linux: declare void @test_16([2 x i64], [2 x i64], i128)
+ // darwin: declare void @test_16(i128, i128, i128)
+ // win: declare void @test_16(i128, i128, i128)
fn test_16(a: Align16, b: Transparent16, c: Wrapped16);
}
@@ -94,9 +94,9 @@ pub struct WrappedI128 {
}
extern "C" {
- // linux: declare void @test_i128(i128, i128, i128)
- // darwin: declare void @test_i128(i128, i128, i128)
- // windows: declare void @test_i128(i128, i128, i128)
+ // linux: declare void @test_i128(i128, i128, i128)
+ // darwin: declare void @test_i128(i128, i128, i128)
+ // win: declare void @test_i128(i128, i128, i128)
fn test_i128(a: I128, b: TransparentI128, c: WrappedI128);
}
@@ -121,9 +121,9 @@ pub struct WrappedPacked {
}
extern "C" {
- // linux: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
- // darwin: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
- // windows: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
+ // linux: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
+ // darwin: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
+ // win: declare void @test_packed([2 x i64], [2 x i64], [2 x i64])
fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked);
}
diff --git a/tests/codegen/array-from_fn.rs b/tests/codegen/array-from_fn.rs
new file mode 100644
index 0000000..7202d0c6
--- /dev/null
+++ b/tests/codegen/array-from_fn.rs
@@ -0,0 +1,13 @@
+//@ revisions: NORMAL OPT
+//@ [NORMAL] compile-flags: -C opt-level=0 -C debuginfo=2
+//@ [OPT] compile-flags: -C opt-level=s -C debuginfo=0
+
+#![crate_type = "lib"]
+#![feature(array_from_fn)]
+
+#[no_mangle]
+pub fn iota() -> [u8; 16] {
+ // OPT-NOT: core..array..Guard
+ // NORMAL: core..array..Guard
+ std::array::from_fn(|i| i as _)
+}
diff --git a/tests/codegen/atomic-operations.rs b/tests/codegen/atomic-operations.rs
index b135027..8a70c94 100644
--- a/tests/codegen/atomic-operations.rs
+++ b/tests/codegen/atomic-operations.rs
@@ -2,7 +2,8 @@
//@ compile-flags: -O
#![crate_type = "lib"]
-use std::sync::atomic::{AtomicI32, Ordering::*};
+use std::sync::atomic::AtomicI32;
+use std::sync::atomic::Ordering::*;
// CHECK-LABEL: @compare_exchange
#[no_mangle]
diff --git a/tests/codegen/branch-protection-old-llvm.rs b/tests/codegen/branch-protection-old-llvm.rs
new file mode 100644
index 0000000..bb3c7a4
--- /dev/null
+++ b/tests/codegen/branch-protection-old-llvm.rs
@@ -0,0 +1,45 @@
+// Test that the correct module flags are emitted with different branch protection flags.
+
+//@ revisions: BTI PACRET LEAF BKEY NONE
+//@ needs-llvm-components: aarch64
+//@ [BTI] compile-flags: -Z branch-protection=bti
+//@ [PACRET] compile-flags: -Z branch-protection=pac-ret
+//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
+//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ ignore-llvm-version: 19 - 99
+
+#![crate_type = "lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+// A basic test function.
+pub fn test() {}
+
+// BTI: !"branch-target-enforcement", i32 1
+// BTI: !"sign-return-address", i32 0
+// BTI: !"sign-return-address-all", i32 0
+// BTI: !"sign-return-address-with-bkey", i32 0
+
+// PACRET: !"branch-target-enforcement", i32 0
+// PACRET: !"sign-return-address", i32 1
+// PACRET: !"sign-return-address-all", i32 0
+// PACRET: !"sign-return-address-with-bkey", i32 0
+
+// LEAF: !"branch-target-enforcement", i32 0
+// LEAF: !"sign-return-address", i32 1
+// LEAF: !"sign-return-address-all", i32 1
+// LEAF: !"sign-return-address-with-bkey", i32 0
+
+// BKEY: !"branch-target-enforcement", i32 0
+// BKEY: !"sign-return-address", i32 1
+// BKEY: !"sign-return-address-all", i32 0
+// BKEY: !"sign-return-address-with-bkey", i32 1
+
+// NONE-NOT: branch-target-enforcement
+// NONE-NOT: sign-return-address
+// NONE-NOT: sign-return-address-all
+// NONE-NOT: sign-return-address-with-bkey
diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs
index a29ec67..2f5ff9e 100644
--- a/tests/codegen/branch-protection.rs
+++ b/tests/codegen/branch-protection.rs
@@ -7,6 +7,7 @@
//@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
//@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ min-llvm-version: 19
#![crate_type = "lib"]
#![feature(no_core, lang_items)]
@@ -16,23 +17,32 @@
trait Sized {}
// A basic test function.
+// CHECK: @test(){{.*}} [[ATTR:#[0-9]+]] {
+#[no_mangle]
pub fn test() {}
+// BTI: attributes [[ATTR]] = {{.*}} "branch-target-enforcement"
// BTI: !"branch-target-enforcement", i32 1
// BTI: !"sign-return-address", i32 0
// BTI: !"sign-return-address-all", i32 0
// BTI: !"sign-return-address-with-bkey", i32 0
+// PACRET: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
+// PACRET-SAME: "sign-return-address-key"="a_key"
// PACRET: !"branch-target-enforcement", i32 0
// PACRET: !"sign-return-address", i32 1
// PACRET: !"sign-return-address-all", i32 0
// PACRET: !"sign-return-address-with-bkey", i32 0
+// LEAF: attributes [[ATTR]] = {{.*}} "sign-return-address"="all"
+// LEAF-SAME: "sign-return-address-key"="a_key"
// LEAF: !"branch-target-enforcement", i32 0
// LEAF: !"sign-return-address", i32 1
// LEAF: !"sign-return-address-all", i32 1
// LEAF: !"sign-return-address-with-bkey", i32 0
+// BKEY: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
+// BKEY-SAME: "sign-return-address-key"="b_key"
// BKEY: !"branch-target-enforcement", i32 0
// BKEY: !"sign-return-address", i32 1
// BKEY: !"sign-return-address-all", i32 0
diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs
index b216899..73c4b33 100644
--- a/tests/codegen/call-metadata.rs
+++ b/tests/codegen/call-metadata.rs
@@ -2,6 +2,7 @@
// scalar value.
//@ compile-flags: -O -C no-prepopulate-passes
+//@ ignore-llvm-version: 19 - 99
#![crate_type = "lib"]
diff --git a/tests/codegen/cast-optimized.rs b/tests/codegen/cast-optimized.rs
index 313b2b4..59cf409 100644
--- a/tests/codegen/cast-optimized.rs
+++ b/tests/codegen/cast-optimized.rs
@@ -20,8 +20,6 @@
// CHECK-LABEL: @char_as_u32_index
#[no_mangle]
pub fn char_as_u32_index(c: char) -> [bool; 22] {
- // CHECK: %[[B:.+]] = icmp ult i32 %c, 1114112
- // CHECK: call void @llvm.assume(i1 %[[B]])
let c = c as u32;
let mut array = [false; 22];
diff --git a/tests/codegen/cold-call-declare-and-call.rs b/tests/codegen/cold-call-declare-and-call.rs
index cd41c0a..b18565e 100644
--- a/tests/codegen/cold-call-declare-and-call.rs
+++ b/tests/codegen/cold-call-declare-and-call.rs
@@ -1,8 +1,8 @@
-//@ revisions: NORMAL WINDOWS
+//@ revisions: NORMAL WIN
//@ compile-flags: -C no-prepopulate-passes
//@[NORMAL] ignore-windows
-//@[WINDOWS] only-windows
-//@[WINDOWS] only-x86_64
+//@[WIN] only-windows
+//@[WIN] only-x86_64
#![crate_type = "lib"]
#![feature(rust_cold_cc)]
@@ -14,8 +14,8 @@
// See the comment in `Target::adjust_abi` for why this differs
-// WINDOWS: define void @this_should_never_happen(i16
-// WINDOWS: call void @this_should_never_happen(i16
+// WIN: define void @this_should_never_happen(i16
+// WIN: call void @this_should_never_happen(i16
#[no_mangle]
pub extern "rust-cold" fn this_should_never_happen(x: u16) {}
diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs
index 87fa89a..aa7ebb4 100644
--- a/tests/codegen/common_prim_int_ptr.rs
+++ b/tests/codegen/common_prim_int_ptr.rs
@@ -28,7 +28,7 @@ pub fn insert_box(x: Box<()>) -> Result<usize, Box<()>> {
// CHECK-LABEL: @extract_int
// CHECK-NOT: nonnull
-// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]])
+// CHECK-SAME: (i{{[0-9]+}} {{[^%]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]])
#[no_mangle]
pub unsafe fn extract_int(x: Result<usize, Box<()>>) -> usize {
// CHECK: [[TEMP:%.+]] = ptrtoint ptr [[PAYLOAD]] to [[USIZE:i[0-9]+]]
@@ -40,7 +40,7 @@ pub unsafe fn extract_int(x: Result<usize, Box<()>>) -> usize {
}
// CHECK-LABEL: @extract_box
-// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]])
+// CHECK-SAME: (i{{[0-9]+}} {{[^%]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]])
#[no_mangle]
pub unsafe fn extract_box(x: Result<usize, Box<i32>>) -> Box<i32> {
// CHECK: ret ptr [[PAYLOAD]]
diff --git a/tests/codegen/const-vector.rs b/tests/codegen/const-vector.rs
new file mode 100644
index 0000000..d368838
--- /dev/null
+++ b/tests/codegen/const-vector.rs
@@ -0,0 +1,107 @@
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+// This test checks that constants of SIMD type are passed as immediate vectors.
+// We ensure that both vector representations (struct with fields and struct wrapping array) work.
+#![crate_type = "lib"]
+#![feature(abi_unadjusted)]
+#![feature(const_trait_impl)]
+#![feature(repr_simd)]
+#![feature(rustc_attrs)]
+#![feature(simd_ffi)]
+#![allow(non_camel_case_types)]
+
+// Setting up structs that can be used as const vectors
+#[repr(simd)]
+#[derive(Clone)]
+pub struct i8x2(i8, i8);
+
+#[repr(simd)]
+#[derive(Clone)]
+pub struct i8x2_arr([i8; 2]);
+
+#[repr(simd)]
+#[derive(Clone)]
+pub struct f32x2(f32, f32);
+
+#[repr(simd)]
+#[derive(Clone)]
+pub struct f32x2_arr([f32; 2]);
+
+#[repr(simd, packed)]
+#[derive(Copy, Clone)]
+pub struct Simd<T, const N: usize>([T; N]);
+
+// The following functions are required for the tests to ensure
+// that they are called with a const vector
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_i8x2(a: i8x2);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_i8x2_two_args(a: i8x2, b: i8x2);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_i8x2_mixed_args(a: i8x2, c: i32, b: i8x2);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_i8x2_arr(a: i8x2_arr);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_f32x2(a: f32x2);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_f32x2_arr(a: f32x2_arr);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_simd(a: Simd<i32, 4>);
+}
+
+extern "unadjusted" {
+ #[no_mangle]
+ fn test_simd_unaligned(a: Simd<i32, 3>);
+}
+
+// Ensure the packed variant of the simd struct does not become a const vector
+// if the size is not a power of 2
+// CHECK: %"Simd<i32, 3>" = type { [3 x i32] }
+
+pub fn do_call() {
+ unsafe {
+ // CHECK: call void @test_i8x2(<2 x i8> <i8 32, i8 64>
+ test_i8x2(const { i8x2(32, 64) });
+
+ // CHECK: call void @test_i8x2_two_args(<2 x i8> <i8 32, i8 64>, <2 x i8> <i8 8, i8 16>
+ test_i8x2_two_args(const { i8x2(32, 64) }, const { i8x2(8, 16) });
+
+ // CHECK: call void @test_i8x2_mixed_args(<2 x i8> <i8 32, i8 64>, i32 43, <2 x i8> <i8 8, i8 16>
+ test_i8x2_mixed_args(const { i8x2(32, 64) }, 43, const { i8x2(8, 16) });
+
+ // CHECK: call void @test_i8x2_arr(<2 x i8> <i8 32, i8 64>
+ test_i8x2_arr(const { i8x2_arr([32, 64]) });
+
+ // CHECK: call void @test_f32x2(<2 x float> <float 0x3FD47AE140000000, float 0x3FE47AE140000000>
+ test_f32x2(const { f32x2(0.32, 0.64) });
+
+ // CHECK: void @test_f32x2_arr(<2 x float> <float 0x3FD47AE140000000, float 0x3FE47AE140000000>
+ test_f32x2_arr(const { f32x2_arr([0.32, 0.64]) });
+
+ // CHECK: call void @test_simd(<4 x i32> <i32 2, i32 4, i32 6, i32 8>
+ test_simd(const { Simd::<i32, 4>([2, 4, 6, 8]) });
+
+ // CHECK: call void @test_simd_unaligned(%"Simd<i32, 3>" %1
+ test_simd_unaligned(const { Simd::<i32, 3>([2, 4, 6]) });
+ }
+}
diff --git a/tests/codegen/default-requires-uwtable.rs b/tests/codegen/default-requires-uwtable.rs
index 567bd55..3cb35ce 100644
--- a/tests/codegen/default-requires-uwtable.rs
+++ b/tests/codegen/default-requires-uwtable.rs
@@ -1,9 +1,9 @@
-//@ revisions: WINDOWS ANDROID
+//@ revisions: WINDOWS_ ANDROID_
//@ compile-flags: -C panic=abort -Copt-level=0
-//@ [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc
-//@ [WINDOWS] needs-llvm-components: x86
-//@ [ANDROID] compile-flags: --target=armv7-linux-androideabi
-//@ [ANDROID] needs-llvm-components: arm
+//@ [WINDOWS_] compile-flags: --target=x86_64-pc-windows-msvc
+//@ [WINDOWS_] needs-llvm-components: x86
+//@ [ANDROID_] compile-flags: --target=armv7-linux-androideabi
+//@ [ANDROID_] needs-llvm-components: arm
#![feature(no_core, lang_items)]
#![crate_type = "lib"]
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index 8da5de6..a24b980 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -34,7 +34,7 @@ pub enum Enum1 {
// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1{{.*}}
// CHECK-NEXT: start:
-// CHECK-NEXT: %1 = add i8 %0, -2
+// CHECK-NEXT: %1 = add{{( nsw)?}} i8 %0, -2
// CHECK-NEXT: %2 = zext i8 %1 to i64
// CHECK-NEXT: %3 = icmp ult i8 %1, 2
// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
index 56504df..bf9f405 100644
--- a/tests/codegen/function-arguments.rs
+++ b/tests/codegen/function-arguments.rs
@@ -50,7 +50,7 @@ pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
x
}
-// CHECK: noundef i32 @char(i32 noundef %x)
+// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x)
#[no_mangle]
pub fn char(x: char) -> char {
x
@@ -68,7 +68,7 @@ pub fn int(x: u64) -> u64 {
x
}
-// CHECK: noundef i64 @nonzero_int(i64 noundef %x)
+// CHECK: noundef{{( range\(i64 1, 0\))?}} i64 @nonzero_int(i64 noundef{{( range\(i64 1, 0\))?}} %x)
#[no_mangle]
pub fn nonzero_int(x: NonZero<u64>) -> NonZero<u64> {
x
@@ -250,7 +250,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] {
x
}
-// CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1)
+// CHECK: { i16, i16 } @enum_id_1(i16 noundef{{( range\(i16 0, 3\))?}} %x.0, i16 %x.1)
#[no_mangle]
pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
x
diff --git a/tests/codegen/instrument-coverage/testprog.rs b/tests/codegen/instrument-coverage/testprog.rs
index eea4d9c..655fe77 100644
--- a/tests/codegen/instrument-coverage/testprog.rs
+++ b/tests/codegen/instrument-coverage/testprog.rs
@@ -1,7 +1,7 @@
//@ edition: 2021
//@ compile-flags: -Zno-profiler-runtime
//@ compile-flags: -Cinstrument-coverage -Copt-level=0
-//@ revisions: LINUX DARWIN WINDOWS
+//@ revisions: LINUX DARWIN WIN
//@ [LINUX] only-linux
//@ [LINUX] filecheck-flags: -DINSTR_PROF_DATA=__llvm_prf_data
@@ -19,13 +19,13 @@
//@ [DARWIN] filecheck-flags: -DINSTR_PROF_COVFUN=__LLVM_COV,__llvm_covfun
//@ [DARWIN] filecheck-flags: -DCOMDAT_IF_SUPPORTED=
-//@ [WINDOWS] only-windows
-//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_DATA=.lprfd$M
-//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_NAME=.lprfn$M
-//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_CNTS=.lprfc$M
-//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_COVMAP=.lcovmap$M
-//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_COVFUN=.lcovfun$M
-//@ [WINDOWS] filecheck-flags: '-DCOMDAT_IF_SUPPORTED=, comdat'
+//@ [WIN] only-windows
+//@ [WIN] filecheck-flags: -DINSTR_PROF_DATA=.lprfd$M
+//@ [WIN] filecheck-flags: -DINSTR_PROF_NAME=.lprfn$M
+//@ [WIN] filecheck-flags: -DINSTR_PROF_CNTS=.lprfc$M
+//@ [WIN] filecheck-flags: -DINSTR_PROF_COVMAP=.lcovmap$M
+//@ [WIN] filecheck-flags: -DINSTR_PROF_COVFUN=.lcovfun$M
+//@ [WIN] filecheck-flags: '-DCOMDAT_IF_SUPPORTED=, comdat'
// ignore-tidy-linelength
@@ -71,7 +71,7 @@ fn main() {
// Check for metadata, variables, declarations, and function definitions injected
// into LLVM IR when compiling with -Cinstrument-coverage.
-// WINDOWS: $__llvm_profile_runtime_user = comdat any
+// WIN: $__llvm_profile_runtime_user = comdat any
// CHECK: @__llvm_coverage_mapping = private constant
// CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
@@ -79,7 +79,7 @@ fn main() {
// CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
// CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
-// WINDOWS: @__llvm_profile_runtime = external{{.*}}global i32
+// WIN: @__llvm_profile_runtime = external{{.*}}global i32
// CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
// CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8
@@ -111,10 +111,10 @@ fn main() {
// CHECK: declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
-// WINDOWS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
-// WINDOWS-NEXT: %1 = load i32, ptr @__llvm_profile_runtime
-// WINDOWS-NEXT: ret i32 %1
-// WINDOWS-NEXT: }
+// WIN: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+// WIN-NEXT: %1 = load i32, ptr @__llvm_profile_runtime
+// WIN-NEXT: ret i32 %1
+// WIN-NEXT: }
// CHECK: attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
-// WINDOWS: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
+// WIN: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs
index 076d6d6..ff2d629 100644
--- a/tests/codegen/intrinsics/nontemporal.rs
+++ b/tests/codegen/intrinsics/nontemporal.rs
@@ -1,13 +1,37 @@
//@ compile-flags: -O
+//@revisions: with_nontemporal without_nontemporal
+//@[with_nontemporal] compile-flags: --target aarch64-unknown-linux-gnu
+//@[with_nontemporal] needs-llvm-components: aarch64
+//@[without_nontemporal] compile-flags: --target x86_64-unknown-linux-gnu
+//@[without_nontemporal] needs-llvm-components: x86
-#![feature(core_intrinsics)]
+// Ensure that we *do* emit the `!nontemporal` flag on architectures where it
+// is well-behaved, but do *not* emit it on architectures where it is ill-behaved.
+// For more context, see <https://github.com/rust-lang/rust/issues/114582> and
+// <https://github.com/llvm/llvm-project/issues/64521>.
+
+#![feature(no_core, lang_items, intrinsics)]
+#![no_core]
#![crate_type = "lib"]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+
+impl Copy for u32 {}
+impl<T> Copy for *mut T {}
+
+extern "rust-intrinsic" {
+ pub fn nontemporal_store<T>(ptr: *mut T, val: T);
+}
+
#[no_mangle]
pub fn a(a: &mut u32, b: u32) {
// CHECK-LABEL: define{{.*}}void @a
- // CHECK: store i32 %b, ptr %a, align 4, !nontemporal
+ // with_nontemporal: store i32 %b, ptr %a, align 4, !nontemporal
+ // without_nontemporal-NOT: nontemporal
unsafe {
- std::intrinsics::nontemporal_store(a, b);
+ nontemporal_store(a, b);
}
}
diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs
new file mode 100644
index 0000000..2054838
--- /dev/null
+++ b/tests/codegen/intrinsics/select_unpredictable.rs
@@ -0,0 +1,35 @@
+//@ compile-flags: -O
+
+#![feature(core_intrinsics)]
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test_int(p: bool, a: u64, b: u64) -> u64 {
+ // CHECK-LABEL: define{{.*}} @test_int
+ // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable
+ core::intrinsics::select_unpredictable(p, a, b)
+}
+
+#[no_mangle]
+pub fn test_pair(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) {
+ // CHECK-LABEL: define{{.*}} @test_pair
+ // CHECK: select i1 %p, {{.*}}, !unpredictable
+ core::intrinsics::select_unpredictable(p, a, b)
+}
+
+struct Large {
+ e: [u64; 100],
+}
+
+#[no_mangle]
+pub fn test_struct(p: bool, a: Large, b: Large) -> Large {
+ // CHECK-LABEL: define{{.*}} @test_struct
+ // CHECK: select i1 %p, {{.*}}, !unpredictable
+ core::intrinsics::select_unpredictable(p, a, b)
+}
+
+#[no_mangle]
+pub fn test_zst(p: bool, a: (), b: ()) -> () {
+ // CHECK-LABEL: define{{.*}} @test_zst
+ core::intrinsics::select_unpredictable(p, a, b)
+}
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 04a91bb..8c8e975 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -6,11 +6,10 @@
#![feature(custom_mir)]
#![allow(unreachable_code)]
-use std::intrinsics::{transmute, transmute_unchecked};
-use std::mem::MaybeUninit;
-
// Some of these need custom MIR to not get removed by MIR optimizations.
use std::intrinsics::mir::*;
+use std::intrinsics::{transmute, transmute_unchecked};
+use std::mem::MaybeUninit;
pub enum ZstNever {}
diff --git a/tests/codegen/issues/issue-107681-unwrap_unchecked.rs b/tests/codegen/issues/issue-107681-unwrap_unchecked.rs
new file mode 100644
index 0000000..7d9679d
--- /dev/null
+++ b/tests/codegen/issues/issue-107681-unwrap_unchecked.rs
@@ -0,0 +1,20 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 19
+
+// Test for #107681.
+// Make sure we don't create `br` or `select` instructions.
+
+#![crate_type = "lib"]
+
+use std::iter::Copied;
+use std::slice::Iter;
+
+#[no_mangle]
+pub unsafe fn foo(x: &mut Copied<Iter<'_, u32>>) -> u32 {
+ // CHECK-LABEL: @foo(
+ // CHECK-NOT: br
+ // CHECK-NOT: select
+ // CHECK: [[RET:%.*]] = load i32, ptr
+ // CHECK-NEXT: ret i32 [[RET]]
+ x.next().unwrap_unchecked()
+}
diff --git a/tests/codegen/issues/issue-118306.rs b/tests/codegen/issues/issue-118306.rs
new file mode 100644
index 0000000..8af1c6a
--- /dev/null
+++ b/tests/codegen/issues/issue-118306.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 19
+//@ only-x86_64
+
+// Test for #118306.
+// Make sure we don't create `br` or `select` instructions.
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn branchy(input: u64) -> u64 {
+ // CHECK-LABEL: @branchy(
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: [[_2:%.*]] = and i64 [[INPUT:%.*]], 3
+ // CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i64], ptr @switch.table.branchy, i64 0, i64 [[_2]]
+ // CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]]
+ // CHECK-NEXT: ret i64 [[SWITCH_LOAD]]
+ match input % 4 {
+ 1 | 2 => 1,
+ 3 => 2,
+ _ => 0,
+ }
+}
diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs
new file mode 100644
index 0000000..4b520a6
--- /dev/null
+++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs
@@ -0,0 +1,19 @@
+//@ compile-flags: -O
+//@ min-llvm-version: 19
+
+#![crate_type = "lib"]
+
+pub enum State {
+ A([u8; 753]),
+ B([u8; 753]),
+}
+
+// CHECK-LABEL: @update
+#[no_mangle]
+pub unsafe fn update(s: *mut State) {
+ // CHECK-NEXT: start:
+ // CHECK-NEXT: store i8
+ // CHECK-NEXT: ret
+ let State::A(v) = s.read() else { std::hint::unreachable_unchecked() };
+ s.write(State::B(v));
+}
diff --git a/tests/codegen/issues/issue-126585.rs b/tests/codegen/issues/issue-126585.rs
new file mode 100644
index 0000000..a468efd
--- /dev/null
+++ b/tests/codegen/issues/issue-126585.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -Copt-level=s
+//@ min-llvm-version: 19
+//@ only-x86_64
+
+// Test for #126585.
+// Ensure that this IR doesn't have extra undef phi input, which also guarantees that this asm
+// doesn't have subsequent labels and unnecessary `jmp` instructions.
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+fn checked_div_round(a: u64, b: u64) -> Option<u64> {
+ // CHECK-LABEL: @checked_div_round
+ // CHECK: phi
+ // CHECK-NOT: undef
+ // CHECK: phi
+ // CHECK-NOT: undef
+ match b {
+ 0 => None,
+ 1 => Some(a),
+ // `a / b` is computable and `(a % b) * 2` can not overflow since `b >= 2`.
+ b => Some(a / b + if (a % b) * 2 >= b { 1 } else { 0 }),
+ }
+}
diff --git a/tests/codegen/issues/issue-68667-unwrap-combinators.rs b/tests/codegen/issues/issue-68667-unwrap-combinators.rs
index 6bd4c56..21a5a5b 100644
--- a/tests/codegen/issues/issue-68667-unwrap-combinators.rs
+++ b/tests/codegen/issues/issue-68667-unwrap-combinators.rs
@@ -5,7 +5,7 @@
// MIR inlining now optimizes this code.
// CHECK-LABEL: @unwrap_combinators
-// CHECK: icmp
+// CHECK: {{icmp|trunc}}
// CHECK-NEXT: icmp
// CHECK-NEXT: select i1
// CHECK-NEXT: ret i1
diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs
index 31020b7..7de224b 100644
--- a/tests/codegen/iter-repeat-n-trivial-drop.rs
+++ b/tests/codegen/iter-repeat-n-trivial-drop.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -O
+//@ compile-flags: -C opt-level=3
//@ only-x86_64
#![crate_type = "lib"]
#![feature(iter_repeat_n)]
+#![feature(array_repeat)]
#[derive(Clone)]
pub struct NotCopy(u16);
@@ -54,3 +55,15 @@ pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
v.extend(std::iter::repeat_n(42_u8, n));
v
}
+
+// Array repeat uses `RepeatN::next_unchecked` internally,
+// so also check that the distinction disappears there.
+
+#[no_mangle]
+// CHECK-LABEL: @array_repeat_not_copy
+pub unsafe fn array_repeat_not_copy(item: NotCopy) -> [NotCopy; 8] {
+ // CHECK: insertelement {{.+}} i16 %item
+ // CHECK: shufflevector <8 x i16> {{.+}} zeroinitializer
+ // CHECK: store <8 x i16>
+ std::array::repeat(item)
+}
diff --git a/tests/codegen/range-attribute.rs b/tests/codegen/range-attribute.rs
new file mode 100644
index 0000000..bb19bec
--- /dev/null
+++ b/tests/codegen/range-attribute.rs
@@ -0,0 +1,68 @@
+// Checks that range metadata gets emitted on functions result and arguments
+// with scalar value.
+
+//@ compile-flags: -O -C no-prepopulate-passes
+//@ min-llvm-version: 19
+
+#![crate_type = "lib"]
+
+use std::num::NonZero;
+
+// Hack to get the correct size for usize
+// CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1)
+#[no_mangle]
+pub fn helper(_: usize) {}
+
+// CHECK: noundef range(i128 1, 0) i128 @nonzero_int(i128 noundef range(i128 1, 0) %x)
+#[no_mangle]
+pub fn nonzero_int(x: NonZero<u128>) -> NonZero<u128> {
+ x
+}
+
+// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x)
+#[no_mangle]
+pub fn optional_bool(x: Option<bool>) -> Option<bool> {
+ x
+}
+
+pub enum Enum0 {
+ A(bool),
+ B,
+ C,
+}
+
+// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x)
+#[no_mangle]
+pub fn enum0_value(x: Enum0) -> Enum0 {
+ x
+}
+
+pub enum Enum1 {
+ A(u64),
+ B(u64),
+ C(u64),
+}
+
+// CHECK: { [[ENUM1_TYP:i[0-9]+]], i64 } @enum1_value([[ENUM1_TYP]] noundef range([[ENUM1_TYP]] 0, 3) %x.0, i64 noundef %x.1)
+#[no_mangle]
+pub fn enum1_value(x: Enum1) -> Enum1 {
+ x
+}
+
+pub enum Enum2 {
+ A(Enum0),
+ B(Enum0),
+ C(Enum0),
+}
+
+// CHECK: { i8, i8 } @enum2_value(i8 noundef range(i8 0, 3) %x.0, i8 noundef %x.1)
+#[no_mangle]
+pub fn enum2_value(x: Enum2) -> Enum2 {
+ x
+}
+
+// CHECK: noundef [[USIZE]] @takes_slice(ptr noalias noundef nonnull readonly align 4 %x.0, [[USIZE]] noundef %x.1)
+#[no_mangle]
+pub fn takes_slice(x: &[i32]) -> usize {
+ x.len()
+}
diff --git a/tests/codegen/repr/transparent-sysv64.rs b/tests/codegen/repr/transparent-sysv64.rs
index afb06dc..0684149 100644
--- a/tests/codegen/repr/transparent-sysv64.rs
+++ b/tests/codegen/repr/transparent-sysv64.rs
@@ -1,12 +1,12 @@
-//@ revisions: linux apple windows
+//@ revisions: linux apple win
//@ compile-flags: -O -C no-prepopulate-passes
//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
//@[linux] needs-llvm-components: x86
//@[apple] compile-flags: --target x86_64-apple-darwin
//@[apple] needs-llvm-components: x86
-//@[windows] compile-flags: --target x86_64-pc-windows-msvc
-//@[windows] needs-llvm-components: x86
+//@[win] compile-flags: --target x86_64-pc-windows-msvc
+//@[win] needs-llvm-components: x86
#![feature(no_core, lang_items)]
#![crate_type = "lib"]
diff --git a/tests/codegen/repr/transparent.rs b/tests/codegen/repr/transparent.rs
index 4b41332..9140b85 100644
--- a/tests/codegen/repr/transparent.rs
+++ b/tests/codegen/repr/transparent.rs
@@ -74,7 +74,7 @@ pub enum Bool {
FileNotFound,
}
-// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1)
+// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?( range\(i8 0, 3\))?}} i8 @test_Gpz(i8 noundef{{( zeroext)?( range\(i8 0, 3\))?}} %_1)
#[no_mangle]
pub extern "C" fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> {
loop {}
diff --git a/tests/codegen/simd/issue-120720-reduce-nan.rs b/tests/codegen/simd/issue-120720-reduce-nan.rs
deleted file mode 100644
index 13af0bb..0000000
--- a/tests/codegen/simd/issue-120720-reduce-nan.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-//@ compile-flags: -C opt-level=3 -C target-cpu=cannonlake
-//@ only-x86_64
-
-// In a previous implementation, _mm512_reduce_add_pd did the reduction with all fast-math flags
-// enabled, making it UB to reduce a vector containing a NaN.
-
-#![crate_type = "lib"]
-#![feature(stdarch_x86_avx512, avx512_target_feature)]
-use std::arch::x86_64::*;
-
-// CHECK-LABEL: @demo(
-#[no_mangle]
-#[target_feature(enable = "avx512f")] // Function-level target feature mismatches inhibit inlining
-pub unsafe fn demo() -> bool {
- // CHECK: %0 = tail call reassoc double @llvm.vector.reduce.fadd.v8f64(
- // CHECK: %_0.i = fcmp uno double %0, 0.000000e+00
- // CHECK: ret i1 %_0.i
- let res =
- unsafe { _mm512_reduce_add_pd(_mm512_set_pd(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, f64::NAN)) };
- res.is_nan()
-}
diff --git a/tests/codegen/sse42-implies-crc32.rs b/tests/codegen/sse42-implies-crc32.rs
index 94fcd77..8a9c496 100644
--- a/tests/codegen/sse42-implies-crc32.rs
+++ b/tests/codegen/sse42-implies-crc32.rs
@@ -12,4 +12,4 @@ pub unsafe fn crc32sse(v: u8) -> u32 {
_mm_crc32_u8(out, v)
}
-// CHECK: attributes #0 {{.*"target-features"=".*\+sse4.2,\+crc32"}}
+// CHECK: attributes #0 {{.*"target-features"=".*\+sse4.2,\+crc32.*"}}
diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs
index 1e2c364..f38a1ae 100644
--- a/tests/codegen/target-feature-overrides.rs
+++ b/tests/codegen/target-feature-overrides.rs
@@ -1,7 +1,7 @@
//@ revisions: COMPAT INCOMPAT
//@ needs-llvm-components: x86
//@ compile-flags: --target=x86_64-unknown-linux-gnu -Copt-level=3
-//@ [COMPAT] compile-flags: -Ctarget-feature=+avx2,+avx
+//@ [COMPAT] compile-flags: -Ctarget-feature=+avx2
//@ [INCOMPAT] compile-flags: -Ctarget-feature=-avx2,-avx
// See also tests/assembly/target-feature-multiple.rs
@@ -39,8 +39,8 @@ pub unsafe fn banana() -> u32 {
}
// CHECK: attributes [[APPLEATTRS]]
-// COMPAT-SAME: "target-features"="+avx2,+avx,+avx"
-// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx"
+// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}"
+// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx,{{.*}}"
// CHECK: attributes [[BANANAATTRS]]
-// COMPAT-SAME: "target-features"="+avx2,+avx"
+// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}"
// INCOMPAT-SAME: "target-features"="-avx2,-avx"
diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs
index 7f0805b..1b4596a 100644
--- a/tests/codegen/tied-features-strength.rs
+++ b/tests/codegen/tied-features-strength.rs
@@ -8,7 +8,7 @@
// is LLVM-14 we can remove the optional regex matching for this feature.
//@ [ENABLE_SVE] compile-flags: -C target-feature=+sve -Copt-level=0
-// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
+// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" }
//@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0
// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map
index b4447a3..b565353 100644
--- a/tests/coverage/mcdc/condition-limit.cov-map
+++ b/tests/coverage/mcdc/condition-limit.cov-map
@@ -1,5 +1,5 @@
Function name: condition_limit::bad
-Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02]
+Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 15, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 44
@@ -48,7 +48,7 @@
- expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4)
- expression 43 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 17
-- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 21, 1) to (start + 3, 9)
- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9)
true = c1
false = (c0 - c1)
@@ -88,7 +88,7 @@
= (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)))
Function name: condition_limit::good
-Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02]
+Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0d, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 32
@@ -125,7 +125,7 @@
- expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4)
- expression 31 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 16
-- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 13, 1) to (start + 3, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage
index 4eb8743..81e832d 100644
--- a/tests/coverage/mcdc/condition-limit.coverage
+++ b/tests/coverage/mcdc/condition-limit.coverage
@@ -1,6 +1,7 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |//@ min-llvm-version: 18
+ LL| |//@ ignore-llvm-version: 19 - 99
LL| |//@ compile-flags: -Zcoverage-options=mcdc
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
LL| |
diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs
index 571c600..2ff46b1 100644
--- a/tests/coverage/mcdc/condition-limit.rs
+++ b/tests/coverage/mcdc/condition-limit.rs
@@ -1,6 +1,7 @@
#![feature(coverage_attribute)]
//@ edition: 2021
//@ min-llvm-version: 18
+//@ ignore-llvm-version: 19 - 99
//@ compile-flags: -Zcoverage-options=mcdc
//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map
index 9a7d15f..ea8dedb 100644
--- a/tests/coverage/mcdc/if.cov-map
+++ b/tests/coverage/mcdc/if.cov-map
@@ -1,5 +1,5 @@
Function name: if::mcdc_check_a
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 10, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -8,7 +8,7 @@
- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -24,7 +24,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: if::mcdc_check_b
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 18, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -33,7 +33,7 @@
- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -49,7 +49,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: if::mcdc_check_both
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 20, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -58,7 +58,7 @@
- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 32, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -74,7 +74,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: if::mcdc_check_neither
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 08, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -83,7 +83,7 @@
- expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -99,7 +99,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: if::mcdc_check_not_tree_decision
-Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 32, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 8
@@ -112,7 +112,7 @@
- expression 6 operands: lhs = Counter(3), rhs = Expression(7, Sub)
- expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2)
Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10)
+- Code(Counter(0)) at (prev + 50, 1) to (start + 3, 10)
- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10)
true = c1
@@ -134,7 +134,7 @@
= (c4 + (c3 + ((c0 - c1) - c2)))
Function name: if::mcdc_check_tree_decision
-Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 28, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 8
@@ -147,7 +147,7 @@
- expression 6 operands: lhs = Counter(3), rhs = Counter(4)
- expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 40, 1) to (start + 3, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -169,7 +169,7 @@
= ((c3 + c4) + (c2 + (c0 - c1)))
Function name: if::mcdc_nested_if
-Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
+Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3c, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 13
@@ -187,7 +187,7 @@
- expression 11 operands: lhs = Counter(4), rhs = Counter(5)
- expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2)
Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 60, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9)
true = c1
diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage
index 91fff07..dc93319 100644
--- a/tests/coverage/mcdc/if.coverage
+++ b/tests/coverage/mcdc/if.coverage
@@ -1,6 +1,7 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |//@ min-llvm-version: 18
+ LL| |//@ ignore-llvm-version: 19 - 99
LL| |//@ compile-flags: -Zcoverage-options=mcdc
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
LL| |
diff --git a/tests/coverage/mcdc/if.rs b/tests/coverage/mcdc/if.rs
index d8e6b61..6f58965 100644
--- a/tests/coverage/mcdc/if.rs
+++ b/tests/coverage/mcdc/if.rs
@@ -1,6 +1,7 @@
#![feature(coverage_attribute)]
//@ edition: 2021
//@ min-llvm-version: 18
+//@ ignore-llvm-version: 19 - 99
//@ compile-flags: -Zcoverage-options=mcdc
//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map
index 09b7291..8bb488c 100644
--- a/tests/coverage/mcdc/inlined_expressions.cov-map
+++ b/tests/coverage/mcdc/inlined_expressions.cov-map
@@ -1,5 +1,5 @@
Function name: inlined_expressions::inlined_instance
-Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
+Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 09, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 3
@@ -7,7 +7,7 @@
- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6)
+- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 6)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6)
true = c1
diff --git a/tests/coverage/mcdc/inlined_expressions.coverage b/tests/coverage/mcdc/inlined_expressions.coverage
index 5b083d6..4e48003 100644
--- a/tests/coverage/mcdc/inlined_expressions.coverage
+++ b/tests/coverage/mcdc/inlined_expressions.coverage
@@ -1,6 +1,7 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |//@ min-llvm-version: 18
+ LL| |//@ ignore-llvm-version: 19 - 99
LL| |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
LL| |
diff --git a/tests/coverage/mcdc/inlined_expressions.rs b/tests/coverage/mcdc/inlined_expressions.rs
index 65f7ee66..fc1e4da 100644
--- a/tests/coverage/mcdc/inlined_expressions.rs
+++ b/tests/coverage/mcdc/inlined_expressions.rs
@@ -1,6 +1,7 @@
#![feature(coverage_attribute)]
//@ edition: 2021
//@ min-llvm-version: 18
+//@ ignore-llvm-version: 19 - 99
//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map
index adeb6cb..0bd2aef 100644
--- a/tests/coverage/mcdc/nested_if.cov-map
+++ b/tests/coverage/mcdc/nested_if.cov-map
@@ -1,5 +1,5 @@
Function name: nested_if::doubly_nested_if_in_condition
-Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
+Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 10, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 14
@@ -18,7 +18,7 @@
- expression 12 operands: lhs = Counter(3), rhs = Expression(13, Add)
- expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 20
-- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -58,7 +58,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: nested_if::nested_if_in_condition
-Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
+Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 08, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 11
@@ -74,7 +74,7 @@
- expression 9 operands: lhs = Counter(3), rhs = Expression(10, Add)
- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -103,7 +103,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: nested_if::nested_in_then_block_in_condition
-Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
+Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 23, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 18
@@ -126,7 +126,7 @@
- expression 16 operands: lhs = Counter(3), rhs = Expression(17, Add)
- expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 20
-- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 35, 1) to (start + 1, 9)
- MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
@@ -167,7 +167,7 @@
= (c3 + (c2 + (c0 - c1)))
Function name: nested_if::nested_single_condition_decision
-Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
+Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 18, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 6
@@ -178,7 +178,7 @@
- expression 4 operands: lhs = Counter(3), rhs = Expression(5, Add)
- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub)
Number of file 0 mappings: 11
-- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9)
+- Code(Counter(0)) at (prev + 24, 1) to (start + 4, 9)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
true = c1
diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage
index a273a71..916bb94 100644
--- a/tests/coverage/mcdc/nested_if.coverage
+++ b/tests/coverage/mcdc/nested_if.coverage
@@ -1,6 +1,7 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |//@ min-llvm-version: 18
+ LL| |//@ ignore-llvm-version: 19 - 99
LL| |//@ compile-flags: -Zcoverage-options=mcdc
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
LL| |
diff --git a/tests/coverage/mcdc/nested_if.rs b/tests/coverage/mcdc/nested_if.rs
index f5068b5..f9ce7a0 100644
--- a/tests/coverage/mcdc/nested_if.rs
+++ b/tests/coverage/mcdc/nested_if.rs
@@ -1,6 +1,7 @@
#![feature(coverage_attribute)]
//@ edition: 2021
//@ min-llvm-version: 18
+//@ ignore-llvm-version: 19 - 99
//@ compile-flags: -Zcoverage-options=mcdc
//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map
index f857683..0c6928b 100644
--- a/tests/coverage/mcdc/non_control_flow.cov-map
+++ b/tests/coverage/mcdc/non_control_flow.cov-map
@@ -1,5 +1,5 @@
Function name: non_control_flow::assign_3
-Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 17, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 9
@@ -13,7 +13,7 @@
- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4)
- expression 8 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40)
+- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 40)
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
= (c1 + ((c2 + c3) + c4))
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -35,7 +35,7 @@
= (c1 + ((c2 + c3) + c4))
Function name: non_control_flow::assign_3_bis
-Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1c, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 7
@@ -47,7 +47,7 @@
- expression 5 operands: lhs = Counter(1), rhs = Counter(2)
- expression 6 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44)
+- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 44)
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
= ((c2 + c3) + c4)
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -68,7 +68,7 @@
= ((c2 + c3) + c4)
Function name: non_control_flow::assign_and
-Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
+Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -77,7 +77,7 @@
- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
- expression 3 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33)
+- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33)
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
= ((c2 + c3) + (c0 - c1))
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -93,7 +93,7 @@
= ((c2 + c3) + (c0 - c1))
Function name: non_control_flow::assign_or
-Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
+Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 12, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 4
@@ -102,7 +102,7 @@
- expression 2 operands: lhs = Counter(0), rhs = Counter(1)
- expression 3 operands: lhs = Counter(0), rhs = Counter(1)
Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32)
+- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32)
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
= ((c1 + c2) + c3)
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -119,15 +119,15 @@
= ((c1 + c2) + c3)
Function name: non_control_flow::foo
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 02, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 0
Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2)
+- Code(Counter(0)) at (prev + 38, 1) to (start + 2, 2)
Function name: non_control_flow::func_call
-Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
+Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 2a, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 3
@@ -135,7 +135,7 @@
- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
- expression 2 operands: lhs = Counter(2), rhs = Counter(3)
Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
+- Code(Counter(0)) at (prev + 42, 1) to (start + 1, 10)
- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10)
true = c1
@@ -148,7 +148,7 @@
= ((c2 + c3) + (c0 - c1))
Function name: non_control_flow::right_comb_tree
-Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
+Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 21, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
Number of files: 1
- file 0 => global file 1
Number of expressions: 19
@@ -172,7 +172,7 @@
- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5)
- expression 18 operands: lhs = Counter(1), rhs = Counter(6)
Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65)
+- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 65)
- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
= (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
diff --git a/tests/coverage/mcdc/non_control_flow.coverage b/tests/coverage/mcdc/non_control_flow.coverage
index 6ae796e..c64f61a 100644
--- a/tests/coverage/mcdc/non_control_flow.coverage
+++ b/tests/coverage/mcdc/non_control_flow.coverage
@@ -1,6 +1,7 @@
LL| |#![feature(coverage_attribute)]
LL| |//@ edition: 2021
LL| |//@ min-llvm-version: 18
+ LL| |//@ ignore-llvm-version: 19 - 99
LL| |//@ compile-flags: -Zcoverage-options=mcdc
LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc
LL| |
diff --git a/tests/coverage/mcdc/non_control_flow.rs b/tests/coverage/mcdc/non_control_flow.rs
index 77e64e6..633d381 100644
--- a/tests/coverage/mcdc/non_control_flow.rs
+++ b/tests/coverage/mcdc/non_control_flow.rs
@@ -1,6 +1,7 @@
#![feature(coverage_attribute)]
//@ edition: 2021
//@ min-llvm-version: 18
+//@ ignore-llvm-version: 19 - 99
//@ compile-flags: -Zcoverage-options=mcdc
//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/crashes/119716-2.rs b/tests/crashes/119716-2.rs
index 9cdc441..47bffb5 100644
--- a/tests/crashes/119716-2.rs
+++ b/tests/crashes/119716-2.rs
@@ -1,4 +1,4 @@
//@ known-bug: #119716
#![feature(non_lifetime_binders)]
trait Trait<T> {}
-fn f<T>() -> impl for<T> Trait<impl Trait<T>> {}
+fn f() -> impl for<T> Trait<impl Trait<T>> {}
diff --git a/tests/crashes/121127.rs b/tests/crashes/121127.rs
index 2e64bf6..e50dc77 100644
--- a/tests/crashes/121127.rs
+++ b/tests/crashes/121127.rs
@@ -1,5 +1,5 @@
//@ known-bug: #121127
-//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes -C debuginfo=2
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes -C debuginfo=2
// Note that as of PR#123949 this only crashes with debuginfo enabled
#![feature(specialization)]
diff --git a/tests/crashes/121613-2.rs b/tests/crashes/121613-2.rs
deleted file mode 100644
index ddc4f37..0000000
--- a/tests/crashes/121613-2.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//@ known-bug: #121613
-fn main() {
- // destructure through a qualified path
- let <Foo as A>::Assoc { br } = StructStruct { br: 2 };
- //~^ ERROR usage of qualified paths in this context is experimental
- let _ = <Foo as A>::Assoc { br: 2 };
- //~^ ERROR usage of qualified paths in this context is experimental
- let <E>::V(..) = E::V(|a, b| a.cmp(b));
- //~^ ERROR usage of qualified paths in this context is experimental
-}
-
-struct StructStruct {
- br: i8,
-}
-
-struct Foo;
-
-trait A {
- type Assoc;
-}
-
-impl A for Foo {
- type Assoc = StructStruct;
-}
-
-enum E {
- V(u8)
-}
diff --git a/tests/crashes/121613.rs b/tests/crashes/121613.rs
deleted file mode 100644
index ec9ba82..0000000
--- a/tests/crashes/121613.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ known-bug: #121613
-fn main() {
- let _ = <Foo as A>::Assoc { br: 2 };
-
- let <E>::V(..) = E::V(|a, b| a.cmp(b));
-}
-
-struct StructStruct {
- br: i8,
-}
-
-struct Foo;
-
-trait A {
- type Assoc;
-}
-
-impl A for Foo {
- type Assoc = StructStruct;
-}
-
-enum E {
- V(u8),
-}
diff --git a/tests/crashes/122909.rs b/tests/crashes/122909.rs
deleted file mode 100644
index 90bba77..0000000
--- a/tests/crashes/122909.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes
-//@ known-bug: #122909
-
-
-use std::sync::{Arc, Context, Weak};
-
-pub struct WeakOnce<T>();
-impl<T> WeakOnce<T> {
- extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
-
- pub fn get(&self) -> Arc<T> {
- self.try_get()
- .unwrap_or_else(|| panic!("Singleton {} not available", std::any::type_name::<T>()))
- }
-}
diff --git a/tests/crashes/122914.rs b/tests/crashes/122914.rs
deleted file mode 100644
index 63a84bc..0000000
--- a/tests/crashes/122914.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #122914
-use std::future::Future;
-use std::pin::Pin;
-
-impl<'a, F> Poll {
- fn project<'_>(self: Pin<&'pin mut Future>) -> Projection<'pin, 'a, F> {
- me.local_set.with(|| {
- let _ = self.poll(cx);
- })
- }
-}
diff --git a/tests/crashes/123809.rs b/tests/crashes/123809.rs
index c7a633a..75abe6d 100644
--- a/tests/crashes/123809.rs
+++ b/tests/crashes/123809.rs
@@ -1,4 +1,4 @@
//@ known-bug: #123809
-type Positive = std::pat::pattern_type!(std::pat:: is 0..);
+type Positive = std::pat::pattern_type!(std::pat is 0..);
pub fn main() {}
diff --git a/tests/crashes/126272.rs b/tests/crashes/126272.rs
deleted file mode 100644
index 3412c7d..0000000
--- a/tests/crashes/126272.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//@ known-bug: rust-lang/rust#126272
-
-#![feature(adt_const_params)]
-#![allow(incomplete_features)]
-
-use std::marker::ConstParamTy;
-
-#[derive(Debug, PartialEq, Eq, ConstParamTy)]
-struct Foo {
- value: i32,
- nested: &'static Bar<std::fmt::Debug>,
-}
-
-#[derive(Debug, PartialEq, Eq, ConstParamTy)]
-struct Bar<T>(T);
-
-struct Test<const F: Foo>;
-
-fn main() {
- let x: Test<
- {
- Foo {
- value: 3,
- nested: &Bar(4),
- }
- },
- > = Test;
-}
diff --git a/tests/crashes/126896.rs b/tests/crashes/126896.rs
index 35bf9d5..49c539d 100644
--- a/tests/crashes/126896.rs
+++ b/tests/crashes/126896.rs
@@ -1,5 +1,5 @@
//@ known-bug: rust-lang/rust#126896
-//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
#![feature(type_alias_impl_trait)]
type Two<'a, 'b> = impl std::fmt::Debug;
diff --git a/tests/crashes/127222.rs b/tests/crashes/127222.rs
deleted file mode 100644
index eda0ea3..0000000
--- a/tests/crashes/127222.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ known-bug: rust-lang/rust#127222
-#[marker]
-trait Foo = PartialEq<i32> + Send;
diff --git a/tests/crashes/127299.rs b/tests/crashes/127299.rs
deleted file mode 100644
index 7eb7838..0000000
--- a/tests/crashes/127299.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: rust-lang/rust#127299
-trait Qux {
- fn bar() -> i32;
-}
-
-pub struct Lint {
- pub desc: &'static Qux,
-}
-
-static FOO: &Lint = &Lint { desc: "desc" };
-
-fn main() {}
diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs
new file mode 100644
index 0000000..105a1c8
--- /dev/null
+++ b/tests/crashes/128094.rs
@@ -0,0 +1,14 @@
+//@ known-bug: rust-lang/rust#128094
+//@ compile-flags: -Zmir-opt-level=5 --edition=2018
+
+pub enum Request {
+ TestSome(T),
+}
+
+pub async fn handle_event(event: Request) {
+ async move {
+ static instance: Request = Request { bar: 17 };
+ &instance
+ }
+ .await;
+}
diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs
new file mode 100644
index 0000000..70fada4
--- /dev/null
+++ b/tests/crashes/128176.rs
@@ -0,0 +1,13 @@
+//@ known-bug: rust-lang/rust#128176
+
+#![feature(generic_const_exprs)]
+#![feature(object_safe_for_dispatch)]
+trait X {
+ type Y<const N: i16>;
+}
+
+const _: () = {
+ fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
+};
+
+fn main() {}
diff --git a/tests/crashes/128190.rs b/tests/crashes/128190.rs
new file mode 100644
index 0000000..0fa7027
--- /dev/null
+++ b/tests/crashes/128190.rs
@@ -0,0 +1,7 @@
+//@ known-bug: rust-lang/rust#128190
+
+fn a(&self) {
+ 15
+}
+
+reuse a as b { struct S; }
diff --git a/tests/crashes/128327.rs b/tests/crashes/128327.rs
new file mode 100644
index 0000000..a63f758
--- /dev/null
+++ b/tests/crashes/128327.rs
@@ -0,0 +1,5 @@
+//@ known-bug: rust-lang/rust#128327
+
+use std::ops::Deref;
+struct Apple((Apple, <&'static [f64] as Deref>::Target(Banana ? Citron)));
+fn main(){}
diff --git a/tests/crashes/128346.rs b/tests/crashes/128346.rs
new file mode 100644
index 0000000..93d9c40
--- /dev/null
+++ b/tests/crashes/128346.rs
@@ -0,0 +1,13 @@
+//@ known-bug: rust-lang/rust#128346
+
+macro_rules! one_rep {
+ ( $($a:ident)* ) => {
+ A(
+ const ${concat($a, Z)}: i32 = 3;
+ )*
+ };
+}
+
+fn main() {
+ one_rep!(A B C);
+}
diff --git a/tests/debuginfo/pretty-std.rs b/tests/debuginfo/pretty-std.rs
index 70827d5..45c6dbf 100644
--- a/tests/debuginfo/pretty-std.rs
+++ b/tests/debuginfo/pretty-std.rs
@@ -81,10 +81,10 @@
// cdb-check:vec,d [...] : { len=4 } [Type: [...]::Vec<u64,alloc::alloc::Global>]
// cdb-check: [len] : 4 [Type: [...]]
// cdb-check: [capacity] : [...] [Type: [...]]
-// cdb-check: [0] : 4 [Type: unsigned __int64]
-// cdb-check: [1] : 5 [Type: unsigned __int64]
-// cdb-check: [2] : 6 [Type: unsigned __int64]
-// cdb-check: [3] : 7 [Type: unsigned __int64]
+// cdb-check: [0] : 4 [Type: u64]
+// cdb-check: [1] : 5 [Type: u64]
+// cdb-check: [2] : 6 [Type: u64]
+// cdb-check: [3] : 7 [Type: u64]
// cdb-command: dx str_slice
// cdb-check:str_slice : "IAMA string slice!" [Type: ref$<str$>]
@@ -141,8 +141,8 @@
// cdb-check: [<Raw View>] [Type: alloc::collections::vec_deque::VecDeque<i32,alloc::alloc::Global>]
// cdb-check: [len] : 0x2 [Type: unsigned [...]]
// cdb-check: [capacity] : 0x8 [Type: unsigned [...]]
-// cdb-check: [0x0] : 90 [Type: int]
-// cdb-check: [0x1] : 20 [Type: int]
+// cdb-check: [0x0] : 90 [Type: i32]
+// cdb-check: [0x1] : 20 [Type: i32]
#![allow(unused_variables)]
use std::collections::{LinkedList, VecDeque};
diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs
index 4a6adc2..2d29ac1 100644
--- a/tests/debuginfo/strings-and-strs.rs
+++ b/tests/debuginfo/strings-and-strs.rs
@@ -7,7 +7,7 @@
// gdb-command:run
// gdb-command:print plain_string
-// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x[...]}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, len: 5}}
+// gdbr-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {inner: alloc::raw_vec::RawVecInner<alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x[...]}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData<u8>}, len: 5}}
// gdb-command:print plain_str
// gdbr-check:$2 = "Hello"
diff --git a/tests/debuginfo/thread-names.rs b/tests/debuginfo/thread-names.rs
index 1b9ada6..6b3b0c7 100644
--- a/tests/debuginfo/thread-names.rs
+++ b/tests/debuginfo/thread-names.rs
@@ -1,8 +1,8 @@
//@ compile-flags:-g
-//@ revisions: macos windows
+//@ revisions: macos win
// We can't set the main thread name on Linux because it renames the process (#97191)
//@[macos] only-macos
-//@[windows] only-windows
+//@[win] only-windows
//@ ignore-sgx
//@ ignore-windows-gnu
diff --git a/tests/incremental/hashes/call_expressions.rs b/tests/incremental/hashes/call_expressions.rs
index 36b6980..71423ef 100644
--- a/tests/incremental/hashes/call_expressions.rs
+++ b/tests/incremental/hashes/call_expressions.rs
@@ -162,7 +162,7 @@ pub fn change_to_ufcs() {
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail3")]
#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")]
#[rustc_clean(cfg="cfail6")]
diff --git a/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs
index 9cd99bf..b827ad9 100644
--- a/tests/incremental/hashes/for_loops.rs
+++ b/tests/incremental/hashes/for_loops.rs
@@ -103,9 +103,9 @@ pub fn change_iterable() {
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")]
+#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, promoted_mir")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")]
+#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, promoted_mir")]
#[rustc_clean(cfg="cfail6")]
pub fn change_iterable() {
let mut _x = 0;
diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs
index a8e0b4b..ed08040 100644
--- a/tests/mir-opt/building/custom/terminators.rs
+++ b/tests/mir-opt/building/custom/terminators.rs
@@ -22,6 +22,18 @@ fn direct_call(x: i32) -> i32 {
}
}
+// EMIT_MIR terminators.tail_call.built.after.mir
+#[custom_mir(dialect = "built")]
+fn tail_call(x: i32) -> i32 {
+ mir! {
+ let y;
+ {
+ y = x + 42;
+ TailCall(ident(y))
+ }
+ }
+}
+
// EMIT_MIR terminators.indirect_call.built.after.mir
#[custom_mir(dialect = "built")]
fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
diff --git a/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir b/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir
new file mode 100644
index 0000000..4cf6e45
--- /dev/null
+++ b/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir
@@ -0,0 +1,11 @@
+// MIR for `tail_call` after built
+
+fn tail_call(_1: i32) -> i32 {
+ let mut _0: i32;
+ let mut _2: i32;
+
+ bb0: {
+ _2 = Add(_1, const 42_i32);
+ tailcall ident::<i32>(Spanned { node: _2, span: $DIR/terminators.rs:32:28: 32:29 (#0) });
+ }
+}
diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
index 9ebfff18..a93743e 100644
--- a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
@@ -37,11 +37,11 @@
}
bb2: {
- falseEdge -> [real: bb7, imaginary: bb3];
+ falseEdge -> [real: bb8, imaginary: bb3];
}
bb3: {
- falseEdge -> [real: bb12, imaginary: bb5];
+ falseEdge -> [real: bb7, imaginary: bb5];
}
bb4: {
@@ -50,7 +50,7 @@
bb5: {
_1 = (const 3_i32, const 3_i32);
- goto -> bb13;
+ goto -> bb14;
}
bb6: {
@@ -58,18 +58,33 @@
}
bb7: {
+ StorageLive(_9);
+ _9 = ((_2 as Some).0: i32);
+ StorageLive(_10);
+ _10 = _9;
+ _1 = (const 2_i32, move _10);
+ StorageDead(_10);
+ StorageDead(_9);
+ goto -> bb14;
+ }
+
+ bb8: {
StorageLive(_6);
_6 = &((_2 as Some).0: i32);
_3 = &fake shallow _2;
StorageLive(_7);
- _7 = guard() -> [return: bb8, unwind: bb15];
- }
-
- bb8: {
- switchInt(move _7) -> [0: bb10, otherwise: bb9];
+ _7 = guard() -> [return: bb10, unwind: bb16];
}
bb9: {
+ goto -> bb3;
+ }
+
+ bb10: {
+ switchInt(move _7) -> [0: bb12, otherwise: bb11];
+ }
+
+ bb11: {
StorageDead(_7);
FakeRead(ForMatchGuard, _3);
FakeRead(ForGuardBinding, _6);
@@ -81,31 +96,20 @@
StorageDead(_8);
StorageDead(_5);
StorageDead(_6);
- goto -> bb13;
- }
-
- bb10: {
- goto -> bb11;
- }
-
- bb11: {
- StorageDead(_7);
- StorageDead(_6);
- goto -> bb3;
+ goto -> bb14;
}
bb12: {
- StorageLive(_9);
- _9 = ((_2 as Some).0: i32);
- StorageLive(_10);
- _10 = _9;
- _1 = (const 2_i32, move _10);
- StorageDead(_10);
- StorageDead(_9);
goto -> bb13;
}
bb13: {
+ StorageDead(_7);
+ StorageDead(_6);
+ goto -> bb9;
+ }
+
+ bb14: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
@@ -113,12 +117,12 @@
return;
}
- bb14: {
+ bb15: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
- bb15 (cleanup): {
+ bb16 (cleanup): {
resume;
}
}
diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
index 4d2989e..0d0ea2b 100644
--- a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
@@ -37,7 +37,7 @@
}
bb2: {
- falseEdge -> [real: bb7, imaginary: bb5];
+ falseEdge -> [real: bb8, imaginary: bb5];
}
bb3: {
@@ -48,7 +48,7 @@
_1 = (const 2_i32, move _10);
StorageDead(_10);
StorageDead(_9);
- goto -> bb13;
+ goto -> bb14;
}
bb4: {
@@ -56,7 +56,7 @@
}
bb5: {
- falseEdge -> [real: bb12, imaginary: bb3];
+ falseEdge -> [real: bb7, imaginary: bb3];
}
bb6: {
@@ -64,18 +64,27 @@
}
bb7: {
+ _1 = (const 3_i32, const 3_i32);
+ goto -> bb14;
+ }
+
+ bb8: {
StorageLive(_6);
_6 = &((_2 as Some).0: i32);
_3 = &fake shallow _2;
StorageLive(_7);
- _7 = guard() -> [return: bb8, unwind: bb15];
- }
-
- bb8: {
- switchInt(move _7) -> [0: bb10, otherwise: bb9];
+ _7 = guard() -> [return: bb10, unwind: bb16];
}
bb9: {
+ falseEdge -> [real: bb3, imaginary: bb5];
+ }
+
+ bb10: {
+ switchInt(move _7) -> [0: bb12, otherwise: bb11];
+ }
+
+ bb11: {
StorageDead(_7);
FakeRead(ForMatchGuard, _3);
FakeRead(ForGuardBinding, _6);
@@ -87,25 +96,20 @@
StorageDead(_8);
StorageDead(_5);
StorageDead(_6);
- goto -> bb13;
- }
-
- bb10: {
- goto -> bb11;
- }
-
- bb11: {
- StorageDead(_7);
- StorageDead(_6);
- falseEdge -> [real: bb3, imaginary: bb5];
+ goto -> bb14;
}
bb12: {
- _1 = (const 3_i32, const 3_i32);
goto -> bb13;
}
bb13: {
+ StorageDead(_7);
+ StorageDead(_6);
+ goto -> bb9;
+ }
+
+ bb14: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
@@ -113,12 +117,12 @@
return;
}
- bb14: {
+ bb15: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
- bb15 (cleanup): {
+ bb16 (cleanup): {
resume;
}
}
diff --git a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
index 4ed9361..87b7e29 100644
--- a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
@@ -43,11 +43,11 @@
}
bb1: {
- falseEdge -> [real: bb14, imaginary: bb4];
+ falseEdge -> [real: bb11, imaginary: bb4];
}
bb2: {
- falseEdge -> [real: bb9, imaginary: bb1];
+ falseEdge -> [real: bb12, imaginary: bb1];
}
bb3: {
@@ -64,11 +64,11 @@
_14 = _2;
_1 = const 4_i32;
StorageDead(_14);
- goto -> bb20;
+ goto -> bb22;
}
bb6: {
- falseEdge -> [real: bb15, imaginary: bb5];
+ falseEdge -> [real: bb9, imaginary: bb5];
}
bb7: {
@@ -81,18 +81,44 @@
}
bb9: {
+ StorageLive(_11);
+ _11 = &((_2 as Some).0: i32);
+ _3 = &fake shallow _2;
+ StorageLive(_12);
+ StorageLive(_13);
+ _13 = (*_11);
+ _12 = guard2(move _13) -> [return: bb18, unwind: bb24];
+ }
+
+ bb10: {
+ falseEdge -> [real: bb7, imaginary: bb5];
+ }
+
+ bb11: {
+ StorageLive(_9);
+ _9 = _2;
+ _1 = const 2_i32;
+ StorageDead(_9);
+ goto -> bb22;
+ }
+
+ bb12: {
StorageLive(_7);
_7 = &((_2 as Some).0: i32);
_3 = &fake shallow _2;
StorageLive(_8);
- _8 = guard() -> [return: bb10, unwind: bb22];
+ _8 = guard() -> [return: bb14, unwind: bb24];
}
- bb10: {
- switchInt(move _8) -> [0: bb12, otherwise: bb11];
+ bb13: {
+ falseEdge -> [real: bb3, imaginary: bb1];
}
- bb11: {
+ bb14: {
+ switchInt(move _8) -> [0: bb16, otherwise: bb15];
+ }
+
+ bb15: {
StorageDead(_8);
FakeRead(ForMatchGuard, _3);
FakeRead(ForGuardBinding, _7);
@@ -101,42 +127,24 @@
_1 = const 1_i32;
StorageDead(_6);
StorageDead(_7);
- goto -> bb20;
- }
-
- bb12: {
- goto -> bb13;
- }
-
- bb13: {
- StorageDead(_8);
- StorageDead(_7);
- falseEdge -> [real: bb3, imaginary: bb1];
- }
-
- bb14: {
- StorageLive(_9);
- _9 = _2;
- _1 = const 2_i32;
- StorageDead(_9);
- goto -> bb20;
- }
-
- bb15: {
- StorageLive(_11);
- _11 = &((_2 as Some).0: i32);
- _3 = &fake shallow _2;
- StorageLive(_12);
- StorageLive(_13);
- _13 = (*_11);
- _12 = guard2(move _13) -> [return: bb16, unwind: bb22];
+ goto -> bb22;
}
bb16: {
- switchInt(move _12) -> [0: bb18, otherwise: bb17];
+ goto -> bb17;
}
bb17: {
+ StorageDead(_8);
+ StorageDead(_7);
+ goto -> bb13;
+ }
+
+ bb18: {
+ switchInt(move _12) -> [0: bb20, otherwise: bb19];
+ }
+
+ bb19: {
StorageDead(_13);
StorageDead(_12);
FakeRead(ForMatchGuard, _3);
@@ -146,21 +154,21 @@
_1 = const 3_i32;
StorageDead(_10);
StorageDead(_11);
- goto -> bb20;
- }
-
- bb18: {
- goto -> bb19;
- }
-
- bb19: {
- StorageDead(_13);
- StorageDead(_12);
- StorageDead(_11);
- falseEdge -> [real: bb7, imaginary: bb5];
+ goto -> bb22;
}
bb20: {
+ goto -> bb21;
+ }
+
+ bb21: {
+ StorageDead(_13);
+ StorageDead(_12);
+ StorageDead(_11);
+ goto -> bb10;
+ }
+
+ bb22: {
PlaceMention(_1);
StorageDead(_2);
StorageDead(_1);
@@ -168,12 +176,12 @@
return;
}
- bb21: {
+ bb23: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
- bb22 (cleanup): {
+ bb24 (cleanup): {
resume;
}
}
diff --git a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir
index 78356a9..bba4d9c 100644
--- a/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/never_patterns.opt1.SimplifyCfg-initial.after.mir
@@ -13,17 +13,17 @@
bb0: {
PlaceMention(_1);
- _2 = discriminant((*_1));
- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
+ falseEdge -> [real: bb4, imaginary: bb1];
}
bb1: {
- FakeRead(ForMatchedPlace(None), _1);
- unreachable;
+ _2 = discriminant((*_1));
+ switchInt(move _2) -> [1: bb3, otherwise: bb2];
}
bb2: {
- falseEdge -> [real: bb4, imaginary: bb3];
+ FakeRead(ForMatchedPlace(None), _1);
+ unreachable;
}
bb3: {
diff --git a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir
index 979fbb2..fc0769d 100644
--- a/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/never_patterns.opt2.SimplifyCfg-initial.after.mir
@@ -11,25 +11,10 @@
bb0: {
PlaceMention(_1);
- _2 = discriminant((*_1));
- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
- }
-
- bb1: {
- FakeRead(ForMatchedPlace(None), _1);
- unreachable;
- }
-
- bb2: {
StorageLive(_3);
_3 = &(((*_1) as Ok).0: u32);
_0 = &(*_3);
StorageDead(_3);
return;
}
-
- bb3: {
- FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
- unreachable;
- }
}
diff --git a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir
index 93ebe60..86347db 100644
--- a/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/never_patterns.opt3.SimplifyCfg-initial.after.mir
@@ -12,24 +12,19 @@
bb0: {
PlaceMention(_1);
_2 = discriminant((*_1));
- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
+ switchInt(move _2) -> [1: bb2, otherwise: bb1];
}
bb1: {
- FakeRead(ForMatchedPlace(None), _1);
- unreachable;
- }
-
- bb2: {
- FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
- unreachable;
- }
-
- bb3: {
StorageLive(_3);
_3 = &(((*_1) as Ok).0: u32);
_0 = &(*_3);
StorageDead(_3);
return;
}
+
+ bb2: {
+ FakeRead(ForMatchedPlace(None), (((*_1) as Err).0: Void));
+ unreachable;
+ }
}
diff --git a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
index 2b5dbac..2bce79a 100644
--- a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
@@ -31,7 +31,7 @@
}
bb2: {
- falseEdge -> [real: bb12, imaginary: bb5];
+ falseEdge -> [real: bb15, imaginary: bb5];
}
bb3: {
@@ -39,7 +39,7 @@
}
bb4: {
- falseEdge -> [real: bb16, imaginary: bb1];
+ falseEdge -> [real: bb13, imaginary: bb1];
}
bb5: {
@@ -51,7 +51,7 @@
}
bb7: {
- falseEdge -> [real: bb15, imaginary: bb3];
+ falseEdge -> [real: bb14, imaginary: bb3];
}
bb8: {
@@ -68,18 +68,33 @@
}
bb11: {
- falseEdge -> [real: bb17, imaginary: bb10];
+ falseEdge -> [real: bb12, imaginary: bb10];
}
bb12: {
+ _0 = const 4_u32;
+ goto -> bb18;
+ }
+
+ bb13: {
+ _0 = const 3_u32;
+ goto -> bb18;
+ }
+
+ bb14: {
+ _0 = const 2_u32;
+ goto -> bb18;
+ }
+
+ bb15: {
_6 = &fake shallow (_3.0: &str);
_7 = &fake shallow (_3.1: bool);
StorageLive(_10);
_10 = const true;
- switchInt(move _10) -> [0: bb14, otherwise: bb13];
+ switchInt(move _10) -> [0: bb17, otherwise: bb16];
}
- bb13: {
+ bb16: {
StorageDead(_10);
FakeRead(ForMatchGuard, _6);
FakeRead(ForMatchGuard, _7);
@@ -87,26 +102,11 @@
goto -> bb18;
}
- bb14: {
+ bb17: {
StorageDead(_10);
falseEdge -> [real: bb3, imaginary: bb5];
}
- bb15: {
- _0 = const 2_u32;
- goto -> bb18;
- }
-
- bb16: {
- _0 = const 3_u32;
- goto -> bb18;
- }
-
- bb17: {
- _0 = const 4_u32;
- goto -> bb18;
- }
-
bb18: {
StorageDead(_3);
return;
diff --git a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
index 07daa3e..e521fb4 100644
--- a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
@@ -23,7 +23,7 @@
}
bb2: {
- falseEdge -> [real: bb9, imaginary: bb3];
+ falseEdge -> [real: bb11, imaginary: bb3];
}
bb3: {
@@ -32,7 +32,7 @@
}
bb4: {
- falseEdge -> [real: bb12, imaginary: bb5];
+ falseEdge -> [real: bb10, imaginary: bb5];
}
bb5: {
@@ -40,7 +40,7 @@
}
bb6: {
- falseEdge -> [real: bb13, imaginary: bb1];
+ falseEdge -> [real: bb9, imaginary: bb1];
}
bb7: {
@@ -54,34 +54,34 @@
}
bb9: {
- _3 = &fake shallow _1;
- StorageLive(_8);
- _8 = _2;
- switchInt(move _8) -> [0: bb11, otherwise: bb10];
+ _0 = const 2_u32;
+ goto -> bb14;
}
bb10: {
+ _0 = const 1_u32;
+ goto -> bb14;
+ }
+
+ bb11: {
+ _3 = &fake shallow _1;
+ StorageLive(_8);
+ _8 = _2;
+ switchInt(move _8) -> [0: bb13, otherwise: bb12];
+ }
+
+ bb12: {
StorageDead(_8);
FakeRead(ForMatchGuard, _3);
_0 = const 0_u32;
goto -> bb14;
}
- bb11: {
+ bb13: {
StorageDead(_8);
falseEdge -> [real: bb1, imaginary: bb3];
}
- bb12: {
- _0 = const 1_u32;
- goto -> bb14;
- }
-
- bb13: {
- _0 = const 2_u32;
- goto -> bb14;
- }
-
bb14: {
return;
}
diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs
index 264c8a3..c2f5e83 100644
--- a/tests/mir-opt/const_prop/offset_of.rs
+++ b/tests/mir-opt/const_prop/offset_of.rs
@@ -2,7 +2,7 @@
//@ test-mir-pass: GVN
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-#![feature(offset_of_enum, offset_of_nested)]
+#![feature(offset_of_enum)]
use std::marker::PhantomData;
use std::mem::offset_of;
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
index 8415789..21d91d0 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
@@ -22,12 +22,11 @@
StorageLive(_3);
StorageLive(_4);
_9 = const main::promoted[0];
-- _4 = _9;
+ _4 = _9;
- _3 = _4;
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
-+ _4 = const {ALLOC0<imm>: &[u32; 3]};
-+ _3 = const {ALLOC0<imm>: &[u32; 3]};
-+ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize));
++ _3 = _9;
++ _2 = _9 as &[u32] (PointerCoercion(Unsize));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
@@ -50,6 +49,4 @@
return;
}
}
-+
-+ ALLOC0 (size: 12, align: 4) { .. }
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
index fea7caa..889114c 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
@@ -22,12 +22,11 @@
StorageLive(_3);
StorageLive(_4);
_9 = const main::promoted[0];
-- _4 = _9;
+ _4 = _9;
- _3 = _4;
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
-+ _4 = const {ALLOC0<imm>: &[u32; 3]};
-+ _3 = const {ALLOC0<imm>: &[u32; 3]};
-+ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize));
++ _3 = _9;
++ _2 = _9 as &[u32] (PointerCoercion(Unsize));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
@@ -50,6 +49,4 @@
return;
}
}
-+
-+ ALLOC0 (size: 12, align: 4) { .. }
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
index 8415789..21d91d0 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
@@ -22,12 +22,11 @@
StorageLive(_3);
StorageLive(_4);
_9 = const main::promoted[0];
-- _4 = _9;
+ _4 = _9;
- _3 = _4;
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
-+ _4 = const {ALLOC0<imm>: &[u32; 3]};
-+ _3 = const {ALLOC0<imm>: &[u32; 3]};
-+ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize));
++ _3 = _9;
++ _2 = _9 as &[u32] (PointerCoercion(Unsize));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
@@ -50,6 +49,4 @@
return;
}
}
-+
-+ ALLOC0 (size: 12, align: 4) { .. }
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
index fea7caa..889114c 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
@@ -22,12 +22,11 @@
StorageLive(_3);
StorageLive(_4);
_9 = const main::promoted[0];
-- _4 = _9;
+ _4 = _9;
- _3 = _4;
- _2 = move _3 as &[u32] (PointerCoercion(Unsize));
-+ _4 = const {ALLOC0<imm>: &[u32; 3]};
-+ _3 = const {ALLOC0<imm>: &[u32; 3]};
-+ _2 = const {ALLOC0<imm>: &[u32; 3]} as &[u32] (PointerCoercion(Unsize));
++ _3 = _9;
++ _2 = _9 as &[u32] (PointerCoercion(Unsize));
StorageDead(_3);
StorageLive(_6);
_6 = const 1_usize;
@@ -50,6 +49,4 @@
return;
}
}
-+
-+ ALLOC0 (size: 12, align: 4) { .. }
diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs
index 265a496..3d1b589 100644
--- a/tests/mir-opt/const_prop/slice_len.rs
+++ b/tests/mir-opt/const_prop/slice_len.rs
@@ -1,5 +1,5 @@
//@ test-mir-pass: GVN
-//@ compile-flags: -Zmir-enable-passes=+InstSimplify -Zdump-mir-exclude-alloc-bytes
+//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg -Zdump-mir-exclude-alloc-bytes
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
// EMIT_MIR_FOR_EACH_BIT_WIDTH
@@ -7,7 +7,7 @@
fn main() {
// CHECK-LABEL: fn main(
// CHECK: debug a => [[a:_.*]];
- // CHECK: [[slice:_.*]] = const {{.*}} as &[u32] (PointerCoercion(Unsize));
+ // CHECK: [[slice:_.*]] = {{.*}} as &[u32] (PointerCoercion(Unsize));
// CHECK: assert(const true,
// CHECK: [[a]] = const 2_u32;
let a = (&[1u32, 2, 3] as &[u32])[1];
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index e60f71f..3d79173 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -55,17 +55,17 @@
bb2: {
+ Coverage::CounterIncrement(3);
- falseEdge -> [real: bb6, imaginary: bb3];
+ falseEdge -> [real: bb8, imaginary: bb3];
}
bb3: {
+ Coverage::CounterIncrement(2);
- falseEdge -> [real: bb8, imaginary: bb4];
+ falseEdge -> [real: bb7, imaginary: bb4];
}
bb4: {
+ Coverage::CounterIncrement(1);
- falseEdge -> [real: bb10, imaginary: bb5];
+ falseEdge -> [real: bb6, imaginary: bb5];
}
bb5: {
@@ -78,34 +78,6 @@
}
bb6: {
- StorageLive(_3);
- _3 = ((_1 as D).0: u32);
- StorageLive(_4);
- _4 = _3;
- _0 = consume(move _4) -> [return: bb7, unwind: bb14];
- }
-
- bb7: {
- StorageDead(_4);
- StorageDead(_3);
- goto -> bb13;
- }
-
- bb8: {
- StorageLive(_5);
- _5 = ((_1 as C).0: u32);
- StorageLive(_6);
- _6 = _5;
- _0 = consume(move _6) -> [return: bb9, unwind: bb14];
- }
-
- bb9: {
- StorageDead(_6);
- StorageDead(_5);
- goto -> bb13;
- }
-
- bb10: {
StorageLive(_7);
_7 = ((_1 as B).0: u32);
StorageLive(_8);
@@ -113,6 +85,34 @@
_0 = consume(move _8) -> [return: bb11, unwind: bb14];
}
+ bb7: {
+ StorageLive(_5);
+ _5 = ((_1 as C).0: u32);
+ StorageLive(_6);
+ _6 = _5;
+ _0 = consume(move _6) -> [return: bb10, unwind: bb14];
+ }
+
+ bb8: {
+ StorageLive(_3);
+ _3 = ((_1 as D).0: u32);
+ StorageLive(_4);
+ _4 = _3;
+ _0 = consume(move _4) -> [return: bb9, unwind: bb14];
+ }
+
+ bb9: {
+ StorageDead(_4);
+ StorageDead(_3);
+ goto -> bb13;
+ }
+
+ bb10: {
+ StorageDead(_6);
+ StorageDead(_5);
+ goto -> bb13;
+ }
+
bb11: {
StorageDead(_8);
StorageDead(_7);
diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs
index 12396b3..bb4a74d 100644
--- a/tests/mir-opt/dataflow-const-prop/offset_of.rs
+++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs
@@ -1,8 +1,6 @@
//@ test-mir-pass: DataflowConstProp
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-#![feature(offset_of_nested)]
-
use std::marker::PhantomData;
use std::mem::offset_of;
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs
index 5d9733f..64c043c 100644
--- a/tests/mir-opt/dataflow-const-prop/slice_len.rs
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs
@@ -1,6 +1,6 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ test-mir-pass: DataflowConstProp
-//@ compile-flags: -Zmir-enable-passes=+InstSimplify
+//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR slice_len.main.DataflowConstProp.diff
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
index 3a5762e..efb28ba 100644
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
+++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
@@ -33,7 +33,7 @@
_8 = const 3_usize;
_9 = Ge(move _7, move _8);
- switchInt(move _9) -> [0: bb7, otherwise: bb8];
-+ switchInt(move _9) -> [0: bb10, otherwise: bb7];
++ switchInt(move _9) -> [0: bb11, otherwise: bb7];
}
bb3: {
@@ -49,48 +49,48 @@
}
bb6: {
-- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
-+ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2];
+- switchInt((*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
++ switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
}
bb7: {
- _0 = const false;
- goto -> bb14;
-+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10];
++ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
}
bb8: {
- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
-+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10];
++ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
}
bb9: {
- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
-+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
++ switchInt((*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
}
bb10: {
-- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7];
+- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
- }
-
- bb11: {
- _0 = const false;
-- goto -> bb14;
-+ goto -> bb12;
- }
-
-- bb12: {
-+ bb11: {
_0 = const true;
- goto -> bb14;
+ goto -> bb12;
}
-- bb13: {
+- bb12: {
- _0 = const true;
- goto -> bb14;
- }
-
+- bb13: {
++ bb11: {
+ _0 = const false;
+- goto -> bb14;
++ goto -> bb12;
+ }
+
- bb14: {
+ bb12: {
StorageDead(_2);
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
index 21b197d..c6e2d3a 100644
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
+++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
@@ -33,7 +33,7 @@
_8 = const 3_usize;
_9 = Ge(move _7, move _8);
- switchInt(move _9) -> [0: bb7, otherwise: bb8];
-+ switchInt(move _9) -> [0: bb10, otherwise: bb7];
++ switchInt(move _9) -> [0: bb11, otherwise: bb7];
}
bb3: {
@@ -49,48 +49,48 @@
}
bb6: {
-- switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
-+ switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2];
+- switchInt((*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
++ switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
}
bb7: {
- _0 = const false;
- goto -> bb14;
-+ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10];
++ switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
}
bb8: {
- switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
-+ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10];
++ switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
}
bb9: {
- switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
-+ switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
++ switchInt((*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
}
bb10: {
-- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7];
+- switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
- }
-
- bb11: {
- _0 = const false;
-- goto -> bb14;
-+ goto -> bb12;
- }
-
-- bb12: {
-+ bb11: {
_0 = const true;
- goto -> bb14;
+ goto -> bb12;
}
-- bb13: {
+- bb12: {
- _0 = const true;
- goto -> bb14;
- }
-
+- bb13: {
++ bb11: {
+ _0 = const false;
+- goto -> bb14;
++ goto -> bb12;
+ }
+
- bb14: {
+ bb12: {
StorageDead(_2);
diff --git a/tests/mir-opt/dont_inline_type_id.rs b/tests/mir-opt/dont_inline_type_id.rs
index ab74894..d389733 100644
--- a/tests/mir-opt/dont_inline_type_id.rs
+++ b/tests/mir-opt/dont_inline_type_id.rs
@@ -2,8 +2,7 @@
//@ test-mir-pass: Inline
//@ compile-flags: --crate-type=lib -C panic=abort
-use std::any::Any;
-use std::any::TypeId;
+use std::any::{Any, TypeId};
struct A<T: ?Sized + 'static> {
a: i32,
diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
index 7776ff0..41ae2fd 100644
--- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -38,15 +38,20 @@
bb2: {
_6 = discriminant((_3.1: std::option::Option<u32>));
- switchInt(move _6) -> [1: bb4, 0: bb1, otherwise: bb7];
+ switchInt(move _6) -> [1: bb5, 0: bb1, otherwise: bb7];
}
bb3: {
_7 = discriminant((_3.1: std::option::Option<u32>));
- switchInt(move _7) -> [0: bb5, 1: bb1, otherwise: bb7];
+ switchInt(move _7) -> [0: bb4, 1: bb1, otherwise: bb7];
}
bb4: {
+ _0 = const 2_u32;
+ goto -> bb6;
+ }
+
+ bb5: {
StorageLive(_9);
_9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
StorageLive(_10);
@@ -57,11 +62,6 @@
goto -> bb6;
}
- bb5: {
- _0 = const 2_u32;
- goto -> bb6;
- }
-
bb6: {
StorageDead(_3);
return;
diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
index b41e952..302fd0b 100644
--- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
@@ -49,7 +49,7 @@
bb2: {
- _6 = discriminant((_3.1: Option2<bool>));
-- switchInt(move _6) -> [0: bb5, otherwise: bb1];
+- switchInt(move _6) -> [0: bb7, otherwise: bb1];
- }
-
- bb3: {
@@ -59,17 +59,11 @@
-
- bb4: {
- _8 = discriminant((_3.1: Option2<bool>));
-- switchInt(move _8) -> [2: bb7, otherwise: bb1];
+- switchInt(move _8) -> [2: bb5, otherwise: bb1];
- }
-
- bb5: {
- StorageLive(_10);
- _10 = (((_3.0: Option2<u32>) as Some).0: u32);
- StorageLive(_11);
- _11 = (((_3.1: Option2<bool>) as Some).0: bool);
- _0 = const 0_u32;
- StorageDead(_11);
- StorageDead(_10);
+ _0 = const 3_u32;
- goto -> bb8;
+ goto -> bb5;
}
@@ -83,7 +77,13 @@
- bb7: {
+ bb4: {
- _0 = const 3_u32;
+ StorageLive(_10);
+ _10 = (((_3.0: Option2<u32>) as Some).0: u32);
+ StorageLive(_11);
+ _11 = (((_3.1: Option2<bool>) as Some).0: bool);
+ _0 = const 0_u32;
+ StorageDead(_11);
+ StorageDead(_10);
- goto -> bb8;
+ goto -> bb5;
}
@@ -101,7 +101,7 @@
+
+ bb7: {
+ StorageDead(_13);
-+ switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6];
++ switchInt(_9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6];
}
}
diff --git a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
index 18dea56..eef4fb3 100644
--- a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
@@ -49,7 +49,7 @@
bb2: {
- _6 = discriminant((_3.1: Option2<u32>));
-- switchInt(move _6) -> [0: bb5, otherwise: bb1];
+- switchInt(move _6) -> [0: bb7, otherwise: bb1];
- }
-
- bb3: {
@@ -59,17 +59,11 @@
-
- bb4: {
- _8 = discriminant((_3.1: Option2<u32>));
-- switchInt(move _8) -> [2: bb7, otherwise: bb1];
+- switchInt(move _8) -> [2: bb5, otherwise: bb1];
- }
-
- bb5: {
- StorageLive(_10);
- _10 = (((_3.0: Option2<u32>) as Some).0: u32);
- StorageLive(_11);
- _11 = (((_3.1: Option2<u32>) as Some).0: u32);
- _0 = const 0_u32;
- StorageDead(_11);
- StorageDead(_10);
+ _0 = const 3_u32;
- goto -> bb8;
+ goto -> bb5;
}
@@ -83,7 +77,13 @@
- bb7: {
+ bb4: {
- _0 = const 3_u32;
+ StorageLive(_10);
+ _10 = (((_3.0: Option2<u32>) as Some).0: u32);
+ StorageLive(_11);
+ _11 = (((_3.1: Option2<u32>) as Some).0: u32);
+ _0 = const 0_u32;
+ StorageDead(_11);
+ StorageDead(_10);
- goto -> bb8;
+ goto -> bb5;
}
@@ -101,7 +101,7 @@
+
+ bb7: {
+ StorageDead(_13);
-+ switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6];
++ switchInt(_9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6];
}
}
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
index 4c3c717..cb03e26 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -52,7 +52,7 @@
bb3: {
_8 = discriminant((_4.2: std::option::Option<u32>));
- switchInt(move _8) -> [1: bb6, 0: bb1, otherwise: bb9];
+ switchInt(move _8) -> [1: bb7, 0: bb1, otherwise: bb9];
}
bb4: {
@@ -62,10 +62,15 @@
bb5: {
_10 = discriminant((_4.2: std::option::Option<u32>));
- switchInt(move _10) -> [0: bb7, 1: bb1, otherwise: bb9];
+ switchInt(move _10) -> [0: bb6, 1: bb1, otherwise: bb9];
}
bb6: {
+ _0 = const 2_u32;
+ goto -> bb8;
+ }
+
+ bb7: {
StorageLive(_13);
_13 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
StorageLive(_14);
@@ -79,11 +84,6 @@
goto -> bb8;
}
- bb7: {
- _0 = const 2_u32;
- goto -> bb8;
- }
-
bb8: {
StorageDead(_4);
return;
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
index 0ea7a10..5634df2 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
@@ -64,8 +64,8 @@
-
- bb3: {
_8 = discriminant((_4.2: Option2<u32>));
-- switchInt(move _8) -> [0: bb8, otherwise: bb1];
-+ switchInt(move _8) -> [0: bb5, otherwise: bb1];
+- switchInt(move _8) -> [0: bb10, otherwise: bb1];
++ switchInt(move _8) -> [0: bb7, otherwise: bb1];
}
- bb4: {
@@ -88,22 +88,13 @@
- bb7: {
+ bb4: {
_12 = discriminant((_4.2: Option2<u32>));
-- switchInt(move _12) -> [2: bb10, otherwise: bb1];
-+ switchInt(move _12) -> [2: bb7, otherwise: bb1];
+- switchInt(move _12) -> [2: bb8, otherwise: bb1];
++ switchInt(move _12) -> [2: bb5, otherwise: bb1];
}
- bb8: {
+ bb5: {
- StorageLive(_15);
- _15 = (((_4.0: Option2<u32>) as Some).0: u32);
- StorageLive(_16);
- _16 = (((_4.1: Option2<u32>) as Some).0: u32);
- StorageLive(_17);
- _17 = (((_4.2: Option2<u32>) as Some).0: u32);
- _0 = const 0_u32;
- StorageDead(_17);
- StorageDead(_16);
- StorageDead(_15);
+ _0 = const 3_u32;
- goto -> bb11;
+ goto -> bb8;
}
@@ -117,7 +108,16 @@
- bb10: {
+ bb7: {
- _0 = const 3_u32;
+ StorageLive(_15);
+ _15 = (((_4.0: Option2<u32>) as Some).0: u32);
+ StorageLive(_16);
+ _16 = (((_4.1: Option2<u32>) as Some).0: u32);
+ StorageLive(_17);
+ _17 = (((_4.2: Option2<u32>) as Some).0: u32);
+ _0 = const 0_u32;
+ StorageDead(_17);
+ StorageDead(_16);
+ StorageDead(_15);
- goto -> bb11;
+ goto -> bb8;
}
diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
index de12fe8..8179d9d 100644
--- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -94,78 +94,56 @@
bb2: {
_35 = deref_copy (_4.1: &ViewportPercentageLength);
_7 = discriminant((*_35));
- switchInt(move _7) -> [0: bb6, otherwise: bb1];
+ switchInt(move _7) -> [0: bb9, otherwise: bb1];
}
bb3: {
_36 = deref_copy (_4.1: &ViewportPercentageLength);
_8 = discriminant((*_36));
- switchInt(move _8) -> [1: bb7, otherwise: bb1];
+ switchInt(move _8) -> [1: bb8, otherwise: bb1];
}
bb4: {
_37 = deref_copy (_4.1: &ViewportPercentageLength);
_9 = discriminant((*_37));
- switchInt(move _9) -> [2: bb8, otherwise: bb1];
+ switchInt(move _9) -> [2: bb7, otherwise: bb1];
}
bb5: {
_38 = deref_copy (_4.1: &ViewportPercentageLength);
_10 = discriminant((*_38));
- switchInt(move _10) -> [3: bb9, otherwise: bb1];
+ switchInt(move _10) -> [3: bb6, otherwise: bb1];
}
bb6: {
- StorageLive(_12);
+ StorageLive(_27);
_39 = deref_copy (_4.0: &ViewportPercentageLength);
- _12 = (((*_39) as Vw).0: f32);
- StorageLive(_13);
+ _27 = (((*_39) as Vmax).0: f32);
+ StorageLive(_28);
_40 = deref_copy (_4.1: &ViewportPercentageLength);
- _13 = (((*_40) as Vw).0: f32);
- StorageLive(_14);
- StorageLive(_15);
- _15 = _12;
- StorageLive(_16);
- _16 = _13;
- _14 = Add(move _15, move _16);
- StorageDead(_16);
- StorageDead(_15);
- _3 = ViewportPercentageLength::Vw(move _14);
- StorageDead(_14);
- StorageDead(_13);
- StorageDead(_12);
+ _28 = (((*_40) as Vmax).0: f32);
+ StorageLive(_29);
+ StorageLive(_30);
+ _30 = _27;
+ StorageLive(_31);
+ _31 = _28;
+ _29 = Add(move _30, move _31);
+ StorageDead(_31);
+ StorageDead(_30);
+ _3 = ViewportPercentageLength::Vmax(move _29);
+ StorageDead(_29);
+ StorageDead(_28);
+ StorageDead(_27);
goto -> bb10;
}
bb7: {
- StorageLive(_17);
- _41 = deref_copy (_4.0: &ViewportPercentageLength);
- _17 = (((*_41) as Vh).0: f32);
- StorageLive(_18);
- _42 = deref_copy (_4.1: &ViewportPercentageLength);
- _18 = (((*_42) as Vh).0: f32);
- StorageLive(_19);
- StorageLive(_20);
- _20 = _17;
- StorageLive(_21);
- _21 = _18;
- _19 = Add(move _20, move _21);
- StorageDead(_21);
- StorageDead(_20);
- _3 = ViewportPercentageLength::Vh(move _19);
- StorageDead(_19);
- StorageDead(_18);
- StorageDead(_17);
- goto -> bb10;
- }
-
- bb8: {
StorageLive(_22);
- _43 = deref_copy (_4.0: &ViewportPercentageLength);
- _22 = (((*_43) as Vmin).0: f32);
+ _41 = deref_copy (_4.0: &ViewportPercentageLength);
+ _22 = (((*_41) as Vmin).0: f32);
StorageLive(_23);
- _44 = deref_copy (_4.1: &ViewportPercentageLength);
- _23 = (((*_44) as Vmin).0: f32);
+ _42 = deref_copy (_4.1: &ViewportPercentageLength);
+ _23 = (((*_42) as Vmin).0: f32);
StorageLive(_24);
StorageLive(_25);
_25 = _22;
@@ -181,25 +159,47 @@
goto -> bb10;
}
+ bb8: {
+ StorageLive(_17);
+ _43 = deref_copy (_4.0: &ViewportPercentageLength);
+ _17 = (((*_43) as Vh).0: f32);
+ StorageLive(_18);
+ _44 = deref_copy (_4.1: &ViewportPercentageLength);
+ _18 = (((*_44) as Vh).0: f32);
+ StorageLive(_19);
+ StorageLive(_20);
+ _20 = _17;
+ StorageLive(_21);
+ _21 = _18;
+ _19 = Add(move _20, move _21);
+ StorageDead(_21);
+ StorageDead(_20);
+ _3 = ViewportPercentageLength::Vh(move _19);
+ StorageDead(_19);
+ StorageDead(_18);
+ StorageDead(_17);
+ goto -> bb10;
+ }
+
bb9: {
- StorageLive(_27);
+ StorageLive(_12);
_45 = deref_copy (_4.0: &ViewportPercentageLength);
- _27 = (((*_45) as Vmax).0: f32);
- StorageLive(_28);
+ _12 = (((*_45) as Vw).0: f32);
+ StorageLive(_13);
_46 = deref_copy (_4.1: &ViewportPercentageLength);
- _28 = (((*_46) as Vmax).0: f32);
- StorageLive(_29);
- StorageLive(_30);
- _30 = _27;
- StorageLive(_31);
- _31 = _28;
- _29 = Add(move _30, move _31);
- StorageDead(_31);
- StorageDead(_30);
- _3 = ViewportPercentageLength::Vmax(move _29);
- StorageDead(_29);
- StorageDead(_28);
- StorageDead(_27);
+ _13 = (((*_46) as Vw).0: f32);
+ StorageLive(_14);
+ StorageLive(_15);
+ _15 = _12;
+ StorageLive(_16);
+ _16 = _13;
+ _14 = Add(move _15, move _16);
+ StorageDead(_16);
+ StorageDead(_15);
+ _3 = ViewportPercentageLength::Vw(move _14);
+ StorageDead(_14);
+ StorageDead(_13);
+ StorageDead(_12);
goto -> bb10;
}
diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
index 350e5fe..651b1de 100644
--- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
@@ -45,12 +45,12 @@
bb2: {
_6 = discriminant((_3.1: std::option::Option<u32>));
- switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1];
+ switchInt(move _6) -> [0: bb6, 1: bb7, otherwise: bb1];
}
bb3: {
_7 = discriminant((_3.1: std::option::Option<u32>));
- switchInt(move _7) -> [0: bb4, 1: bb7, otherwise: bb1];
+ switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb1];
}
bb4: {
@@ -59,13 +59,10 @@
}
bb5: {
- StorageLive(_9);
- _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
- StorageLive(_10);
- _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
- _0 = const 0_u32;
- StorageDead(_10);
- StorageDead(_9);
+ StorageLive(_12);
+ _12 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
+ _0 = const 2_u32;
+ StorageDead(_12);
goto -> bb8;
}
@@ -78,10 +75,13 @@
}
bb7: {
- StorageLive(_12);
- _12 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
- _0 = const 2_u32;
- StorageDead(_12);
+ StorageLive(_9);
+ _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
+ StorageLive(_10);
+ _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
+ _0 = const 0_u32;
+ StorageDead(_10);
+ StorageDead(_9);
goto -> bb8;
}
diff --git a/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff b/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff
new file mode 100644
index 0000000..279c1a1
--- /dev/null
+++ b/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff
@@ -0,0 +1,13 @@
+- // MIR for `pointee` before ElaborateBoxDerefs
++ // MIR for `pointee` after ElaborateBoxDerefs
+
+ fn pointee(_1: Box<i32>) -> () {
+- debug foo => (*_1);
++ debug foo => (*(((_1.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>).0: *const i32));
+ let mut _0: ();
+
+ bb0: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/elaborate_box_deref_in_debuginfo.rs b/tests/mir-opt/elaborate_box_deref_in_debuginfo.rs
new file mode 100644
index 0000000..0046e71
--- /dev/null
+++ b/tests/mir-opt/elaborate_box_deref_in_debuginfo.rs
@@ -0,0 +1,20 @@
+// skip-filecheck
+//@ test-mir-pass: ElaborateBoxDerefs
+
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+
+// EMIT_MIR elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff
+#[custom_mir(dialect = "built")]
+fn pointee(opt: Box<i32>) {
+ mir!(
+ debug foo => *opt;
+ {
+ Return()
+ }
+ )
+}
+
+fn main() {}
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff
index 9d5042c..4e495c3 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff
@@ -21,14 +21,14 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
+ _3 = _1;
_2 = <Q as Query>::cache::<T>(move _3) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageDead(_3);
StorageLive(_4);
- _4 = &(*_2);
+ _4 = _2;
- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> [return: bb2, unwind unreachable];
+ StorageLive(_5);
+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff
index 9bd3855..7fdb761 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff
@@ -21,14 +21,14 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
+ _3 = _1;
_2 = <Q as Query>::cache::<T>(move _3) -> [return: bb1, unwind continue];
}
bb1: {
StorageDead(_3);
StorageLive(_4);
- _4 = &(*_2);
+ _4 = _2;
- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> [return: bb2, unwind continue];
+ StorageLive(_5);
+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff
index d7801b7..8df4408 100644
--- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff
@@ -8,7 +8,7 @@
bb0: {
StorageLive(_2);
- _2 = &(*_1);
+ _2 = _1;
_0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> [return: bb1, unwind unreachable];
}
diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff
index 7b1cf89..43a0621 100644
--- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff
@@ -8,7 +8,7 @@
bb0: {
StorageLive(_2);
- _2 = &(*_1);
+ _2 = _1;
_0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> [return: bb1, unwind continue];
}
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff
index 96e16d0..e72c312 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff
@@ -13,7 +13,7 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
+ _3 = _1;
_2 = move _3 as &dyn Cache<V = <C as Cache>::V> (PointerCoercion(Unsize));
StorageDead(_3);
- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> [return: bb1, unwind unreachable];
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff
index 06d65ab..46728f9 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff
@@ -13,7 +13,7 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
+ _3 = _1;
_2 = move _3 as &dyn Cache<V = <C as Cache>::V> (PointerCoercion(Unsize));
StorageDead(_3);
- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> [return: bb1, unwind continue];
diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
index a6198ca..f524b05 100644
--- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
@@ -26,9 +26,9 @@
_4 = &_3;
StorageLive(_5);
StorageLive(_6);
- _6 = &(*_2);
+ _6 = _2;
StorageLive(_7);
- _7 = &(*_2);
+ _7 = _2;
_5 = (move _6, move _7);
StorageLive(_8);
_8 = move (_5.0: &i32);
diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
index dcce4aa..ec3c79e 100644
--- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -31,14 +31,14 @@
StorageLive(_4);
_10 = const bar::promoted[1];
Retag(_10);
- _4 = &(*_10);
- _3 = &(*_4);
+ _4 = _10;
+ _3 = _4;
StorageLive(_6);
StorageLive(_7);
_9 = const bar::promoted[0];
Retag(_9);
- _7 = &(*_9);
- _6 = &(*_7);
+ _7 = _9;
+ _6 = _7;
Retag(_3);
Retag(_6);
StorageLive(_11);
diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir
index 2441e3f..d7b4302 100644
--- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir
+++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir
@@ -7,7 +7,7 @@
bb0: {
StorageLive(_2);
- _2 = &(*_1);
+ _2 = _1;
_0 = <dyn X as X>::y(move _2) -> [return: bb1, unwind unreachable];
}
diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir
index da18a5a..0d6f3e6 100644
--- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir
@@ -7,7 +7,7 @@
bb0: {
StorageLive(_2);
- _2 = &(*_1);
+ _2 = _1;
_0 = <dyn X as X>::y(move _2) -> [return: bb1, unwind continue];
}
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir
index f0d1cfe..af79c7c 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir
@@ -12,8 +12,8 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
- _2 = move _3 as &dyn X (PointerCoercion(Unsize));
+ _3 = _1;
+ _2 = move _3;
StorageDead(_3);
_0 = <dyn X as X>::y(move _2) -> [return: bb1, unwind unreachable];
}
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir
index f37b081..bf5a56b 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir
@@ -12,8 +12,8 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
- _2 = move _3 as &dyn X (PointerCoercion(Unsize));
+ _3 = _1;
+ _2 = move _3;
StorageDead(_3);
_0 = <dyn X as X>::y(move _2) -> [return: bb1, unwind continue];
}
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
index 7cc65ef..8c45703 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
@@ -14,11 +14,11 @@
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
- _4 = &mut (*_1);
+ _4 = _1;
_3 = _4;
- _2 = &mut (*_3);
+ _2 = _3;
StorageDead(_4);
- _0 = &mut (*_2);
+ _0 = _2;
StorageDead(_3);
StorageDead(_2);
return;
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
index 408cc5b..e27d9fe 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir
@@ -16,7 +16,7 @@
StorageLive(_2);
StorageLive(_3);
StorageLive(_4);
- _4 = &mut (*_1);
+ _4 = _1;
StorageLive(_5);
StorageLive(_6);
_5 = (*_4);
@@ -24,9 +24,9 @@
_3 = &mut (*_6);
StorageDead(_6);
StorageDead(_5);
- _2 = &mut (*_3);
+ _2 = _3;
StorageDead(_4);
- _0 = &mut (*_2);
+ _0 = _2;
StorageDead(_3);
StorageDead(_2);
return;
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
index bad7f31..da0464c 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
@@ -12,9 +12,9 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
+ _3 = _1;
_2 = _3;
- _0 = &(*_2);
+ _0 = _2;
StorageDead(_3);
StorageDead(_2);
return;
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
index 4d20f6c..25eaedf 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir
@@ -14,7 +14,7 @@
bb0: {
StorageLive(_2);
StorageLive(_3);
- _3 = &(*_1);
+ _3 = _1;
StorageLive(_4);
StorageLive(_5);
_4 = (*_3);
@@ -22,7 +22,7 @@
_2 = &(*_5);
StorageDead(_5);
StorageDead(_4);
- _0 = &(*_2);
+ _0 = _2;
StorageDead(_3);
StorageDead(_2);
return;
diff --git a/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
index 5c09963..fea5f4f 100644
--- a/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `eq_false` before InstSimplify
-+ // MIR for `eq_false` after InstSimplify
+- // MIR for `eq_false` before InstSimplify-after-simplifycfg
++ // MIR for `eq_false` after InstSimplify-after-simplifycfg
fn eq_false(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
index a80133b..9a509cc 100644
--- a/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `eq_true` before InstSimplify
-+ // MIR for `eq_true` after InstSimplify
+- // MIR for `eq_true` before InstSimplify-after-simplifycfg
++ // MIR for `eq_true` after InstSimplify-after-simplifycfg
fn eq_true(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
index 8235d52..e4ec4c8 100644
--- a/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `false_eq` before InstSimplify
-+ // MIR for `false_eq` after InstSimplify
+- // MIR for `false_eq` before InstSimplify-after-simplifycfg
++ // MIR for `false_eq` after InstSimplify-after-simplifycfg
fn false_eq(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
index 77d076c..3aea55f 100644
--- a/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `false_ne` before InstSimplify
-+ // MIR for `false_ne` after InstSimplify
+- // MIR for `false_ne` before InstSimplify-after-simplifycfg
++ // MIR for `false_ne` after InstSimplify-after-simplifycfg
fn false_ne(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
index 2362b11..b6e8910 100644
--- a/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `ne_false` before InstSimplify
-+ // MIR for `ne_false` after InstSimplify
+- // MIR for `ne_false` before InstSimplify-after-simplifycfg
++ // MIR for `ne_false` after InstSimplify-after-simplifycfg
fn ne_false(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
index 6ccbd2f..974738b 100644
--- a/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `ne_true` before InstSimplify
-+ // MIR for `ne_true` after InstSimplify
+- // MIR for `ne_true` before InstSimplify-after-simplifycfg
++ // MIR for `ne_true` after InstSimplify-after-simplifycfg
fn ne_true(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.rs b/tests/mir-opt/instsimplify/bool_compare.rs
index d1d903f..3911f81 100644
--- a/tests/mir-opt/instsimplify/bool_compare.rs
+++ b/tests/mir-opt/instsimplify/bool_compare.rs
@@ -1,55 +1,55 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
-// EMIT_MIR bool_compare.eq_true.InstSimplify.diff
+// EMIT_MIR bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
fn eq_true(x: bool) -> u32 {
// CHECK-LABEL: fn eq_true(
// CHECK-NOT: Eq(
if x == true { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.true_eq.InstSimplify.diff
+// EMIT_MIR bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
fn true_eq(x: bool) -> u32 {
// CHECK-LABEL: fn true_eq(
// CHECK-NOT: Eq(
if true == x { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.ne_true.InstSimplify.diff
+// EMIT_MIR bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
fn ne_true(x: bool) -> u32 {
// CHECK-LABEL: fn ne_true(
// CHECK: Not(
if x != true { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.true_ne.InstSimplify.diff
+// EMIT_MIR bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
fn true_ne(x: bool) -> u32 {
// CHECK-LABEL: fn true_ne(
// CHECK: Not(
if true != x { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.eq_false.InstSimplify.diff
+// EMIT_MIR bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
fn eq_false(x: bool) -> u32 {
// CHECK-LABEL: fn eq_false(
// CHECK: Not(
if x == false { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.false_eq.InstSimplify.diff
+// EMIT_MIR bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
fn false_eq(x: bool) -> u32 {
// CHECK-LABEL: fn false_eq(
// CHECK: Not(
if false == x { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.ne_false.InstSimplify.diff
+// EMIT_MIR bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
fn ne_false(x: bool) -> u32 {
// CHECK-LABEL: fn ne_false(
// CHECK-NOT: Ne(
if x != false { 0 } else { 1 }
}
-// EMIT_MIR bool_compare.false_ne.InstSimplify.diff
+// EMIT_MIR bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
fn false_ne(x: bool) -> u32 {
// CHECK-LABEL: fn false_ne(
// CHECK-NOT: Ne(
diff --git a/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
index 1867532..240835b 100644
--- a/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `true_eq` before InstSimplify
-+ // MIR for `true_eq` after InstSimplify
+- // MIR for `true_eq` before InstSimplify-after-simplifycfg
++ // MIR for `true_eq` after InstSimplify-after-simplifycfg
fn true_eq(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
index dc91cf8..1e2b2c2 100644
--- a/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `true_ne` before InstSimplify
-+ // MIR for `true_ne` after InstSimplify
+- // MIR for `true_ne` before InstSimplify-after-simplifycfg
++ // MIR for `true_ne` after InstSimplify-after-simplifycfg
fn true_ne(_1: bool) -> u32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify.diff b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff
similarity index 85%
rename from tests/mir-opt/instsimplify/casts.redundant.InstSimplify.diff
rename to tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff
index e7451d5..7001589 100644
--- a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `redundant` before InstSimplify
-+ // MIR for `redundant` after InstSimplify
+- // MIR for `redundant` before InstSimplify-after-simplifycfg
++ // MIR for `redundant` after InstSimplify-after-simplifycfg
fn redundant(_1: *const &u8) -> *const &u8 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff b/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff
similarity index 81%
rename from tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff
rename to tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff
index e87ac76..e1045db 100644
--- a/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `roundtrip` before InstSimplify
-+ // MIR for `roundtrip` after InstSimplify
+- // MIR for `roundtrip` before InstSimplify-after-simplifycfg
++ // MIR for `roundtrip` after InstSimplify-after-simplifycfg
fn roundtrip(_1: *const u8) -> *const u8 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/casts.rs b/tests/mir-opt/instsimplify/casts.rs
index 15ceea7..24dbb67 100644
--- a/tests/mir-opt/instsimplify/casts.rs
+++ b/tests/mir-opt/instsimplify/casts.rs
@@ -1,4 +1,4 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
//@ compile-flags: -Zinline-mir
#![crate_type = "lib"]
#![feature(core_intrinsics)]
@@ -8,7 +8,7 @@ fn generic_cast<T, U>(x: *const T) -> *const U {
x as *const U
}
-// EMIT_MIR casts.redundant.InstSimplify.diff
+// EMIT_MIR casts.redundant.InstSimplify-after-simplifycfg.diff
pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
// CHECK-LABEL: fn redundant(
// CHECK: inlined generic_cast
@@ -16,7 +16,7 @@ pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
generic_cast::<&'a u8, &'b u8>(x) as *const &'a u8
}
-// EMIT_MIR casts.roundtrip.InstSimplify.diff
+// EMIT_MIR casts.roundtrip.InstSimplify-after-simplifycfg.diff
pub fn roundtrip(x: *const u8) -> *const u8 {
// CHECK-LABEL: fn roundtrip(
// CHECK: _4 = _1;
@@ -25,7 +25,7 @@ pub fn roundtrip(x: *const u8) -> *const u8 {
x as *mut u8 as *const u8
}
-// EMIT_MIR casts.roundtrip.InstSimplify.diff
+// EMIT_MIR casts.roundtrip.InstSimplify-after-simplifycfg.diff
pub fn cast_thin_via_aggregate(x: *const u8) -> *const () {
// CHECK-LABEL: fn cast_thin_via_aggregate(
// CHECK: _2 = _1;
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
similarity index 93%
rename from tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-abort.diff
rename to tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
index 3e7d0ce..a7de09c 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-abort.diff
+++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
@@ -1,5 +1,5 @@
-- // MIR for `norm2` before InstSimplify
-+ // MIR for `norm2` after InstSimplify
+- // MIR for `norm2` before InstSimplify-after-simplifycfg
++ // MIR for `norm2` after InstSimplify-after-simplifycfg
fn norm2(_1: [f32; 2]) -> f32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
similarity index 93%
rename from tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-unwind.diff
rename to tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
index 4833c10..c15f7e4 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-unwind.diff
+++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
@@ -1,5 +1,5 @@
-- // MIR for `norm2` before InstSimplify
-+ // MIR for `norm2` after InstSimplify
+- // MIR for `norm2` before InstSimplify-after-simplifycfg
++ // MIR for `norm2` after InstSimplify-after-simplifycfg
fn norm2(_1: [f32; 2]) -> f32 {
debug x => _1;
diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs
index f12284f..91f43f7 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.rs
+++ b/tests/mir-opt/instsimplify/combine_array_len.rs
@@ -1,7 +1,7 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
-// EMIT_MIR combine_array_len.norm2.InstSimplify.diff
+// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff
fn norm2(x: [f32; 2]) -> f32 {
// CHECK-LABEL: fn norm2(
// CHECK-NOT: Len(
diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs b/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs
index 7b1f3d1..4f72883 100644
--- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs
+++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs
@@ -1,7 +1,7 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-// EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstSimplify.diff
+// EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.diff
#[derive(Clone)]
struct MyThing<T> {
v: T,
diff --git "a/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify.panic-abort.diff" "b/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify-after-simplifycfg.panic-abort.diff"
similarity index 93%
rename from "tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify.panic-abort.diff"
rename to "tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify-after-simplifycfg.panic-abort.diff"
index 48586f8..c6f858d 100644
--- "a/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify.panic-abort.diff"
+++ "b/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify-after-simplifycfg.panic-abort.diff"
@@ -1,5 +1,5 @@
-- // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` before InstSimplify
-+ // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` after InstSimplify
+- // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` before InstSimplify-after-simplifycfg
++ // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` after InstSimplify-after-simplifycfg
fn <impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone(_1: &MyThing<T>) -> MyThing<T> {
debug self => _1;
diff --git "a/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify.panic-unwind.diff" "b/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify-after-simplifycfg.panic-unwind.diff"
similarity index 94%
rename from "tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify.panic-unwind.diff"
rename to "tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify-after-simplifycfg.panic-unwind.diff"
index a57266e..691ab1f 100644
--- "a/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify.panic-unwind.diff"
+++ "b/tests/mir-opt/instsimplify/combine_clone_of_primitives.\173impl\0430\175-clone.InstSimplify-after-simplifycfg.panic-unwind.diff"
@@ -1,5 +1,5 @@
-- // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` before InstSimplify
-+ // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` after InstSimplify
+- // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` before InstSimplify-after-simplifycfg
++ // MIR for `<impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone` after InstSimplify-after-simplifycfg
fn <impl at $DIR/combine_clone_of_primitives.rs:5:10: 5:15>::clone(_1: &MyThing<T>) -> MyThing<T> {
debug self => _1;
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
similarity index 94%
rename from tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
rename to tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
index 17730e662..9844aa2 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `adt_transmutes` before InstSimplify
-+ // MIR for `adt_transmutes` after InstSimplify
+- // MIR for `adt_transmutes` before InstSimplify-after-simplifycfg
++ // MIR for `adt_transmutes` after InstSimplify-after-simplifycfg
fn adt_transmutes() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
similarity index 84%
rename from tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify.diff
rename to tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
index 58ae591..589f715 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `identity_transmutes` before InstSimplify
-+ // MIR for `identity_transmutes` after InstSimplify
+- // MIR for `identity_transmutes` before InstSimplify-after-simplifycfg
++ // MIR for `identity_transmutes` after InstSimplify-after-simplifycfg
fn identity_transmutes() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
similarity index 80%
rename from tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify.diff
rename to tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
index 8eff802..b7baa89 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `integer_transmutes` before InstSimplify
-+ // MIR for `integer_transmutes` after InstSimplify
+- // MIR for `integer_transmutes` before InstSimplify-after-simplifycfg
++ // MIR for `integer_transmutes` after InstSimplify-after-simplifycfg
fn integer_transmutes() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.rs b/tests/mir-opt/instsimplify/combine_transmutes.rs
index c3622c2..23f10b7 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.rs
+++ b/tests/mir-opt/instsimplify/combine_transmutes.rs
@@ -1,4 +1,4 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
//@ compile-flags: -C panic=abort
#![crate_type = "lib"]
#![feature(core_intrinsics)]
@@ -7,7 +7,7 @@
use std::intrinsics::mir::*;
use std::mem::{transmute, ManuallyDrop, MaybeUninit};
-// EMIT_MIR combine_transmutes.identity_transmutes.InstSimplify.diff
+// EMIT_MIR combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
pub unsafe fn identity_transmutes() {
// CHECK-LABEL: fn identity_transmutes(
// CHECK-NOT: as i32 (Transmute);
@@ -19,7 +19,7 @@ pub unsafe fn identity_transmutes() {
}
#[custom_mir(dialect = "runtime", phase = "initial")]
-// EMIT_MIR combine_transmutes.integer_transmutes.InstSimplify.diff
+// EMIT_MIR combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
pub unsafe fn integer_transmutes() {
// CHECK-LABEL: fn integer_transmutes(
// CHECK-NOT: _i32 as u32 (Transmute);
@@ -43,7 +43,7 @@ pub unsafe fn integer_transmutes() {
}
}
-// EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify.diff
+// EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
pub unsafe fn adt_transmutes() {
// CHECK-LABEL: fn adt_transmutes(
// CHECK: as u8 (Transmute);
diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify.diff b/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
similarity index 70%
rename from tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify.diff
rename to tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
index e2b45c8..7596aa2 100644
--- a/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `assert_zero` before InstSimplify
-+ // MIR for `assert_zero` after InstSimplify
+- // MIR for `assert_zero` before InstSimplify-after-simplifycfg
++ // MIR for `assert_zero` after InstSimplify-after-simplifycfg
fn assert_zero(_1: u8) -> u8 {
let mut _0: u8;
diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
index a47d9d5..d610ba5f 100644
--- a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
+++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
@@ -1,11 +1,11 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
#![feature(custom_mir, core_intrinsics)]
#![crate_type = "lib"]
use std::intrinsics::mir::*;
-// EMIT_MIR duplicate_switch_targets.assert_zero.InstSimplify.diff
+// EMIT_MIR duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
pub unsafe fn assert_zero(x: u8) -> u8 {
// CHECK-LABEL: fn assert_zero(
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
similarity index 84%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
index 2ecacb5..d35844b 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `generic` before InstSimplify
-+ // MIR for `generic` after InstSimplify
+- // MIR for `generic` before InstSimplify-after-simplifycfg
++ // MIR for `generic` after InstSimplify-after-simplifycfg
fn generic() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
similarity index 70%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
index d29af09..6ddd848 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `generic_ref` before InstSimplify
-+ // MIR for `generic_ref` after InstSimplify
+- // MIR for `generic_ref` before InstSimplify-after-simplifycfg
++ // MIR for `generic_ref` after InstSimplify-after-simplifycfg
fn generic_ref() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
similarity index 87%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
index 1be386a..1b7aa12 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `panics` before InstSimplify
-+ // MIR for `panics` after InstSimplify
+- // MIR for `panics` before InstSimplify-after-simplifycfg
++ // MIR for `panics` after InstSimplify-after-simplifycfg
fn panics() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
similarity index 85%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
index f2e6978..20e046d 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `removable` before InstSimplify
-+ // MIR for `removable` after InstSimplify
+- // MIR for `removable` before InstSimplify-after-simplifycfg
++ // MIR for `removable` after InstSimplify-after-simplifycfg
fn removable() -> () {
let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.rs b/tests/mir-opt/instsimplify/intrinsic_asserts.rs
index c031c97..c71e08b 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.rs
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.rs
@@ -1,10 +1,10 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
#![crate_type = "lib"]
#![feature(core_intrinsics)]
// All these assertions pass, so all the intrinsic calls should be deleted.
-// EMIT_MIR intrinsic_asserts.removable.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
pub fn removable() {
// CHECK-LABEL: fn removable(
// CHECK-NOT: assert_inhabited
@@ -18,7 +18,7 @@ pub fn removable() {
enum Never {}
// These assertions all diverge, so their target blocks should become None.
-// EMIT_MIR intrinsic_asserts.panics.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
pub fn panics() {
// CHECK-LABEL: fn panics(
// CHECK: assert_inhabited::<Never>() -> unwind
@@ -30,7 +30,7 @@ pub fn panics() {
}
// Whether or not these asserts pass isn't known, so they shouldn't be modified.
-// EMIT_MIR intrinsic_asserts.generic.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
pub fn generic<T>() {
// CHECK-LABEL: fn generic(
// CHECK: assert_inhabited::<T>() -> [return:
@@ -42,7 +42,7 @@ pub fn generic<T>() {
}
// Whether or not these asserts pass isn't known, so they shouldn't be modified.
-// EMIT_MIR intrinsic_asserts.generic_ref.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
pub fn generic_ref<T>() {
// CHECK-LABEL: fn generic_ref(
// CHECK: assert_mem_uninitialized_valid::<&T>() -> [return:
diff --git a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
similarity index 91%
rename from tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff
rename to tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
index 52b3d1e..ca26f02 100644
--- a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `pointers` before InstSimplify
-+ // MIR for `pointers` after InstSimplify
+- // MIR for `pointers` before InstSimplify-after-simplifycfg
++ // MIR for `pointers` after InstSimplify-after-simplifycfg
fn pointers(_1: *const [i32], _2: *mut i32) -> () {
debug const_ptr => _1;
diff --git a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff
similarity index 91%
rename from tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff
rename to tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff
index ca0828a..928ee3a 100644
--- a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `references` before InstSimplify
-+ // MIR for `references` after InstSimplify
+- // MIR for `references` before InstSimplify-after-simplifycfg
++ // MIR for `references` after InstSimplify-after-simplifycfg
fn references(_1: &i32, _2: &mut [i32]) -> () {
debug const_ref => _1;
diff --git a/tests/mir-opt/instsimplify/ref_of_deref.rs b/tests/mir-opt/instsimplify/ref_of_deref.rs
index 37e164b..dc0f5f8 100644
--- a/tests/mir-opt/instsimplify/ref_of_deref.rs
+++ b/tests/mir-opt/instsimplify/ref_of_deref.rs
@@ -1,11 +1,11 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
#![crate_type = "lib"]
#![feature(raw_ref_op)]
// For each of these, only 2 of the 6 should simplify,
// as the others have the wrong types.
-// EMIT_MIR ref_of_deref.references.InstSimplify.diff
+// EMIT_MIR ref_of_deref.references.InstSimplify-after-simplifycfg.diff
// CHECK-LABEL: references
pub fn references(const_ref: &i32, mut_ref: &mut [i32]) {
// CHECK: _3 = _1;
@@ -22,7 +22,7 @@ pub fn references(const_ref: &i32, mut_ref: &mut [i32]) {
let _f = &raw mut *mut_ref;
}
-// EMIT_MIR ref_of_deref.pointers.InstSimplify.diff
+// EMIT_MIR ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
// CHECK-LABEL: pointers
pub unsafe fn pointers(const_ptr: *const [i32], mut_ptr: *mut i32) {
// CHECK: _3 = &(*_1);
diff --git a/tests/mir-opt/instsimplify/ub_check.rs b/tests/mir-opt/instsimplify/ub_check.rs
index 5f13f5b..ee72511 100644
--- a/tests/mir-opt/instsimplify/ub_check.rs
+++ b/tests/mir-opt/instsimplify/ub_check.rs
@@ -1,7 +1,7 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
//@ compile-flags: -Cdebug-assertions=no -Zinline-mir
-// EMIT_MIR ub_check.unwrap_unchecked.InstSimplify.diff
+// EMIT_MIR ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
pub fn unwrap_unchecked(x: Option<i32>) -> i32 {
// CHECK-LABEL: fn unwrap_unchecked(
// CHECK-NOT: UbChecks()
diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
similarity index 89%
rename from tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff
rename to tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
index 4d8d658..7ef77e7 100644
--- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `unwrap_unchecked` before InstSimplify
-+ // MIR for `unwrap_unchecked` after InstSimplify
+- // MIR for `unwrap_unchecked` before InstSimplify-after-simplifycfg
++ // MIR for `unwrap_unchecked` after InstSimplify-after-simplifycfg
fn unwrap_unchecked(_1: Option<i32>) -> i32 {
debug x => _1;
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
index 1f88339..861ee1d 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
@@ -5,7 +5,7 @@
debug x => _1;
let mut _0: ();
let _2: &[T];
- let mut _3: &[T; 3];
+ let _3: &[T; 3];
let _4: [T; 3];
let mut _5: usize;
let mut _6: bool;
@@ -23,12 +23,10 @@
}
bb0: {
- StorageLive(_3);
StorageLive(_4);
_4 = [_1, _1, _1];
_3 = &_4;
- _2 = move _3 as &[T] (PointerCoercion(Unsize));
- StorageDead(_3);
+ _2 = _3 as &[T] (PointerCoercion(Unsize));
nop;
nop;
goto -> bb2;
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
index 19a581b..f27be95 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
@@ -5,7 +5,7 @@
debug x => _1;
let mut _0: ();
let _2: &[T];
- let mut _3: &[T; 3];
+ let _3: &[T; 3];
let _4: [T; 3];
let mut _5: usize;
let mut _6: bool;
@@ -23,12 +23,10 @@
}
bb0: {
- StorageLive(_3);
StorageLive(_4);
_4 = [_1, _1, _1];
_3 = &_4;
- _2 = move _3 as &[T] (PointerCoercion(Unsize));
- StorageDead(_3);
+ _2 = _3 as &[T] (PointerCoercion(Unsize));
nop;
nop;
goto -> bb2;
diff --git a/tests/mir-opt/issue_78192.f.InstSimplify.diff b/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff
similarity index 79%
rename from tests/mir-opt/issue_78192.f.InstSimplify.diff
rename to tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff
index 10e3dd2..53957bb 100644
--- a/tests/mir-opt/issue_78192.f.InstSimplify.diff
+++ b/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `f` before InstSimplify
-+ // MIR for `f` after InstSimplify
+- // MIR for `f` before InstSimplify-after-simplifycfg
++ // MIR for `f` after InstSimplify-after-simplifycfg
fn f(_1: &T) -> *const T {
debug a => _1;
@@ -17,8 +17,7 @@
StorageLive(_4);
_4 = &raw const (*_1);
_3 = &_4;
-- _2 = &(*_3);
-+ _2 = _3;
+ _2 = _3;
StorageDead(_3);
_0 = (*_2);
StorageDead(_4);
diff --git a/tests/mir-opt/issue_78192.rs b/tests/mir-opt/issue_78192.rs
index 857b1de..a82f0e3 100644
--- a/tests/mir-opt/issue_78192.rs
+++ b/tests/mir-opt/issue_78192.rs
@@ -9,4 +9,4 @@ fn main() {
f(&2);
}
-// EMIT_MIR issue_78192.f.InstSimplify.diff
+// EMIT_MIR issue_78192.f.InstSimplify-after-simplifycfg.diff
diff --git a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff
index bbbfe90..8009721 100644
--- a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff
+++ b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff
@@ -24,7 +24,7 @@
bb1: {
_4 = discriminant(_1);
- switchInt(move _4) -> [0: bb4, 1: bb5, 2: bb6, 3: bb3, otherwise: bb2];
+ switchInt(move _4) -> [0: bb6, 1: bb5, 2: bb4, 3: bb3, otherwise: bb2];
}
bb2: {
@@ -39,11 +39,11 @@
}
bb4: {
- StorageLive(_5);
- _5 = DFA::B;
- _1 = move _5;
+ StorageLive(_7);
+ _7 = DFA::D;
+ _1 = move _7;
_3 = const ();
- StorageDead(_5);
+ StorageDead(_7);
goto -> bb1;
}
@@ -57,11 +57,11 @@
}
bb6: {
- StorageLive(_7);
- _7 = DFA::D;
- _1 = move _7;
+ StorageLive(_5);
+ _5 = DFA::B;
+ _1 = move _5;
_3 = const ();
- StorageDead(_7);
+ StorageDead(_5);
goto -> bb1;
}
}
diff --git a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff
index bbbfe90..8009721 100644
--- a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff
+++ b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff
@@ -24,7 +24,7 @@
bb1: {
_4 = discriminant(_1);
- switchInt(move _4) -> [0: bb4, 1: bb5, 2: bb6, 3: bb3, otherwise: bb2];
+ switchInt(move _4) -> [0: bb6, 1: bb5, 2: bb4, 3: bb3, otherwise: bb2];
}
bb2: {
@@ -39,11 +39,11 @@
}
bb4: {
- StorageLive(_5);
- _5 = DFA::B;
- _1 = move _5;
+ StorageLive(_7);
+ _7 = DFA::D;
+ _1 = move _7;
_3 = const ();
- StorageDead(_5);
+ StorageDead(_7);
goto -> bb1;
}
@@ -57,11 +57,11 @@
}
bb6: {
- StorageLive(_7);
- _7 = DFA::D;
- _1 = move _7;
+ StorageLive(_5);
+ _5 = DFA::B;
+ _1 = move _5;
_3 = const ();
- StorageDead(_7);
+ StorageDead(_5);
goto -> bb1;
}
}
diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs
index e5d8525..6486a32 100644
--- a/tests/mir-opt/jump_threading.rs
+++ b/tests/mir-opt/jump_threading.rs
@@ -93,19 +93,19 @@ fn dfa() {
// CHECK: {{_.*}} = DFA::A;
// CHECK: goto -> bb1;
// CHECK: bb1: {
- // CHECK: switchInt({{.*}}) -> [0: bb4, 1: bb5, 2: bb6, 3: bb3, otherwise: bb2];
+ // CHECK: switchInt({{.*}}) -> [0: bb6, 1: bb5, 2: bb4, 3: bb3, otherwise: bb2];
// CHECK: bb2: {
// CHECK: unreachable;
// CHECK: bb3: {
// CHECK: return;
// CHECK: bb4: {
- // CHECK: {{_.*}} = DFA::B;
+ // CHECK: {{_.*}} = DFA::D;
// CHECK: goto -> bb1;
// CHECK: bb5: {
// CHECK: {{_.*}} = DFA::C;
// CHECK: goto -> bb1;
// CHECK: bb6: {
- // CHECK: {{_.*}} = DFA::D;
+ // CHECK: {{_.*}} = DFA::B;
// CHECK: goto -> bb1;
let mut state = DFA::A;
loop {
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 4f29e52..3c4a84b 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -33,17 +33,17 @@
bb0: {
PlaceMention(_2);
- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1];
-+ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
++ switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1];
}
bb1: {
- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3];
-+ switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2];
++ switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2];
}
bb2: {
-- falseEdge -> [real: bb8, imaginary: bb1];
-+ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17];
+- falseEdge -> [real: bb9, imaginary: bb1];
++ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4];
}
bb3: {
@@ -51,11 +51,11 @@
- }
-
- bb4: {
-- falseEdge -> [real: bb13, imaginary: bb3];
+- falseEdge -> [real: bb8, imaginary: bb3];
- }
-
- bb5: {
-- falseEdge -> [real: bb20, imaginary: bb6];
+- falseEdge -> [real: bb7, imaginary: bb6];
- }
-
- bb6: {
@@ -63,20 +63,38 @@
_15 = (_2.1: bool);
StorageLive(_16);
_16 = move (_2.2: std::string::String);
-- goto -> bb19;
-+ goto -> bb16;
+- goto -> bb20;
++ goto -> bb17;
}
- bb7: {
+ bb4: {
- _0 = const 1_i32;
-- drop(_7) -> [return: bb18, unwind: bb25];
-+ drop(_7) -> [return: bb15, unwind: bb22];
+ StorageLive(_15);
+ _15 = (_2.1: bool);
+ StorageLive(_16);
+ _16 = move (_2.2: std::string::String);
+- goto -> bb20;
++ goto -> bb17;
}
- bb8: {
+ bb5: {
StorageLive(_6);
+ _6 = &(_2.0: bool);
+ StorageLive(_8);
+ _8 = &(_2.2: std::string::String);
+- _3 = &fake shallow (_2.0: bool);
+- _4 = &fake shallow (_2.1: bool);
+ StorageLive(_12);
+ StorageLive(_13);
+ _13 = _1;
+- switchInt(move _13) -> [0: bb16, otherwise: bb15];
++ switchInt(move _13) -> [0: bb13, otherwise: bb12];
+ }
+
+- bb9: {
++ bb6: {
+ StorageLive(_6);
_6 = &(_2.1: bool);
StorageLive(_8);
_8 = &(_2.2: std::string::String);
@@ -85,12 +103,19 @@
StorageLive(_9);
StorageLive(_10);
_10 = _1;
-- switchInt(move _10) -> [0: bb10, otherwise: bb9];
-+ switchInt(move _10) -> [0: bb7, otherwise: bb6];
+- switchInt(move _10) -> [0: bb12, otherwise: bb11];
++ switchInt(move _10) -> [0: bb9, otherwise: bb8];
}
-- bb9: {
-+ bb6: {
+- bb10: {
++ bb7: {
+ _0 = const 1_i32;
+- drop(_7) -> [return: bb19, unwind: bb25];
++ drop(_7) -> [return: bb16, unwind: bb22];
+ }
+
+- bb11: {
++ bb8: {
_0 = const 3_i32;
StorageDead(_10);
StorageDead(_9);
@@ -98,15 +123,15 @@
+ goto -> bb20;
}
-- bb10: {
-+ bb7: {
+- bb12: {
++ bb9: {
_9 = (*_6);
-- switchInt(move _9) -> [0: bb12, otherwise: bb11];
-+ switchInt(move _9) -> [0: bb9, otherwise: bb8];
+- switchInt(move _9) -> [0: bb14, otherwise: bb13];
++ switchInt(move _9) -> [0: bb11, otherwise: bb10];
}
-- bb11: {
-+ bb8: {
+- bb13: {
++ bb10: {
StorageDead(_10);
StorageDead(_9);
- FakeRead(ForMatchGuard, _3);
@@ -117,12 +142,12 @@
_5 = (_2.1: bool);
StorageLive(_7);
_7 = move (_2.2: std::string::String);
-- goto -> bb7;
-+ goto -> bb4;
+- goto -> bb10;
++ goto -> bb7;
}
-- bb12: {
-+ bb9: {
+- bb14: {
++ bb11: {
StorageDead(_10);
StorageDead(_9);
StorageDead(_8);
@@ -131,23 +156,8 @@
+ goto -> bb1;
}
-- bb13: {
-+ bb10: {
- StorageLive(_6);
- _6 = &(_2.0: bool);
- StorageLive(_8);
- _8 = &(_2.2: std::string::String);
-- _3 = &fake shallow (_2.0: bool);
-- _4 = &fake shallow (_2.1: bool);
- StorageLive(_12);
- StorageLive(_13);
- _13 = _1;
-- switchInt(move _13) -> [0: bb15, otherwise: bb14];
-+ switchInt(move _13) -> [0: bb12, otherwise: bb11];
- }
-
-- bb14: {
-+ bb11: {
+- bb15: {
++ bb12: {
_0 = const 3_i32;
StorageDead(_13);
StorageDead(_12);
@@ -155,15 +165,15 @@
+ goto -> bb20;
}
-- bb15: {
-+ bb12: {
- _12 = (*_6);
-- switchInt(move _12) -> [0: bb17, otherwise: bb16];
-+ switchInt(move _12) -> [0: bb14, otherwise: bb13];
- }
-
- bb16: {
+ bb13: {
+ _12 = (*_6);
+- switchInt(move _12) -> [0: bb18, otherwise: bb17];
++ switchInt(move _12) -> [0: bb15, otherwise: bb14];
+ }
+
+- bb17: {
++ bb14: {
StorageDead(_13);
StorageDead(_12);
- FakeRead(ForMatchGuard, _3);
@@ -174,12 +184,12 @@
_5 = (_2.0: bool);
StorageLive(_7);
_7 = move (_2.2: std::string::String);
-- goto -> bb7;
-+ goto -> bb4;
+- goto -> bb10;
++ goto -> bb7;
}
-- bb17: {
-+ bb14: {
+- bb18: {
++ bb15: {
StorageDead(_13);
StorageDead(_12);
StorageDead(_8);
@@ -188,8 +198,8 @@
+ goto -> bb2;
}
-- bb18: {
-+ bb15: {
+- bb19: {
++ bb16: {
StorageDead(_7);
StorageDead(_5);
StorageDead(_8);
@@ -198,23 +208,13 @@
+ goto -> bb19;
}
-- bb19: {
-+ bb16: {
+- bb20: {
++ bb17: {
_0 = const 2_i32;
- drop(_16) -> [return: bb21, unwind: bb25];
+ drop(_16) -> [return: bb18, unwind: bb22];
}
-- bb20: {
-+ bb17: {
- StorageLive(_15);
- _15 = (_2.1: bool);
- StorageLive(_16);
- _16 = move (_2.2: std::string::String);
-- goto -> bb19;
-+ goto -> bb16;
- }
-
- bb21: {
+ bb18: {
StorageDead(_16);
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 4f29e52..3c4a84b 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -33,17 +33,17 @@
bb0: {
PlaceMention(_2);
- switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1];
-+ switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
++ switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1];
}
bb1: {
- switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3];
-+ switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2];
++ switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2];
}
bb2: {
-- falseEdge -> [real: bb8, imaginary: bb1];
-+ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17];
+- falseEdge -> [real: bb9, imaginary: bb1];
++ switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4];
}
bb3: {
@@ -51,11 +51,11 @@
- }
-
- bb4: {
-- falseEdge -> [real: bb13, imaginary: bb3];
+- falseEdge -> [real: bb8, imaginary: bb3];
- }
-
- bb5: {
-- falseEdge -> [real: bb20, imaginary: bb6];
+- falseEdge -> [real: bb7, imaginary: bb6];
- }
-
- bb6: {
@@ -63,20 +63,38 @@
_15 = (_2.1: bool);
StorageLive(_16);
_16 = move (_2.2: std::string::String);
-- goto -> bb19;
-+ goto -> bb16;
+- goto -> bb20;
++ goto -> bb17;
}
- bb7: {
+ bb4: {
- _0 = const 1_i32;
-- drop(_7) -> [return: bb18, unwind: bb25];
-+ drop(_7) -> [return: bb15, unwind: bb22];
+ StorageLive(_15);
+ _15 = (_2.1: bool);
+ StorageLive(_16);
+ _16 = move (_2.2: std::string::String);
+- goto -> bb20;
++ goto -> bb17;
}
- bb8: {
+ bb5: {
StorageLive(_6);
+ _6 = &(_2.0: bool);
+ StorageLive(_8);
+ _8 = &(_2.2: std::string::String);
+- _3 = &fake shallow (_2.0: bool);
+- _4 = &fake shallow (_2.1: bool);
+ StorageLive(_12);
+ StorageLive(_13);
+ _13 = _1;
+- switchInt(move _13) -> [0: bb16, otherwise: bb15];
++ switchInt(move _13) -> [0: bb13, otherwise: bb12];
+ }
+
+- bb9: {
++ bb6: {
+ StorageLive(_6);
_6 = &(_2.1: bool);
StorageLive(_8);
_8 = &(_2.2: std::string::String);
@@ -85,12 +103,19 @@
StorageLive(_9);
StorageLive(_10);
_10 = _1;
-- switchInt(move _10) -> [0: bb10, otherwise: bb9];
-+ switchInt(move _10) -> [0: bb7, otherwise: bb6];
+- switchInt(move _10) -> [0: bb12, otherwise: bb11];
++ switchInt(move _10) -> [0: bb9, otherwise: bb8];
}
-- bb9: {
-+ bb6: {
+- bb10: {
++ bb7: {
+ _0 = const 1_i32;
+- drop(_7) -> [return: bb19, unwind: bb25];
++ drop(_7) -> [return: bb16, unwind: bb22];
+ }
+
+- bb11: {
++ bb8: {
_0 = const 3_i32;
StorageDead(_10);
StorageDead(_9);
@@ -98,15 +123,15 @@
+ goto -> bb20;
}
-- bb10: {
-+ bb7: {
+- bb12: {
++ bb9: {
_9 = (*_6);
-- switchInt(move _9) -> [0: bb12, otherwise: bb11];
-+ switchInt(move _9) -> [0: bb9, otherwise: bb8];
+- switchInt(move _9) -> [0: bb14, otherwise: bb13];
++ switchInt(move _9) -> [0: bb11, otherwise: bb10];
}
-- bb11: {
-+ bb8: {
+- bb13: {
++ bb10: {
StorageDead(_10);
StorageDead(_9);
- FakeRead(ForMatchGuard, _3);
@@ -117,12 +142,12 @@
_5 = (_2.1: bool);
StorageLive(_7);
_7 = move (_2.2: std::string::String);
-- goto -> bb7;
-+ goto -> bb4;
+- goto -> bb10;
++ goto -> bb7;
}
-- bb12: {
-+ bb9: {
+- bb14: {
++ bb11: {
StorageDead(_10);
StorageDead(_9);
StorageDead(_8);
@@ -131,23 +156,8 @@
+ goto -> bb1;
}
-- bb13: {
-+ bb10: {
- StorageLive(_6);
- _6 = &(_2.0: bool);
- StorageLive(_8);
- _8 = &(_2.2: std::string::String);
-- _3 = &fake shallow (_2.0: bool);
-- _4 = &fake shallow (_2.1: bool);
- StorageLive(_12);
- StorageLive(_13);
- _13 = _1;
-- switchInt(move _13) -> [0: bb15, otherwise: bb14];
-+ switchInt(move _13) -> [0: bb12, otherwise: bb11];
- }
-
-- bb14: {
-+ bb11: {
+- bb15: {
++ bb12: {
_0 = const 3_i32;
StorageDead(_13);
StorageDead(_12);
@@ -155,15 +165,15 @@
+ goto -> bb20;
}
-- bb15: {
-+ bb12: {
- _12 = (*_6);
-- switchInt(move _12) -> [0: bb17, otherwise: bb16];
-+ switchInt(move _12) -> [0: bb14, otherwise: bb13];
- }
-
- bb16: {
+ bb13: {
+ _12 = (*_6);
+- switchInt(move _12) -> [0: bb18, otherwise: bb17];
++ switchInt(move _12) -> [0: bb15, otherwise: bb14];
+ }
+
+- bb17: {
++ bb14: {
StorageDead(_13);
StorageDead(_12);
- FakeRead(ForMatchGuard, _3);
@@ -174,12 +184,12 @@
_5 = (_2.0: bool);
StorageLive(_7);
_7 = move (_2.2: std::string::String);
-- goto -> bb7;
-+ goto -> bb4;
+- goto -> bb10;
++ goto -> bb7;
}
-- bb17: {
-+ bb14: {
+- bb18: {
++ bb15: {
StorageDead(_13);
StorageDead(_12);
StorageDead(_8);
@@ -188,8 +198,8 @@
+ goto -> bb2;
}
-- bb18: {
-+ bb15: {
+- bb19: {
++ bb16: {
StorageDead(_7);
StorageDead(_5);
StorageDead(_8);
@@ -198,23 +208,13 @@
+ goto -> bb19;
}
-- bb19: {
-+ bb16: {
+- bb20: {
++ bb17: {
_0 = const 2_i32;
- drop(_16) -> [return: bb21, unwind: bb25];
+ drop(_16) -> [return: bb18, unwind: bb22];
}
-- bb20: {
-+ bb17: {
- StorageLive(_15);
- _15 = (_2.1: bool);
- StorageLive(_16);
- _16 = move (_2.2: std::string::String);
-- goto -> bb19;
-+ goto -> bb16;
- }
-
- bb21: {
+ bb18: {
StorageDead(_16);
diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
index 1f20349..fc34ce7 100644
--- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
@@ -5,37 +5,42 @@
debug i => _1;
let mut _0: u128;
let mut _2: i128;
++ let mut _3: i128;
bb0: {
_2 = discriminant(_1);
- switchInt(move _2) -> [1: bb3, 2: bb4, 3: bb5, 340282366920938463463374607431768211455: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const core::num::<impl u128>::MAX;
- goto -> bb6;
- }
-
- bb3: {
- _0 = const 1_u128;
- goto -> bb6;
- }
-
- bb4: {
- _0 = const 2_u128;
- goto -> bb6;
- }
-
- bb5: {
- _0 = const 3_u128;
- goto -> bb6;
- }
-
- bb6: {
+- switchInt(move _2) -> [1: bb5, 2: bb4, 3: bb3, 340282366920938463463374607431768211455: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const core::num::<impl u128>::MAX;
+- goto -> bb6;
+- }
+-
+- bb3: {
+- _0 = const 3_u128;
+- goto -> bb6;
+- }
+-
+- bb4: {
+- _0 = const 2_u128;
+- goto -> bb6;
+- }
+-
+- bb5: {
+- _0 = const 1_u128;
+- goto -> bb6;
+- }
+-
+- bb6: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as u128 (IntToInt);
++ StorageDead(_3);
return;
}
}
diff --git a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff
deleted file mode 100644
index 4b43531..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,37 +0,0 @@
-- // MIR for `match_i16_i8` before MatchBranchSimplification
-+ // MIR for `match_i16_i8` after MatchBranchSimplification
-
- fn match_i16_i8(_1: EnumAi16) -> i8 {
- debug i => _1;
- let mut _0: i8;
- let mut _2: i16;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(move _2) -> [65535: bb3, 2: bb4, 65533: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const -3_i8;
- goto -> bb5;
- }
-
- bb3: {
- _0 = const -1_i8;
- goto -> bb5;
- }
-
- bb4: {
- _0 = const 2_i8;
- goto -> bb5;
- }
-
- bb5: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff
deleted file mode 100644
index 8a39073..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,37 +0,0 @@
-- // MIR for `match_i8_i16` before MatchBranchSimplification
-+ // MIR for `match_i8_i16` after MatchBranchSimplification
-
- fn match_i8_i16(_1: EnumAi8) -> i16 {
- debug i => _1;
- let mut _0: i16;
- let mut _2: i8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const -3_i16;
- goto -> bb5;
- }
-
- bb3: {
- _0 = const -1_i16;
- goto -> bb5;
- }
-
- bb4: {
- _0 = const 2_i16;
- goto -> bb5;
- }
-
- bb5: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff
deleted file mode 100644
index b021779..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,37 +0,0 @@
-- // MIR for `match_i8_i16_failed` before MatchBranchSimplification
-+ // MIR for `match_i8_i16_failed` after MatchBranchSimplification
-
- fn match_i8_i16_failed(_1: EnumAi8) -> i16 {
- debug i => _1;
- let mut _0: i16;
- let mut _2: i8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const 3_i16;
- goto -> bb5;
- }
-
- bb3: {
- _0 = const -1_i16;
- goto -> bb5;
- }
-
- bb4: {
- _0 = const 2_i16;
- goto -> bb5;
- }
-
- bb5: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff
new file mode 100644
index 0000000..7f8c2ab
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff
@@ -0,0 +1,52 @@
+- // MIR for `match_sext_i8_i16` before MatchBranchSimplification
++ // MIR for `match_sext_i8_i16` after MatchBranchSimplification
+
+ fn match_sext_i8_i16(_1: EnumAi8) -> i16 {
+ debug i => _1;
+ let mut _0: i16;
+ let mut _2: i8;
++ let mut _3: i8;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 127_i16;
+- goto -> bb7;
+- }
+-
+- bb3: {
+- _0 = const 1_i16;
+- goto -> bb7;
+- }
+-
+- bb4: {
+- _0 = const 0_i16;
+- goto -> bb7;
+- }
+-
+- bb5: {
+- _0 = const -1_i16;
+- goto -> bb7;
+- }
+-
+- bb6: {
+- _0 = const -128_i16;
+- goto -> bb7;
+- }
+-
+- bb7: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as i16 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..94ec229
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_sext_i8_i16_failed` before MatchBranchSimplification
++ // MIR for `match_sext_i8_i16_failed` after MatchBranchSimplification
+
+ fn match_sext_i8_i16_failed(_1: EnumAi8) -> i16 {
+ debug i => _1;
+ let mut _0: i16;
+ let mut _2: i8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 127_i16;
+ goto -> bb7;
+ }
+
+ bb3: {
+ _0 = const 1_i16;
+ goto -> bb7;
+ }
+
+ bb4: {
+ _0 = const 0_i16;
+ goto -> bb7;
+ }
+
+ bb5: {
+ _0 = const 255_i16;
+ goto -> bb7;
+ }
+
+ bb6: {
+ _0 = const -128_i16;
+ goto -> bb7;
+ }
+
+ bb7: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff
new file mode 100644
index 0000000..86d0d0b
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff
@@ -0,0 +1,52 @@
+- // MIR for `match_sext_i8_u16` before MatchBranchSimplification
++ // MIR for `match_sext_i8_u16` after MatchBranchSimplification
+
+ fn match_sext_i8_u16(_1: EnumAi8) -> u16 {
+ debug i => _1;
+ let mut _0: u16;
+ let mut _2: i8;
++ let mut _3: i8;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 127_u16;
+- goto -> bb7;
+- }
+-
+- bb3: {
+- _0 = const 1_u16;
+- goto -> bb7;
+- }
+-
+- bb4: {
+- _0 = const 0_u16;
+- goto -> bb7;
+- }
+-
+- bb5: {
+- _0 = const u16::MAX;
+- goto -> bb7;
+- }
+-
+- bb6: {
+- _0 = const 65408_u16;
+- goto -> bb7;
+- }
+-
+- bb7: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as u16 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..281f373
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_sext_i8_u16_failed` before MatchBranchSimplification
++ // MIR for `match_sext_i8_u16_failed` after MatchBranchSimplification
+
+ fn match_sext_i8_u16_failed(_1: EnumAi8) -> u16 {
+ debug i => _1;
+ let mut _0: u16;
+ let mut _2: i8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 127_u16;
+ goto -> bb7;
+ }
+
+ bb3: {
+ _0 = const 1_u16;
+ goto -> bb7;
+ }
+
+ bb4: {
+ _0 = const 0_u16;
+ goto -> bb7;
+ }
+
+ bb5: {
+ _0 = const 255_u16;
+ goto -> bb7;
+ }
+
+ bb6: {
+ _0 = const 65408_u16;
+ goto -> bb7;
+ }
+
+ bb7: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff
new file mode 100644
index 0000000..d3d27be
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff
@@ -0,0 +1,77 @@
+- // MIR for `match_trunc_i16_i8` before MatchBranchSimplification
++ // MIR for `match_trunc_i16_i8` after MatchBranchSimplification
+
+ fn match_trunc_i16_i8(_1: EnumAi16) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: i16;
++ let mut _3: i16;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const i8::MAX;
+- goto -> bb12;
+- }
+-
+- bb3: {
+- _0 = const 1_i8;
+- goto -> bb12;
+- }
+-
+- bb4: {
+- _0 = const 0_i8;
+- goto -> bb12;
+- }
+-
+- bb5: {
+- _0 = const -1_i8;
+- goto -> bb12;
+- }
+-
+- bb6: {
+- _0 = const i8::MIN;
+- goto -> bb12;
+- }
+-
+- bb7: {
+- _0 = const i8::MAX;
+- goto -> bb12;
+- }
+-
+- bb8: {
+- _0 = const 1_i8;
+- goto -> bb12;
+- }
+-
+- bb9: {
+- _0 = const 0_i8;
+- goto -> bb12;
+- }
+-
+- bb10: {
+- _0 = const -1_i8;
+- goto -> bb12;
+- }
+-
+- bb11: {
+- _0 = const i8::MIN;
+- goto -> bb12;
+- }
+-
+- bb12: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as i8 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..7f663ba
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff
@@ -0,0 +1,72 @@
+- // MIR for `match_trunc_i16_i8_failed` before MatchBranchSimplification
++ // MIR for `match_trunc_i16_i8_failed` after MatchBranchSimplification
+
+ fn match_trunc_i16_i8_failed(_1: EnumAi16) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: i16;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const -127_i8;
+ goto -> bb12;
+ }
+
+ bb3: {
+ _0 = const 1_i8;
+ goto -> bb12;
+ }
+
+ bb4: {
+ _0 = const 0_i8;
+ goto -> bb12;
+ }
+
+ bb5: {
+ _0 = const -1_i8;
+ goto -> bb12;
+ }
+
+ bb6: {
+ _0 = const i8::MIN;
+ goto -> bb12;
+ }
+
+ bb7: {
+ _0 = const i8::MAX;
+ goto -> bb12;
+ }
+
+ bb8: {
+ _0 = const 1_i8;
+ goto -> bb12;
+ }
+
+ bb9: {
+ _0 = const 0_i8;
+ goto -> bb12;
+ }
+
+ bb10: {
+ _0 = const -1_i8;
+ goto -> bb12;
+ }
+
+ bb11: {
+ _0 = const i8::MIN;
+ goto -> bb12;
+ }
+
+ bb12: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff
new file mode 100644
index 0000000..5fe8991
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff
@@ -0,0 +1,77 @@
+- // MIR for `match_trunc_i16_u8` before MatchBranchSimplification
++ // MIR for `match_trunc_i16_u8` after MatchBranchSimplification
+
+ fn match_trunc_i16_u8(_1: EnumAi16) -> u8 {
+ debug i => _1;
+ let mut _0: u8;
+ let mut _2: i16;
++ let mut _3: i16;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 127_u8;
+- goto -> bb12;
+- }
+-
+- bb3: {
+- _0 = const 1_u8;
+- goto -> bb12;
+- }
+-
+- bb4: {
+- _0 = const 0_u8;
+- goto -> bb12;
+- }
+-
+- bb5: {
+- _0 = const u8::MAX;
+- goto -> bb12;
+- }
+-
+- bb6: {
+- _0 = const 128_u8;
+- goto -> bb12;
+- }
+-
+- bb7: {
+- _0 = const 127_u8;
+- goto -> bb12;
+- }
+-
+- bb8: {
+- _0 = const 1_u8;
+- goto -> bb12;
+- }
+-
+- bb9: {
+- _0 = const 0_u8;
+- goto -> bb12;
+- }
+-
+- bb10: {
+- _0 = const u8::MAX;
+- goto -> bb12;
+- }
+-
+- bb11: {
+- _0 = const 128_u8;
+- goto -> bb12;
+- }
+-
+- bb12: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as u8 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..1c0ffb3
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff
@@ -0,0 +1,72 @@
+- // MIR for `match_trunc_i16_u8_failed` before MatchBranchSimplification
++ // MIR for `match_trunc_i16_u8_failed` after MatchBranchSimplification
+
+ fn match_trunc_i16_u8_failed(_1: EnumAi16) -> u8 {
+ debug i => _1;
+ let mut _0: u8;
+ let mut _2: i16;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const -127_i8 as u8 (IntToInt);
+ goto -> bb12;
+ }
+
+ bb3: {
+ _0 = const 1_u8;
+ goto -> bb12;
+ }
+
+ bb4: {
+ _0 = const 0_u8;
+ goto -> bb12;
+ }
+
+ bb5: {
+ _0 = const u8::MAX;
+ goto -> bb12;
+ }
+
+ bb6: {
+ _0 = const 128_u8;
+ goto -> bb12;
+ }
+
+ bb7: {
+ _0 = const 127_u8;
+ goto -> bb12;
+ }
+
+ bb8: {
+ _0 = const 1_u8;
+ goto -> bb12;
+ }
+
+ bb9: {
+ _0 = const 0_u8;
+ goto -> bb12;
+ }
+
+ bb10: {
+ _0 = const u8::MAX;
+ goto -> bb12;
+ }
+
+ bb11: {
+ _0 = const 128_u8;
+ goto -> bb12;
+ }
+
+ bb12: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff
new file mode 100644
index 0000000..85f97a1
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff
@@ -0,0 +1,67 @@
+- // MIR for `match_trunc_u16_i8` before MatchBranchSimplification
++ // MIR for `match_trunc_u16_i8` after MatchBranchSimplification
+
+ fn match_trunc_u16_i8(_1: EnumAu16) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: u16;
++ let mut _3: u16;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const -1_i8;
+- goto -> bb10;
+- }
+-
+- bb3: {
+- _0 = const i8::MIN;
+- goto -> bb10;
+- }
+-
+- bb4: {
+- _0 = const i8::MAX;
+- goto -> bb10;
+- }
+-
+- bb5: {
+- _0 = const 0_i8;
+- goto -> bb10;
+- }
+-
+- bb6: {
+- _0 = const -1_i8;
+- goto -> bb10;
+- }
+-
+- bb7: {
+- _0 = const i8::MIN;
+- goto -> bb10;
+- }
+-
+- bb8: {
+- _0 = const i8::MAX;
+- goto -> bb10;
+- }
+-
+- bb9: {
+- _0 = const 0_i8;
+- goto -> bb10;
+- }
+-
+- bb10: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as i8 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..cf6c86a
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff
@@ -0,0 +1,62 @@
+- // MIR for `match_trunc_u16_i8_failed` before MatchBranchSimplification
++ // MIR for `match_trunc_u16_i8_failed` after MatchBranchSimplification
+
+ fn match_trunc_u16_i8_failed(_1: EnumAu16) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: u16;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 1_i8;
+ goto -> bb10;
+ }
+
+ bb3: {
+ _0 = const i8::MIN;
+ goto -> bb10;
+ }
+
+ bb4: {
+ _0 = const i8::MAX;
+ goto -> bb10;
+ }
+
+ bb5: {
+ _0 = const 0_i8;
+ goto -> bb10;
+ }
+
+ bb6: {
+ _0 = const -1_i8;
+ goto -> bb10;
+ }
+
+ bb7: {
+ _0 = const i8::MIN;
+ goto -> bb10;
+ }
+
+ bb8: {
+ _0 = const i8::MAX;
+ goto -> bb10;
+ }
+
+ bb9: {
+ _0 = const 0_i8;
+ goto -> bb10;
+ }
+
+ bb10: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff
new file mode 100644
index 0000000..768d838
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff
@@ -0,0 +1,67 @@
+- // MIR for `match_trunc_u16_u8` before MatchBranchSimplification
++ // MIR for `match_trunc_u16_u8` after MatchBranchSimplification
+
+ fn match_trunc_u16_u8(_1: EnumAu16) -> u8 {
+ debug i => _1;
+ let mut _0: u8;
+ let mut _2: u16;
++ let mut _3: u16;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const u8::MAX;
+- goto -> bb10;
+- }
+-
+- bb3: {
+- _0 = const 128_u8;
+- goto -> bb10;
+- }
+-
+- bb4: {
+- _0 = const 127_u8;
+- goto -> bb10;
+- }
+-
+- bb5: {
+- _0 = const 0_u8;
+- goto -> bb10;
+- }
+-
+- bb6: {
+- _0 = const u8::MAX;
+- goto -> bb10;
+- }
+-
+- bb7: {
+- _0 = const 128_u8;
+- goto -> bb10;
+- }
+-
+- bb8: {
+- _0 = const 127_u8;
+- goto -> bb10;
+- }
+-
+- bb9: {
+- _0 = const 0_u8;
+- goto -> bb10;
+- }
+-
+- bb10: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as u8 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..109e97b
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff
@@ -0,0 +1,62 @@
+- // MIR for `match_trunc_u16_u8_failed` before MatchBranchSimplification
++ // MIR for `match_trunc_u16_u8_failed` after MatchBranchSimplification
+
+ fn match_trunc_u16_u8_failed(_1: EnumAu16) -> u8 {
+ debug i => _1;
+ let mut _0: u8;
+ let mut _2: u16;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 127_u8;
+ goto -> bb10;
+ }
+
+ bb3: {
+ _0 = const 128_u8;
+ goto -> bb10;
+ }
+
+ bb4: {
+ _0 = const 127_u8;
+ goto -> bb10;
+ }
+
+ bb5: {
+ _0 = const 0_u8;
+ goto -> bb10;
+ }
+
+ bb6: {
+ _0 = const u8::MAX;
+ goto -> bb10;
+ }
+
+ bb7: {
+ _0 = const 128_u8;
+ goto -> bb10;
+ }
+
+ bb8: {
+ _0 = const 127_u8;
+ goto -> bb10;
+ }
+
+ bb9: {
+ _0 = const 0_u8;
+ goto -> bb10;
+ }
+
+ bb10: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff
deleted file mode 100644
index 72ad609..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,32 +0,0 @@
-- // MIR for `match_u8_i16` before MatchBranchSimplification
-+ // MIR for `match_u8_i16` after MatchBranchSimplification
-
- fn match_u8_i16(_1: EnumAu8) -> i16 {
- debug i => _1;
- let mut _0: i16;
- let mut _2: u8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const 2_i16;
- goto -> bb4;
- }
-
- bb3: {
- _0 = const 1_i16;
- goto -> bb4;
- }
-
- bb4: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff
deleted file mode 100644
index 3333cd7..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-- // MIR for `match_u8_i16_2` before MatchBranchSimplification
-+ // MIR for `match_u8_i16_2` after MatchBranchSimplification
-
- fn match_u8_i16_2(_1: EnumAu8) -> i16 {
- let mut _0: i16;
- let mut _2: u8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(_2) -> [1: bb3, 2: bb1, otherwise: bb2];
- }
-
- bb1: {
- _0 = const 2_i16;
- goto -> bb3;
- }
-
- bb2: {
- unreachable;
- }
-
- bb3: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff
deleted file mode 100644
index 6da19e4..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,32 +0,0 @@
-- // MIR for `match_u8_i16_failed` before MatchBranchSimplification
-+ // MIR for `match_u8_i16_failed` after MatchBranchSimplification
-
- fn match_u8_i16_failed(_1: EnumAu8) -> i16 {
- debug i => _1;
- let mut _0: i16;
- let mut _2: u8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const 3_i16;
- goto -> bb4;
- }
-
- bb3: {
- _0 = const 1_i16;
- goto -> bb4;
- }
-
- bb4: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff
deleted file mode 100644
index 8fa497f..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,31 +0,0 @@
-- // MIR for `match_u8_i16_fallback` before MatchBranchSimplification
-+ // MIR for `match_u8_i16_fallback` after MatchBranchSimplification
-
- fn match_u8_i16_fallback(_1: u8) -> i16 {
- debug i => _1;
- let mut _0: i16;
-
- bb0: {
- switchInt(_1) -> [1: bb2, 2: bb3, otherwise: bb1];
- }
-
- bb1: {
- _0 = const 3_i16;
- goto -> bb4;
- }
-
- bb2: {
- _0 = const 1_i16;
- goto -> bb4;
- }
-
- bb3: {
- _0 = const 2_i16;
- goto -> bb4;
- }
-
- bb4: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff
new file mode 100644
index 0000000..d63eed7
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_u8_i8` before MatchBranchSimplification
++ // MIR for `match_u8_i8` after MatchBranchSimplification
+
+ fn match_u8_i8(_1: EnumAu8) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: u8;
++ let mut _3: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const -1_i8;
+- goto -> bb6;
+- }
+-
+- bb3: {
+- _0 = const i8::MIN;
+- goto -> bb6;
+- }
+-
+- bb4: {
+- _0 = const i8::MAX;
+- goto -> bb6;
+- }
+-
+- bb5: {
+- _0 = const 0_i8;
+- goto -> bb6;
+- }
+-
+- bb6: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as i8 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff
new file mode 100644
index 0000000..98dee18
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff
@@ -0,0 +1,80 @@
+- // MIR for `match_u8_i8_2` before MatchBranchSimplification
++ // MIR for `match_u8_i8_2` after MatchBranchSimplification
+
+ fn match_u8_i8_2(_1: EnumAu8) -> (i8, i8) {
+ debug i => _1;
+ let mut _0: (i8, i8);
+ let _2: i8;
+ let _4: ();
+ let mut _5: u8;
+ let mut _6: i8;
+ let mut _7: i8;
++ let mut _8: u8;
+ scope 1 {
+ debug a => _2;
+ let _3: i8;
+ scope 2 {
+ debug b => _3;
+ }
+ }
+
+ bb0: {
+ StorageLive(_2);
+ StorageLive(_3);
+ StorageLive(_4);
+ _5 = discriminant(_1);
+- switchInt(move _5) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _2 = const -1_i8;
+- _3 = const -1_i8;
++ StorageLive(_8);
++ _8 = move _5;
++ _2 = _8 as i8 (IntToInt);
++ _3 = _8 as i8 (IntToInt);
+ _4 = ();
+- goto -> bb6;
+- }
+-
+- bb3: {
+- _2 = const i8::MIN;
+- _3 = const i8::MIN;
+- _4 = ();
+- goto -> bb6;
+- }
+-
+- bb4: {
+- _2 = const i8::MAX;
+- _3 = const i8::MAX;
+- _4 = ();
+- goto -> bb6;
+- }
+-
+- bb5: {
+- _2 = const 0_i8;
+- _3 = const 0_i8;
+- _4 = ();
+- goto -> bb6;
+- }
+-
+- bb6: {
++ StorageDead(_8);
+ StorageDead(_4);
+ StorageLive(_6);
+ _6 = _2;
+ StorageLive(_7);
+ _7 = _3;
+ _0 = (move _6, move _7);
+ StorageDead(_7);
+ StorageDead(_6);
+ StorageDead(_3);
+ StorageDead(_2);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..901dda5
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff
@@ -0,0 +1,74 @@
+- // MIR for `match_u8_i8_2_failed` before MatchBranchSimplification
++ // MIR for `match_u8_i8_2_failed` after MatchBranchSimplification
+
+ fn match_u8_i8_2_failed(_1: EnumAu8) -> (i8, i8) {
+ debug i => _1;
+ let mut _0: (i8, i8);
+ let _2: i8;
+ let _4: ();
+ let mut _5: u8;
+ let mut _6: i8;
+ let mut _7: i8;
+ scope 1 {
+ debug a => _2;
+ let _3: i8;
+ scope 2 {
+ debug b => _3;
+ }
+ }
+
+ bb0: {
+ StorageLive(_2);
+ StorageLive(_3);
+ StorageLive(_4);
+ _5 = discriminant(_1);
+ switchInt(move _5) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _2 = const -1_i8;
+ _3 = const 1_i8;
+ _4 = ();
+ goto -> bb6;
+ }
+
+ bb3: {
+ _2 = const i8::MIN;
+ _3 = const i8::MIN;
+ _4 = ();
+ goto -> bb6;
+ }
+
+ bb4: {
+ _2 = const i8::MAX;
+ _3 = const i8::MAX;
+ _4 = ();
+ goto -> bb6;
+ }
+
+ bb5: {
+ _2 = const 0_i8;
+ _3 = const 0_i8;
+ _4 = ();
+ goto -> bb6;
+ }
+
+ bb6: {
+ StorageDead(_4);
+ StorageLive(_6);
+ _6 = _2;
+ StorageLive(_7);
+ _7 = _3;
+ _0 = (move _6, move _7);
+ StorageDead(_7);
+ StorageDead(_6);
+ StorageDead(_3);
+ StorageDead(_2);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..ac96be5
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff
@@ -0,0 +1,42 @@
+- // MIR for `match_u8_i8_failed` before MatchBranchSimplification
++ // MIR for `match_u8_i8_failed` after MatchBranchSimplification
+
+ fn match_u8_i8_failed(_1: EnumAu8) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 1_i8;
+ goto -> bb6;
+ }
+
+ bb3: {
+ _0 = const i8::MIN;
+ goto -> bb6;
+ }
+
+ bb4: {
+ _0 = const i8::MAX;
+ goto -> bb6;
+ }
+
+ bb5: {
+ _0 = const 0_i8;
+ goto -> bb6;
+ }
+
+ bb6: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff
new file mode 100644
index 0000000..9ebf2cf
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff
@@ -0,0 +1,42 @@
+- // MIR for `match_u8_i8_failed_len_1` before MatchBranchSimplification
++ // MIR for `match_u8_i8_failed_len_1` after MatchBranchSimplification
+
+ fn match_u8_i8_failed_len_1(_1: EnumAu8) -> i8 {
+ let mut _0: i8;
+ let mut _2: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5];
+ }
+
+ bb1: {
+ _0 = const 0_i8;
+ goto -> bb6;
+ }
+
+ bb2: {
+ _0 = const i8::MAX;
+ _0 = const i8::MAX;
+ goto -> bb6;
+ }
+
+ bb3: {
+ _0 = const i8::MIN;
+ goto -> bb6;
+ }
+
+ bb4: {
+ _0 = const -1_i8;
+ goto -> bb6;
+ }
+
+ bb5: {
+ unreachable;
+ }
+
+ bb6: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff
new file mode 100644
index 0000000..5548567
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff
@@ -0,0 +1,42 @@
+- // MIR for `match_u8_i8_failed_len_2` before MatchBranchSimplification
++ // MIR for `match_u8_i8_failed_len_2` after MatchBranchSimplification
+
+ fn match_u8_i8_failed_len_2(_1: EnumAu8) -> i8 {
+ let mut _0: i8;
+ let mut _2: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5];
+ }
+
+ bb1: {
+ _0 = const 0_i8;
+ goto -> bb6;
+ }
+
+ bb2: {
+ _0 = const i8::MAX;
+ goto -> bb6;
+ }
+
+ bb3: {
+ _0 = const i8::MIN;
+ goto -> bb6;
+ }
+
+ bb4: {
+ _0 = const -1_i8;
+ _0 = const -1_i8;
+ goto -> bb6;
+ }
+
+ bb5: {
+ unreachable;
+ }
+
+ bb6: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff
new file mode 100644
index 0000000..3566550
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff
@@ -0,0 +1,38 @@
+- // MIR for `match_u8_i8_fallback` before MatchBranchSimplification
++ // MIR for `match_u8_i8_fallback` after MatchBranchSimplification
+
+ fn match_u8_i8_fallback(_1: EnumAu8) -> i8 {
+ debug i => _1;
+ let mut _0: i8;
+ let mut _2: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [0: bb4, 127: bb3, 128: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ _0 = const -1_i8;
+ goto -> bb5;
+ }
+
+ bb2: {
+ _0 = const i8::MIN;
+ goto -> bb5;
+ }
+
+ bb3: {
+ _0 = const i8::MAX;
+ goto -> bb5;
+ }
+
+ bb4: {
+ _0 = const 0_i8;
+ goto -> bb5;
+ }
+
+ bb5: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff
deleted file mode 100644
index 043fdb1..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,37 +0,0 @@
-- // MIR for `match_u8_u16` before MatchBranchSimplification
-+ // MIR for `match_u8_u16` after MatchBranchSimplification
-
- fn match_u8_u16(_1: EnumBu8) -> u16 {
- debug i => _1;
- let mut _0: u16;
- let mut _2: u8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(move _2) -> [1: bb3, 2: bb4, 5: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const 5_u16;
- goto -> bb5;
- }
-
- bb3: {
- _0 = const 1_u16;
- goto -> bb5;
- }
-
- bb4: {
- _0 = const 2_u16;
- goto -> bb5;
- }
-
- bb5: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff
deleted file mode 100644
index b47de6a..0000000
--- a/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff
+++ /dev/null
@@ -1,37 +0,0 @@
-- // MIR for `match_u8_u16_2` before MatchBranchSimplification
-+ // MIR for `match_u8_u16_2` after MatchBranchSimplification
-
- fn match_u8_u16_2(_1: EnumBu8) -> i16 {
- let mut _0: i16;
- let mut _2: u8;
-
- bb0: {
- _2 = discriminant(_1);
- switchInt(_2) -> [1: bb1, 2: bb2, 5: bb3, otherwise: bb4];
- }
-
- bb1: {
- _0 = const 1_i16;
- goto -> bb5;
- }
-
- bb2: {
- _0 = const 2_i16;
- goto -> bb5;
- }
-
- bb3: {
- _0 = const 5_i16;
- _0 = const 5_i16;
- goto -> bb5;
- }
-
- bb4: {
- unreachable;
- }
-
- bb5: {
- return;
- }
- }
-
diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff
new file mode 100644
index 0000000..e00a604
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_zext_u8_i16` before MatchBranchSimplification
++ // MIR for `match_zext_u8_i16` after MatchBranchSimplification
+
+ fn match_zext_u8_i16(_1: EnumAu8) -> i16 {
+ debug i => _1;
+ let mut _0: i16;
+ let mut _2: u8;
++ let mut _3: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 255_i16;
+- goto -> bb6;
+- }
+-
+- bb3: {
+- _0 = const 128_i16;
+- goto -> bb6;
+- }
+-
+- bb4: {
+- _0 = const 127_i16;
+- goto -> bb6;
+- }
+-
+- bb5: {
+- _0 = const 0_i16;
+- goto -> bb6;
+- }
+-
+- bb6: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as i16 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..a19cd79
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff
@@ -0,0 +1,42 @@
+- // MIR for `match_zext_u8_i16_failed` before MatchBranchSimplification
++ // MIR for `match_zext_u8_i16_failed` after MatchBranchSimplification
+
+ fn match_zext_u8_i16_failed(_1: EnumAu8) -> i16 {
+ debug i => _1;
+ let mut _0: i16;
+ let mut _2: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 255_i16;
+ goto -> bb6;
+ }
+
+ bb3: {
+ _0 = const 128_i16;
+ goto -> bb6;
+ }
+
+ bb4: {
+ _0 = const -127_i16;
+ goto -> bb6;
+ }
+
+ bb5: {
+ _0 = const 0_i16;
+ goto -> bb6;
+ }
+
+ bb6: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff
new file mode 100644
index 0000000..befb911
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff
@@ -0,0 +1,47 @@
+- // MIR for `match_zext_u8_u16` before MatchBranchSimplification
++ // MIR for `match_zext_u8_u16` after MatchBranchSimplification
+
+ fn match_zext_u8_u16(_1: EnumAu8) -> u16 {
+ debug i => _1;
+ let mut _0: u16;
+ let mut _2: u8;
++ let mut _3: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 255_u16;
+- goto -> bb6;
+- }
+-
+- bb3: {
+- _0 = const 128_u16;
+- goto -> bb6;
+- }
+-
+- bb4: {
+- _0 = const 127_u16;
+- goto -> bb6;
+- }
+-
+- bb5: {
+- _0 = const 0_u16;
+- goto -> bb6;
+- }
+-
+- bb6: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as u16 (IntToInt);
++ StorageDead(_3);
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff
new file mode 100644
index 0000000..f781f88
--- /dev/null
+++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff
@@ -0,0 +1,42 @@
+- // MIR for `match_zext_u8_u16_failed` before MatchBranchSimplification
++ // MIR for `match_zext_u8_u16_failed` after MatchBranchSimplification
+
+ fn match_zext_u8_u16_failed(_1: EnumAu8) -> u16 {
+ debug i => _1;
+ let mut _0: u16;
+ let mut _2: u8;
+
+ bb0: {
+ _2 = discriminant(_1);
+ switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1];
+ }
+
+ bb1: {
+ unreachable;
+ }
+
+ bb2: {
+ _0 = const 255_u16;
+ goto -> bb6;
+ }
+
+ bb3: {
+ _0 = const 128_u16;
+ goto -> bb6;
+ }
+
+ bb4: {
+ _0 = const 65407_u16;
+ goto -> bb6;
+ }
+
+ bb5: {
+ _0 = const 0_u16;
+ goto -> bb6;
+ }
+
+ bb6: {
+ return;
+ }
+ }
+
diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs
index 176d68b..6787e58 100644
--- a/tests/mir-opt/matches_reduce_branches.rs
+++ b/tests/mir-opt/matches_reduce_branches.rs
@@ -3,6 +3,7 @@
#![feature(repr128)]
#![feature(core_intrinsics)]
#![feature(custom_mir)]
+#![allow(non_camel_case_types)]
use std::intrinsics::mir::*;
@@ -12,6 +13,7 @@ fn foo(bar: Option<()>) {
// CHECK: = Eq(
// CHECK: switchInt
// CHECK-NOT: switchInt
+ // CHECK: return
if matches!(bar, None) {
()
}
@@ -23,6 +25,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) {
// CHECK: = Ne(
// CHECK: = Eq(
// CHECK-NOT: switchInt
+ // CHECK: return
let a;
let b;
let c;
@@ -52,6 +55,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) {
fn match_nested_if() -> bool {
// CHECK-LABEL: fn match_nested_if(
// CHECK-NOT: switchInt
+ // CHECK: return
let val = match () {
() if if if if true { true } else { false } { true } else { false } {
true
@@ -66,174 +70,528 @@ fn match_nested_if() -> bool {
val
}
+// # Fold switchInt into IntToInt.
+// To simplify writing and checking these test cases, I use the first character of
+// each case to distinguish the sign of the number:
+// 'u' for unsigned, '_' for negative, and 'o' for non-negative.
+// Followed by a decimal number, and add the corresponding radix representation.
+// For example, o127_0x7f represents 127i8, and _1_0xff represents -1i8.
+
+// ## Cast but without numeric conversion.
+
#[repr(u8)]
enum EnumAu8 {
- A = 1,
- B = 2,
-}
-
-// EMIT_MIR matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff
-fn match_u8_i16(i: EnumAu8) -> i16 {
- // CHECK-LABEL: fn match_u8_i16(
- // CHECK: switchInt
- match i {
- EnumAu8::A => 1,
- EnumAu8::B => 2,
- }
-}
-
-// EMIT_MIR matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff
-// Check for different instruction lengths
-#[custom_mir(dialect = "built")]
-fn match_u8_i16_2(i: EnumAu8) -> i16 {
- // CHECK-LABEL: fn match_u8_i16_2(
- // CHECK: switchInt
- mir! {
- {
- let a = Discriminant(i);
- match a {
- 1 => bb1,
- 2 => bb2,
- _ => unreachable_bb,
- }
- }
- bb1 = {
- Goto(ret)
- }
- bb2 = {
- RET = 2;
- Goto(ret)
- }
- unreachable_bb = {
- Unreachable()
- }
- ret = {
- Return()
- }
- }
-}
-
-// EMIT_MIR matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff
-fn match_u8_i16_failed(i: EnumAu8) -> i16 {
- // CHECK-LABEL: fn match_u8_i16_failed(
- // CHECK: switchInt
- match i {
- EnumAu8::A => 1,
- EnumAu8::B => 3,
- }
-}
-
-// EMIT_MIR matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff
-fn match_u8_i16_fallback(i: u8) -> i16 {
- // CHECK-LABEL: fn match_u8_i16_fallback(
- // CHECK: switchInt
- match i {
- 1 => 1,
- 2 => 2,
- _ => 3,
- }
-}
-
-#[repr(u8)]
-enum EnumBu8 {
- A = 1,
- B = 2,
- C = 5,
-}
-
-// EMIT_MIR matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff
-fn match_u8_u16(i: EnumBu8) -> u16 {
- // CHECK-LABEL: fn match_u8_u16(
- // CHECK: switchInt
- match i {
- EnumBu8::A => 1,
- EnumBu8::B => 2,
- EnumBu8::C => 5,
- }
-}
-
-// EMIT_MIR matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff
-// Check for different instruction lengths
-#[custom_mir(dialect = "built")]
-fn match_u8_u16_2(i: EnumBu8) -> i16 {
- // CHECK-LABEL: fn match_u8_u16_2(
- // CHECK: switchInt
- mir! {
- {
- let a = Discriminant(i);
- match a {
- 1 => bb1,
- 2 => bb2,
- 5 => bb5,
- _ => unreachable_bb,
- }
- }
- bb1 = {
- RET = 1;
- Goto(ret)
- }
- bb2 = {
- RET = 2;
- Goto(ret)
- }
- bb5 = {
- RET = 5;
- RET = 5;
- Goto(ret)
- }
- unreachable_bb = {
- Unreachable()
- }
- ret = {
- Return()
- }
- }
+ u0_0x00 = 0,
+ u127_0x7f = 127,
+ u128_0x80 = 128,
+ u255_0xff = 255,
}
#[repr(i8)]
enum EnumAi8 {
- A = -1,
- B = 2,
- C = -3,
+ _128_0x80 = -128,
+ _1_0xff = -1,
+ o0_0x00 = 0,
+ o1_0x01 = 1,
+ o127_0x7f = 127,
}
-// EMIT_MIR matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff
-fn match_i8_i16(i: EnumAi8) -> i16 {
- // CHECK-LABEL: fn match_i8_i16(
- // CHECK: switchInt
+// EMIT_MIR matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff
+fn match_u8_i8(i: EnumAu8) -> i8 {
+ // CHECK-LABEL: fn match_u8_i8(
+ // CHECK-NOT: switchInt
+ // CHECK: return
match i {
- EnumAi8::A => -1,
- EnumAi8::B => 2,
- EnumAi8::C => -3,
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => 127,
+ EnumAu8::u128_0x80 => -128,
+ EnumAu8::u255_0xff => -1,
}
}
-// EMIT_MIR matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff
-fn match_i8_i16_failed(i: EnumAi8) -> i16 {
- // CHECK-LABEL: fn match_i8_i16_failed(
+// EMIT_MIR matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff
+fn match_u8_i8_failed(i: EnumAu8) -> i8 {
+ // CHECK-LABEL: fn match_u8_i8_failed(
// CHECK: switchInt
+ // CHECK: return
match i {
- EnumAi8::A => -1,
- EnumAi8::B => 2,
- EnumAi8::C => 3,
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => 127,
+ EnumAu8::u128_0x80 => -128,
+ EnumAu8::u255_0xff => 1, // failed
}
}
+// EMIT_MIR matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff
+fn match_u8_i8_2(i: EnumAu8) -> (i8, i8) {
+ // CHECK-LABEL: fn match_u8_i8_2(
+ // CHECK-NOT: switchInt
+ // CHECK: IntToInt
+ // CHECK: IntToInt
+ // CHECK: return
+ let a: i8;
+ let b: i8;
+ match i {
+ EnumAu8::u0_0x00 => {
+ a = 0;
+ b = 0;
+ ()
+ }
+ EnumAu8::u127_0x7f => {
+ a = 127;
+ b = 127;
+ ()
+ }
+ EnumAu8::u128_0x80 => {
+ a = -128;
+ b = -128;
+ ()
+ }
+ EnumAu8::u255_0xff => {
+ a = -1;
+ b = -1;
+ ()
+ }
+ };
+ (a, b)
+}
+
+// EMIT_MIR matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff
+fn match_u8_i8_2_failed(i: EnumAu8) -> (i8, i8) {
+ // CHECK-LABEL: fn match_u8_i8_2_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ let a: i8;
+ let b: i8;
+ match i {
+ EnumAu8::u0_0x00 => {
+ a = 0;
+ b = 0;
+ ()
+ }
+ EnumAu8::u127_0x7f => {
+ a = 127;
+ b = 127;
+ ()
+ }
+ EnumAu8::u128_0x80 => {
+ a = -128;
+ b = -128;
+ ()
+ }
+ EnumAu8::u255_0xff => {
+ a = -1;
+ b = 1; // failed
+ ()
+ }
+ };
+ (a, b)
+}
+
+// EMIT_MIR matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff
+fn match_u8_i8_fallback(i: EnumAu8) -> i8 {
+ // CHECK-LABEL: fn match_u8_i8_fallback(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => 127,
+ EnumAu8::u128_0x80 => -128,
+ _ => -1,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff
+// Check for different instruction lengths
+#[custom_mir(dialect = "built")]
+fn match_u8_i8_failed_len_1(i: EnumAu8) -> i8 {
+ // CHECK-LABEL: fn match_u8_i8_failed_len_1(
+ // CHECK: switchInt
+ // CHECK: return
+ mir! {
+ {
+ let a = Discriminant(i);
+ match a {
+ 0 => bb1,
+ 127 => bb2,
+ 128 => bb3,
+ 255 => bb4,
+ _ => unreachable_bb,
+ }
+ }
+ bb1 = {
+ RET = 0;
+ Goto(ret)
+ }
+ bb2 = {
+ RET = 127;
+ RET = 127;
+ Goto(ret)
+ }
+ bb3 = {
+ RET = -128;
+ Goto(ret)
+ }
+ bb4 = {
+ RET = -1;
+ Goto(ret)
+ }
+ unreachable_bb = {
+ Unreachable()
+ }
+ ret = {
+ Return()
+ }
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff
+// Check for different instruction lengths
+#[custom_mir(dialect = "built")]
+fn match_u8_i8_failed_len_2(i: EnumAu8) -> i8 {
+ // CHECK-LABEL: fn match_u8_i8_failed_len_2(
+ // CHECK: switchInt
+ // CHECK: return
+ mir! {
+ {
+ let a = Discriminant(i);
+ match a {
+ 0 => bb1,
+ 127 => bb2,
+ 128 => bb3,
+ 255 => bb4,
+ _ => unreachable_bb,
+ }
+ }
+ bb1 = {
+ RET = 0;
+ Goto(ret)
+ }
+ bb2 = {
+ RET = 127;
+ Goto(ret)
+ }
+ bb3 = {
+ RET = -128;
+ Goto(ret)
+ }
+ bb4 = {
+ RET = -1;
+ RET = -1;
+ Goto(ret)
+ }
+ unreachable_bb = {
+ Unreachable()
+ }
+ ret = {
+ Return()
+ }
+ }
+}
+
+// ## Cast with sext.
+
+// EMIT_MIR matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff
+fn match_sext_i8_i16(i: EnumAi8) -> i16 {
+ // CHECK-LABEL: fn match_sext_i8_i16(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ EnumAi8::_128_0x80 => -128,
+ EnumAi8::_1_0xff => -1,
+ EnumAi8::o0_0x00 => 0,
+ EnumAi8::o1_0x01 => 1,
+ EnumAi8::o127_0x7f => 127,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff
+// Converting `-1i8` to `255i16` is zext.
+fn match_sext_i8_i16_failed(i: EnumAi8) -> i16 {
+ // CHECK-LABEL: fn match_sext_i8_i16_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ EnumAi8::_128_0x80 => -128,
+ EnumAi8::_1_0xff => 255, // failed
+ EnumAi8::o0_0x00 => 0,
+ EnumAi8::o1_0x01 => 1,
+ EnumAi8::o127_0x7f => 127,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff
+fn match_sext_i8_u16(i: EnumAi8) -> u16 {
+ // CHECK-LABEL: fn match_sext_i8_u16(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ EnumAi8::_128_0x80 => 0xff80,
+ EnumAi8::_1_0xff => 0xffff,
+ EnumAi8::o0_0x00 => 0,
+ EnumAi8::o1_0x01 => 1,
+ EnumAi8::o127_0x7f => 127,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff
+// Converting `-1i8` to `255u16` is zext.
+fn match_sext_i8_u16_failed(i: EnumAi8) -> u16 {
+ // CHECK-LABEL: fn match_sext_i8_u16_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ EnumAi8::_128_0x80 => 0xff80,
+ EnumAi8::_1_0xff => 0x00ff, // failed
+ EnumAi8::o0_0x00 => 0,
+ EnumAi8::o1_0x01 => 1,
+ EnumAi8::o127_0x7f => 127,
+ }
+}
+
+// ## Cast with zext.
+
+// EMIT_MIR matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff
+fn match_zext_u8_u16(i: EnumAu8) -> u16 {
+ // CHECK-LABEL: fn match_zext_u8_u16(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => 0x7f,
+ EnumAu8::u128_0x80 => 128,
+ EnumAu8::u255_0xff => 255,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff
+fn match_zext_u8_u16_failed(i: EnumAu8) -> u16 {
+ // CHECK-LABEL: fn match_zext_u8_u16_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => 0xff7f, // failed
+ EnumAu8::u128_0x80 => 128,
+ EnumAu8::u255_0xff => 255,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff
+fn match_zext_u8_i16(i: EnumAu8) -> i16 {
+ // CHECK-LABEL: fn match_zext_u8_i16(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => 127,
+ EnumAu8::u128_0x80 => 128,
+ EnumAu8::u255_0xff => 255,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff
+fn match_zext_u8_i16_failed(i: EnumAu8) -> i16 {
+ // CHECK-LABEL: fn match_zext_u8_i16_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ EnumAu8::u0_0x00 => 0,
+ EnumAu8::u127_0x7f => -127, // failed
+ EnumAu8::u128_0x80 => 128,
+ EnumAu8::u255_0xff => 255,
+ }
+}
+
+// ## Cast with trunc.
+
+#[repr(u16)]
+enum EnumAu16 {
+ // 0x00nn
+ u0_0x0000 = 0,
+ u127_0x007f = 127,
+ u128_0x0080 = 128,
+ u255_0x00ff = 255,
+ // 0xffnn
+ u65280_0xff00 = 65280,
+ u65407_0xff7f = 65407,
+ u65408_0xff80 = 65408,
+ u65535_0xffff = 65535,
+}
+
#[repr(i16)]
enum EnumAi16 {
- A = -1,
- B = 2,
- C = -3,
+ // 0x00nn
+ o128_0x0080 = 128,
+ o255_0x00ff = 255,
+ o0_0x0000 = 0,
+ o1_0x0001 = 1,
+ o127_0x007f = 127,
+ // 0xffnn
+ _128_0xff80 = -128,
+ _1_0xffff = -1,
+ o0_0xff00 = -256,
+ o1_0xff01 = -255,
+ o127_0xff7f = -129,
}
-// EMIT_MIR matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff
-fn match_i16_i8(i: EnumAi16) -> i8 {
- // CHECK-LABEL: fn match_i16_i8(
- // CHECK: switchInt
+// EMIT_MIR matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff
+fn match_trunc_i16_i8(i: EnumAi16) -> i8 {
+ // CHECK-LABEL: fn match_trunc_i16_i8(
+ // CHECK-NOT: switchInt
+ // CHECK: return
match i {
- EnumAi16::A => -1,
- EnumAi16::B => 2,
- EnumAi16::C => -3,
+ // 0x00nn
+ EnumAi16::o128_0x0080 => -128,
+ EnumAi16::o255_0x00ff => -1,
+ EnumAi16::o0_0x0000 => 0,
+ EnumAi16::o1_0x0001 => 1,
+ EnumAi16::o127_0x007f => 127,
+ // 0xffnn
+ EnumAi16::_128_0xff80 => -128,
+ EnumAi16::_1_0xffff => -1,
+ EnumAi16::o0_0xff00 => 0,
+ EnumAi16::o1_0xff01 => 1,
+ EnumAi16::o127_0xff7f => 127,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff
+fn match_trunc_i16_i8_failed(i: EnumAi16) -> i8 {
+ // CHECK-LABEL: fn match_trunc_i16_i8_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAi16::o128_0x0080 => -128,
+ EnumAi16::o255_0x00ff => -1,
+ EnumAi16::o0_0x0000 => 0,
+ EnumAi16::o1_0x0001 => 1,
+ EnumAi16::o127_0x007f => 127,
+ // 0xffnn
+ EnumAi16::_128_0xff80 => -128,
+ EnumAi16::_1_0xffff => -1,
+ EnumAi16::o0_0xff00 => 0,
+ EnumAi16::o1_0xff01 => 1,
+ EnumAi16::o127_0xff7f => -127, // failed
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff
+fn match_trunc_i16_u8(i: EnumAi16) -> u8 {
+ // CHECK-LABEL: fn match_trunc_i16_u8(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAi16::o128_0x0080 => 128,
+ EnumAi16::o255_0x00ff => 255,
+ EnumAi16::o0_0x0000 => 0,
+ EnumAi16::o1_0x0001 => 1,
+ EnumAi16::o127_0x007f => 127,
+ // 0xffnn
+ EnumAi16::_128_0xff80 => 128,
+ EnumAi16::_1_0xffff => 255,
+ EnumAi16::o0_0xff00 => 0,
+ EnumAi16::o1_0xff01 => 1,
+ EnumAi16::o127_0xff7f => 127,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff
+fn match_trunc_i16_u8_failed(i: EnumAi16) -> u8 {
+ // CHECK-LABEL: fn match_trunc_i16_u8_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAi16::o128_0x0080 => 128,
+ EnumAi16::o255_0x00ff => 255,
+ EnumAi16::o0_0x0000 => 0,
+ EnumAi16::o1_0x0001 => 1,
+ EnumAi16::o127_0x007f => 127,
+ // 0xffnn
+ EnumAi16::_128_0xff80 => 128,
+ EnumAi16::_1_0xffff => 255,
+ EnumAi16::o0_0xff00 => 0,
+ EnumAi16::o1_0xff01 => 1,
+ EnumAi16::o127_0xff7f => -127i8 as u8, // failed
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff
+fn match_trunc_u16_u8(i: EnumAu16) -> u8 {
+ // CHECK-LABEL: fn match_trunc_u16_u8(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAu16::u0_0x0000 => 0,
+ EnumAu16::u127_0x007f => 127,
+ EnumAu16::u128_0x0080 => 128,
+ EnumAu16::u255_0x00ff => 255,
+ // 0xffnn
+ EnumAu16::u65280_0xff00 => 0,
+ EnumAu16::u65407_0xff7f => 127,
+ EnumAu16::u65408_0xff80 => 128,
+ EnumAu16::u65535_0xffff => 255,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff
+fn match_trunc_u16_u8_failed(i: EnumAu16) -> u8 {
+ // CHECK-LABEL: fn match_trunc_u16_u8_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAu16::u0_0x0000 => 0,
+ EnumAu16::u127_0x007f => 127,
+ EnumAu16::u128_0x0080 => 128,
+ EnumAu16::u255_0x00ff => 255,
+ // 0xffnn
+ EnumAu16::u65280_0xff00 => 0,
+ EnumAu16::u65407_0xff7f => 127,
+ EnumAu16::u65408_0xff80 => 128,
+ EnumAu16::u65535_0xffff => 127, // failed
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff
+fn match_trunc_u16_i8(i: EnumAu16) -> i8 {
+ // CHECK-LABEL: fn match_trunc_u16_i8(
+ // CHECK-NOT: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAu16::u0_0x0000 => 0,
+ EnumAu16::u127_0x007f => 127,
+ EnumAu16::u128_0x0080 => -128,
+ EnumAu16::u255_0x00ff => -1,
+ // 0xffnn
+ EnumAu16::u65280_0xff00 => 0,
+ EnumAu16::u65407_0xff7f => 127,
+ EnumAu16::u65408_0xff80 => -128,
+ EnumAu16::u65535_0xffff => -1,
+ }
+}
+
+// EMIT_MIR matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff
+fn match_trunc_u16_i8_failed(i: EnumAu16) -> i8 {
+ // CHECK-LABEL: fn match_trunc_u16_i8_failed(
+ // CHECK: switchInt
+ // CHECK: return
+ match i {
+ // 0x00nn
+ EnumAu16::u0_0x0000 => 0,
+ EnumAu16::u127_0x007f => 127,
+ EnumAu16::u128_0x0080 => -128,
+ EnumAu16::u255_0x00ff => -1,
+ // 0xffnn
+ EnumAu16::u65280_0xff00 => 0,
+ EnumAu16::u65407_0xff7f => 127,
+ EnumAu16::u65408_0xff80 => -128,
+ EnumAu16::u65535_0xffff => 1,
}
}
@@ -248,7 +606,8 @@ enum EnumAi128 {
// EMIT_MIR matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
fn match_i128_u128(i: EnumAi128) -> u128 {
// CHECK-LABEL: fn match_i128_u128(
- // CHECK: switchInt
+ // CHECK-NOT: switchInt
+ // CHECK: return
match i {
EnumAi128::A => 1,
EnumAi128::B => 2,
@@ -262,15 +621,34 @@ fn main() {
let _ = foo(Some(()));
let _ = bar(0);
let _ = match_nested_if();
- let _ = match_u8_i16(EnumAu8::A);
- let _ = match_u8_i16_2(EnumAu8::A);
- let _ = match_u8_i16_failed(EnumAu8::A);
- let _ = match_u8_i16_fallback(1);
- let _ = match_u8_u16(EnumBu8::A);
- let _ = match_u8_u16_2(EnumBu8::A);
- let _ = match_i8_i16(EnumAi8::A);
- let _ = match_i8_i16_failed(EnumAi8::A);
- let _ = match_i8_i16(EnumAi8::A);
- let _ = match_i16_i8(EnumAi16::A);
+
+ let _: i8 = match_u8_i8(EnumAu8::u0_0x00);
+ let _: i8 = match_u8_i8_failed(EnumAu8::u0_0x00);
+ let _: (i8, i8) = match_u8_i8_2(EnumAu8::u0_0x00);
+ let _: (i8, i8) = match_u8_i8_2_failed(EnumAu8::u0_0x00);
+ let _: i8 = match_u8_i8_fallback(EnumAu8::u0_0x00);
+ let _: i8 = match_u8_i8_failed_len_1(EnumAu8::u0_0x00);
+ let _: i8 = match_u8_i8_failed_len_2(EnumAu8::u0_0x00);
+
+ let _: i16 = match_sext_i8_i16(EnumAi8::o0_0x00);
+ let _: i16 = match_sext_i8_i16_failed(EnumAi8::o0_0x00);
+ let _: u16 = match_sext_i8_u16(EnumAi8::o0_0x00);
+ let _: u16 = match_sext_i8_u16_failed(EnumAi8::o0_0x00);
+
+ let _: u16 = match_zext_u8_u16(EnumAu8::u0_0x00);
+ let _: u16 = match_zext_u8_u16_failed(EnumAu8::u0_0x00);
+ let _: i16 = match_zext_u8_i16(EnumAu8::u0_0x00);
+ let _: i16 = match_zext_u8_i16_failed(EnumAu8::u0_0x00);
+
+ let _: i8 = match_trunc_i16_i8(EnumAi16::o0_0x0000);
+ let _: i8 = match_trunc_i16_i8_failed(EnumAi16::o0_0x0000);
+ let _: u8 = match_trunc_i16_u8(EnumAi16::o0_0x0000);
+ let _: u8 = match_trunc_i16_u8_failed(EnumAi16::o0_0x0000);
+
+ let _: i8 = match_trunc_u16_i8(EnumAu16::u0_0x0000);
+ let _: i8 = match_trunc_u16_i8_failed(EnumAu16::u0_0x0000);
+ let _: u8 = match_trunc_u16_u8(EnumAu16::u0_0x0000);
+ let _: u8 = match_trunc_u16_u8_failed(EnumAu16::u0_0x0000);
+
let _ = match_i128_u128(EnumAi128::A);
}
diff --git a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
index 157f9c9..11a18f5 100644
--- a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
@@ -5,27 +5,32 @@
debug e => _1;
let mut _0: u8;
let mut _2: isize;
++ let mut _3: isize;
bb0: {
_2 = discriminant(_1);
- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const 1_u8;
- goto -> bb4;
- }
-
- bb3: {
- _0 = const 0_u8;
- goto -> bb4;
- }
-
- bb4: {
+- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 1_u8;
+- goto -> bb4;
+- }
+-
+- bb3: {
+- _0 = const 0_u8;
+- goto -> bb4;
+- }
+-
+- bb4: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as u8 (IntToInt);
++ StorageDead(_3);
return;
}
}
diff --git a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
index 1908377..809badc 100644
--- a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
@@ -5,27 +5,32 @@
debug e => _1;
let mut _0: i8;
let mut _2: isize;
++ let mut _3: isize;
bb0: {
_2 = discriminant(_1);
- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
- }
-
- bb1: {
- unreachable;
- }
-
- bb2: {
- _0 = const 1_i8;
- goto -> bb4;
- }
-
- bb3: {
- _0 = const 0_i8;
- goto -> bb4;
- }
-
- bb4: {
+- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
+- }
+-
+- bb1: {
+- unreachable;
+- }
+-
+- bb2: {
+- _0 = const 1_i8;
+- goto -> bb4;
+- }
+-
+- bb3: {
+- _0 = const 0_i8;
+- goto -> bb4;
+- }
+-
+- bb4: {
++ StorageLive(_3);
++ _3 = move _2;
++ _0 = _3 as i8 (IntToInt);
++ StorageDead(_3);
return;
}
}
diff --git a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir
index e357e78..6c76a72 100644
--- a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir
@@ -39,7 +39,7 @@
}
bb5: {
- falseEdge -> [real: bb10, imaginary: bb6];
+ falseEdge -> [real: bb12, imaginary: bb6];
}
bb6: {
@@ -47,18 +47,19 @@
}
bb7: {
- falseEdge -> [real: bb12, imaginary: bb8];
+ falseEdge -> [real: bb10, imaginary: bb8];
}
bb8: {
- falseEdge -> [real: bb13, imaginary: bb3];
+ falseEdge -> [real: bb9, imaginary: bb3];
}
bb9: {
- _0 = const ();
- StorageDead(_4);
- StorageDead(_3);
- goto -> bb14;
+ StorageLive(_3);
+ _3 = (_1.0: (i32, i32));
+ StorageLive(_4);
+ _4 = (_1.1: i32);
+ goto -> bb13;
}
bb10: {
@@ -66,7 +67,7 @@
_3 = (_1.0: (i32, i32));
StorageLive(_4);
_4 = (_1.1: i32);
- goto -> bb9;
+ goto -> bb13;
}
bb11: {
@@ -74,7 +75,7 @@
_3 = (_1.0: (i32, i32));
StorageLive(_4);
_4 = (_1.1: i32);
- goto -> bb9;
+ goto -> bb13;
}
bb12: {
@@ -82,15 +83,14 @@
_3 = (_1.0: (i32, i32));
StorageLive(_4);
_4 = (_1.1: i32);
- goto -> bb9;
+ goto -> bb13;
}
bb13: {
- StorageLive(_3);
- _3 = (_1.0: (i32, i32));
- StorageLive(_4);
- _4 = (_1.1: i32);
- goto -> bb9;
+ _0 = const ();
+ StorageDead(_4);
+ StorageDead(_3);
+ goto -> bb14;
}
bb14: {
diff --git a/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir
index eafe95b..8b0ef7b 100644
--- a/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir
@@ -22,7 +22,7 @@
}
bb3: {
- falseEdge -> [real: bb9, imaginary: bb4];
+ falseEdge -> [real: bb12, imaginary: bb4];
}
bb4: {
@@ -30,11 +30,11 @@
}
bb5: {
- falseEdge -> [real: bb10, imaginary: bb6];
+ falseEdge -> [real: bb11, imaginary: bb6];
}
bb6: {
- falseEdge -> [real: bb11, imaginary: bb1];
+ falseEdge -> [real: bb10, imaginary: bb1];
}
bb7: {
@@ -43,26 +43,26 @@
}
bb8: {
- falseEdge -> [real: bb12, imaginary: bb7];
+ falseEdge -> [real: bb9, imaginary: bb7];
}
bb9: {
- _1 = const 1_i32;
+ _1 = const 4_i32;
goto -> bb13;
}
bb10: {
- _1 = const 2_i32;
- goto -> bb13;
- }
-
- bb11: {
_1 = const 3_i32;
goto -> bb13;
}
+ bb11: {
+ _1 = const 2_i32;
+ goto -> bb13;
+ }
+
bb12: {
- _1 = const 4_i32;
+ _1 = const 1_i32;
goto -> bb13;
}
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 465cb1a..30c122d 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -24,7 +24,7 @@
let _13: std::alloc::AllocError;
let mut _14: !;
let mut _15: &dyn std::fmt::Debug;
- let mut _16: &std::alloc::AllocError;
+ let _16: &std::alloc::AllocError;
scope 7 {
}
scope 8 {
@@ -73,34 +73,33 @@
StorageLive(_6);
StorageLive(_7);
_9 = const main::promoted[0];
-- _7 = _9;
-+ _7 = const {ALLOC1<imm>: &std::alloc::Global};
+ _7 = _9;
StorageLive(_8);
- _8 = _1;
- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable];
+ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
-+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
}
bb4: {
StorageDead(_8);
StorageDead(_7);
StorageLive(_12);
+ StorageLive(_16);
_12 = discriminant(_6);
switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
}
bb5: {
StorageLive(_15);
- StorageLive(_16);
_16 = &_13;
- _15 = move _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
- StorageDead(_16);
+ _15 = _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
_14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable;
}
bb6: {
_5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
+ StorageDead(_16);
StorageDead(_12);
StorageDead(_6);
- StorageLive(_17);
@@ -119,11 +118,9 @@
+ nop;
return;
}
- }
++ }
+
+ ALLOC0 (size: 8, align: 4) {
+ 00 00 00 00 __ __ __ __ │ ....░░░░
-+ }
-+
-+ ALLOC1 (size: 0, align: 1) {}
+ }
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
index 4a37c86..9344946 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
@@ -81,13 +81,12 @@
StorageLive(_6);
StorageLive(_7);
_9 = const main::promoted[0];
-- _7 = _9;
-+ _7 = const {ALLOC1<imm>: &std::alloc::Global};
+ _7 = _9;
StorageLive(_8);
- _8 = _1;
- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue];
+ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }};
-+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
}
bb5: {
@@ -95,11 +94,9 @@
StorageDead(_7);
_5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
}
- }
++ }
+
+ ALLOC0 (size: 8, align: 4) {
+ 00 00 00 00 __ __ __ __ │ ....░░░░
-+ }
-+
-+ ALLOC1 (size: 0, align: 1) {}
+ }
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index 925d899..4443595 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -24,7 +24,7 @@
let _13: std::alloc::AllocError;
let mut _14: !;
let mut _15: &dyn std::fmt::Debug;
- let mut _16: &std::alloc::AllocError;
+ let _16: &std::alloc::AllocError;
scope 7 {
}
scope 8 {
@@ -73,34 +73,33 @@
StorageLive(_6);
StorageLive(_7);
_9 = const main::promoted[0];
-- _7 = _9;
-+ _7 = const {ALLOC1<imm>: &std::alloc::Global};
+ _7 = _9;
StorageLive(_8);
- _8 = _1;
- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable];
+ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
-+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable];
}
bb4: {
StorageDead(_8);
StorageDead(_7);
StorageLive(_12);
+ StorageLive(_16);
_12 = discriminant(_6);
switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
}
bb5: {
StorageLive(_15);
- StorageLive(_16);
_16 = &_13;
- _15 = move _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
- StorageDead(_16);
+ _15 = _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
_14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable;
}
bb6: {
_5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
+ StorageDead(_16);
StorageDead(_12);
StorageDead(_6);
- StorageLive(_17);
@@ -119,11 +118,9 @@
+ nop;
return;
}
- }
++ }
+
+ ALLOC0 (size: 16, align: 8) {
+ 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░
-+ }
-+
-+ ALLOC1 (size: 0, align: 1) {}
+ }
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
index ec2e95f..c958480 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
@@ -81,13 +81,12 @@
StorageLive(_6);
StorageLive(_7);
_9 = const main::promoted[0];
-- _7 = _9;
-+ _7 = const {ALLOC1<imm>: &std::alloc::Global};
+ _7 = _9;
StorageLive(_8);
- _8 = _1;
- _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue];
+ _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }};
-+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1<imm>: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue];
}
bb5: {
@@ -95,11 +94,9 @@
StorageDead(_7);
_5 = Result::<NonNull<[u8]>, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue];
}
- }
++ }
+
+ ALLOC0 (size: 16, align: 8) {
+ 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░
-+ }
-+
-+ ALLOC1 (size: 0, align: 1) {}
+ }
diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
index cb29473..e537dd6 100644
--- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
@@ -30,13 +30,11 @@
bb2: {
StorageLive(_5);
- StorageLive(_4);
_4 = &mut _3;
_5 = <std::vec::IntoIter<impl Sized> as Iterator>::next(move _4) -> [return: bb3, unwind: bb9];
}
bb3: {
- StorageDead(_4);
_6 = discriminant(_5);
switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8];
}
diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.rs b/tests/mir-opt/pre-codegen/no_inlined_clone.rs
new file mode 100644
index 0000000..475b230
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/no_inlined_clone.rs
@@ -0,0 +1,12 @@
+#![crate_type = "lib"]
+
+// EMIT_MIR no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
+
+// CHECK-LABEL: ::clone(
+// CHECK-NOT: inlined clone::impls::<impl Clone for {{.*}}>::clone
+// CHECK: return;
+
+#[derive(Clone)]
+struct Foo {
+ a: i32,
+}
diff --git "a/tests/mir-opt/pre-codegen/no_inlined_clone.\173impl\0430\175-clone.PreCodegen.after.mir" "b/tests/mir-opt/pre-codegen/no_inlined_clone.\173impl\0430\175-clone.PreCodegen.after.mir"
new file mode 100644
index 0000000..71898da
--- /dev/null
+++ "b/tests/mir-opt/pre-codegen/no_inlined_clone.\173impl\0430\175-clone.PreCodegen.after.mir"
@@ -0,0 +1,15 @@
+// MIR for `<impl at $DIR/no_inlined_clone.rs:9:10: 9:15>::clone` after PreCodegen
+
+fn <impl at $DIR/no_inlined_clone.rs:9:10: 9:15>::clone(_1: &Foo) -> Foo {
+ debug self => _1;
+ let mut _0: Foo;
+ let mut _2: i32;
+
+ bb0: {
+ StorageLive(_2);
+ _2 = ((*_1).0: i32);
+ _0 = Foo { a: move _2 };
+ StorageDead(_2);
+ return;
+ }
+}
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
index 802bfbb..c01a12e 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
@@ -37,7 +37,7 @@
_4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
StorageLive(_5);
_5 = const 3_usize;
- _6 = Len(_4);
+ _6 = const 6_usize;
_7 = Lt(_5, _6);
assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable];
}
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
index de94a55..64028e4 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
@@ -37,7 +37,7 @@
_4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
StorageLive(_5);
_5 = const 3_usize;
- _6 = Len(_4);
+ _6 = const 6_usize;
_7 = Lt(_5, _6);
assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue];
}
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
index 802bfbb..c01a12e 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
@@ -37,7 +37,7 @@
_4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
StorageLive(_5);
_5 = const 3_usize;
- _6 = Len(_4);
+ _6 = const 6_usize;
_7 = Lt(_5, _6);
assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable];
}
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
index de94a55..64028e4 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
@@ -37,7 +37,7 @@
_4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
StorageLive(_5);
_5 = const 3_usize;
- _6 = Len(_4);
+ _6 = const 6_usize;
_7 = Lt(_5, _6);
assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue];
}
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
index ce79a33..a7fe52d 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
@@ -36,13 +36,11 @@
bb1: {
StorageLive(_7);
- StorageLive(_6);
_6 = &mut _5;
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
}
bb2: {
- StorageDead(_6);
_8 = discriminant(_7);
switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7];
}
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
index 602ecb7..3e2bbcd 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
@@ -36,13 +36,11 @@
bb1: {
StorageLive(_7);
- StorageLive(_6);
_6 = &mut _5;
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
}
bb2: {
- StorageDead(_6);
_8 = discriminant(_7);
switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7];
}
diff --git "a/tests/mir-opt/pre-codegen/slice_filter.variant_a-\173closure\0430\175.PreCodegen.after.mir" "b/tests/mir-opt/pre-codegen/slice_filter.variant_a-\173closure\0430\175.PreCodegen.after.mir"
index dfa1323..e382f74 100644
--- "a/tests/mir-opt/pre-codegen/slice_filter.variant_a-\173closure\0430\175.PreCodegen.after.mir"
+++ "b/tests/mir-opt/pre-codegen/slice_filter.variant_a-\173closure\0430\175.PreCodegen.after.mir"
@@ -32,7 +32,7 @@
debug other => _10;
scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
debug self => _4;
- debug other => _9;
+ debug other => _6;
let mut _11: usize;
let mut _12: usize;
}
@@ -42,7 +42,7 @@
debug other => _16;
scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
debug self => _7;
- debug other => _15;
+ debug other => _5;
let mut _17: usize;
let mut _18: usize;
}
@@ -52,7 +52,7 @@
debug other => _22;
scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
debug self => _6;
- debug other => _21;
+ debug other => _4;
}
}
scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
@@ -60,7 +60,7 @@
debug other => _26;
scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
debug self => _5;
- debug other => _25;
+ debug other => _7;
let mut _27: usize;
let mut _28: usize;
}
@@ -77,7 +77,8 @@
StorageLive(_8);
_8 = &_4;
StorageLive(_10);
- _9 = &((*_3).2: usize);
+ StorageLive(_9);
+ _9 = _6;
_10 = &_9;
_11 = ((*_3).0: usize);
_12 = ((*_3).2: usize);
@@ -86,19 +87,22 @@
}
bb1: {
+ StorageDead(_9);
StorageDead(_10);
StorageDead(_8);
goto -> bb4;
}
bb2: {
+ StorageDead(_9);
StorageDead(_10);
StorageDead(_8);
StorageLive(_19);
StorageLive(_14);
_14 = &_7;
StorageLive(_16);
- _15 = &((*_3).1: usize);
+ StorageLive(_15);
+ _15 = _5;
_16 = &_15;
StorageLive(_17);
_17 = ((*_3).3: usize);
@@ -111,6 +115,7 @@
}
bb3: {
+ StorageDead(_15);
StorageDead(_16);
StorageDead(_14);
goto -> bb4;
@@ -121,13 +126,15 @@
StorageLive(_20);
_20 = &_6;
StorageLive(_22);
- _21 = &((*_3).0: usize);
+ StorageLive(_21);
+ _21 = _4;
_22 = &_21;
_23 = Le(_12, _11);
switchInt(move _23) -> [0: bb5, otherwise: bb6];
}
bb5: {
+ StorageDead(_21);
StorageDead(_22);
StorageDead(_20);
_0 = const false;
@@ -135,12 +142,14 @@
}
bb6: {
+ StorageDead(_21);
StorageDead(_22);
StorageDead(_20);
StorageLive(_24);
_24 = &_5;
StorageLive(_26);
- _25 = &((*_3).3: usize);
+ StorageLive(_25);
+ _25 = _7;
_26 = &_25;
StorageLive(_27);
_27 = ((*_3).1: usize);
@@ -149,6 +158,7 @@
_0 = Le(move _27, move _28);
StorageDead(_28);
StorageDead(_27);
+ StorageDead(_25);
StorageDead(_26);
StorageDead(_24);
goto -> bb7;
@@ -160,6 +170,7 @@
}
bb8: {
+ StorageDead(_15);
StorageDead(_16);
StorageDead(_14);
_0 = const true;
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
index d7f09fa..58e9b45 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
@@ -20,7 +20,7 @@
}
bb0: {
- StorageLive(_7);
+ StorageLive(_8);
StorageLive(_4);
StorageLive(_3);
_3 = PtrMetadata(_1);
@@ -36,7 +36,7 @@
bb2: {
StorageDead(_3);
- StorageLive(_8);
+ StorageLive(_7);
StorageLive(_5);
_5 = &raw mut (*_1);
StorageLive(_6);
@@ -45,14 +45,14 @@
StorageDead(_6);
StorageDead(_5);
_8 = &mut (*_7);
- _0 = Option::<&mut u32>::Some(move _8);
- StorageDead(_8);
+ _0 = Option::<&mut u32>::Some(_8);
+ StorageDead(_7);
goto -> bb3;
}
bb3: {
StorageDead(_4);
- StorageDead(_7);
+ StorageDead(_8);
return;
}
}
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
index d7f09fa..58e9b45 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
@@ -20,7 +20,7 @@
}
bb0: {
- StorageLive(_7);
+ StorageLive(_8);
StorageLive(_4);
StorageLive(_3);
_3 = PtrMetadata(_1);
@@ -36,7 +36,7 @@
bb2: {
StorageDead(_3);
- StorageLive(_8);
+ StorageLive(_7);
StorageLive(_5);
_5 = &raw mut (*_1);
StorageLive(_6);
@@ -45,14 +45,14 @@
StorageDead(_6);
StorageDead(_5);
_8 = &mut (*_7);
- _0 = Option::<&mut u32>::Some(move _8);
- StorageDead(_8);
+ _0 = Option::<&mut u32>::Some(_8);
+ StorageDead(_7);
goto -> bb3;
}
bb3: {
StorageDead(_4);
- StorageDead(_7);
+ StorageDead(_8);
return;
}
}
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
index 2f13cfa..ee80726 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
@@ -35,6 +35,7 @@
bb0: {
_3 = move (_2.0: usize);
_4 = move (_2.1: usize);
+ StorageLive(_11);
StorageLive(_5);
_5 = &raw mut (*_1);
StorageLive(_8);
@@ -56,6 +57,7 @@
StorageDead(_8);
StorageDead(_5);
_0 = &mut (*_11);
+ StorageDead(_11);
return;
}
}
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
index 2f13cfa..ee80726 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
@@ -35,6 +35,7 @@
bb0: {
_3 = move (_2.0: usize);
_4 = move (_2.1: usize);
+ StorageLive(_11);
StorageLive(_5);
_5 = &raw mut (*_1);
StorageLive(_8);
@@ -56,6 +57,7 @@
StorageDead(_8);
StorageDead(_5);
_0 = &mut (*_11);
+ StorageDead(_11);
return;
}
}
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index d5fdb2e..4c766c6 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -108,13 +108,11 @@
bb4: {
StorageLive(_15);
- StorageLive(_14);
_14 = &mut _13;
_15 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
}
bb5: {
- StorageDead(_14);
_16 = discriminant(_15);
switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
}
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index cc2beac..03de9fd 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -98,13 +98,11 @@
bb4: {
StorageLive(_14);
- StorageLive(_13);
_13 = &mut _12;
_14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind unreachable];
}
bb5: {
- StorageDead(_13);
_15 = discriminant(_14);
switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
}
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index d66edb2..c7c7222 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -98,13 +98,11 @@
bb4: {
StorageLive(_14);
- StorageLive(_13);
_13 = &mut _12;
_14 = <std::slice::Iter<'_, T> as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
}
bb5: {
- StorageDead(_13);
_15 = discriminant(_14);
switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
}
diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir
index 485dc91..c76e531 100644
--- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir
@@ -3,16 +3,14 @@
fn outer(_1: u8) -> u8 {
debug v => _1; // in scope 0 at $DIR/spans.rs:10:14: 10:15
let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:10:24: 10:26
- let mut _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13
+ let _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13
scope 1 (inlined inner) { // at $DIR/spans.rs:11:5: 11:14
debug x => _2; // in scope 1 at $DIR/spans.rs:14:14: 14:15
}
bb0: {
- StorageLive(_2); // scope 0 at $DIR/spans.rs:11:11: 11:13
_2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13
_0 = _1; // scope 1 at $DIR/spans.rs:15:5: 15:7
- StorageDead(_2); // scope 0 at $DIR/spans.rs:11:13: 11:14
return; // scope 0 at $DIR/spans.rs:12:2: 12:2
}
}
diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir
index 485dc91..c76e531 100644
--- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir
@@ -3,16 +3,14 @@
fn outer(_1: u8) -> u8 {
debug v => _1; // in scope 0 at $DIR/spans.rs:10:14: 10:15
let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:10:24: 10:26
- let mut _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13
+ let _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13
scope 1 (inlined inner) { // at $DIR/spans.rs:11:5: 11:14
debug x => _2; // in scope 1 at $DIR/spans.rs:14:14: 14:15
}
bb0: {
- StorageLive(_2); // scope 0 at $DIR/spans.rs:11:11: 11:13
_2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13
_0 = _1; // scope 1 at $DIR/spans.rs:15:5: 15:7
- StorageDead(_2); // scope 0 at $DIR/spans.rs:11:13: 11:14
return; // scope 0 at $DIR/spans.rs:12:2: 12:2
}
}
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 1c9ed25..0fe4fd3 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -5,61 +5,93 @@
let mut _0: &[u8];
scope 1 (inlined <Vec<u8> as Deref>::deref) {
debug self => _1;
- let mut _4: *const u8;
- let mut _5: usize;
+ let mut _7: usize;
scope 2 (inlined Vec::<u8>::as_ptr) {
debug self => _1;
let mut _2: &alloc::raw_vec::RawVec<u8>;
scope 3 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
debug self => _2;
- let mut _3: std::ptr::NonNull<u8>;
- scope 4 (inlined Unique::<u8>::as_ptr) {
- debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _3;
- debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
- scope 5 (inlined NonNull::<u8>::as_ptr) {
+ let mut _3: &alloc::raw_vec::RawVecInner;
+ scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
+ debug self => _3;
+ let mut _6: std::ptr::NonNull<u8>;
+ scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
debug self => _3;
+ let mut _4: std::ptr::NonNull<u8>;
+ scope 6 (inlined Unique::<u8>::cast::<u8>) {
+ debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
+ debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ scope 7 (inlined NonNull::<u8>::cast::<u8>) {
+ debug self => _4;
+ scope 8 (inlined NonNull::<u8>::as_ptr) {
+ debug self => _4;
+ let mut _5: *const u8;
+ }
+ }
+ }
+ scope 9 (inlined #[track_caller] <Unique<u8> as Into<NonNull<u8>>>::into) {
+ debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+ debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ scope 10 (inlined <NonNull<u8> as From<Unique<u8>>>::from) {
+ debug ((unique: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+ debug ((unique: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ scope 11 (inlined Unique::<u8>::as_non_null_ptr) {
+ debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+ debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ }
+ }
+ }
+ }
+ scope 12 (inlined NonNull::<u8>::as_ptr) {
+ debug self => _6;
}
}
}
}
- scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) {
- debug data => _4;
- debug len => _5;
- let _6: *const [u8];
- scope 7 (inlined core::ub_checks::check_language_ub) {
- scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
+ scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) {
+ debug data => _5;
+ debug len => _7;
+ let _8: *const [u8];
+ scope 14 (inlined core::ub_checks::check_language_ub) {
+ scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
}
}
- scope 9 (inlined std::mem::size_of::<u8>) {
+ scope 16 (inlined std::mem::size_of::<u8>) {
}
- scope 10 (inlined align_of::<u8>) {
+ scope 17 (inlined align_of::<u8>) {
}
- scope 11 (inlined slice_from_raw_parts::<u8>) {
- debug data => _4;
- debug len => _5;
- scope 12 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
- debug data_pointer => _4;
- debug metadata => _5;
+ scope 18 (inlined slice_from_raw_parts::<u8>) {
+ debug data => _5;
+ debug len => _7;
+ scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
+ debug data_pointer => _5;
+ debug metadata => _7;
}
}
}
}
bb0: {
- StorageLive(_4);
StorageLive(_2);
_2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
StorageLive(_3);
- _3 = ((((*_1).0: alloc::raw_vec::RawVec<u8>).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
- _4 = (_3.0: *const u8);
+ _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
+ StorageLive(_6);
+ StorageLive(_4);
+ _4 = (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
+ _5 = (_4.0: *const u8);
+ _6 = NonNull::<u8> { pointer: _5 };
+ StorageDead(_4);
+ StorageDead(_6);
StorageDead(_3);
StorageDead(_2);
- StorageLive(_5);
- _5 = ((*_1).1: usize);
- _6 = *const [u8] from (_4, _5);
- StorageDead(_5);
- StorageDead(_4);
- _0 = &(*_6);
+ StorageLive(_7);
+ _7 = ((*_1).1: usize);
+ StorageLive(_8);
+ _8 = *const [u8] from (_5, _7);
+ _0 = &(*_8);
+ StorageDead(_8);
+ StorageDead(_7);
return;
}
}
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 1c9ed25..0fe4fd3 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -5,61 +5,93 @@
let mut _0: &[u8];
scope 1 (inlined <Vec<u8> as Deref>::deref) {
debug self => _1;
- let mut _4: *const u8;
- let mut _5: usize;
+ let mut _7: usize;
scope 2 (inlined Vec::<u8>::as_ptr) {
debug self => _1;
let mut _2: &alloc::raw_vec::RawVec<u8>;
scope 3 (inlined alloc::raw_vec::RawVec::<u8>::ptr) {
debug self => _2;
- let mut _3: std::ptr::NonNull<u8>;
- scope 4 (inlined Unique::<u8>::as_ptr) {
- debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _3;
- debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
- scope 5 (inlined NonNull::<u8>::as_ptr) {
+ let mut _3: &alloc::raw_vec::RawVecInner;
+ scope 4 (inlined alloc::raw_vec::RawVecInner::ptr::<u8>) {
+ debug self => _3;
+ let mut _6: std::ptr::NonNull<u8>;
+ scope 5 (inlined alloc::raw_vec::RawVecInner::non_null::<u8>) {
debug self => _3;
+ let mut _4: std::ptr::NonNull<u8>;
+ scope 6 (inlined Unique::<u8>::cast::<u8>) {
+ debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _4;
+ debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ scope 7 (inlined NonNull::<u8>::cast::<u8>) {
+ debug self => _4;
+ scope 8 (inlined NonNull::<u8>::as_ptr) {
+ debug self => _4;
+ let mut _5: *const u8;
+ }
+ }
+ }
+ scope 9 (inlined #[track_caller] <Unique<u8> as Into<NonNull<u8>>>::into) {
+ debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+ debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ scope 10 (inlined <NonNull<u8> as From<Unique<u8>>>::from) {
+ debug ((unique: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+ debug ((unique: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ scope 11 (inlined Unique::<u8>::as_non_null_ptr) {
+ debug ((self: Unique<u8>).0: std::ptr::NonNull<u8>) => _6;
+ debug ((self: Unique<u8>).1: std::marker::PhantomData<u8>) => const PhantomData::<u8>;
+ }
+ }
+ }
+ }
+ scope 12 (inlined NonNull::<u8>::as_ptr) {
+ debug self => _6;
}
}
}
}
- scope 6 (inlined std::slice::from_raw_parts::<'_, u8>) {
- debug data => _4;
- debug len => _5;
- let _6: *const [u8];
- scope 7 (inlined core::ub_checks::check_language_ub) {
- scope 8 (inlined core::ub_checks::check_language_ub::runtime) {
+ scope 13 (inlined std::slice::from_raw_parts::<'_, u8>) {
+ debug data => _5;
+ debug len => _7;
+ let _8: *const [u8];
+ scope 14 (inlined core::ub_checks::check_language_ub) {
+ scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
}
}
- scope 9 (inlined std::mem::size_of::<u8>) {
+ scope 16 (inlined std::mem::size_of::<u8>) {
}
- scope 10 (inlined align_of::<u8>) {
+ scope 17 (inlined align_of::<u8>) {
}
- scope 11 (inlined slice_from_raw_parts::<u8>) {
- debug data => _4;
- debug len => _5;
- scope 12 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
- debug data_pointer => _4;
- debug metadata => _5;
+ scope 18 (inlined slice_from_raw_parts::<u8>) {
+ debug data => _5;
+ debug len => _7;
+ scope 19 (inlined std::ptr::from_raw_parts::<[u8], u8>) {
+ debug data_pointer => _5;
+ debug metadata => _7;
}
}
}
}
bb0: {
- StorageLive(_4);
StorageLive(_2);
_2 = &((*_1).0: alloc::raw_vec::RawVec<u8>);
StorageLive(_3);
- _3 = ((((*_1).0: alloc::raw_vec::RawVec<u8>).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
- _4 = (_3.0: *const u8);
+ _3 = &(((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner);
+ StorageLive(_6);
+ StorageLive(_4);
+ _4 = (((((*_1).0: alloc::raw_vec::RawVec<u8>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>);
+ _5 = (_4.0: *const u8);
+ _6 = NonNull::<u8> { pointer: _5 };
+ StorageDead(_4);
+ StorageDead(_6);
StorageDead(_3);
StorageDead(_2);
- StorageLive(_5);
- _5 = ((*_1).1: usize);
- _6 = *const [u8] from (_4, _5);
- StorageDead(_5);
- StorageDead(_4);
- _0 = &(*_6);
+ StorageLive(_7);
+ _7 = ((*_1).1: usize);
+ StorageLive(_8);
+ _8 = *const [u8] from (_5, _7);
+ _0 = &(*_8);
+ StorageDead(_8);
+ StorageDead(_7);
return;
}
}
diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
index 8d87438..998b899 100644
--- a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
+++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
@@ -8,9 +8,9 @@
bb0: {
StorageLive(_1);
- _1 = const <T as MyTrait>::ASSOC_INT;
-- switchInt(_1) -> [7: bb2, 42: bb3, otherwise: bb1];
+- switchInt(_1) -> [7: bb3, 42: bb2, otherwise: bb1];
+ nop;
-+ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb2, 42: bb3, otherwise: bb1];
++ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb3, 42: bb2, otherwise: bb1];
}
bb1: {
@@ -19,12 +19,12 @@
}
bb2: {
- _0 = const "hello";
+ _0 = const "towel";
goto -> bb4;
}
bb3: {
- _0 = const "towel";
+ _0 = const "hello";
goto -> bb4;
}
diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
index 8d87438..998b899 100644
--- a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
+++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
@@ -8,9 +8,9 @@
bb0: {
StorageLive(_1);
- _1 = const <T as MyTrait>::ASSOC_INT;
-- switchInt(_1) -> [7: bb2, 42: bb3, otherwise: bb1];
+- switchInt(_1) -> [7: bb3, 42: bb2, otherwise: bb1];
+ nop;
-+ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb2, 42: bb3, otherwise: bb1];
++ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb3, 42: bb2, otherwise: bb1];
}
bb1: {
@@ -19,12 +19,12 @@
}
bb2: {
- _0 = const "hello";
+ _0 = const "towel";
goto -> bb4;
}
bb3: {
- _0 = const "towel";
+ _0 = const "hello";
goto -> bb4;
}
diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
index f192f3f..30f66ef 100644
--- a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
+++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
@@ -20,8 +20,8 @@
bb1: {
StorageDead(_2);
-- switchInt(_1) -> [7: bb3, 42: bb4, otherwise: bb2];
-+ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb3, 42: bb4, otherwise: bb2];
+- switchInt(_1) -> [7: bb4, 42: bb3, otherwise: bb2];
++ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb4, 42: bb3, otherwise: bb2];
}
bb2: {
@@ -30,12 +30,12 @@
}
bb3: {
- _0 = const "hello";
+ _0 = const "towel";
goto -> bb5;
}
bb4: {
- _0 = const "towel";
+ _0 = const "hello";
goto -> bb5;
}
diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
index 261faf4..ed12ad4 100644
--- a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
+++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
@@ -20,8 +20,8 @@
bb1: {
StorageDead(_2);
-- switchInt(_1) -> [7: bb3, 42: bb4, otherwise: bb2];
-+ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb3, 42: bb4, otherwise: bb2];
+- switchInt(_1) -> [7: bb4, 42: bb3, otherwise: bb2];
++ switchInt(const <T as MyTrait>::ASSOC_INT) -> [7: bb4, 42: bb3, otherwise: bb2];
}
bb2: {
@@ -30,12 +30,12 @@
}
bb3: {
- _0 = const "hello";
+ _0 = const "towel";
goto -> bb5;
}
bb4: {
- _0 = const "towel";
+ _0 = const "hello";
goto -> bb5;
}
diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff
index 098b620..c0ea9fa 100644
--- a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff
@@ -8,8 +8,8 @@
bb0: {
_2 = discriminant(_1);
-- switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1];
-+ switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5];
+- switchInt(move _2) -> [1: bb2, 2: bb3, otherwise: bb1];
++ switchInt(move _2) -> [1: bb2, 2: bb3, otherwise: bb5];
}
bb1: {
@@ -18,12 +18,12 @@
}
bb2: {
- _0 = const 1_u32;
+ _0 = const 2_u32;
goto -> bb4;
}
bb3: {
- _0 = const 2_u32;
+ _0 = const 1_u32;
goto -> bb4;
}
diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff
index 995e32b..2082e80 100644
--- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff
@@ -8,8 +8,8 @@
bb0: {
_2 = discriminant(_1);
-- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
-+ switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5];
+- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
++ switchInt(move _2) -> [0: bb5, 1: bb2, 2: bb1, otherwise: bb5];
}
bb1: {
@@ -18,12 +18,12 @@
}
bb2: {
- _0 = const 1_u32;
+ _0 = const 2_u32;
goto -> bb4;
}
bb3: {
- _0 = const 2_u32;
+ _0 = const 1_u32;
goto -> bb4;
}
diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff
index da7a2bd..1e1ddfa 100644
--- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff
+++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-abort.diff
@@ -19,14 +19,16 @@
bb1: {
_2 = discriminant(_1);
-- switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb2];
-+ _5 = Eq(_2, const 0_isize);
+- switchInt(move _2) -> [1: bb3, otherwise: bb2];
++ _5 = Ne(_2, const 1_isize);
+ assume(move _5);
-+ goto -> bb4;
++ goto -> bb2;
}
bb2: {
- unreachable;
+ _0 = const ();
+ StorageDead(_1);
+ return;
}
bb3: {
@@ -35,11 +37,5 @@
- StorageLive(_4);
unreachable;
}
-
- bb4: {
- _0 = const ();
- StorageDead(_1);
- return;
- }
}
diff --git a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff
index a2121fc..809d24a 100644
--- a/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff
+++ b/tests/mir-opt/unreachable.as_match.UnreachablePropagation.panic-unwind.diff
@@ -19,14 +19,16 @@
bb1: {
_2 = discriminant(_1);
-- switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb2];
-+ _5 = Eq(_2, const 0_isize);
+- switchInt(move _2) -> [1: bb3, otherwise: bb2];
++ _5 = Ne(_2, const 1_isize);
+ assume(move _5);
-+ goto -> bb4;
++ goto -> bb2;
}
bb2: {
- unreachable;
+ _0 = const ();
+ StorageDead(_1);
+ return;
}
bb3: {
@@ -35,11 +37,5 @@
- StorageLive(_4);
unreachable;
}
-
- bb4: {
- _0 = const ();
- StorageDead(_1);
- return;
- }
}
diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs
index 881e354..f7f4815 100644
--- a/tests/mir-opt/unreachable.rs
+++ b/tests/mir-opt/unreachable.rs
@@ -45,18 +45,16 @@ fn as_match() {
// CHECK: bb0: {
// CHECK: {{_.*}} = empty()
// CHECK: bb1: {
- // CHECK: [[eq:_.*]] = Eq({{.*}}, const 0_isize);
+ // CHECK: [[eq:_.*]] = Ne({{.*}}, const 1_isize);
// CHECK-NEXT: assume(move [[eq]]);
- // CHECK-NEXT: goto -> bb4;
+ // CHECK-NEXT: goto -> bb2;
// CHECK: bb2: {
- // CHECK-NEXT: unreachable;
+ // CHECK: return;
// CHECK: bb3: {
// CHECK-NEXT: unreachable;
- // CHECK: bb4: {
- // CHECK: return;
match empty() {
- None => {}
Some(_x) => match _x {},
+ None => {}
}
}
diff --git a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff
index e5dab5d..ed54a38 100644
--- a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff
@@ -30,8 +30,8 @@
StorageLive(_4);
_4 = &(_1.1: Test3);
_5 = discriminant((*_4));
-- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
-+ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
+- switchInt(move _5) -> [0: bb5, 1: bb4, 2: bb3, 3: bb2, otherwise: bb1];
++ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb3, 3: bb2, otherwise: bb1];
}
bb1: {
@@ -47,7 +47,10 @@
}
bb3: {
- _3 = const "A(Empty)";
+ StorageLive(_7);
+ _7 = const "C";
+ _3 = &(*_7);
+ StorageDead(_7);
goto -> bb6;
}
@@ -60,10 +63,7 @@
}
bb5: {
- StorageLive(_7);
- _7 = const "C";
- _3 = &(*_7);
- StorageDead(_7);
+ _3 = const "A(Empty)";
goto -> bb6;
}
@@ -72,8 +72,8 @@
StorageDead(_3);
StorageLive(_9);
_10 = discriminant((_1.1: Test3));
-- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
-+ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
+- switchInt(move _10) -> [0: bb10, 1: bb9, 2: bb8, 3: bb7, otherwise: bb1];
++ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb8, 3: bb7, otherwise: bb1];
}
bb7: {
@@ -85,7 +85,10 @@
}
bb8: {
- _9 = const "A(Empty)";
+ StorageLive(_12);
+ _12 = const "C";
+ _9 = &(*_12);
+ StorageDead(_12);
goto -> bb11;
}
@@ -98,10 +101,7 @@
}
bb10: {
- StorageLive(_12);
- _12 = const "C";
- _9 = &(*_12);
- StorageDead(_12);
+ _9 = const "A(Empty)";
goto -> bb11;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff
index e5dab5d..ed54a38 100644
--- a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff
@@ -30,8 +30,8 @@
StorageLive(_4);
_4 = &(_1.1: Test3);
_5 = discriminant((*_4));
-- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
-+ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
+- switchInt(move _5) -> [0: bb5, 1: bb4, 2: bb3, 3: bb2, otherwise: bb1];
++ switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb3, 3: bb2, otherwise: bb1];
}
bb1: {
@@ -47,7 +47,10 @@
}
bb3: {
- _3 = const "A(Empty)";
+ StorageLive(_7);
+ _7 = const "C";
+ _3 = &(*_7);
+ StorageDead(_7);
goto -> bb6;
}
@@ -60,10 +63,7 @@
}
bb5: {
- StorageLive(_7);
- _7 = const "C";
- _3 = &(*_7);
- StorageDead(_7);
+ _3 = const "A(Empty)";
goto -> bb6;
}
@@ -72,8 +72,8 @@
StorageDead(_3);
StorageLive(_9);
_10 = discriminant((_1.1: Test3));
-- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
-+ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
+- switchInt(move _10) -> [0: bb10, 1: bb9, 2: bb8, 3: bb7, otherwise: bb1];
++ switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb8, 3: bb7, otherwise: bb1];
}
bb7: {
@@ -85,7 +85,10 @@
}
bb8: {
- _9 = const "A(Empty)";
+ StorageLive(_12);
+ _12 = const "C";
+ _9 = &(*_12);
+ StorageDead(_12);
goto -> bb11;
}
@@ -98,10 +101,7 @@
}
bb10: {
- StorageLive(_12);
- _12 = const "C";
- _9 = &(*_12);
- StorageDead(_12);
+ _9 = const "A(Empty)";
goto -> bb11;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff
index 02b9f02..be934ac 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
StorageLive(_2);
_2 = Test1::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
}
@@ -27,11 +27,6 @@
}
bb2: {
- _1 = const "A(Empty)";
- goto -> bb4;
- }
-
- bb3: {
StorageLive(_4);
_4 = const "B(Empty)";
_1 = &(*_4);
@@ -39,6 +34,11 @@
goto -> bb4;
}
+ bb3: {
+ _1 = const "A(Empty)";
+ goto -> bb4;
+ }
+
bb4: {
StorageDead(_2);
StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff
index 02b9f02..be934ac 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
StorageLive(_2);
_2 = Test1::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
}
@@ -27,11 +27,6 @@
}
bb2: {
- _1 = const "A(Empty)";
- goto -> bb4;
- }
-
- bb3: {
StorageLive(_4);
_4 = const "B(Empty)";
_1 = &(*_4);
@@ -39,6 +34,11 @@
goto -> bb4;
}
+ bb3: {
+ _1 = const "A(Empty)";
+ goto -> bb4;
+ }
+
bb4: {
StorageDead(_2);
StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff
index d337644..1200618 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
StorageLive(_2);
_2 = Test3::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
+ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
}
@@ -27,11 +27,6 @@
}
bb2: {
- _1 = const "A(Empty)";
- goto -> bb4;
- }
-
- bb3: {
StorageLive(_4);
_4 = const "B(Empty)";
_1 = &(*_4);
@@ -39,6 +34,11 @@
goto -> bb4;
}
+ bb3: {
+ _1 = const "A(Empty)";
+ goto -> bb4;
+ }
+
bb4: {
StorageDead(_2);
StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff
index d337644..1200618 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
StorageLive(_2);
_2 = Test3::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
+ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
}
@@ -27,11 +27,6 @@
}
bb2: {
- _1 = const "A(Empty)";
- goto -> bb4;
- }
-
- bb3: {
StorageLive(_4);
_4 = const "B(Empty)";
_1 = &(*_4);
@@ -39,6 +34,11 @@
goto -> bb4;
}
+ bb3: {
+ _1 = const "A(Empty)";
+ goto -> bb4;
+ }
+
bb4: {
StorageDead(_2);
StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff
index 8f0d5b7..b86814d 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
StorageLive(_2);
_2 = Test4::C;
_3 = discriminant(_2);
- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+ switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
}
bb1: {
@@ -26,11 +26,6 @@
}
bb2: {
- _1 = const "A(i32)";
- goto -> bb4;
- }
-
- bb3: {
StorageLive(_4);
_4 = const "B(i32)";
_1 = &(*_4);
@@ -38,6 +33,11 @@
goto -> bb4;
}
+ bb3: {
+ _1 = const "A(i32)";
+ goto -> bb4;
+ }
+
bb4: {
StorageDead(_2);
StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff
index 8f0d5b7..b86814d 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
StorageLive(_2);
_2 = Test4::C;
_3 = discriminant(_2);
- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+ switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
}
bb1: {
@@ -26,11 +26,6 @@
}
bb2: {
- _1 = const "A(i32)";
- goto -> bb4;
- }
-
- bb3: {
StorageLive(_4);
_4 = const "B(i32)";
_1 = &(*_4);
@@ -38,6 +33,11 @@
goto -> bb4;
}
+ bb3: {
+ _1 = const "A(i32)";
+ goto -> bb4;
+ }
+
bb4: {
StorageDead(_2);
StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff
index b1ecd00..424ac6b 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff
@@ -15,8 +15,8 @@
StorageLive(_2);
_2 = Test4::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
-+ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
++ switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, 3: bb1, otherwise: bb6];
}
bb1: {
@@ -28,7 +28,10 @@
}
bb2: {
- _1 = const "A(i32)";
+ StorageLive(_5);
+ _5 = const "C";
+ _1 = &(*_5);
+ StorageDead(_5);
goto -> bb5;
}
@@ -41,10 +44,7 @@
}
bb4: {
- StorageLive(_5);
- _5 = const "C";
- _1 = &(*_5);
- StorageDead(_5);
+ _1 = const "A(i32)";
goto -> bb5;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
index b1ecd00..424ac6b 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
@@ -15,8 +15,8 @@
StorageLive(_2);
_2 = Test4::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
-+ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+- switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
++ switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, 3: bb1, otherwise: bb6];
}
bb1: {
@@ -28,7 +28,10 @@
}
bb2: {
- _1 = const "A(i32)";
+ StorageLive(_5);
+ _5 = const "C";
+ _1 = &(*_5);
+ StorageDead(_5);
goto -> bb5;
}
@@ -41,10 +44,7 @@
}
bb4: {
- StorageLive(_5);
- _5 = const "C";
- _1 = &(*_5);
- StorageDead(_5);
+ _1 = const "A(i32)";
goto -> bb5;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff
index 28c6d4f..4cd6d3f 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff
@@ -16,8 +16,8 @@
StorageLive(_2);
_2 = Test4::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
-+ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+- switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, otherwise: bb1];
++ switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, 3: bb1, otherwise: bb8];
}
bb1: {
@@ -29,23 +29,18 @@
}
bb2: {
- switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+ switchInt(((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1];
}
bb3: {
- _1 = const "A(1)";
+ StorageLive(_6);
+ _6 = const "C";
+ _1 = &(*_6);
+ StorageDead(_6);
goto -> bb7;
}
bb4: {
- StorageLive(_4);
- _4 = const "A(2)";
- _1 = &(*_4);
- StorageDead(_4);
- goto -> bb7;
- }
-
- bb5: {
StorageLive(_5);
_5 = const "B(i32)";
_1 = &(*_5);
@@ -53,11 +48,16 @@
goto -> bb7;
}
+ bb5: {
+ StorageLive(_4);
+ _4 = const "A(2)";
+ _1 = &(*_4);
+ StorageDead(_4);
+ goto -> bb7;
+ }
+
bb6: {
- StorageLive(_6);
- _6 = const "C";
- _1 = &(*_6);
- StorageDead(_6);
+ _1 = const "A(1)";
goto -> bb7;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff
index 28c6d4f..4cd6d3f 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff
@@ -16,8 +16,8 @@
StorageLive(_2);
_2 = Test4::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
-+ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+- switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, otherwise: bb1];
++ switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, 3: bb1, otherwise: bb8];
}
bb1: {
@@ -29,23 +29,18 @@
}
bb2: {
- switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+ switchInt(((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1];
}
bb3: {
- _1 = const "A(1)";
+ StorageLive(_6);
+ _6 = const "C";
+ _1 = &(*_6);
+ StorageDead(_6);
goto -> bb7;
}
bb4: {
- StorageLive(_4);
- _4 = const "A(2)";
- _1 = &(*_4);
- StorageDead(_4);
- goto -> bb7;
- }
-
- bb5: {
StorageLive(_5);
_5 = const "B(i32)";
_1 = &(*_5);
@@ -53,11 +48,16 @@
goto -> bb7;
}
+ bb5: {
+ StorageLive(_4);
+ _4 = const "A(2)";
+ _1 = &(*_4);
+ StorageDead(_4);
+ goto -> bb7;
+ }
+
bb6: {
- StorageLive(_6);
- _6 = const "C";
- _1 = &(*_6);
- StorageDead(_6);
+ _1 = const "A(1)";
goto -> bb7;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff
index f36a7ef..2de1f77 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff
@@ -15,8 +15,8 @@
StorageLive(_2);
_2 = Test5::<T>::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
-+ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7];
+- switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, otherwise: bb1];
++ switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, 3: bb1, otherwise: bb7];
}
bb1: {
@@ -28,7 +28,10 @@
}
bb2: {
- _1 = const "A(T)";
+ StorageLive(_5);
+ _5 = const "C";
+ _1 = &(*_5);
+ StorageDead(_5);
goto -> bb5;
}
@@ -41,10 +44,7 @@
}
bb4: {
- StorageLive(_5);
- _5 = const "C";
- _1 = &(*_5);
- StorageDead(_5);
+ _1 = const "A(T)";
goto -> bb5;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
index 20e31c2..5afb78c 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
@@ -15,8 +15,8 @@
StorageLive(_2);
_2 = Test5::<T>::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
-+ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8];
+- switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, otherwise: bb1];
++ switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, 3: bb1, otherwise: bb8];
}
bb1: {
@@ -28,7 +28,10 @@
}
bb2: {
- _1 = const "A(T)";
+ StorageLive(_5);
+ _5 = const "C";
+ _1 = &(*_5);
+ StorageDead(_5);
goto -> bb5;
}
@@ -41,10 +44,7 @@
}
bb4: {
- StorageLive(_5);
- _5 = const "C";
- _1 = &(*_5);
- StorageDead(_5);
+ _1 = const "A(T)";
goto -> bb5;
}
diff --git a/tests/mir-opt/unreachable_enum_branching.rs b/tests/mir-opt/unreachable_enum_branching.rs
index 6005dc5..7647f9b 100644
--- a/tests/mir-opt/unreachable_enum_branching.rs
+++ b/tests/mir-opt/unreachable_enum_branching.rs
@@ -49,7 +49,7 @@ struct Plop {
fn simple() {
// CHECK-LABEL: fn simple(
// CHECK: [[discr:_.*]] = discriminant(
- // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb2, otherwise: [[unreachable]]];
+ // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb1, otherwise: [[unreachable]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test1::C {
@@ -120,7 +120,7 @@ fn otherwise_t3() {
fn otherwise_t4_unreachable_default() {
// CHECK-LABEL: fn otherwise_t4_unreachable_default(
// CHECK: [[discr:_.*]] = discriminant(
- // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+ // CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test4::C {
@@ -135,7 +135,7 @@ fn otherwise_t4_unreachable_default() {
fn otherwise_t4_unreachable_default_2() {
// CHECK-LABEL: fn otherwise_t4_unreachable_default_2(
// CHECK: [[discr:_.*]] = discriminant(
- // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]];
+ // CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test4::C {
@@ -151,7 +151,7 @@ fn otherwise_t4_unreachable_default_2() {
fn otherwise_t4() {
// CHECK-LABEL: fn otherwise_t4(
// CHECK: [[discr:_.*]] = discriminant(
- // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]];
+ // CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NOT: unreachable;
// CHECK: }
@@ -166,7 +166,7 @@ fn otherwise_t4() {
fn otherwise_t5_unreachable_default<T>() {
// CHECK-LABEL: fn otherwise_t5_unreachable_default(
// CHECK: [[discr:_.*]] = discriminant(
- // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+ // CHECK: switchInt(move [[discr]]) -> [255: {{bb.*}}, 0: {{bb.*}}, 5: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
// CHECK: [[unreachable]]: {
// CHECK-NEXT: unreachable;
match Test5::<T>::C {
@@ -183,7 +183,7 @@ fn byref() {
let plop = Plop { xx: 51, test3: Test3::C };
// CHECK: [[ref_discr:_.*]] = discriminant((*
- // CHECK: switchInt(move [[ref_discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb5, 3: bb2, otherwise: [[unreachable]]];
+ // CHECK: switchInt(move [[ref_discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable]]];
match &plop.test3 {
Test3::A(_) => "A(Empty)",
Test3::B(_) => "B(Empty)",
@@ -195,7 +195,7 @@ fn byref() {
// CHECK-NEXT: unreachable;
// CHECK: [[discr:_.*]] = discriminant(
- // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]];
+ // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable]]];
match plop.test3 {
Test3::A(_) => "A(Empty)",
Test3::B(_) => "B(Empty)",
diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff
index a85fc0d..5c08648 100644
--- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff
@@ -14,40 +14,40 @@
StorageLive(_2);
_2 = Test1::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
-+ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
+- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
}
bb1: {
- unreachable;
- }
-
- bb2: {
StorageLive(_5);
_5 = const "C";
_1 = &(*_5);
StorageDead(_5);
- goto -> bb5;
+ goto -> bb4;
}
- bb3: {
- _1 = const "A(Empty)";
- goto -> bb5;
- }
-
- bb4: {
+ bb2: {
StorageLive(_4);
_4 = const "B(Empty)";
_1 = &(*_4);
StorageDead(_4);
- goto -> bb5;
+ goto -> bb4;
}
- bb5: {
+ bb3: {
+ _1 = const "A(Empty)";
+ goto -> bb4;
+ }
+
+ bb4: {
StorageDead(_2);
StorageDead(_1);
_0 = const ();
return;
++ }
++
++ bb5: {
++ unreachable;
}
}
diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff
index a85fc0d..5c08648 100644
--- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff
@@ -14,40 +14,40 @@
StorageLive(_2);
_2 = Test1::C;
_3 = discriminant(_2);
-- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
-+ switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
+- switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
++ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
}
bb1: {
- unreachable;
- }
-
- bb2: {
StorageLive(_5);
_5 = const "C";
_1 = &(*_5);
StorageDead(_5);
- goto -> bb5;
+ goto -> bb4;
}
- bb3: {
- _1 = const "A(Empty)";
- goto -> bb5;
- }
-
- bb4: {
+ bb2: {
StorageLive(_4);
_4 = const "B(Empty)";
_1 = &(*_4);
StorageDead(_4);
- goto -> bb5;
+ goto -> bb4;
}
- bb5: {
+ bb3: {
+ _1 = const "A(Empty)";
+ goto -> bb4;
+ }
+
+ bb4: {
StorageDead(_2);
StorageDead(_1);
_0 = const ();
return;
++ }
++
++ bb5: {
++ unreachable;
}
}
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
index fec4a4b..024ce97 100644
--- a/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
@@ -3,8 +3,6 @@
// Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current
// `rustc` version and the `since` property in feature stability gating is properly respected.
-use std::path::PathBuf;
-
use run_make_support::{aux_build, rfs, rustc, source_root};
fn main() {
diff --git a/tests/run-make/arguments-non-c-like-enum/rmake.rs b/tests/run-make/arguments-non-c-like-enum/rmake.rs
index 036691e..f8e077e 100644
--- a/tests/run-make/arguments-non-c-like-enum/rmake.rs
+++ b/tests/run-make/arguments-non-c-like-enum/rmake.rs
@@ -4,8 +4,6 @@
use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib_name};
pub fn main() {
- use std::path::Path;
-
rustc().input("nonclike.rs").crate_type("staticlib").run();
cc().input("test.c")
.input(static_lib_name("nonclike"))
diff --git a/tests/run-make/branch-protection-check-IBT/_rmake.rs b/tests/run-make/branch-protection-check-IBT/_rmake.rs
index d66ecf9..9115140 100644
--- a/tests/run-make/branch-protection-check-IBT/_rmake.rs
+++ b/tests/run-make/branch-protection-check-IBT/_rmake.rs
@@ -8,9 +8,7 @@
//@ ignore-test
// FIXME(jieyouxu): see the FIXME in the Makefile
-use run_make_support::llvm_readobj;
-use run_make_support::rustc;
-use run_make_support::{cwd, env_var};
+use run_make_support::{cwd, env_var, llvm_readobj, rustc};
fn main() {
let llvm_components = env_var("LLVM_COMPONENTS");
diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
index ee35350..6d04501 100644
--- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs
+++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs
@@ -5,7 +5,6 @@
use run_make_support::rfs::remove_file;
use run_make_support::{cc, extra_c_flags, run, rustc, static_lib_name};
-use std::fs;
fn main() {
rustc().input("foo.rs").run();
diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
index 196c644..0a959c3 100644
--- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
+++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs
@@ -1,9 +1,7 @@
#![crate_type = "staticlib"]
#![feature(c_variadic)]
-use std::ffi::VaList;
-use std::ffi::{c_char, c_double, c_int, c_long, c_longlong};
-use std::ffi::{CStr, CString};
+use std::ffi::{c_char, c_double, c_int, c_long, c_longlong, CStr, CString, VaList};
macro_rules! continue_if {
($cond:expr) => {
diff --git a/tests/run-make/cdylib-dylib-linkage/Makefile b/tests/run-make/cdylib-dylib-linkage/Makefile
deleted file mode 100644
index db8393d..0000000
--- a/tests/run-make/cdylib-dylib-linkage/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-# This test checks that cdylibs can link against dylibs as dependencies, after this restriction was disabled.
-# See https://github.com/rust-lang/rust/commit/72aaa3a414d17aa0c4f19feafa5bab5f84b60e63
-
-# ignore-cross-compile
-include ../tools.mk
-
-TARGET_SYSROOT := $(shell $(RUSTC) --print sysroot)/lib/rustlib/$(TARGET)/lib
-
-ifdef IS_MSVC
-LIBSTD := $(wildcard $(TARGET_SYSROOT)/libstd-*.dll.lib)
-else
-LIBSTD := $(wildcard $(TARGET_SYSROOT)/$(call DYLIB_GLOB,std))
-STD := $(basename $(patsubst lib%,%, $(notdir $(LIBSTD))))
-endif
-
-all: $(call RUN_BINFILE,foo)
- $(call RUN,foo)
-
-ifdef IS_MSVC
-CLIBS := $(TMPDIR)/foo.dll.lib $(TMPDIR)/bar.dll.lib $(LIBSTD)
-$(call RUN_BINFILE,foo): $(call DYLIB,foo)
- $(CC) $(CFLAGS) foo.c $(CLIBS) $(call OUT_EXE,foo)
-else
-CLIBS := -lfoo -lbar -l$(STD) -L $(TMPDIR) -L $(TARGET_SYSROOT)
-$(call RUN_BINFILE,foo): $(call DYLIB,foo)
- $(CC) $(CFLAGS) foo.c $(CLIBS) -o $(call RUN_BINFILE,foo)
-endif
-
-$(call DYLIB,foo):
- $(RUSTC) -C prefer-dynamic bar.rs
- $(RUSTC) foo.rs
diff --git a/tests/run-make/cdylib-dylib-linkage/rmake.rs b/tests/run-make/cdylib-dylib-linkage/rmake.rs
new file mode 100644
index 0000000..a8fd8e2
--- /dev/null
+++ b/tests/run-make/cdylib-dylib-linkage/rmake.rs
@@ -0,0 +1,41 @@
+// Previously, rustc mandated that cdylibs could only link against rlibs as dependencies,
+// making linkage between cdylibs and dylibs impossible. After this was changed in #68448,
+// this test attempts to link both `foo` (a cdylib) and `bar` (a dylib) and checks that
+// both compilation and execution are successful.
+// See https://github.com/rust-lang/rust/pull/68448
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{
+ bin_name, cc, dynamic_lib_extension, dynamic_lib_name, filename_contains, has_extension,
+ has_prefix, has_suffix, is_msvc, msvc_import_dynamic_lib_name, path, run, rustc,
+ shallow_find_files, target,
+};
+
+fn main() {
+ rustc().arg("-Cprefer-dynamic").input("bar.rs").run();
+ rustc().input("foo.rs").run();
+ let sysroot = rustc().print("sysroot").run().stdout_utf8();
+ let sysroot = sysroot.trim();
+ let target_sysroot = path(sysroot).join("lib/rustlib").join(target()).join("lib");
+ if is_msvc() {
+ let mut libs = shallow_find_files(&target_sysroot, |path| {
+ has_prefix(path, "libstd-") && has_suffix(path, ".dll.lib")
+ });
+ libs.push(path(msvc_import_dynamic_lib_name("foo")));
+ libs.push(path(msvc_import_dynamic_lib_name("bar")));
+ cc().input("foo.c").args(&libs).out_exe("foo").run();
+ } else {
+ let stdlibs = shallow_find_files(&target_sysroot, |path| {
+ has_extension(path, dynamic_lib_extension()) && filename_contains(path, "std")
+ });
+ cc().input("foo.c")
+ .args(&[dynamic_lib_name("foo"), dynamic_lib_name("bar")])
+ .arg(stdlibs.get(0).unwrap())
+ .library_search_path(&target_sysroot)
+ .output(bin_name("foo"))
+ .run();
+ }
+ run("foo");
+}
diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs
index a16adea..1557f50 100644
--- a/tests/run-make/comment-section/rmake.rs
+++ b/tests/run-make/comment-section/rmake.rs
@@ -7,12 +7,7 @@
// FIXME(jieyouxu): check cross-compile setup
//@ ignore-cross-compile
-use std::path::PathBuf;
-
-use run_make_support::llvm_readobj;
-use run_make_support::rfs;
-use run_make_support::rustc;
-use run_make_support::{cwd, env_var, run_in_tmpdir};
+use run_make_support::{cwd, env_var, llvm_readobj, rfs, rustc};
fn main() {
let target = env_var("TARGET");
diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs
index 43d1d69..42ed07d 100644
--- a/tests/run-make/compiler-builtins/rmake.rs
+++ b/tests/run-make/compiler-builtins/rmake.rs
@@ -14,16 +14,15 @@
#![deny(warnings)]
-use run_make_support::object::read::archive::ArchiveFile;
-use run_make_support::object::read::Object;
-use run_make_support::object::ObjectSection;
-use run_make_support::object::ObjectSymbol;
-use run_make_support::object::RelocationTarget;
-use run_make_support::rfs::{read, read_dir};
-use run_make_support::{cmd, env_var, object};
use std::collections::HashSet;
use std::path::PathBuf;
+use run_make_support::object::read::archive::ArchiveFile;
+use run_make_support::object::read::Object;
+use run_make_support::object::{ObjectSection, ObjectSymbol, RelocationTarget};
+use run_make_support::rfs::{read, read_dir};
+use run_make_support::{cmd, env_var, object};
+
fn main() {
let target_dir = PathBuf::from("target");
let target = env_var("TARGET");
diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs
index 3a656f2..5ba1a18 100644
--- a/tests/run-make/compressed-debuginfo/rmake.rs
+++ b/tests/run-make/compressed-debuginfo/rmake.rs
@@ -5,7 +5,7 @@
// FIXME: This test isn't comprehensive and isn't covering all possible combinations.
-use run_make_support::{assert_contains, cmd, llvm_readobj, run_in_tmpdir, rustc};
+use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc};
fn check_compression(compression: &str, to_find: &str) {
run_in_tmpdir(|| {
diff --git a/tests/run-make/const_fn_mir/rmake.rs b/tests/run-make/const_fn_mir/rmake.rs
index 1ba9342..0c33b1c 100644
--- a/tests/run-make/const_fn_mir/rmake.rs
+++ b/tests/run-make/const_fn_mir/rmake.rs
@@ -2,7 +2,7 @@
//@ needs-unwind
-use run_make_support::{cwd, diff, rustc};
+use run_make_support::{diff, rustc};
fn main() {
rustc().input("main.rs").emit("mir").output("dump-actual.mir").run();
diff --git a/tests/run-make/issue-36710/foo.cpp b/tests/run-make/cpp-global-destructors/foo.cpp
similarity index 100%
rename from tests/run-make/issue-36710/foo.cpp
rename to tests/run-make/cpp-global-destructors/foo.cpp
diff --git a/tests/run-make/issue-36710/foo.rs b/tests/run-make/cpp-global-destructors/foo.rs
similarity index 100%
rename from tests/run-make/issue-36710/foo.rs
rename to tests/run-make/cpp-global-destructors/foo.rs
diff --git a/tests/run-make/cpp-global-destructors/rmake.rs b/tests/run-make/cpp-global-destructors/rmake.rs
new file mode 100644
index 0000000..9bc5c84
--- /dev/null
+++ b/tests/run-make/cpp-global-destructors/rmake.rs
@@ -0,0 +1,26 @@
+// Some start files were missed when originally writing the logic to swap in musl start files.
+// This caused #36710. After the fix in #50105, this test checks that linking to C++ code
+// with global destructors works.
+// See https://github.com/rust-lang/rust/pull/50105
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+//@ ignore-none
+// Reason: no-std is not supported.
+//@ ignore-wasm32
+//@ ignore-wasm64
+// Reason: compiling C++ to WASM may cause problems.
+
+// Neither of these are tested in full CI.
+//@ ignore-nvptx64-nvidia-cuda
+// Reason: can't find crate "std"
+//@ ignore-sgx
+
+use run_make_support::{build_native_static_lib_cxx, run, rustc};
+
+fn main() {
+ build_native_static_lib_cxx("foo");
+ rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run();
+ run("foo");
+}
diff --git a/tests/run-make/issue-69368/a.rs b/tests/run-make/crate-circular-deps-link/a.rs
similarity index 100%
rename from tests/run-make/issue-69368/a.rs
rename to tests/run-make/crate-circular-deps-link/a.rs
diff --git a/tests/run-make/issue-69368/b.rs b/tests/run-make/crate-circular-deps-link/b.rs
similarity index 100%
rename from tests/run-make/issue-69368/b.rs
rename to tests/run-make/crate-circular-deps-link/b.rs
diff --git a/tests/run-make/issue-69368/c.rs b/tests/run-make/crate-circular-deps-link/c.rs
similarity index 100%
rename from tests/run-make/issue-69368/c.rs
rename to tests/run-make/crate-circular-deps-link/c.rs
diff --git a/tests/run-make/crate-circular-deps-link/rmake.rs b/tests/run-make/crate-circular-deps-link/rmake.rs
new file mode 100644
index 0000000..7cc28ac
--- /dev/null
+++ b/tests/run-make/crate-circular-deps-link/rmake.rs
@@ -0,0 +1,20 @@
+// Test that previously triggered a linker failure with root cause
+// similar to one found in the issue #69368.
+//
+// The crate that provides oom lang item is missing some other lang
+// items. Necessary to prevent the use of start-group / end-group.
+//
+// The weak lang items are defined in a separate compilation units,
+// so that linker could omit them if not used.
+//
+// The crates that need those weak lang items are dependencies of
+// crates that provide them.
+// See https://github.com/rust-lang/rust/issues/69371
+
+use run_make_support::rustc;
+
+fn main() {
+ rustc().input("a.rs").run();
+ rustc().input("b.rs").run();
+ rustc().input("c.rs").run();
+}
diff --git a/tests/run-make/crate-hash-rustc-version/rmake.rs b/tests/run-make/crate-hash-rustc-version/rmake.rs
index 97b3dd3..c7c36cf 100644
--- a/tests/run-make/crate-hash-rustc-version/rmake.rs
+++ b/tests/run-make/crate-hash-rustc-version/rmake.rs
@@ -4,8 +4,7 @@
//@ ignore-cross-compile
//@ only-unix
-use run_make_support::llvm;
-use run_make_support::{diff, dynamic_lib_name, is_darwin, run, run_fail, rustc};
+use run_make_support::{diff, dynamic_lib_name, is_darwin, llvm, run, run_fail, rustc};
fn llvm_readobj() -> llvm::LlvmReadobj {
let mut cmd = llvm::llvm_readobj();
diff --git a/tests/run-make/crate-loading/multiple-dep-versions-1.rs b/tests/run-make/crate-loading/multiple-dep-versions-1.rs
new file mode 100644
index 0000000..2d35163
--- /dev/null
+++ b/tests/run-make/crate-loading/multiple-dep-versions-1.rs
@@ -0,0 +1,6 @@
+#![crate_name = "dependency"]
+#![crate_type = "rlib"]
+pub struct Type;
+pub trait Trait {}
+impl Trait for Type {}
+pub fn do_something<X: Trait>(_: X) {}
diff --git a/tests/run-make/crate-loading/multiple-dep-versions-2.rs b/tests/run-make/crate-loading/multiple-dep-versions-2.rs
new file mode 100644
index 0000000..a5df3dc
--- /dev/null
+++ b/tests/run-make/crate-loading/multiple-dep-versions-2.rs
@@ -0,0 +1,6 @@
+#![crate_name = "dependency"]
+#![crate_type = "rlib"]
+pub struct Type(pub i32);
+pub trait Trait {}
+impl Trait for Type {}
+pub fn do_something<X: Trait>(_: X) {}
diff --git a/tests/run-make/crate-loading/multiple-dep-versions.rs b/tests/run-make/crate-loading/multiple-dep-versions.rs
new file mode 100644
index 0000000..5a6cb03
--- /dev/null
+++ b/tests/run-make/crate-loading/multiple-dep-versions.rs
@@ -0,0 +1,8 @@
+extern crate dep_2_reexport;
+extern crate dependency;
+use dep_2_reexport::do_something;
+use dependency::Type;
+
+fn main() {
+ do_something(Type);
+}
diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs
new file mode 100644
index 0000000..d7abd58
--- /dev/null
+++ b/tests/run-make/crate-loading/rmake.rs
@@ -0,0 +1,26 @@
+//@ only-linux
+//@ ignore-wasm32
+//@ ignore-wasm64
+
+use run_make_support::{rust_lib_name, rustc};
+
+fn main() {
+ rustc().input("multiple-dep-versions-1.rs").run();
+ rustc().input("multiple-dep-versions-2.rs").extra_filename("2").metadata("2").run();
+
+ rustc()
+ .input("multiple-dep-versions.rs")
+ .extern_("dependency", rust_lib_name("dependency"))
+ .extern_("dep_2_reexport", rust_lib_name("dependency2"))
+ .run_fail()
+ .assert_stderr_contains(
+ "you have multiple different versions of crate `dependency` in your dependency graph",
+ )
+ .assert_stderr_contains(
+ "two types coming from two different versions of the same crate are different types \
+ even if they look the same",
+ )
+ .assert_stderr_contains("this type doesn't implement the required trait")
+ .assert_stderr_contains("this type implements the required trait")
+ .assert_stderr_contains("this is the required trait");
+}
diff --git a/tests/run-make/cross-lang-lto-clang/Makefile b/tests/run-make/cross-lang-lto-clang/Makefile
deleted file mode 100644
index acf49c8..0000000
--- a/tests/run-make/cross-lang-lto-clang/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-# needs-force-clang-based-tests
-
-# This test makes sure that cross-language inlining actually works by checking
-# the generated machine code.
-
-include ../tools.mk
-
-all: cpp-executable rust-executable
-
-cpp-executable:
- $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs
- $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3
- # Make sure we don't find a call instruction to the function we expect to
- # always be inlined.
- "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined"
- # As a sanity check, make sure we do find a call instruction to a
- # non-inlined function
- "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined"
-
-rust-executable:
- $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2
- (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
- $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain
- "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined"
- "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined"
diff --git a/tests/run-make/cross-lang-lto-clang/rmake.rs b/tests/run-make/cross-lang-lto-clang/rmake.rs
new file mode 100644
index 0000000..1b15a54
--- /dev/null
+++ b/tests/run-make/cross-lang-lto-clang/rmake.rs
@@ -0,0 +1,62 @@
+// This test checks that cross-language inlining actually works by checking
+// the generated machine code.
+// See https://github.com/rust-lang/rust/pull/57514
+
+//@ needs-force-clang-based-tests
+// NOTE(#126180): This test only runs on `x86_64-gnu-debug`, because that CI job sets
+// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their
+// name.
+
+use run_make_support::{clang, env_var, llvm_ar, llvm_objdump, rustc, static_lib_name};
+
+fn main() {
+ rustc()
+ .linker_plugin_lto("on")
+ .output(static_lib_name("rustlib-xlto"))
+ .opt_level("2")
+ .codegen_units(1)
+ .input("rustlib.rs")
+ .run();
+ clang()
+ .lto("thin")
+ .use_ld("lld")
+ .arg("-lrustlib-xlto")
+ .out_exe("cmain")
+ .input("cmain.c")
+ .arg("-O3")
+ .run();
+ // Make sure we don't find a call instruction to the function we expect to
+ // always be inlined.
+ llvm_objdump()
+ .disassemble()
+ .input("cmain")
+ .run()
+ .assert_stdout_not_contains_regex("call.*rust_always_inlined");
+ // As a sanity check, make sure we do find a call instruction to a
+ // non-inlined function
+ llvm_objdump()
+ .disassemble()
+ .input("cmain")
+ .run()
+ .assert_stdout_contains_regex("call.*rust_never_inlined");
+ clang().input("clib.c").lto("thin").arg("-c").out_exe("clib.o").arg("-O2").run();
+ llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run();
+ rustc()
+ .linker_plugin_lto("on")
+ .opt_level("2")
+ .linker(&env_var("CLANG"))
+ .link_arg("-fuse-ld=lld")
+ .input("main.rs")
+ .output("rsmain")
+ .run();
+ llvm_objdump()
+ .disassemble()
+ .input("rsmain")
+ .run()
+ .assert_stdout_not_contains_regex("call.*c_always_inlined");
+ llvm_objdump()
+ .disassemble()
+ .input("rsmain")
+ .run()
+ .assert_stdout_contains_regex("call.*c_never_inlined");
+}
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/clib.c b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/clib.c
similarity index 100%
rename from tests/run-make/cross-lang-lto-pgo-smoketest/clib.c
rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/clib.c
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/cmain.c b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/cmain.c
similarity index 100%
rename from tests/run-make/cross-lang-lto-pgo-smoketest/cmain.c
rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/cmain.c
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/main.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/main.rs
similarity index 100%
rename from tests/run-make/cross-lang-lto-pgo-smoketest/main.rs
rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/main.rs
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs
new file mode 100644
index 0000000..03c9af4
--- /dev/null
+++ b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs
@@ -0,0 +1,120 @@
+// This test makes sure that cross-language inlining can be used in conjunction
+// with profile-guided optimization. The test only tests that the whole workflow
+// can be executed without anything crashing. It does not test whether PGO or
+// xLTO have any specific effect on the generated code.
+// See https://github.com/rust-lang/rust/pull/61036
+
+//@ needs-force-clang-based-tests
+// NOTE(#126180): This test would only run on `x86_64-gnu-debug`, because that CI job sets
+// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their
+// name.
+
+//@ needs-profiler-support
+// FIXME(Oneirical): Except that due to the reliance on llvm-profdata, this test
+// never runs, because `x86_64-gnu-debug` does not have the `profiler_builtins` crate.
+
+//FIXME(Oneirical): There was a strange workaround for MSVC on this test
+// which added -C panic=abort to every RUSTC call. It was justified as follows:
+
+// "LLVM doesn't support instrumenting binaries that use SEH:
+// https://bugs.llvm.org/show_bug.cgi?id=41279
+// Things work fine with -Cpanic=abort though."
+
+// This isn't very pertinent, however, as the test does not get run on any
+// MSVC platforms.
+
+use run_make_support::{
+ clang, env_var, has_extension, has_prefix, llvm_ar, llvm_profdata, rfs, run, rustc,
+ shallow_find_files, static_lib_name,
+};
+
+fn main() {
+ rustc()
+ .linker_plugin_lto("on")
+ .output(static_lib_name("rustlib-xlto"))
+ .opt_level("3")
+ .codegen_units(1)
+ .input("rustlib.rs")
+ .arg("-Cprofile-generate=cpp-profdata")
+ .run();
+ clang()
+ .lto("thin")
+ .arg("-fprofile-generate=cpp-profdata")
+ .use_ld("lld")
+ .arg("-lrustlib-xlto")
+ .out_exe("cmain")
+ .input("cmain.c")
+ .arg("-O3")
+ .run();
+ run("cmain");
+ // Postprocess the profiling data so it can be used by the compiler
+ let profraw_files = shallow_find_files("cpp-profdata", |path| {
+ has_prefix(path, "default") && has_extension(path, "profraw")
+ });
+ let profraw_file = profraw_files.get(0).unwrap();
+ llvm_profdata().merge().output("cpp-profdata/merged.profdata").input(profraw_file).run();
+ rustc()
+ .linker_plugin_lto("on")
+ .profile_use("cpp-profdata/merged.profdata")
+ .output(static_lib_name("rustlib-xlto"))
+ .opt_level("3")
+ .codegen_units(1)
+ .input("rustlib.rs")
+ .run();
+ clang()
+ .lto("thin")
+ .arg("-fprofile-use=cpp-profdata/merged.profdata")
+ .use_ld("lld")
+ .arg("-lrustlib-xlto")
+ .out_exe("cmain")
+ .input("cmain.c")
+ .arg("-O3")
+ .run();
+
+ clang()
+ .input("clib.c")
+ .arg("-fprofile-generate=rs-profdata")
+ .lto("thin")
+ .arg("-c")
+ .out_exe("clib.o")
+ .arg("-O3")
+ .run();
+ llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run();
+ rustc()
+ .linker_plugin_lto("on")
+ .opt_level("3")
+ .codegen_units(1)
+ .arg("-Cprofile-generate=rs-profdata")
+ .linker(&env_var("CLANG"))
+ .link_arg("-fuse-ld=lld")
+ .input("main.rs")
+ .output("rsmain")
+ .run();
+ run("rsmain");
+ // Postprocess the profiling data so it can be used by the compiler
+ let profraw_files = shallow_find_files("rs-profdata", |path| {
+ has_prefix(path, "default") && has_extension(path, "profraw")
+ });
+ let profraw_file = profraw_files.get(0).unwrap();
+ llvm_profdata().merge().output("rs-profdata/merged.profdata").input(profraw_file).run();
+ clang()
+ .input("clib.c")
+ .arg("-fprofile-use=rs-profdata/merged.profdata")
+ .arg("-c")
+ .lto("thin")
+ .out_exe("clib.o")
+ .arg("-O3")
+ .run();
+ rfs::remove_file(static_lib_name("xyz"));
+ llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run();
+ rustc()
+ .linker_plugin_lto("on")
+ .opt_level("3")
+ .codegen_units(1)
+ .arg("-Cprofile-use=rs-profdata/merged.profdata")
+ .linker(&env_var("CLANG"))
+ .link_arg("-fuse-ld=lld")
+ .input("main.rs")
+ .output("rsmain")
+ .run();
+}
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rustlib.rs
similarity index 100%
rename from tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs
rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/rustlib.rs
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile
deleted file mode 100644
index 738e23f..0000000
--- a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile
+++ /dev/null
@@ -1,90 +0,0 @@
-# needs-force-clang-based-tests
-
-# FIXME(#126180): This test doesn't actually run anywhere, because the only
-# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests.
-
-# This test makes sure that cross-language inlining can be used in conjunction
-# with profile-guided optimization. The test only tests that the whole workflow
-# can be executed without anything crashing. It does not test whether PGO or
-# xLTO have any specific effect on the generated code.
-
-include ../tools.mk
-
-COMMON_FLAGS=-Copt-level=3 -Ccodegen-units=1
-
-# LLVM doesn't support instrumenting binaries that use SEH:
-# https://bugs.llvm.org/show_bug.cgi?id=41279
-#
-# Things work fine with -Cpanic=abort though.
-ifdef IS_MSVC
-COMMON_FLAGS+= -Cpanic=abort
-endif
-
-all: cpp-executable rust-executable
-
-cpp-executable:
- $(RUSTC) -Clinker-plugin-lto=on \
- -Cprofile-generate="$(TMPDIR)"/cpp-profdata \
- -o "$(TMPDIR)"/librustlib-xlto.a \
- $(COMMON_FLAGS) \
- ./rustlib.rs
- $(CLANG) -flto=thin \
- -fprofile-generate="$(TMPDIR)"/cpp-profdata \
- -fuse-ld=lld \
- -L "$(TMPDIR)" \
- -lrustlib-xlto \
- -o "$(TMPDIR)"/cmain \
- -O3 \
- ./cmain.c
- $(TMPDIR)/cmain
- # Postprocess the profiling data so it can be used by the compiler
- "$(LLVM_BIN_DIR)"/llvm-profdata merge \
- -o "$(TMPDIR)"/cpp-profdata/merged.profdata \
- "$(TMPDIR)"/cpp-profdata/default_*.profraw
- $(RUSTC) -Clinker-plugin-lto=on \
- -Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
- -o "$(TMPDIR)"/librustlib-xlto.a \
- $(COMMON_FLAGS) \
- ./rustlib.rs
- $(CLANG) -flto=thin \
- -fprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \
- -fuse-ld=lld \
- -L "$(TMPDIR)" \
- -lrustlib-xlto \
- -o "$(TMPDIR)"/cmain \
- -O3 \
- ./cmain.c
-
-rust-executable:
- exit
- $(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3
- (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
- $(RUSTC) -Clinker-plugin-lto=on \
- -Cprofile-generate="$(TMPDIR)"/rs-profdata \
- -L$(TMPDIR) \
- $(COMMON_FLAGS) \
- -Clinker=$(CLANG) \
- -Clink-arg=-fuse-ld=lld \
- -o $(TMPDIR)/rsmain \
- ./main.rs
- $(TMPDIR)/rsmain
- # Postprocess the profiling data so it can be used by the compiler
- "$(LLVM_BIN_DIR)"/llvm-profdata merge \
- -o "$(TMPDIR)"/rs-profdata/merged.profdata \
- "$(TMPDIR)"/rs-profdata/default_*.profraw
- $(CLANG) ./clib.c \
- -fprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \
- -flto=thin \
- -c \
- -o $(TMPDIR)/clib.o \
- -O3
- rm "$(TMPDIR)"/libxyz.a
- (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
- $(RUSTC) -Clinker-plugin-lto=on \
- -Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \
- -L$(TMPDIR) \
- $(COMMON_FLAGS) \
- -Clinker=$(CLANG) \
- -Clink-arg=-fuse-ld=lld \
- -o $(TMPDIR)/rsmain \
- ./main.rs
diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
index f40da66..9257335 100644
--- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
+++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
@@ -3,16 +3,17 @@
//@ needs-force-clang-based-tests
//@ needs-llvm-components riscv
-// FIXME(#126180): This test doesn't actually run anywhere, because the only
-// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests.
+//@ needs-force-clang-based-tests
+// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets
+// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their
+// name.
+// However, this test does not run at all as its name does not contain "clang".
+
+use std::path::PathBuf;
+use std::process::{Command, Output};
+use std::{env, str};
use run_make_support::{bin_name, clang, llvm_readobj, rustc};
-use std::{
- env,
- path::PathBuf,
- process::{Command, Output},
- str,
-};
fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float: bool) {
eprintln!("Checking target {target}");
diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/Makefile b/tests/run-make/cross-lang-lto-upstream-rlibs/Makefile
deleted file mode 100644
index 6f1caa3..0000000
--- a/tests/run-make/cross-lang-lto-upstream-rlibs/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-include ../tools.mk
-
-# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same
-# (so fixing it is harder). See #57765 for context
-ifndef IS_WINDOWS
-
-# This test makes sure that we don't loose upstream object files when compiling
-# staticlibs with -C linker-plugin-lto
-
-all: staticlib.rs upstream.rs
- $(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1
-
- # Check No LTO
- $(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -L. -o $(TMPDIR)/staticlib.a
- (cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a)
- # Make sure the upstream object file was included
- ls $(TMPDIR)/upstream.*.rcgu.o
-
- # Cleanup
- rm $(TMPDIR)/*
-
- # Check ThinLTO
- $(RUSTC) upstream.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin
- $(RUSTC) staticlib.rs -C linker-plugin-lto -Ccodegen-units=1 -Clto=thin -L. -o $(TMPDIR)/staticlib.a
- (cd $(TMPDIR); "$(LLVM_BIN_DIR)"/llvm-ar x ./staticlib.a)
- ls $(TMPDIR)/upstream.*.rcgu.o
-
-else
-
-all:
-
-endif
diff --git a/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs
new file mode 100644
index 0000000..f0b8fa7
--- /dev/null
+++ b/tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs
@@ -0,0 +1,57 @@
+// When using the flag -C linker-plugin-lto, static libraries could lose their upstream object
+// files during compilation. This bug was fixed in #53031, and this test compiles a staticlib
+// dependent on upstream, checking that the upstream object file still exists after no LTO and
+// thin LTO.
+// See https://github.com/rust-lang/rust/pull/53031
+
+use run_make_support::{
+ cwd, has_extension, has_prefix, has_suffix, llvm_ar, rfs, rustc, shallow_find_files,
+ static_lib_name,
+};
+
+fn main() {
+ // The test starts with no LTO enabled.
+ rustc().input("upstream.rs").arg("-Clinker-plugin-lto").codegen_units(1).run();
+ rustc()
+ .input("staticlib.rs")
+ .arg("-Clinker-plugin-lto")
+ .codegen_units(1)
+ .output(static_lib_name("staticlib"))
+ .run();
+ llvm_ar().extract().arg(static_lib_name("staticlib")).run();
+ // Ensure the upstream object file was included.
+ assert_eq!(
+ shallow_find_files(cwd(), |path| {
+ has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o")
+ })
+ .len(),
+ 1
+ );
+ // Remove all output files that are not source Rust code for cleanup.
+ for file in shallow_find_files(cwd(), |path| !has_extension(path, "rs")) {
+ rfs::remove_file(file)
+ }
+
+ // Check it again, with Thin LTO.
+ rustc()
+ .input("upstream.rs")
+ .arg("-Clinker-plugin-lto")
+ .codegen_units(1)
+ .arg("-Clto=thin")
+ .run();
+ rustc()
+ .input("staticlib.rs")
+ .arg("-Clinker-plugin-lto")
+ .codegen_units(1)
+ .arg("-Clto=thin")
+ .output(static_lib_name("staticlib"))
+ .run();
+ llvm_ar().extract().arg(static_lib_name("staticlib")).run();
+ assert_eq!(
+ shallow_find_files(cwd(), |path| {
+ has_prefix(path, "upstream.") && has_suffix(path, ".rcgu.o")
+ })
+ .len(),
+ 1
+ );
+}
diff --git a/tests/run-make/cross-lang-lto/Makefile b/tests/run-make/cross-lang-lto/Makefile
deleted file mode 100644
index 92058f9..0000000
--- a/tests/run-make/cross-lang-lto/Makefile
+++ /dev/null
@@ -1,57 +0,0 @@
-
-include ../tools.mk
-
-# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same
-# (so fixing it is harder). See #57765 for context
-ifndef IS_WINDOWS
-
-# This test makes sure that the object files we generate are actually
-# LLVM bitcode files (as used by linker LTO plugins) when compiling with
-# -Clinker-plugin-lto.
-
-# this only succeeds for bitcode files
-ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1))
-EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1))
-
-BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1
-BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj
-
-all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib
-
-staticlib: lib.rs
- $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a
- $(call EXTRACT_OBJS, liblib.a)
- for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
-
-staticlib-fat-lto: lib.rs
- $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat
- $(call EXTRACT_OBJS, liblib-fat-lto.a)
- for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
-
-staticlib-thin-lto: lib.rs
- $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin
- $(call EXTRACT_OBJS, liblib-thin-lto.a)
- for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
-
-rlib: lib.rs
- $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib
- $(call EXTRACT_OBJS, liblib.rlib)
- for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done
-
-cdylib: lib.rs
- $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o
- $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o)
-
-rdylib: lib.rs
- $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o
- $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o)
-
-exe: lib.rs
- $(BUILD_EXE) -o $(TMPDIR)/exe.o
- $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o)
-
-else
-
-all:
-
-endif
diff --git a/tests/run-make/cross-lang-lto/rmake.rs b/tests/run-make/cross-lang-lto/rmake.rs
new file mode 100644
index 0000000..dc376b5
--- /dev/null
+++ b/tests/run-make/cross-lang-lto/rmake.rs
@@ -0,0 +1,110 @@
+// This test checks that the object files we generate are actually
+// LLVM bitcode files (as used by linker LTO plugins) when compiling with
+// -Clinker-plugin-lto.
+// See https://github.com/rust-lang/rust/pull/50000
+
+#![feature(path_file_prefix)]
+
+use std::path::PathBuf;
+
+use run_make_support::{
+ cwd, has_extension, has_prefix, llvm_ar, llvm_bcanalyzer, path, rfs, rust_lib_name, rustc,
+ shallow_find_files, static_lib_name,
+};
+
+fn main() {
+ check_bitcode(LibBuild {
+ source: path("lib.rs"),
+ crate_type: Some("staticlib"),
+ output: path(static_lib_name("liblib")),
+ lto: None,
+ emit_obj: false,
+ });
+ check_bitcode(LibBuild {
+ source: path("lib.rs"),
+ crate_type: Some("staticlib"),
+ output: path(static_lib_name("liblib-fat-lto")),
+ lto: Some("fat"),
+ emit_obj: false,
+ });
+ check_bitcode(LibBuild {
+ source: path("lib.rs"),
+ crate_type: Some("staticlib"),
+ output: path(static_lib_name("liblib-thin-lto")),
+ lto: Some("thin"),
+ emit_obj: false,
+ });
+ check_bitcode(LibBuild {
+ source: path("lib.rs"),
+ crate_type: Some("rlib"),
+ output: path(rust_lib_name("liblib")),
+ lto: None,
+ emit_obj: false,
+ });
+ check_bitcode(LibBuild {
+ source: path("lib.rs"),
+ crate_type: Some("cdylib"),
+ output: path("cdylib.o"),
+ lto: None,
+ emit_obj: true,
+ });
+ check_bitcode(LibBuild {
+ source: path("lib.rs"),
+ crate_type: Some("dylib"),
+ output: path("rdylib.o"),
+ lto: None,
+ emit_obj: true,
+ });
+ check_bitcode(LibBuild {
+ source: path("main.rs"),
+ crate_type: None,
+ output: path("exe.o"),
+ lto: None,
+ emit_obj: true,
+ });
+}
+
+#[track_caller]
+fn check_bitcode(instructions: LibBuild) {
+ let mut rustc = rustc();
+ rustc
+ .input(instructions.source)
+ .output(&instructions.output)
+ .opt_level("2")
+ .codegen_units(1)
+ .arg("-Clinker-plugin-lto");
+ if instructions.emit_obj {
+ rustc.emit("obj");
+ }
+ if let Some(crate_type) = instructions.crate_type {
+ rustc.crate_type(crate_type);
+ }
+ if let Some(lto) = instructions.lto {
+ rustc.arg(format!("-Clto={lto}"));
+ }
+ rustc.run();
+
+ if instructions.output.extension().unwrap() != "o" {
+ // Remove all potential leftover object files, then turn the output into an object file.
+ for object in shallow_find_files(cwd(), |path| has_extension(path, "o")) {
+ rfs::remove_file(object);
+ }
+ llvm_ar().extract().arg(&instructions.output).run();
+ }
+
+ for object in shallow_find_files(cwd(), |path| {
+ has_prefix(path, instructions.output.file_prefix().unwrap().to_str().unwrap())
+ && has_extension(path, "o")
+ }) {
+ // All generated object files should be LLVM bitcode files - this will fail otherwise.
+ llvm_bcanalyzer().input(object).run();
+ }
+}
+
+struct LibBuild {
+ source: PathBuf,
+ crate_type: Option<&'static str>,
+ output: PathBuf,
+ lto: Option<&'static str>,
+ emit_obj: bool,
+}
diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs
index 6bff5c0..246539b 100644
--- a/tests/run-make/doctests-keep-binaries/rmake.rs
+++ b/tests/run-make/doctests-keep-binaries/rmake.rs
@@ -1,9 +1,10 @@
// Check that valid binaries are persisted by running them, regardless of whether the
// --run or --no-run option is used.
+use std::path::Path;
+
use run_make_support::rfs::{create_dir, remove_dir_all};
use run_make_support::{run, rustc, rustdoc};
-use std::path::Path;
fn setup_test_env<F: FnOnce(&Path, &Path)>(callback: F) {
let out_dir = Path::new("doctests");
diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs
index 5d829b9..c7be829 100644
--- a/tests/run-make/doctests-runtool/rmake.rs
+++ b/tests/run-make/doctests-runtool/rmake.rs
@@ -1,8 +1,9 @@
// Tests behavior of rustdoc `--runtool`.
+use std::path::PathBuf;
+
use run_make_support::rfs::{create_dir, remove_dir_all};
use run_make_support::{rustc, rustdoc};
-use std::path::PathBuf;
fn mkdir(name: &str) -> PathBuf {
let dir = PathBuf::from(name);
diff --git a/tests/run-make/dos-device-input/rmake.rs b/tests/run-make/dos-device-input/rmake.rs
new file mode 100644
index 0000000..dee3b86
--- /dev/null
+++ b/tests/run-make/dos-device-input/rmake.rs
@@ -0,0 +1,13 @@
+//@ only-windows
+// Reason: dos devices are a Windows thing
+
+use std::path::Path;
+
+use run_make_support::{rustc, static_lib_name};
+
+fn main() {
+ rustc().input(r"\\.\NUL").crate_type("staticlib").run();
+ rustc().input(r"\\?\NUL").crate_type("staticlib").run();
+
+ assert!(Path::new(&static_lib_name("rust_out")).exists());
+}
diff --git a/tests/run-make/dump-ice-to-disk/rmake.rs b/tests/run-make/dump-ice-to-disk/rmake.rs
index 2fb5c82..48b4071 100644
--- a/tests/run-make/dump-ice-to-disk/rmake.rs
+++ b/tests/run-make/dump-ice-to-disk/rmake.rs
@@ -1,81 +1,197 @@
-// This test checks if internal compilation error (ICE) log files work as expected.
-// - Get the number of lines from the log files without any configuration options,
-// then check that the line count doesn't change if the backtrace gets configured to be short
-// or full.
-// - Check that disabling ICE logging results in zero files created.
-// - Check that the ICE files contain some of the expected strings.
-// See https://github.com/rust-lang/rust/pull/108714
+//! This test checks if Internal Compilation Error (ICE) dump files `rustc-ice*.txt` work as
+//! expected.
+//!
+//! - Basic sanity checks on a default ICE dump.
+//! - Get the number of lines from the dump files without any `RUST_BACKTRACE` options, then check
+//! ICE dump file (line count) is not affected by `RUSTC_BACKTRACE` settings.
+//! - Check that disabling ICE dumping results in zero dump files created.
+//! - Check that the ICE dump contain some of the expected strings.
+//! - Check that `RUST_BACKTRACE=0` prevents ICE dump from created.
+//! - Exercise the `-Zmetrics-dir` nightly flag (#128914):
+//! - When `-Zmetrics=dir=PATH` is present but `RUSTC_ICE` is not set, check that the ICE dump
+//! is placed under `PATH`.
+//! - When `RUSTC_ICE=RUSTC_ICE_PATH` and `-Zmetrics-dir=METRICS_PATH` are both provided, check
+//! that `RUSTC_ICE_PATH` takes precedence and no ICE dump is emitted under `METRICS_PATH`.
+//!
+//! See <https://github.com/rust-lang/rust/pull/108714>.
-use run_make_support::{cwd, has_extension, has_prefix, rfs, rustc, shallow_find_files};
+//@ ignore-windows
+// FIXME(#128911): @jieyouxu: This test is sometimes for whatever forsaken reason flakey in
+// `i686-mingw`, and I cannot reproduce it locally. The error messages upon assertion failure in
+// this test is intentionally extremely verbose to aid debugging that issue.
-fn main() {
- rustc().input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
- let default = get_text_from_ice(".").lines().count();
- clear_ice_files();
+use std::cell::OnceCell;
+use std::path::{Path, PathBuf};
- rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
- let ice_text = get_text_from_ice(cwd());
- let default_set = ice_text.lines().count();
- let content = ice_text;
- let ice_files = shallow_find_files(cwd(), |path| {
- has_prefix(path, "rustc-ice") && has_extension(path, "txt")
- });
- assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file.
- let ice_file_name =
- ice_files.first().and_then(|f| f.file_name()).and_then(|n| n.to_str()).unwrap();
- // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on Windows.
- assert!(!ice_file_name.contains(":"), "{ice_file_name}");
+use run_make_support::{
+ cwd, filename_contains, has_extension, has_prefix, rfs, run_in_tmpdir, rustc,
+ shallow_find_files,
+};
- clear_ice_files();
- rustc()
- .env("RUSTC_ICE", cwd())
- .input("lib.rs")
- .env("RUST_BACKTRACE", "short")
- .arg("-Ztreat-err-as-bug=1")
- .run_fail();
- let short = get_text_from_ice(cwd()).lines().count();
- clear_ice_files();
- rustc()
- .env("RUSTC_ICE", cwd())
- .input("lib.rs")
- .env("RUST_BACKTRACE", "full")
- .arg("-Ztreat-err-as-bug=1")
- .run_fail();
- let full = get_text_from_ice(cwd()).lines().count();
- clear_ice_files();
-
- // The ICE dump is explicitly disabled. Therefore, this should produce no files.
- rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
- let ice_files = shallow_find_files(cwd(), |path| {
- has_prefix(path, "rustc-ice") && has_extension(path, "txt")
- });
- assert!(ice_files.is_empty()); // There should be 0 ICE files.
-
- // The line count should not change.
- assert_eq!(short, default_set);
- assert_eq!(short, default);
- assert_eq!(full, default_set);
- assert!(default > 0);
- // Some of the expected strings in an ICE file should appear.
- assert!(content.contains("thread 'rustc' panicked at"));
- assert!(content.contains("stack backtrace:"));
+#[derive(Debug)]
+struct IceDump {
+ name: &'static str,
+ path: PathBuf,
+ message: String,
}
-fn clear_ice_files() {
- let ice_files = shallow_find_files(cwd(), |path| {
- has_prefix(path, "rustc-ice") && has_extension(path, "txt")
- });
- for file in ice_files {
- rfs::remove_file(file);
+impl IceDump {
+ fn lines_count(&self) -> usize {
+ self.message.lines().count()
}
}
#[track_caller]
-fn get_text_from_ice(dir: impl AsRef<std::path::Path>) -> String {
- let ice_files =
- shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt"));
+fn assert_ice_len_equals(left: &IceDump, right: &IceDump) {
+ let left_len = left.lines_count();
+ let right_len = right.lines_count();
+
+ if left_len != right_len {
+ eprintln!("=== {} ICE MESSAGE ({} lines) ====", left.name, left_len);
+ eprintln!("{}", left.message);
+
+ eprintln!("=== {} ICE MESSAGE ({} lines) ====", right.name, right_len);
+ eprintln!("{}", right.message);
+
+ eprintln!("====================================");
+ panic!(
+ "ICE message length mismatch: {} has {} lines but {} has {} lines",
+ left.name, left_len, right.name, right_len
+ );
+ }
+}
+
+fn find_ice_dumps_in_dir<P: AsRef<Path>>(dir: P) -> Vec<PathBuf> {
+ shallow_find_files(dir, |path| has_prefix(path, "rustc-ice") && has_extension(path, "txt"))
+}
+
+// Assert only one `rustc-ice*.txt` ICE file exists, and extract the ICE message from the ICE file.
+#[track_caller]
+fn extract_exactly_one_ice_file<P: AsRef<Path>>(name: &'static str, dir: P) -> IceDump {
+ let ice_files = find_ice_dumps_in_dir(dir);
assert_eq!(ice_files.len(), 1); // There should only be 1 ICE file.
- let ice_file = ice_files.get(0).unwrap();
- let output = rfs::read_to_string(ice_file);
- output
+ let path = ice_files.get(0).unwrap();
+ let message = rfs::read_to_string(path);
+ IceDump { name, path: path.to_path_buf(), message }
+}
+
+fn main() {
+ // Establish baseline ICE message.
+ let mut default_ice_dump = OnceCell::new();
+ run_in_tmpdir(|| {
+ rustc().env("RUSTC_ICE", cwd()).input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
+ let dump = extract_exactly_one_ice_file("baseline", cwd());
+ // Ensure that the ICE dump path doesn't contain `:`, because they cause problems on
+ // Windows.
+ assert!(!filename_contains(&dump.path, ":"), "{} contains `:`", dump.path.display());
+ // Some of the expected strings in an ICE file should appear.
+ assert!(dump.message.contains("thread 'rustc' panicked at"));
+ assert!(dump.message.contains("stack backtrace:"));
+ default_ice_dump.set(dump).unwrap();
+ });
+ let default_ice_dump = default_ice_dump.get().unwrap();
+
+ test_backtrace_short(default_ice_dump);
+ test_backtrace_full(default_ice_dump);
+ test_backtrace_disabled(default_ice_dump);
+ test_ice_dump_disabled();
+
+ test_metrics_dir(default_ice_dump);
+}
+
+#[track_caller]
+fn test_backtrace_short(baseline: &IceDump) {
+ run_in_tmpdir(|| {
+ rustc()
+ .env("RUSTC_ICE", cwd())
+ .input("lib.rs")
+ .env("RUST_BACKTRACE", "short")
+ .arg("-Ztreat-err-as-bug=1")
+ .run_fail();
+ let dump = extract_exactly_one_ice_file("RUST_BACKTRACE=short", cwd());
+ // Backtrace length in dump shouldn't be changed by `RUST_BACKTRACE`.
+ assert_ice_len_equals(baseline, &dump);
+ });
+}
+
+#[track_caller]
+fn test_backtrace_full(baseline: &IceDump) {
+ run_in_tmpdir(|| {
+ rustc()
+ .env("RUSTC_ICE", cwd())
+ .input("lib.rs")
+ .env("RUST_BACKTRACE", "full")
+ .arg("-Ztreat-err-as-bug=1")
+ .run_fail();
+ let dump = extract_exactly_one_ice_file("RUST_BACKTRACE=full", cwd());
+ // Backtrace length in dump shouldn't be changed by `RUST_BACKTRACE`.
+ assert_ice_len_equals(baseline, &dump);
+ });
+}
+
+#[track_caller]
+fn test_backtrace_disabled(baseline: &IceDump) {
+ run_in_tmpdir(|| {
+ rustc()
+ .env("RUSTC_ICE", cwd())
+ .input("lib.rs")
+ .env("RUST_BACKTRACE", "0")
+ .arg("-Ztreat-err-as-bug=1")
+ .run_fail();
+ let dump = extract_exactly_one_ice_file("RUST_BACKTRACE=disabled", cwd());
+ // Backtrace length in dump shouldn't be changed by `RUST_BACKTRACE`.
+ assert_ice_len_equals(baseline, &dump);
+ });
+}
+
+#[track_caller]
+fn test_ice_dump_disabled() {
+ // The ICE dump is explicitly disabled. Therefore, this should produce no files.
+ run_in_tmpdir(|| {
+ rustc().env("RUSTC_ICE", "0").input("lib.rs").arg("-Ztreat-err-as-bug=1").run_fail();
+ let ice_files = find_ice_dumps_in_dir(cwd());
+ assert!(ice_files.is_empty(), "there should be no ICE files if `RUSTC_ICE=0` is set");
+ });
+}
+
+#[track_caller]
+fn test_metrics_dir(baseline: &IceDump) {
+ test_flag_only(baseline);
+ test_flag_and_env(baseline);
+}
+
+#[track_caller]
+fn test_flag_only(baseline: &IceDump) {
+ run_in_tmpdir(|| {
+ let metrics_arg = format!("-Zmetrics-dir={}", cwd().display());
+ rustc()
+ .env_remove("RUSTC_ICE") // prevent interference from environment
+ .input("lib.rs")
+ .arg("-Ztreat-err-as-bug=1")
+ .arg(metrics_arg)
+ .run_fail();
+ let dump = extract_exactly_one_ice_file("-Zmetrics-dir only", cwd());
+ assert_ice_len_equals(baseline, &dump);
+ });
+}
+
+#[track_caller]
+fn test_flag_and_env(baseline: &IceDump) {
+ run_in_tmpdir(|| {
+ let metrics_arg = format!("-Zmetrics-dir={}", cwd().display());
+ let real_dir = cwd().join("actually_put_ice_here");
+ rfs::create_dir(&real_dir);
+ rustc()
+ .input("lib.rs")
+ .env("RUSTC_ICE", &real_dir)
+ .arg("-Ztreat-err-as-bug=1")
+ .arg(metrics_arg)
+ .run_fail();
+
+ let cwd_ice_files = find_ice_dumps_in_dir(cwd());
+ assert!(cwd_ice_files.is_empty(), "RUSTC_ICE should override -Zmetrics-dir");
+
+ let dump = extract_exactly_one_ice_file("RUSTC_ICE overrides -Zmetrics-dir", real_dir);
+ assert_ice_len_equals(baseline, &dump);
+ });
}
diff --git a/tests/run-make/dylib-soname/rmake.rs b/tests/run-make/dylib-soname/rmake.rs
index a0215a6..cec0d46 100644
--- a/tests/run-make/dylib-soname/rmake.rs
+++ b/tests/run-make/dylib-soname/rmake.rs
@@ -4,7 +4,6 @@
//@ only-linux
//@ ignore-cross-compile
-use run_make_support::regex::Regex;
use run_make_support::{cmd, run_in_tmpdir, rustc};
fn main() {
diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs
index 33c1231..8ac9073 100644
--- a/tests/run-make/emit-shared-files/rmake.rs
+++ b/tests/run-make/emit-shared-files/rmake.rs
@@ -5,9 +5,10 @@
// `all-shared` should only emit files that can be shared between crates.
// See https://github.com/rust-lang/rust/pull/83478
-use run_make_support::{has_extension, has_prefix, rustdoc, shallow_find_files};
use std::path::Path;
+use run_make_support::{has_extension, has_prefix, rustdoc, shallow_find_files};
+
fn main() {
rustdoc()
.arg("-Zunstable-options")
diff --git a/tests/run-make/extern-flag-disambiguates/rmake.rs b/tests/run-make/extern-flag-disambiguates/rmake.rs
index 2d7d7f6..89cda02 100644
--- a/tests/run-make/extern-flag-disambiguates/rmake.rs
+++ b/tests/run-make/extern-flag-disambiguates/rmake.rs
@@ -1,6 +1,6 @@
//@ ignore-cross-compile
-use run_make_support::{cwd, run, rustc};
+use run_make_support::{run, rustc};
// Attempt to build this dependency tree:
//
diff --git a/tests/run-make/fmt-write-bloat/Makefile b/tests/run-make/fmt-write-bloat/Makefile
deleted file mode 100644
index 70e04b9..0000000
--- a/tests/run-make/fmt-write-bloat/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-include ../tools.mk
-
-# ignore-windows
-
-ifeq ($(shell $(RUSTC) -vV | grep 'host: $(TARGET)'),)
-
-# Don't run this test when cross compiling.
-all:
-
-else
-
-NM = nm
-
-PANIC_SYMS = panic_bounds_check Debug
-
-# Allow for debug_assert!() in debug builds of std.
-ifdef NO_DEBUG_ASSERTIONS
-PANIC_SYMS += panicking panic_fmt pad_integral Display Debug
-endif
-
-all: main.rs
- $(RUSTC) $< -O
- $(NM) $(call RUN_BINFILE,main) | $(CGREP) -v $(PANIC_SYMS)
-
-endif
diff --git a/tests/run-make/fmt-write-bloat/main.rs b/tests/run-make/fmt-write-bloat/main.rs
index e86c4801..6f206d6 100644
--- a/tests/run-make/fmt-write-bloat/main.rs
+++ b/tests/run-make/fmt-write-bloat/main.rs
@@ -5,7 +5,7 @@
use core::fmt;
use core::fmt::Write;
-#[link(name = "c")]
+#[cfg_attr(not(windows), link(name = "c"))]
extern "C" {}
struct Dummy;
diff --git a/tests/run-make/fmt-write-bloat/rmake.rs b/tests/run-make/fmt-write-bloat/rmake.rs
new file mode 100644
index 0000000..6875ef9
--- /dev/null
+++ b/tests/run-make/fmt-write-bloat/rmake.rs
@@ -0,0 +1,40 @@
+//! Before #78122, writing any `fmt::Arguments` would trigger the inclusion of `usize` formatting
+//! and padding code in the resulting binary, because indexing used in `fmt::write` would generate
+//! code using `panic_bounds_check`, which prints the index and length.
+//!
+//! These bounds checks are not necessary, as `fmt::Arguments` never contains any out-of-bounds
+//! indexes. The test is a `run-make` test, because it needs to check the result after linking. A
+//! codegen or assembly test doesn't check the parts that will be pulled in from `core` by the
+//! linker.
+//!
+//! In this test, we try to check that the `usize` formatting and padding code are not present in
+//! the final binary by checking that panic symbols such as `panic_bounds_check` are **not**
+//! present.
+//!
+//! Some CI jobs try to run faster by disabling debug assertions (through setting
+//! `NO_DEBUG_ASSERTIONS=1`). If debug assertions are disabled, then we can check for the absence of
+//! additional `usize` formatting and padding related symbols.
+
+//@ ignore-windows
+// Reason:
+// - MSVC targets really need to parse the .pdb file (aka the debug information).
+// On Windows there's an API for that (dbghelp) which maybe we can use
+// - MinGW targets have a lot of symbols included in their runtime which we can't avoid.
+// We would need to make the symbols we're looking for more specific for this test to work.
+//@ ignore-cross-compile
+
+use run_make_support::env::no_debug_assertions;
+use run_make_support::rustc;
+use run_make_support::symbols::any_symbol_contains;
+
+fn main() {
+ rustc().input("main.rs").opt().run();
+ // panic machinery identifiers, these should not appear in the final binary
+ let mut panic_syms = vec!["panic_bounds_check", "Debug"];
+ if no_debug_assertions() {
+ // if debug assertions are allowed, we need to allow these,
+ // otherwise, add them to the list of symbols to deny.
+ panic_syms.extend_from_slice(&["panicking", "panic_fmt", "pad_integral", "Display"]);
+ }
+ assert!(!any_symbol_contains("main", &panic_syms));
+}
diff --git a/tests/run-make/foreign-double-unwind/Makefile b/tests/run-make/foreign-double-unwind/Makefile
deleted file mode 100644
index b5e5280..0000000
--- a/tests/run-make/foreign-double-unwind/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# ignore-cross-compile
-# needs-unwind
-include ../tools.mk
-
-all: foo
- $(call RUN,foo) | $(CGREP) -v unreachable
-
-foo: foo.rs $(call NATIVE_STATICLIB,foo)
- $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS)
-
-$(TMPDIR)/libfoo.o: foo.cpp
- $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/foreign-double-unwind/rmake.rs b/tests/run-make/foreign-double-unwind/rmake.rs
new file mode 100644
index 0000000..9bd3b4c
--- /dev/null
+++ b/tests/run-make/foreign-double-unwind/rmake.rs
@@ -0,0 +1,21 @@
+// When using foreign function interface (FFI) with C++, it is possible
+// to run into a "double unwind" if either both Rust and C++ run into a panic
+// and exception at the same time, or C++ encounters two exceptions. In this case,
+// one of the panic unwinds would be leaked and the other would be kept, leading
+// to undefined behaviour. After this was fixed in #92911, this test checks that
+// the keyword "unreachable" indicative of this bug triggering in this specific context
+// does not appear after successfully compiling and executing the program.
+// See https://github.com/rust-lang/rust/pull/92911
+
+//@ needs-unwind
+// Reason: this test exercises panic unwinding
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib_cxx, run_fail, rustc};
+
+fn main() {
+ build_native_static_lib_cxx("foo");
+ rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run();
+ run_fail("foo").assert_stdout_not_contains("unreachable");
+}
diff --git a/tests/run-make/foreign-exceptions/Makefile b/tests/run-make/foreign-exceptions/Makefile
deleted file mode 100644
index 56c41b2..0000000
--- a/tests/run-make/foreign-exceptions/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# ignore-cross-compile
-# needs-unwind
-include ../tools.mk
-
-all: foo
- $(call RUN,foo)
-
-foo: foo.rs $(call NATIVE_STATICLIB,foo)
- $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS)
-
-$(TMPDIR)/libfoo.o: foo.cpp
- $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/foreign-exceptions/rmake.rs b/tests/run-make/foreign-exceptions/rmake.rs
new file mode 100644
index 0000000..929319f
--- /dev/null
+++ b/tests/run-make/foreign-exceptions/rmake.rs
@@ -0,0 +1,19 @@
+// This test was created to check that compilation and execution still works
+// after the addition of a new feature, in #65646: the ability to unwind panics
+// and exceptions back and forth between Rust and C++. This is a basic smoke test,
+// this feature being broken in quiet or subtle ways could still result in this test
+// passing.
+// See https://github.com/rust-lang/rust/pull/65646
+
+//@ needs-unwind
+// Reason: this test exercises panic unwinding
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_static_lib_cxx, run, rustc};
+
+fn main() {
+ build_native_static_lib_cxx("foo");
+ rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run();
+ run("foo");
+}
diff --git a/tests/run-make/git_clone_sha1.sh b/tests/run-make/git_clone_sha1.sh
deleted file mode 100644
index 626e4e4..0000000
--- a/tests/run-make/git_clone_sha1.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash -x
-
-# Usage: $0 project_name url sha1
-# Get the crate with the specified sha1.
-#
-# all arguments are required.
-#
-# See below link for git usage:
-# https://stackoverflow.com/questions/3489173#14091182
-
-# Mandatory arguments:
-PROJECT_NAME=$1
-URL=$2
-SHA1=$3
-
-function err_exit() {
- echo "ERROR:" $*
- exit 1
-}
-
-git clone $URL $PROJECT_NAME || err_exit
-cd $PROJECT_NAME || err_exit
-git reset --hard $SHA1 || err_exit
diff --git a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs
index 8ba3a03..1c13677 100644
--- a/tests/run-make/ice-dep-cannot-find-dep/rmake.rs
+++ b/tests/run-make/ice-dep-cannot-find-dep/rmake.rs
@@ -16,7 +16,7 @@
// If we used `rustc` the additional '-L rmake_out' option would allow rustc to
// actually find the crate.
-use run_make_support::{bare_rustc, rfs, rust_lib_name, rustc};
+use run_make_support::{bare_rustc, rust_lib_name, rustc};
fn main() {
rustc().crate_name("a").crate_type("rlib").input("a.rs").arg("--verbose").run();
diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
index 14e7567..47dce85 100644
--- a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
+++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs
@@ -13,8 +13,7 @@
//@ ignore-nvptx64-nvidia-cuda
// FIXME: can't find crate for `std`
-use run_make_support::rfs;
-use run_make_support::rustc;
+use run_make_support::{rfs, rustc};
fn main() {
rfs::create_dir("src");
diff --git a/tests/run-make/incr-test-moved-file/rmake.rs b/tests/run-make/incr-test-moved-file/rmake.rs
index f314e11..0ba1b0d 100644
--- a/tests/run-make/incr-test-moved-file/rmake.rs
+++ b/tests/run-make/incr-test-moved-file/rmake.rs
@@ -14,7 +14,7 @@
//@ ignore-nvptx64-nvidia-cuda
// FIXME: can't find crate for 'std'
-use run_make_support::{rfs, rust_lib_name, rustc};
+use run_make_support::{rfs, rustc};
fn main() {
rfs::create_dir("incr");
diff --git a/tests/run-make/incremental-debugger-visualizer/rmake.rs b/tests/run-make/incremental-debugger-visualizer/rmake.rs
index 985816f..07c920c 100644
--- a/tests/run-make/incremental-debugger-visualizer/rmake.rs
+++ b/tests/run-make/incremental-debugger-visualizer/rmake.rs
@@ -3,7 +3,6 @@
// See https://github.com/rust-lang/rust/pull/111641
use run_make_support::{invalid_utf8_contains, invalid_utf8_not_contains, rfs, rustc};
-use std::io::Read;
fn main() {
rfs::create_file("foo.py");
diff --git a/tests/run-make/inline-always-many-cgu/rmake.rs b/tests/run-make/inline-always-many-cgu/rmake.rs
index 5a6929c..678b949 100644
--- a/tests/run-make/inline-always-many-cgu/rmake.rs
+++ b/tests/run-make/inline-always-many-cgu/rmake.rs
@@ -1,9 +1,8 @@
-use run_make_support::regex::Regex;
-use run_make_support::rfs;
-use run_make_support::rustc;
-
use std::ffi::OsStr;
+use run_make_support::regex::Regex;
+use run_make_support::{rfs, rustc};
+
fn main() {
rustc().input("foo.rs").emit("llvm-ir").codegen_units(2).run();
let re = Regex::new(r"\bcall\b").unwrap();
diff --git a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs
index d0f193d..4309767 100644
--- a/tests/run-make/intrinsic-unreachable/exit-unreachable.rs
+++ b/tests/run-make/intrinsic-unreachable/exit-unreachable.rs
@@ -1,7 +1,6 @@
#![feature(core_intrinsics)]
#![crate_type = "lib"]
use std::arch::asm;
-
use std::intrinsics;
#[allow(unreachable_code)]
diff --git a/tests/run-make/invalid-library/rmake.rs b/tests/run-make/invalid-library/rmake.rs
index 42afb74..6b3ae1d 100644
--- a/tests/run-make/invalid-library/rmake.rs
+++ b/tests/run-make/invalid-library/rmake.rs
@@ -4,8 +4,7 @@
// one appearing in stderr in this scenario.
// See https://github.com/rust-lang/rust/pull/12645
-use run_make_support::rfs;
-use run_make_support::{llvm_ar, rustc};
+use run_make_support::{llvm_ar, rfs, rustc};
fn main() {
rfs::create_file("lib.rmeta");
diff --git a/tests/run-make/issue-107495-archive-permissions/rmake.rs b/tests/run-make/issue-107495-archive-permissions/rmake.rs
index f47b8d7..f210b7c 100644
--- a/tests/run-make/issue-107495-archive-permissions/rmake.rs
+++ b/tests/run-make/issue-107495-archive-permissions/rmake.rs
@@ -3,12 +3,12 @@
#[cfg(unix)]
extern crate libc;
-use run_make_support::{aux_build, rfs};
-
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
+use run_make_support::{aux_build, rfs};
+
fn main() {
#[cfg(unix)]
unsafe {
diff --git a/tests/run-make/issue-35164/Makefile b/tests/run-make/issue-35164/Makefile
deleted file mode 100644
index 38aa6f1..0000000
--- a/tests/run-make/issue-35164/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
- $(RUSTC) main.rs --error-format json 2>&1 | $(CGREP) -e '"byte_start":23\b' '"byte_end":29\b'
diff --git a/tests/run-make/issue-36710/Makefile b/tests/run-make/issue-36710/Makefile
deleted file mode 100644
index 7b91107..0000000
--- a/tests/run-make/issue-36710/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# ignore-cross-compile
-# ignore-none no-std is not supported
-# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM
-# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM
-# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
-# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain
-# (see dist-i586-gnu-i586-i686-musl Dockerfile)
-# ignore-sgx
-
-include ../tools.mk
-
-all: foo
- $(call RUN,foo)
-
-foo: foo.rs $(call NATIVE_STATICLIB,foo)
- $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET)
-
-$(TMPDIR)/libfoo.o: foo.cpp
- $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/issue-47551/Makefile b/tests/run-make/issue-47551/Makefile
deleted file mode 100644
index 3fe0a6e..0000000
--- a/tests/run-make/issue-47551/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# only-linux
-# ignore-32bit
-
-include ../tools.mk
-
-all:
- # --target $(TARGET) ensures the right gcc flags are used for cross compilation
- $(RUSTC) --target $(TARGET) eh_frame-terminator.rs
- $(call RUN,eh_frame-terminator) | $(CGREP) '1122334455667788'
- objdump --dwarf=frames $(TMPDIR)/eh_frame-terminator | $(CGREP) 'ZERO terminator'
diff --git a/tests/run-make/issue-69368/Makefile b/tests/run-make/issue-69368/Makefile
deleted file mode 100644
index b1229d1..0000000
--- a/tests/run-make/issue-69368/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# Test that previously triggered a linker failure with root cause
-# similar to one found in the issue #69368.
-#
-# The crate that provides oom lang item is missing some other lang
-# items. Necessary to prevent the use of start-group / end-group.
-#
-# The weak lang items are defined in a separate compilation units,
-# so that linker could omit them if not used.
-#
-# The crates that need those weak lang items are dependencies of
-# crates that provide them.
-
-all:
- $(RUSTC) a.rs
- $(RUSTC) b.rs
- $(RUSTC) c.rs
diff --git a/tests/run-make/issue-88756-default-output/Makefile b/tests/run-make/issue-88756-default-output/Makefile
deleted file mode 100644
index d1c3d0f..0000000
--- a/tests/run-make/issue-88756-default-output/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
- $(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout
diff --git a/tests/run-make/issue-88756-default-output/README.md b/tests/run-make/issue-88756-default-output/README.md
deleted file mode 100644
index 8cbfac4..0000000
--- a/tests/run-make/issue-88756-default-output/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756).
diff --git a/tests/run-make/issue-88756-default-output/x.rs b/tests/run-make/issue-88756-default-output/x.rs
deleted file mode 100644
index 5df7576..0000000
--- a/tests/run-make/issue-88756-default-output/x.rs
+++ /dev/null
@@ -1 +0,0 @@
-// nothing to see here
diff --git a/tests/run-make/issue-35164/main.rs b/tests/run-make/json-error-no-offset/main.rs
similarity index 100%
rename from tests/run-make/issue-35164/main.rs
rename to tests/run-make/json-error-no-offset/main.rs
diff --git a/tests/run-make/json-error-no-offset/rmake.rs b/tests/run-make/json-error-no-offset/rmake.rs
new file mode 100644
index 0000000..629d9c4
--- /dev/null
+++ b/tests/run-make/json-error-no-offset/rmake.rs
@@ -0,0 +1,15 @@
+// The byte positions in json format error logging used to have a small, difficult
+// to predict offset. This was changed to be the top of the file every time in #42973,
+// and this test checks that the measurements appearing in the standard error are correct.
+// See https://github.com/rust-lang/rust/issues/35164
+
+use run_make_support::rustc;
+
+fn main() {
+ rustc()
+ .input("main.rs")
+ .error_format("json")
+ .run()
+ .assert_stderr_contains(r#""byte_start":23"#)
+ .assert_stderr_contains(r#""byte_end":29"#);
+}
diff --git a/tests/run-make/issue-35164/submodule/mod.rs b/tests/run-make/json-error-no-offset/submodule/mod.rs
similarity index 100%
rename from tests/run-make/issue-35164/submodule/mod.rs
rename to tests/run-make/json-error-no-offset/submodule/mod.rs
diff --git a/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs b/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs
index 766acfc..0c5e120 100644
--- a/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs
+++ b/tests/run-make/lib-trait-for-trait-no-ice/rmake.rs
@@ -5,9 +5,10 @@
// the lib crate-type flag was actually followed.
// See https://github.com/rust-lang/rust/issues/18943
-use run_make_support::{rust_lib_name, rustc};
use std::path::Path;
+use run_make_support::{rust_lib_name, rustc};
+
fn main() {
rustc().input("foo.rs").crate_type("lib").run();
assert!(Path::new(&rust_lib_name("foo")).exists());
diff --git a/tests/run-make/libtest-thread-limit/test.rs b/tests/run-make/libtest-thread-limit/test.rs
index 88e8a49..87e1d51 100644
--- a/tests/run-make/libtest-thread-limit/test.rs
+++ b/tests/run-make/libtest-thread-limit/test.rs
@@ -1,8 +1,6 @@
-use std::{
- io::ErrorKind,
- sync::OnceLock,
- thread::{self, Builder, ThreadId},
-};
+use std::io::ErrorKind;
+use std::sync::OnceLock;
+use std::thread::{self, Builder, ThreadId};
static THREAD_ID: OnceLock<ThreadId> = OnceLock::new();
diff --git a/tests/run-make/link-args-order/rmake.rs b/tests/run-make/link-args-order/rmake.rs
index d238ad2..b7ef833 100644
--- a/tests/run-make/link-args-order/rmake.rs
+++ b/tests/run-make/link-args-order/rmake.rs
@@ -3,15 +3,14 @@
// checks that linker arguments remain intact and in the order they were originally passed in.
// See https://github.com/rust-lang/rust/pull/70665
-//@ ignore-msvc
-// Reason: the ld linker does not exist on Windows.
-
-use run_make_support::rustc;
+use run_make_support::{is_msvc, rustc};
fn main() {
+ let linker = if is_msvc() { "msvc" } else { "ld" };
+
rustc()
.input("empty.rs")
- .linker_flavor("ld")
+ .linker_flavor(linker)
.link_arg("a")
.link_args("b c")
.link_args("d e")
@@ -20,7 +19,7 @@ fn main() {
.assert_stderr_contains(r#""a" "b" "c" "d" "e" "f""#);
rustc()
.input("empty.rs")
- .linker_flavor("ld")
+ .linker_flavor(linker)
.arg("-Zpre-link-arg=a")
.arg("-Zpre-link-args=b c")
.arg("-Zpre-link-args=d e")
diff --git a/tests/run-make/link-cfg/Makefile b/tests/run-make/link-cfg/Makefile
deleted file mode 100644
index a409970..0000000
--- a/tests/run-make/link-cfg/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all: $(call DYLIB,return1) $(call DYLIB,return2) $(call NATIVE_STATICLIB,return3)
- ls $(TMPDIR)
- $(BARE_RUSTC) --print cfg --target x86_64-unknown-linux-musl | $(CGREP) crt-static
-
- $(RUSTC) no-deps.rs --cfg foo
- $(call RUN,no-deps)
- $(RUSTC) no-deps.rs --cfg bar
- $(call RUN,no-deps)
-
- $(RUSTC) dep.rs
- $(RUSTC) with-deps.rs --cfg foo
- $(call RUN,with-deps)
- $(RUSTC) with-deps.rs --cfg bar
- $(call RUN,with-deps)
-
- $(RUSTC) dep-with-staticlib.rs
- $(RUSTC) with-staticlib-deps.rs --cfg foo
- $(call RUN,with-staticlib-deps)
- $(RUSTC) with-staticlib-deps.rs --cfg bar
- $(call RUN,with-staticlib-deps)
diff --git a/tests/run-make/link-cfg/rmake.rs b/tests/run-make/link-cfg/rmake.rs
new file mode 100644
index 0000000..732de5d
--- /dev/null
+++ b/tests/run-make/link-cfg/rmake.rs
@@ -0,0 +1,43 @@
+// The `#[link(cfg(..))]` annotation means that the `#[link]`
+// directive is only active in a compilation unit if that `cfg` value is satisfied.
+// For example, when compiling an rlib, these directives are just encoded and
+// ignored for dylibs, and all staticlibs are continued to be put into the rlib as
+// usual. When placing that rlib into a staticlib, executable, or dylib, however,
+// the `cfg` is evaluated *as if it were defined in the final artifact* and the
+// library is decided to be linked or not.
+// This test exercises this new feature by testing it with no dependencies, then
+// with only dynamic libraries, then with both a staticlib and dylibs. Compilation
+// and execution should be successful.
+// See https://github.com/rust-lang/rust/pull/37545
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{bare_rustc, build_native_dynamic_lib, build_native_static_lib, run, rustc};
+
+fn main() {
+ build_native_dynamic_lib("return1");
+ build_native_dynamic_lib("return2");
+ build_native_static_lib("return3");
+ bare_rustc()
+ .print("cfg")
+ .target("x86_64-unknown-linux-musl")
+ .run()
+ .assert_stdout_contains("crt-static");
+ rustc().input("no-deps.rs").cfg("foo").run();
+ run("no-deps");
+ rustc().input("no-deps.rs").cfg("bar").run();
+ run("no-deps");
+
+ rustc().input("dep.rs").run();
+ rustc().input("with-deps.rs").cfg("foo").run();
+ run("with-deps");
+ rustc().input("with-deps.rs").cfg("bar").run();
+ run("with-deps");
+
+ rustc().input("dep-with-staticlib.rs").run();
+ rustc().input("with-staticlib-deps.rs").cfg("foo").run();
+ run("with-staticlib-deps");
+ rustc().input("with-staticlib-deps.rs").cfg("bar").run();
+ run("with-staticlib-deps");
+}
diff --git a/tests/run-make/link-dedup/rmake.rs b/tests/run-make/link-dedup/rmake.rs
index 9bff3a4..6075f31 100644
--- a/tests/run-make/link-dedup/rmake.rs
+++ b/tests/run-make/link-dedup/rmake.rs
@@ -5,20 +5,37 @@
// Without the --cfg flag, there should be a single -ltesta, no more, no less.
// See https://github.com/rust-lang/rust/pull/84794
-//@ ignore-msvc
+use std::fmt::Write;
-use run_make_support::rustc;
+use run_make_support::{is_msvc, rustc};
fn main() {
rustc().input("depa.rs").run();
rustc().input("depb.rs").run();
rustc().input("depc.rs").run();
+
let output = rustc().input("empty.rs").cfg("bar").run_fail();
- output.assert_stderr_contains(r#""-ltesta" "-ltestb" "-ltesta""#);
+ output.assert_stderr_contains(needle_from_libs(&["testa", "testb", "testa"]));
+
let output = rustc().input("empty.rs").run_fail();
- output.assert_stderr_contains(r#""-ltesta""#);
- let output = rustc().input("empty.rs").run_fail();
- output.assert_stderr_not_contains(r#""-ltestb""#);
- let output = rustc().input("empty.rs").run_fail();
- output.assert_stderr_not_contains(r#""-ltesta" "-ltesta" "-ltesta""#);
+ output.assert_stderr_contains(needle_from_libs(&["testa"]));
+ output.assert_stderr_not_contains(needle_from_libs(&["testb"]));
+ output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa", "testa"]));
+ // Adjacent identical native libraries are no longer deduplicated if
+ // they come from different crates (https://github.com/rust-lang/rust/pull/103311)
+ // so the following will fail:
+ //output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa"]));
+}
+
+fn needle_from_libs(libs: &[&str]) -> String {
+ let mut needle = String::new();
+ for lib in libs {
+ if is_msvc() {
+ let _ = needle.write_fmt(format_args!(r#""{lib}.lib" "#));
+ } else {
+ let _ = needle.write_fmt(format_args!(r#""-l{lib}" "#));
+ }
+ }
+ needle.pop(); // remove trailing space
+ needle
}
diff --git a/tests/run-make/issue-47551/eh_frame-terminator.rs b/tests/run-make/link-eh-frame-terminator/eh_frame-terminator.rs
similarity index 100%
rename from tests/run-make/issue-47551/eh_frame-terminator.rs
rename to tests/run-make/link-eh-frame-terminator/eh_frame-terminator.rs
diff --git a/tests/run-make/link-eh-frame-terminator/rmake.rs b/tests/run-make/link-eh-frame-terminator/rmake.rs
new file mode 100644
index 0000000..6bfae38
--- /dev/null
+++ b/tests/run-make/link-eh-frame-terminator/rmake.rs
@@ -0,0 +1,23 @@
+// The gcc driver is supposed to add a terminator to link files, and the rustc
+// driver previously failed to do this, resulting in a segmentation fault
+// with an older version of LLVM. This test checks that the terminator is present
+// after the fix in #85395.
+// See https://github.com/rust-lang/rust/issues/47551
+
+//@ only-linux
+// Reason: the ZERO terminator is unique to the Linux architecture.
+//@ ignore-32bit
+// Reason: the usage of a large array in the test causes an out-of-memory
+// error on 32 bit systems.
+
+use run_make_support::{bin_name, llvm_objdump, run, rustc};
+
+fn main() {
+ rustc().input("eh_frame-terminator.rs").run();
+ run("eh_frame-terminator").assert_stdout_contains("1122334455667788");
+ llvm_objdump()
+ .arg("--dwarf=frames")
+ .input(bin_name("eh_frame-terminator"))
+ .run()
+ .assert_stdout_contains("ZERO terminator");
+}
diff --git a/tests/run-make/llvm-outputs/rmake.rs b/tests/run-make/llvm-outputs/rmake.rs
index 2dc3030..b8ac21c 100644
--- a/tests/run-make/llvm-outputs/rmake.rs
+++ b/tests/run-make/llvm-outputs/rmake.rs
@@ -1,8 +1,9 @@
// test that directories get created when emitting llvm bitcode and IR
-use run_make_support::{cwd, run_in_tmpdir, rustc};
use std::path::PathBuf;
+use run_make_support::{cwd, run_in_tmpdir, rustc};
+
fn main() {
let mut path_bc = PathBuf::new();
let mut path_ir = PathBuf::new();
diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/Makefile b/tests/run-make/long-linker-command-lines-cmd-exe/Makefile
deleted file mode 100644
index e43aab7..0000000
--- a/tests/run-make/long-linker-command-lines-cmd-exe/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-all:
- $(RUSTC) foo.rs -g
- cp foo.bat $(TMPDIR)/
- OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo)
diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs b/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs
index 1d5202d..a28cc79 100644
--- a/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs
+++ b/tests/run-make/long-linker-command-lines-cmd-exe/foo.rs
@@ -1,16 +1,3 @@
-// Like the `long-linker-command-lines` test this test attempts to blow
-// a command line limit for running the linker. Unlike that test, however,
-// this test is testing `cmd.exe` specifically rather than the OS.
-//
-// Unfortunately `cmd.exe` has a 8192 limit which is relatively small
-// in the grand scheme of things and anyone sripting rustc's linker
-// is probably using a `*.bat` script and is likely to hit this limit.
-//
-// This test uses a `foo.bat` script as the linker which just simply
-// delegates back to this program. The compiler should use a lower
-// limit for arguments before passing everything via `@`, which
-// means that everything should still succeed here.
-
use std::env;
use std::fs::{self, File};
use std::io::{BufWriter, Read, Write};
@@ -18,13 +5,8 @@
use std::process::Command;
fn main() {
- if !cfg!(windows) {
- return;
- }
-
- let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
- let ok = tmpdir.join("ok");
- let not_ok = tmpdir.join("not_ok");
+ let ok = PathBuf::from("ok");
+ let not_ok = PathBuf::from("not_ok");
if env::var("YOU_ARE_A_LINKER").is_ok() {
match env::args_os().find(|a| a.to_string_lossy().contains("@")) {
Some(file) => {
@@ -45,7 +27,7 @@ fn main() {
for i in (1..).map(|i| i * 10) {
println!("attempt: {}", i);
- let file = tmpdir.join("bar.rs");
+ let file = PathBuf::from("bar.rs");
let mut f = BufWriter::new(File::create(&file).unwrap());
let mut lib_name = String::new();
for _ in 0..i {
@@ -63,8 +45,6 @@ fn main() {
.arg(&file)
.arg("-C")
.arg(&bat_linker)
- .arg("--out-dir")
- .arg(&tmpdir)
.env("YOU_ARE_A_LINKER", "1")
.env("MY_LINKER", &me)
.status()
diff --git a/tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs b/tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs
new file mode 100644
index 0000000..60ed2c5
--- /dev/null
+++ b/tests/run-make/long-linker-command-lines-cmd-exe/rmake.rs
@@ -0,0 +1,26 @@
+// Like the `long-linker-command-lines` test this test attempts to blow
+// a command line limit for running the linker. Unlike that test, however,
+// this test is testing `cmd.exe` specifically rather than the OS.
+//
+// Unfortunately, the maximum length of the string that you can use at the
+// command prompt (`cmd.exe`) is 8191 characters.
+// Anyone scripting rustc's linker
+// is probably using a `*.bat` script and is likely to hit this limit.
+//
+// This test uses a `foo.bat` script as the linker which just simply
+// delegates back to this program. The compiler should use a lower
+// limit for arguments before passing everything via `@`, which
+// means that everything should still succeed here.
+// See https://github.com/rust-lang/rust/pull/47507
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+//@ only-windows
+// Reason: this test is specific to Windows executables
+
+use run_make_support::{run, rustc};
+
+fn main() {
+ rustc().input("foo.rs").arg("-g").run();
+ run("foo");
+}
diff --git a/tests/run-make/long-linker-command-lines/Makefile b/tests/run-make/long-linker-command-lines/Makefile
deleted file mode 100644
index b573038e..0000000
--- a/tests/run-make/long-linker-command-lines/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
-
-all:
- $(RUSTC) foo.rs -g -O
- RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo)
diff --git a/tests/run-make/long-linker-command-lines/foo.rs b/tests/run-make/long-linker-command-lines/foo.rs
index 9d4a701..5b30c06 100644
--- a/tests/run-make/long-linker-command-lines/foo.rs
+++ b/tests/run-make/long-linker-command-lines/foo.rs
@@ -1,12 +1,3 @@
-// This is a test which attempts to blow out the system limit with how many
-// arguments can be passed to a process. This'll successively call rustc with
-// larger and larger argument lists in an attempt to find one that's way too
-// big for the system at hand. This file itself is then used as a "linker" to
-// detect when the process creation succeeds.
-//
-// Eventually we should see an argument that looks like `@` as we switch from
-// passing literal arguments to passing everything in the file.
-
use std::collections::HashSet;
use std::env;
use std::fs::{self, File};
@@ -43,8 +34,7 @@ fn read_linker_args(path: &Path) -> String {
}
fn main() {
- let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap());
- let ok = tmpdir.join("ok");
+ let ok = PathBuf::from("ok");
if env::var("YOU_ARE_A_LINKER").is_ok() {
if let Some(file) = env::args_os().find(|a| a.to_string_lossy().contains("@")) {
let file = file.to_str().expect("non-utf8 file argument");
@@ -53,11 +43,11 @@ fn main() {
return;
}
- let rustc = env::var_os("RUSTC").unwrap_or("rustc".into());
+ let rustc = env::var_os("RUSTC").unwrap();
let me_as_linker = format!("linker={}", env::current_exe().unwrap().display());
for i in (1..).map(|i| i * 100) {
println!("attempt: {}", i);
- let file = tmpdir.join("bar.rs");
+ let file = PathBuf::from("bar.rs");
let mut expected_libs = write_test_case(&file, i);
drop(fs::remove_file(&ok));
@@ -65,8 +55,6 @@ fn main() {
.arg(&file)
.arg("-C")
.arg(&me_as_linker)
- .arg("--out-dir")
- .arg(&tmpdir)
.env("YOU_ARE_A_LINKER", "1")
.output()
.unwrap();
diff --git a/tests/run-make/long-linker-command-lines/rmake.rs b/tests/run-make/long-linker-command-lines/rmake.rs
new file mode 100644
index 0000000..e832d7f
--- /dev/null
+++ b/tests/run-make/long-linker-command-lines/rmake.rs
@@ -0,0 +1,19 @@
+// This is a test which attempts to blow out the system limit with how many
+// arguments can be passed to a process. This'll successively call rustc with
+// larger and larger argument lists in an attempt to find one that's way too
+// big for the system at hand. This file itself is then used as a "linker" to
+// detect when the process creation succeeds.
+//
+// Eventually we should see an argument that looks like `@` as we switch from
+// passing literal arguments to passing everything in the file.
+// See https://github.com/rust-lang/rust/issues/41190
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{run, rustc};
+
+fn main() {
+ rustc().input("foo.rs").arg("-g").opt().run();
+ run("foo");
+}
diff --git a/tests/run-make/ls-metadata/rmake.rs b/tests/run-make/ls-metadata/rmake.rs
index 45299a4..42db97a 100644
--- a/tests/run-make/ls-metadata/rmake.rs
+++ b/tests/run-make/ls-metadata/rmake.rs
@@ -6,8 +6,7 @@
//@ ignore-cross-compile
-use run_make_support::rfs;
-use run_make_support::rustc;
+use run_make_support::{rfs, rustc};
fn main() {
rustc().input("foo.rs").run();
diff --git a/tests/run-make/lto-readonly-lib/rmake.rs b/tests/run-make/lto-readonly-lib/rmake.rs
index d0ba3fb..78f2b58 100644
--- a/tests/run-make/lto-readonly-lib/rmake.rs
+++ b/tests/run-make/lto-readonly-lib/rmake.rs
@@ -7,7 +7,6 @@
//@ ignore-cross-compile
-use run_make_support::rfs;
use run_make_support::{run, rust_lib_name, rustc, test_while_readonly};
fn main() {
diff --git a/tests/run-make/manual-crate-name/rmake.rs b/tests/run-make/manual-crate-name/rmake.rs
index f171f78..9085b6c 100644
--- a/tests/run-make/manual-crate-name/rmake.rs
+++ b/tests/run-make/manual-crate-name/rmake.rs
@@ -1,6 +1,7 @@
-use run_make_support::rustc;
use std::path::Path;
+use run_make_support::rustc;
+
fn main() {
rustc().input("bar.rs").crate_name("foo").run();
assert!(Path::new("libfoo.rlib").is_file());
diff --git a/tests/run-make/mte-ffi/bar.h b/tests/run-make/mte-ffi/bar.h
new file mode 100644
index 0000000..a2292ae
--- /dev/null
+++ b/tests/run-make/mte-ffi/bar.h
@@ -0,0 +1,43 @@
+#ifndef __BAR_H
+#define __BAR_H
+
+#include <sys/mman.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+#include <stdio.h>
+
+// Set the allocation tag on the destination address using the STG instruction.
+#define set_tag(tagged_addr) do { \
+ asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \
+} while (0)
+
+int mte_enabled() {
+ return (getauxval(AT_HWCAP2)) & HWCAP2_MTE;
+}
+
+void *alloc_page() {
+ // Enable MTE with synchronous checking
+ if (prctl(PR_SET_TAGGED_ADDR_CTRL,
+ PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT),
+ 0, 0, 0))
+ {
+ perror("prctl() failed");
+ }
+
+ // Using `mmap` allows us to ensure that, on systems which support MTE, the allocated
+ // memory is 16-byte aligned for MTE.
+ // This also allows us to explicitly specify whether the region should be protected by
+ // MTE or not.
+ if (mte_enabled()) {
+ void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE),
+ PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ } else {
+ void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE),
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
+ -1, 0);
+ }
+}
+
+#endif // __BAR_H
diff --git a/tests/run-make/mte-ffi/bar_float.c b/tests/run-make/mte-ffi/bar_float.c
new file mode 100644
index 0000000..a1590f6
--- /dev/null
+++ b/tests/run-make/mte-ffi/bar_float.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "bar.h"
+
+extern void foo(char*);
+
+void bar(char *ptr) {
+ if (((uintptr_t)ptr >> 56) != 0x1f) {
+ fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
+ exit(1);
+ }
+}
+
+int main(void)
+{
+ float *ptr = alloc_page();
+ if (ptr == MAP_FAILED)
+ {
+ perror("mmap() failed");
+ return EXIT_FAILURE;
+ }
+
+ // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
+ // and a different value in the ignored top 4 bits.
+ ptr = (float *)((uintptr_t)ptr | 0x1fl << 56);
+
+ if (mte_enabled()) {
+ set_tag(ptr);
+ }
+
+ ptr[0] = 2.0f;
+ ptr[1] = 1.5f;
+
+ foo(ptr); // should change the contents of the page and call `bar`
+
+ if (ptr[0] != 0.5f || ptr[1] != 0.2f) {
+ fprintf(stderr, "invalid data in memory; expected '0.5 0.2', got '%f %f'\n",
+ ptr[0], ptr[1]);
+ return EXIT_FAILURE;
+ }
+
+ return 0;
+}
diff --git a/tests/run-make/mte-ffi/bar_function.c b/tests/run-make/mte-ffi/bar_function.c
new file mode 100644
index 0000000..1fa48d3
--- /dev/null
+++ b/tests/run-make/mte-ffi/bar_function.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "bar.h"
+
+typedef void (*fp)(int (*)());
+
+extern void foo(fp);
+
+void bar(int (*ptr)()) {
+ if (((uintptr_t)ptr >> 56) != 0x2f) {
+ fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
+ exit(1);
+ }
+
+ int r = (*ptr)();
+ if (r != 32) {
+ fprintf(stderr, "invalid return value; expected 32, got '%d'\n", r);
+ exit(1);
+ }
+}
+
+int main(void)
+{
+ fp ptr = alloc_page();
+ if (ptr == MAP_FAILED)
+ {
+ perror("mmap() failed");
+ return EXIT_FAILURE;
+ }
+
+ // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
+ // and a different value in the ignored top 4 bits.
+ ptr = (fp)((uintptr_t)&bar | 0x1fl << 56);
+
+ foo(ptr);
+
+ return 0;
+}
diff --git a/tests/run-make/mte-ffi/bar_int.c b/tests/run-make/mte-ffi/bar_int.c
new file mode 100644
index 0000000..d1c79e9
--- /dev/null
+++ b/tests/run-make/mte-ffi/bar_int.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "bar.h"
+
+extern void foo(unsigned int *);
+
+void bar(char *ptr) {
+ if (((uintptr_t)ptr >> 56) != 0x1f) {
+ fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
+ exit(1);
+ }
+}
+
+int main(void)
+{
+ // Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag.
+ // It's only necessary that the tag is preserved across FFI bounds for this test.
+ unsigned int *ptr;
+
+ ptr = alloc_page();
+ if (ptr == MAP_FAILED)
+ {
+ perror("mmap() failed");
+ return EXIT_FAILURE;
+ }
+
+ // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
+ // and a different value in the ignored top 4 bits.
+ ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56);
+
+ if (mte_enabled()) {
+ set_tag(ptr);
+ }
+
+ ptr[0] = 61;
+ ptr[1] = 62;
+
+ foo(ptr); // should change the contents of the page to start with 0x63 0x64 and call `bar`
+
+ if (ptr[0] != 0x63 || ptr[1] != 0x64) {
+ fprintf(stderr, "invalid data in memory; expected '63 64', got '%d %d'\n", ptr[0], ptr[1]);
+ return EXIT_FAILURE;
+ }
+
+ return 0;
+}
diff --git a/tests/run-make/mte-ffi/bar_string.c b/tests/run-make/mte-ffi/bar_string.c
new file mode 100644
index 0000000..5669ffd
--- /dev/null
+++ b/tests/run-make/mte-ffi/bar_string.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "bar.h"
+
+extern void foo(char*);
+
+void bar(char *ptr) {
+ if (((uintptr_t)ptr >> 56) != 0x2f) {
+ fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
+ exit(1);
+ }
+
+ if (strcmp(ptr, "cd")) {
+ fprintf(stderr, "invalid data in memory; expected 'cd', got '%s'\n", ptr);
+ exit(1);
+ }
+}
+
+int main(void)
+{
+ // Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag.
+ // It's only necessary that the tag is preserved across FFI bounds for this test.
+ char *ptr;
+
+ ptr = alloc_page();
+ if (ptr == MAP_FAILED)
+ {
+ perror("mmap() failed");
+ return EXIT_FAILURE;
+ }
+
+ // Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
+ // and a different value in the ignored top 4 bits.
+ ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56);
+
+ if (mte_enabled()) {
+ set_tag(ptr);
+ }
+
+ ptr[0] = 'a';
+ ptr[1] = 'b';
+ ptr[2] = '\0';
+
+ foo(ptr);
+
+ return 0;
+}
diff --git a/tests/run-make/mte-ffi/foo_float.rs b/tests/run-make/mte-ffi/foo_float.rs
new file mode 100644
index 0000000..c1bedd5
--- /dev/null
+++ b/tests/run-make/mte-ffi/foo_float.rs
@@ -0,0 +1,19 @@
+#![crate_type = "cdylib"]
+#![crate_name = "foo"]
+
+use std::os::raw::c_float;
+
+extern "C" {
+ fn bar(ptr: *const c_float);
+}
+
+#[no_mangle]
+pub extern "C" fn foo(ptr: *mut c_float) {
+ assert_eq!((ptr as usize) >> 56, 0x1f);
+
+ unsafe {
+ *ptr = 0.5;
+ *ptr.wrapping_add(1) = 0.2;
+ bar(ptr);
+ }
+}
diff --git a/tests/run-make/mte-ffi/foo_function.rs b/tests/run-make/mte-ffi/foo_function.rs
new file mode 100644
index 0000000..2c8e0b2
--- /dev/null
+++ b/tests/run-make/mte-ffi/foo_function.rs
@@ -0,0 +1,17 @@
+#![crate_type = "cdylib"]
+#![crate_name = "foo"]
+
+extern "C" fn ret32() -> i32 {
+ 32
+}
+
+#[no_mangle]
+pub extern "C" fn foo(ptr: extern "C" fn(extern "C" fn() -> i32)) {
+ assert_eq!((ptr as usize) >> 56, 0x1f);
+
+ // Store an arbitrary tag in the tag bits, and convert back to the correct pointer type.
+ let p = ((ret32 as usize) | (0x2f << 56)) as *const ();
+ let p: extern "C" fn() -> i32 = unsafe { std::mem::transmute(p) };
+
+ unsafe { ptr(p) }
+}
diff --git a/tests/run-make/mte-ffi/foo_int.rs b/tests/run-make/mte-ffi/foo_int.rs
new file mode 100644
index 0000000..106d863
--- /dev/null
+++ b/tests/run-make/mte-ffi/foo_int.rs
@@ -0,0 +1,19 @@
+#![crate_type = "cdylib"]
+#![crate_name = "foo"]
+
+use std::os::raw::c_uint;
+
+extern "C" {
+ fn bar(ptr: *const c_uint);
+}
+
+#[no_mangle]
+pub extern "C" fn foo(ptr: *mut c_uint) {
+ assert_eq!((ptr as usize) >> 56, 0x1f);
+
+ unsafe {
+ *ptr = 0x63;
+ *ptr.wrapping_add(1) = 0x64;
+ bar(ptr);
+ }
+}
diff --git a/tests/run-make/mte-ffi/foo_string.rs b/tests/run-make/mte-ffi/foo_string.rs
new file mode 100644
index 0000000..5474480
--- /dev/null
+++ b/tests/run-make/mte-ffi/foo_string.rs
@@ -0,0 +1,27 @@
+#![crate_type = "cdylib"]
+#![crate_name = "foo"]
+
+use std::arch::asm;
+use std::ffi::{CStr, CString};
+use std::os::raw::c_char;
+
+extern "C" {
+ fn bar(ptr: *const c_char);
+}
+
+#[no_mangle]
+pub extern "C" fn foo(ptr: *const c_char) {
+ assert_eq!((ptr as usize) >> 56, 0x1f);
+
+ let s = unsafe { CStr::from_ptr(ptr) };
+ assert_eq!(s.to_str().unwrap(), "ab");
+
+ let s = CString::from_vec_with_nul("cd\0".into()).unwrap();
+ let mut p = ((s.as_ptr() as usize) | (0x2f << 56)) as *const c_char;
+ unsafe {
+ #[cfg(target_feature = "mte")]
+ asm!("stg {p}, [{p}]", p = inout(reg) p);
+
+ bar(p);
+ }
+}
diff --git a/tests/run-make/mte-ffi/rmake.rs b/tests/run-make/mte-ffi/rmake.rs
new file mode 100644
index 0000000..f4fafb7
--- /dev/null
+++ b/tests/run-make/mte-ffi/rmake.rs
@@ -0,0 +1,38 @@
+// Tests that MTE tags and values stored in the top byte of a pointer (TBI) are
+// preserved across FFI boundaries (C <-> Rust).
+// This test does not require MTE: whilst the test will use MTE if available, if it is not,
+// arbitrary tag bits are set using TBI.
+
+// This test is only valid for AArch64.
+// The linker must be explicitly specified when cross-compiling, so it is limited to
+// `aarch64-unknown-linux-gnu`.
+//@ only-aarch64-unknown-linux-gnu
+
+use run_make_support::{cc, dynamic_lib_name, extra_c_flags, run, rustc, target};
+
+fn main() {
+ run_test("int");
+ run_test("float");
+ run_test("string");
+ run_test("function");
+}
+
+fn run_test(variant: &str) {
+ let flags = {
+ let mut flags = extra_c_flags();
+ flags.push("-march=armv8.5-a+memtag");
+ flags
+ };
+ println!("{variant} test...");
+ rustc()
+ .input(format!("foo_{variant}.rs"))
+ .target(target())
+ .linker("aarch64-linux-gnu-gcc")
+ .run();
+ cc().input(format!("bar_{variant}.c"))
+ .input(dynamic_lib_name("foo"))
+ .out_exe("test")
+ .args(&flags)
+ .run();
+ run("test");
+}
diff --git a/tests/run-make/multiple-emits/rmake.rs b/tests/run-make/multiple-emits/rmake.rs
index 67c0ebb..8a5eb1d 100644
--- a/tests/run-make/multiple-emits/rmake.rs
+++ b/tests/run-make/multiple-emits/rmake.rs
@@ -1,4 +1,4 @@
-use run_make_support::{cwd, path, rustc};
+use run_make_support::{path, rustc};
fn main() {
rustc().input("foo.rs").emit("asm,llvm-ir").output("out").run();
diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs
new file mode 100644
index 0000000..f00123f
--- /dev/null
+++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs
@@ -0,0 +1,89 @@
+#![feature(naked_functions, asm_const, linkage)]
+#![crate_type = "dylib"]
+
+use std::arch::asm;
+
+pub trait TraitWithConst {
+ const COUNT: u32;
+}
+
+struct Test;
+
+impl TraitWithConst for Test {
+ const COUNT: u32 = 1;
+}
+
+#[no_mangle]
+fn entry() {
+ private_vanilla();
+ private_naked();
+
+ public_vanilla_generic::<Test>();
+ public_naked_generic::<Test>();
+}
+
+extern "C" fn private_vanilla() -> u32 {
+ 42
+}
+
+#[naked]
+extern "C" fn private_naked() -> u32 {
+ unsafe { asm!("mov rax, 42", "ret", options(noreturn)) }
+}
+
+#[no_mangle]
+pub extern "C" fn public_vanilla() -> u32 {
+ 42
+}
+
+#[naked]
+#[no_mangle]
+pub extern "C" fn public_naked() -> u32 {
+ unsafe { asm!("mov rax, 42", "ret", options(noreturn)) }
+}
+
+pub extern "C" fn public_vanilla_generic<T: TraitWithConst>() -> u32 {
+ T::COUNT
+}
+
+#[naked]
+pub extern "C" fn public_naked_generic<T: TraitWithConst>() -> u32 {
+ unsafe { asm!("mov rax, {}", "ret", const T::COUNT, options(noreturn)) }
+}
+
+#[linkage = "external"]
+extern "C" fn vanilla_external_linkage() -> u32 {
+ 42
+}
+
+#[naked]
+#[linkage = "external"]
+extern "C" fn naked_external_linkage() -> u32 {
+ unsafe { asm!("mov rax, 42", "ret", options(noreturn)) }
+}
+
+#[cfg(not(windows))]
+#[linkage = "weak"]
+extern "C" fn vanilla_weak_linkage() -> u32 {
+ 42
+}
+
+#[naked]
+#[cfg(not(windows))]
+#[linkage = "weak"]
+extern "C" fn naked_weak_linkage() -> u32 {
+ unsafe { asm!("mov rax, 42", "ret", options(noreturn)) }
+}
+
+// functions that are declared in an `extern "C"` block are currently not exported
+// this maybe should change in the future, this is just tracking the current behavior
+// reported in https://github.com/rust-lang/rust/issues/128071
+std::arch::global_asm! {
+ ".globl function_defined_in_global_asm",
+ "function_defined_in_global_asm:",
+ "ret",
+}
+
+extern "C" {
+ pub fn function_defined_in_global_asm();
+}
diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs
new file mode 100644
index 0000000..07ff253
--- /dev/null
+++ b/tests/run-make/naked-symbol-visibility/rmake.rs
@@ -0,0 +1,98 @@
+//@ ignore-windows
+//@ only-x86_64
+use run_make_support::object::read::{File, Object, Symbol};
+use run_make_support::object::ObjectSymbol;
+use run_make_support::targets::is_windows;
+use run_make_support::{dynamic_lib_name, rfs, rustc};
+
+fn main() {
+ let rdylib_name = dynamic_lib_name("a_rust_dylib");
+ rustc().arg("-Zshare-generics=no").input("a_rust_dylib.rs").run();
+
+ let binary_data = rfs::read(&rdylib_name);
+ let rdylib = File::parse(&*binary_data).unwrap();
+
+ // naked should mirror vanilla
+ not_exported(&rdylib, "private_vanilla");
+ not_exported(&rdylib, "private_naked");
+
+ global_function(&rdylib, "public_vanilla");
+ global_function(&rdylib, "public_naked");
+
+ not_exported(&rdylib, "public_vanilla_generic");
+ not_exported(&rdylib, "public_naked_generic");
+
+ global_function(&rdylib, "vanilla_external_linkage");
+ global_function(&rdylib, "naked_external_linkage");
+
+ // FIXME: make this work on windows (gnu and msvc). See the PR
+ // https://github.com/rust-lang/rust/pull/128362 for some approaches
+ // that don't work
+ //
+ // #[linkage = "weak"] does not work well on windows, we get
+ //
+ // lib.def : error LNK2001: unresolved external symbol naked_weak_linkage␍
+ // lib.def : error LNK2001: unresolved external symbol vanilla_weak_linkage
+ //
+ // so just skip weak symbols on windows (for now)
+ if !is_windows() {
+ weak_function(&rdylib, "vanilla_weak_linkage");
+ weak_function(&rdylib, "naked_weak_linkage");
+ }
+
+ // functions that are declared in an `extern "C"` block are currently not exported
+ // this maybe should change in the future, this is just tracking the current behavior
+ // reported in https://github.com/rust-lang/rust/issues/128071
+ not_exported(&rdylib, "function_defined_in_global_asm");
+
+ // share generics should expose the generic functions
+ rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run();
+ let binary_data = rfs::read(&rdylib_name);
+ let rdylib = File::parse(&*binary_data).unwrap();
+
+ global_function(&rdylib, "public_vanilla_generic");
+ global_function(&rdylib, "public_naked_generic");
+}
+
+#[track_caller]
+fn global_function(file: &File, symbol_name: &str) {
+ let symbols = find_dynamic_symbol(file, symbol_name);
+ let [symbol] = symbols.as_slice() else {
+ panic!("symbol {symbol_name} occurs {} times", symbols.len())
+ };
+
+ assert!(symbol.is_definition(), "`{symbol_name}` is not a function");
+ assert!(symbol.is_global(), "`{symbol_name}` is not marked as global");
+}
+
+#[track_caller]
+fn weak_function(file: &File, symbol_name: &str) {
+ let symbols = find_dynamic_symbol(file, symbol_name);
+ let [symbol] = symbols.as_slice() else {
+ panic!("symbol {symbol_name} occurs {} times", symbols.len())
+ };
+
+ assert!(symbol.is_definition(), "`{symbol_name}` is not a function");
+ assert!(symbol.is_weak(), "`{symbol_name}` is not marked as weak");
+}
+
+#[track_caller]
+fn not_exported(file: &File, symbol_name: &str) {
+ assert_eq!(find_dynamic_symbol(file, symbol_name).len(), 0)
+}
+
+fn find_subsequence(haystack: &[u8], needle: &[u8]) -> bool {
+ haystack.windows(needle.len()).any(|window| window == needle)
+}
+
+fn find_dynamic_symbol<'file, 'data>(
+ file: &'file File<'data>,
+ expected: &str,
+) -> Vec<Symbol<'data, 'file>> {
+ file.exports()
+ .unwrap()
+ .into_iter()
+ .filter(|e| find_subsequence(e.name(), expected.as_bytes()))
+ .filter_map(|e| file.symbol_by_name_bytes(e.name()))
+ .collect()
+}
diff --git a/tests/run-make/native-link-modifier-whole-archive/Makefile b/tests/run-make/native-link-modifier-whole-archive/Makefile
deleted file mode 100644
index 5eb7a41..0000000
--- a/tests/run-make/native-link-modifier-whole-archive/Makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
-
-# This test case makes sure that native libraries are linked with appropriate semantics
-# when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
-#
-# The test works by checking that the resulting executables produce the expected output,
-# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
-# that code would never make it into the final executable and we'd thus be missing some
-# of the output.
-
-include ../tools.mk
-
-all: $(TMPDIR)/$(call BIN,directly_linked) \
- $(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive) \
- $(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive) \
- $(TMPDIR)/$(call BIN,indirectly_linked) \
- $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
- $(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
- $(call RUN,directly_linked_test_plus_whole_archive) --nocapture | $(CGREP) 'static-initializer.'
- $(call RUN,directly_linked_test_minus_whole_archive) --nocapture | $(CGREP) -v 'static-initializer.'
- $(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
- $(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
-
-# Native lib linked directly into executable
-$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
- $(RUSTC) directly_linked.rs -l static:+whole-archive=c_static_lib_with_constructor
-
-# Native lib linked into test executable, +whole-archive
-$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
- $(RUSTC) directly_linked_test_plus_whole_archive.rs --test -l static:+whole-archive=c_static_lib_with_constructor
-# Native lib linked into test executable, -whole-archive
-$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
- $(RUSTC) directly_linked_test_minus_whole_archive.rs --test -l static:-whole-archive=c_static_lib_with_constructor
-
-# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
-$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
- $(RUSTC) indirectly_linked.rs
-
-# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
-$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
- $(RUSTC) indirectly_linked_via_attr.rs
-
-# Native lib linked into rlib with via commandline
-$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
- $(RUSTC) rlib_with_cmdline_native_lib.rs --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
-
-# Native lib linked into rlib via `#[link()]` attribute on extern block.
-$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
- $(RUSTC) native_lib_in_src.rs --crate-type=rlib
-
-$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
- $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/native-link-modifier-whole-archive/rmake.rs b/tests/run-make/native-link-modifier-whole-archive/rmake.rs
new file mode 100644
index 0000000..b8b8140
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/rmake.rs
@@ -0,0 +1,86 @@
+// This test case makes sure that native libraries are linked with appropriate semantics
+// when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
+// The test works by checking that the resulting executables produce the expected output,
+// part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
+// that code would never make it into the final executable and we'd thus be missing some
+// of the output.
+// See https://github.com/rust-lang/rust/issues/88085
+
+//@ ignore-cross-compile
+// Reason: compiling C++ code does not work well when cross-compiling
+// plus, the compiled binary is executed
+
+use run_make_support::{cxx, is_msvc, llvm_ar, run, run_with_args, rustc, static_lib_name};
+
+fn main() {
+ let mut cxx = cxx();
+ if is_msvc() {
+ cxx.arg("-EHs");
+ }
+ cxx.input("c_static_lib_with_constructor.cpp")
+ .arg("-c")
+ .out_exe("libc_static_lib_with_constructor")
+ .run();
+
+ let mut llvm_ar = llvm_ar();
+ llvm_ar.obj_to_ar();
+ if is_msvc() {
+ llvm_ar
+ .output_input(
+ static_lib_name("c_static_lib_with_constructor"),
+ "libc_static_lib_with_constructor.obj",
+ )
+ .run();
+ } else {
+ llvm_ar
+ .output_input(
+ static_lib_name("c_static_lib_with_constructor"),
+ "libc_static_lib_with_constructor",
+ )
+ .run();
+ }
+
+ // Native lib linked directly into executable
+ rustc()
+ .input("directly_linked.rs")
+ .arg("-lstatic:+whole-archive=c_static_lib_with_constructor")
+ .run();
+
+ // Native lib linked into test executable, +whole-archive
+ rustc()
+ .input("directly_linked_test_plus_whole_archive.rs")
+ .arg("--test")
+ .arg("-lstatic:+whole-archive=c_static_lib_with_constructor")
+ .run();
+
+ // Native lib linked into test executable, -whole-archive
+ rustc()
+ .input("directly_linked_test_minus_whole_archive.rs")
+ .arg("--test")
+ .arg("-lstatic:-whole-archive=c_static_lib_with_constructor")
+ .run();
+
+ // Native lib linked into rlib with via commandline
+ rustc()
+ .input("rlib_with_cmdline_native_lib.rs")
+ .crate_type("rlib")
+ .arg("-lstatic:-bundle,+whole-archive=c_static_lib_with_constructor")
+ .run();
+ // Native lib linked into RLIB via `-l static:-bundle,+whole-archive`
+ // RLIB linked into executable
+ rustc().input("indirectly_linked.rs").run();
+
+ // Native lib linked into rlib via `#[link()]` attribute on extern block.
+ rustc().input("native_lib_in_src.rs").crate_type("rlib").run();
+ // Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
+ rustc().input("indirectly_linked_via_attr.rs").run();
+
+ run("directly_linked").assert_stdout_contains("static-initializer.directly_linked.");
+ run_with_args("directly_linked_test_plus_whole_archive", &["--nocapture"])
+ .assert_stdout_contains("static-initializer.");
+ run_with_args("directly_linked_test_minus_whole_archive", &["--nocapture"])
+ .assert_stdout_not_contains("static-initializer.");
+ run("indirectly_linked").assert_stdout_contains("static-initializer.indirectly_linked.");
+ run("indirectly_linked_via_attr")
+ .assert_stdout_contains("static-initializer.native_lib_in_src.");
+}
diff --git a/tests/run-make/no-builtins-attribute/Makefile b/tests/run-make/no-builtins-attribute/Makefile
deleted file mode 100644
index 0ce95fa..0000000
--- a/tests/run-make/no-builtins-attribute/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include ../tools.mk
-
-# We want to check if `no-builtins` is also added to the function declarations in the used crate.
-
-all:
- $(RUSTC) no_builtins.rs --emit=link
- $(RUSTC) main.rs --emit=llvm-ir
-
- cat "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck.main.txt
diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs
new file mode 100644
index 0000000..1e15b0c
--- /dev/null
+++ b/tests/run-make/no-builtins-attribute/rmake.rs
@@ -0,0 +1,13 @@
+// `no_builtins` is an attribute related to LLVM's optimizations. In order to ensure that it has an
+// effect on link-time optimizations (LTO), it should be added to function declarations in a crate.
+// This test uses the `llvm-filecheck` tool to determine that this attribute is successfully
+// being added to these function declarations.
+// See https://github.com/rust-lang/rust/pull/113716
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+ rustc().input("no_builtins.rs").emit("link").run();
+ rustc().input("main.rs").emit("llvm-ir").run();
+ llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run();
+}
diff --git a/tests/run-make/no-duplicate-libs/main.rs b/tests/run-make/no-duplicate-libs/main.rs
index b25ef35..d8d5d58 100644
--- a/tests/run-make/no-duplicate-libs/main.rs
+++ b/tests/run-make/no-duplicate-libs/main.rs
@@ -1,6 +1,6 @@
-#[link(name = "foo")] // linker should drop this library, no symbols used
-#[link(name = "bar")] // symbol comes from this library
-#[link(name = "foo")] // now linker picks up `foo` b/c `bar` library needs it
+#[link(name = "foo", kind = "static")] // linker should drop this library, no symbols used
+#[link(name = "bar", kind = "static")] // symbol comes from this library
+#[link(name = "foo", kind = "static")] // now linker picks up `foo` b/c `bar` library needs it
extern "C" {
fn bar();
}
diff --git a/tests/run-make/no-duplicate-libs/rmake.rs b/tests/run-make/no-duplicate-libs/rmake.rs
index 469348e..b670679 100644
--- a/tests/run-make/no-duplicate-libs/rmake.rs
+++ b/tests/run-make/no-duplicate-libs/rmake.rs
@@ -9,9 +9,6 @@
//@ ignore-cross-compile
// Reason: the compiled binary is executed
-//@ ignore-msvc
-// Reason: native compilation results in an unresolved external symbol
-
use run_make_support::{build_native_static_lib, run, rustc};
fn main() {
diff --git a/tests/run-make/no-intermediate-extras/rmake.rs b/tests/run-make/no-intermediate-extras/rmake.rs
index 0641417..0b12da6 100644
--- a/tests/run-make/no-intermediate-extras/rmake.rs
+++ b/tests/run-make/no-intermediate-extras/rmake.rs
@@ -5,9 +5,10 @@
//@ ignore-cross-compile
-use run_make_support::rustc;
use std::fs;
+use run_make_support::rustc;
+
fn main() {
rustc().crate_type("rlib").arg("--test").input("foo.rs").run();
assert!(
diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs
index 0042e4d..d708192 100644
--- a/tests/run-make/non-unicode-env/rmake.rs
+++ b/tests/run-make/non-unicode-env/rmake.rs
@@ -1,5 +1,4 @@
-use run_make_support::rfs;
-use run_make_support::rustc;
+use run_make_support::{rfs, rustc};
fn main() {
#[cfg(unix)]
diff --git a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
index ef316f11..42bd4b1 100644
--- a/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
+++ b/tests/run-make/non-unicode-in-incremental-dir/rmake.rs
@@ -8,7 +8,7 @@ fn main() {
match std::fs::create_dir(&non_unicode) {
// If an error occurs, check if creating a directory with a valid Unicode name would
// succeed.
- Err(e) if std::fs::create_dir("valid_unicode").is_ok() => {
+ Err(_) if std::fs::create_dir("valid_unicode").is_ok() => {
// Filesystem doesn't appear support non-Unicode paths.
return;
}
diff --git a/tests/run-make/obey-crate-type-flag/rmake.rs b/tests/run-make/obey-crate-type-flag/rmake.rs
index 8d6eb23..3fef4b7 100644
--- a/tests/run-make/obey-crate-type-flag/rmake.rs
+++ b/tests/run-make/obey-crate-type-flag/rmake.rs
@@ -5,10 +5,11 @@
//@ ignore-cross-compile
+use std::path::Path;
+
use run_make_support::{
cwd, dynamic_lib_name, has_extension, rfs, rust_lib_name, rustc, shallow_find_files,
};
-use std::path::Path;
fn main() {
rustc().input("test.rs").run();
diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs
index c51b215..c0569af 100644
--- a/tests/run-make/output-type-permutations/rmake.rs
+++ b/tests/run-make/output-type-permutations/rmake.rs
@@ -4,11 +4,12 @@
// files are exactly what is expected, no more, no less.
// See https://github.com/rust-lang/rust/pull/12020
+use std::path::PathBuf;
+
use run_make_support::{
bin_name, dynamic_lib_name, filename_not_in_denylist, rfs, rust_lib_name, rustc,
shallow_find_files, static_lib_name,
};
-use std::path::PathBuf;
// Each test takes 4 arguments:
// `must_exist`: output files which must be found - if any are absent, the test fails
@@ -112,7 +113,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "asm-emit".to_string(),
},
|| {
@@ -122,7 +123,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "asm-emit2".to_string(),
},
|| {
@@ -132,7 +133,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "asm-emit3".to_string(),
},
|| {
@@ -143,7 +144,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "llvm-ir-emit".to_string(),
},
|| {
@@ -153,7 +154,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "llvm-ir-emit2".to_string(),
},
|| {
@@ -163,7 +164,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "llvm-ir-emit3".to_string(),
},
|| {
@@ -174,7 +175,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "llvm-bc-emit".to_string(),
},
|| {
@@ -184,7 +185,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "llvm-bc-emit2".to_string(),
},
|| {
@@ -194,7 +195,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "llvm-bc-emit3".to_string(),
},
|| {
@@ -205,7 +206,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "obj-emit".to_string(),
},
|| {
@@ -215,7 +216,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "obj-emit2".to_string(),
},
|| {
@@ -225,7 +226,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "obj-emit3".to_string(),
},
|| {
@@ -267,7 +268,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "rlib".to_string(),
},
|| {
@@ -277,7 +278,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "rlib2".to_string(),
},
|| {
@@ -287,7 +288,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "rlib3".to_string(),
},
|| {
@@ -374,7 +375,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "staticlib".to_string(),
},
|| {
@@ -384,7 +385,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "staticlib2".to_string(),
},
|| {
@@ -394,7 +395,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["foo"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "staticlib3".to_string(),
},
|| {
@@ -448,7 +449,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["ir", rust_lib_name("bar")],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "rlib-ir".to_string(),
},
|| {
@@ -465,7 +466,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["ir", "asm", "bc", "obj", "link"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "staticlib-all".to_string(),
},
|| {
@@ -483,7 +484,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["ir", "asm", "bc", "obj", "link"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "staticlib-all2".to_string(),
},
|| {
@@ -522,7 +523,7 @@ fn main() {
assert_expected_output_files(
Expectations {
expected_files: s!["bar.bc", rust_lib_name("bar"), "foo.bc"],
- allowed_files: s![],
+ allowed_files: vec![],
test_dir: "rlib-emits".to_string(),
},
|| {
diff --git a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs
index 3f412bf..aa38eb6 100644
--- a/tests/run-make/parallel-rustc-no-overwrite/rmake.rs
+++ b/tests/run-make/parallel-rustc-no-overwrite/rmake.rs
@@ -5,10 +5,11 @@
// conflicts. This test uses this flag and checks for successful compilation.
// See https://github.com/rust-lang/rust/pull/83846
-use run_make_support::{rfs, rustc};
use std::sync::{Arc, Barrier};
use std::thread;
+use run_make_support::{rfs, rustc};
+
fn main() {
rfs::create_file("lib.rs");
let barrier = Arc::new(Barrier::new(2));
diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/Makefile b/tests/run-make/pdb-buildinfo-cl-cmd/Makefile
deleted file mode 100644
index a7be301..0000000
--- a/tests/run-make/pdb-buildinfo-cl-cmd/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-include ../tools.mk
-
-# only-windows-msvc
-
-# tests if the pdb contains the following information in the LF_BUILDINFO:
-# 1. the commandline args to compile it (cmd)
-# 2. full path to the compiler (cl)
-
-# we just do a stringsearch on the pdb, as these need to show up at least once, as the LF_BUILDINFO is created for each cgu
-# actual parsing would be better, but this is a simple and good enough solution for now
-
-all:
- $(RUSTC_ORIGINAL) main.rs -g --crate-name my_crate_name --crate-type bin -C metadata=dc9ef878b0a48666 --out-dir $(TMPDIR)
- cat '$(TMPDIR)/my_crate_name.pdb' | grep -F '$(RUSTC_ORIGINAL)'
-# using a file containing the string so I don't have problems with escaping quotes and spaces
- cat '$(TMPDIR)/my_crate_name.pdb' | grep -f 'stringlist.txt'
diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs
new file mode 100644
index 0000000..2ab9057
--- /dev/null
+++ b/tests/run-make/pdb-buildinfo-cl-cmd/rmake.rs
@@ -0,0 +1,39 @@
+// Check if the pdb file contains the following information in the LF_BUILDINFO:
+// 1. full path to the compiler (cl)
+// 2. the commandline args to compile it (cmd)
+// This is because these used to be missing in #96475.
+// See https://github.com/rust-lang/rust/pull/113492
+
+//@ only-windows-msvc
+// Reason: pdb files are unique to this architecture
+
+use run_make_support::{assert_contains, bstr, env_var, rfs, rustc};
+
+fn main() {
+ rustc()
+ .input("main.rs")
+ .arg("-g")
+ .crate_name("my_crate_name")
+ .crate_type("bin")
+ .metadata("dc9ef878b0a48666")
+ .run();
+ let tests = [
+ &env_var("RUSTC"),
+ r#""main.rs""#,
+ r#""-g""#,
+ r#""--crate-name""#,
+ r#""my_crate_name""#,
+ r#""--crate-type""#,
+ r#""bin""#,
+ r#""-Cmetadata=dc9ef878b0a48666""#,
+ ];
+ for test in tests {
+ assert_pdb_contains(test);
+ }
+}
+
+fn assert_pdb_contains(needle: &str) {
+ let needle = needle.as_bytes();
+ use bstr::ByteSlice;
+ assert!(&rfs::read("my_crate_name.pdb").find(needle).is_some());
+}
diff --git a/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt b/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt
deleted file mode 100644
index 634e9f1..0000000
--- a/tests/run-make/pdb-buildinfo-cl-cmd/stringlist.txt
+++ /dev/null
@@ -1 +0,0 @@
-"main.rs" "-g" "--crate-name" "my_crate_name" "--crate-type" "bin" "-C" "metadata=dc9ef878b0a48666" "--out-dir"
\ No newline at end of file
diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs
index 588c5c6..ef33d00 100644
--- a/tests/run-make/pgo-branch-weights/rmake.rs
+++ b/tests/run-make/pgo-branch-weights/rmake.rs
@@ -10,9 +10,10 @@
//@ needs-profiler-support
//@ ignore-cross-compile
-use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run_with_args, rustc};
use std::path::Path;
+use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run_with_args, rustc};
+
fn main() {
let path_prof_data_dir = Path::new("prof_data_dir");
let path_merged_profdata = path_prof_data_dir.join("merged.profdata");
diff --git a/tests/run-make/pgo-gen-lto/Makefile b/tests/run-make/pgo-gen-lto/Makefile
deleted file mode 100644
index 54164c9..0000000
--- a/tests/run-make/pgo-gen-lto/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# needs-profiler-support
-# ignore-cross-compile
-
-include ../tools.mk
-
-COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
-
-all:
- $(RUSTC) $(COMPILE_FLAGS) test.rs
- $(call RUN,test) || exit 1
- [ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
diff --git a/tests/run-make/pgo-gen-lto/rmake.rs b/tests/run-make/pgo-gen-lto/rmake.rs
new file mode 100644
index 0000000..53d1623
--- /dev/null
+++ b/tests/run-make/pgo-gen-lto/rmake.rs
@@ -0,0 +1,22 @@
+// A simple smoke test: when rustc compiles with profiling enabled, a profraw file
+// should be generated.
+// See https://github.com/rust-lang/rust/pull/48346
+
+//@ needs-profiler-support
+// Reason: this exercises LTO profiling
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{cwd, has_extension, has_prefix, run, rustc, shallow_find_files};
+
+fn main() {
+ rustc().opt_level("3").arg("-Clto=fat").profile_generate(cwd()).input("test.rs").run();
+ run("test");
+ assert_eq!(
+ shallow_find_files(cwd(), |path| {
+ has_prefix(path, "default_") && has_extension(path, "profraw")
+ })
+ .len(),
+ 1
+ );
+}
diff --git a/tests/run-make/pgo-indirect-call-promotion/Makefile b/tests/run-make/pgo-indirect-call-promotion/Makefile
deleted file mode 100644
index 8d1e69c..0000000
--- a/tests/run-make/pgo-indirect-call-promotion/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# needs-profiler-support
-# ignore-cross-compile
-
-include ../tools.mk
-
-all:
- # We don't compile `opaque` with either optimizations or instrumentation.
- # We don't compile `opaque` with either optimizations or instrumentation.
- $(RUSTC) $(COMMON_FLAGS) opaque.rs
- # Compile the test program with instrumentation
- mkdir -p "$(TMPDIR)"/prof_data_dir
- $(RUSTC) $(COMMON_FLAGS) interesting.rs \
- -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O -Ccodegen-units=1
- $(RUSTC) $(COMMON_FLAGS) main.rs -Cprofile-generate="$(TMPDIR)"/prof_data_dir -O
- # The argument below generates to the expected branch weights
- $(call RUN,main) || exit 1
- "$(LLVM_BIN_DIR)"/llvm-profdata merge \
- -o "$(TMPDIR)"/prof_data_dir/merged.profdata \
- "$(TMPDIR)"/prof_data_dir
- $(RUSTC) $(COMMON_FLAGS) interesting.rs \
- -Cprofile-use="$(TMPDIR)"/prof_data_dir/merged.profdata -O \
- -Ccodegen-units=1 --emit=llvm-ir
- cat "$(TMPDIR)"/interesting.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt
diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs
new file mode 100644
index 0000000..d0ccfd8
--- /dev/null
+++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs
@@ -0,0 +1,33 @@
+// This test checks that indirect call promotion is performed. The test
+// programs calls the same function a thousand times through a function pointer.
+// Only PGO data provides the information that it actually always is the same
+// function. We verify that the indirect call promotion pass inserts a check
+// whether it can make a direct call instead of the indirect call.
+// See https://github.com/rust-lang/rust/pull/66631
+
+//@ needs-profiler-support
+// Reason: llvm_profdata is used
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run, rustc};
+
+fn main() {
+ // We don't compile `opaque` with either optimizations or instrumentation.
+ rustc().input("opaque.rs").run();
+ // Compile the test program with instrumentation
+ rfs::create_dir("prof_data_dir");
+ rustc().input("interesting.rs").profile_generate("prof_data_dir").opt().codegen_units(1).run();
+ rustc().input("main.rs").profile_generate("prof_data_dir").opt().run();
+ // The argument below generates to the expected branch weights
+ run("main");
+ llvm_profdata().merge().output("prof_data_dir/merged.profdata").input("prof_data_dir").run();
+ rustc()
+ .input("interesting.rs")
+ .profile_use("prof_data_dir/merged.profdata")
+ .opt()
+ .codegen_units(1)
+ .emit("llvm-ir")
+ .run();
+ llvm_filecheck().patterns("filecheck-patterns.txt").stdin(rfs::read("interesting.ll")).run();
+}
diff --git a/tests/run-make/pretty-print-with-dep-file/rmake.rs b/tests/run-make/pretty-print-with-dep-file/rmake.rs
index d7a29ff..5d42208 100644
--- a/tests/run-make/pretty-print-with-dep-file/rmake.rs
+++ b/tests/run-make/pretty-print-with-dep-file/rmake.rs
@@ -5,9 +5,10 @@
// does not get an unexpected dep-info file.
// See https://github.com/rust-lang/rust/issues/112898
-use run_make_support::{invalid_utf8_contains, rfs, rustc};
use std::path::Path;
+use run_make_support::{invalid_utf8_contains, rfs, rustc};
+
fn main() {
rustc().emit("dep-info").arg("-Zunpretty=expanded").input("with-dep.rs").run();
invalid_utf8_contains("with-dep.d", "with-dep.rs");
diff --git a/tests/run-make/print-calling-conventions/Makefile b/tests/run-make/print-calling-conventions/Makefile
deleted file mode 100644
index 27b87e6..0000000
--- a/tests/run-make/print-calling-conventions/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
- $(RUSTC) --print calling-conventions
diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs
index d83e8a3..471a99b 100644
--- a/tests/run-make/print-cfg/rmake.rs
+++ b/tests/run-make/print-cfg/rmake.rs
@@ -6,7 +6,6 @@
//! It also checks that some targets have the correct set cfgs.
use std::collections::HashSet;
-use std::ffi::OsString;
use std::iter::FromIterator;
use std::path::PathBuf;
@@ -91,10 +90,8 @@ fn check_(output: &str, includes: &[&str], disallow: &[&str]) {
// --print=cfg=PATH
{
let tmp_path = PathBuf::from(format!("{target}.cfg"));
- let mut print_arg = OsString::from("--print=cfg=");
- print_arg.push(tmp_path.as_os_str());
- rustc().target(target).arg(print_arg).run();
+ rustc().target(target).print(&format!("cfg={}", tmp_path.display())).run();
let output = rfs::read_to_string(&tmp_path);
diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs
index 4a79910..f6f7f7c 100644
--- a/tests/run-make/print-check-cfg/rmake.rs
+++ b/tests/run-make/print-check-cfg/rmake.rs
@@ -4,7 +4,6 @@
use std::collections::HashSet;
use std::iter::FromIterator;
-use std::ops::Deref;
use run_make_support::rustc;
@@ -87,7 +86,7 @@ fn main() {
fn check(CheckCfg { args, contains }: CheckCfg) {
let output =
- rustc().input("lib.rs").arg("-Zunstable-options").arg("--print=check-cfg").args(args).run();
+ rustc().input("lib.rs").arg("-Zunstable-options").print("check-cfg").args(args).run();
let stdout = output.stdout_utf8();
diff --git a/tests/run-make/print-native-static-libs/rmake.rs b/tests/run-make/print-native-static-libs/rmake.rs
index b4e7c0e..a51ac93 100644
--- a/tests/run-make/print-native-static-libs/rmake.rs
+++ b/tests/run-make/print-native-static-libs/rmake.rs
@@ -12,8 +12,6 @@
//@ ignore-cross-compile
//@ ignore-wasm
-use std::io::BufRead;
-
use run_make_support::{is_msvc, rustc};
fn main() {
diff --git a/tests/run-make/print-target-list/Makefile b/tests/run-make/print-target-list/Makefile
deleted file mode 100644
index f23c40d..0000000
--- a/tests/run-make/print-target-list/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-# Checks that all the targets returned by `rustc --print target-list` are valid
-# target specifications
-all:
- for target in $(shell $(BARE_RUSTC) --print target-list); do \
- $(BARE_RUSTC) --target $$target --print sysroot; \
- done
diff --git a/tests/run-make/print-target-list/rmake.rs b/tests/run-make/print-target-list/rmake.rs
new file mode 100644
index 0000000..743ed52
--- /dev/null
+++ b/tests/run-make/print-target-list/rmake.rs
@@ -0,0 +1,21 @@
+// Checks that all the targets returned by `rustc --print target-list` are valid
+// target specifications
+
+use run_make_support::bare_rustc;
+
+// FIXME(127877): certain experimental targets fail with creating a 'LLVM TargetMachine'
+// in CI, so we skip them
+const EXPERIMENTAL_TARGETS: &[&str] = &["avr", "m68k", "csky", "xtensa"];
+
+fn main() {
+ let targets = bare_rustc().print("target-list").run().stdout_utf8();
+
+ for target in targets.lines() {
+ // skip experimental targets that would otherwise fail
+ if EXPERIMENTAL_TARGETS.iter().any(|experimental| target.contains(experimental)) {
+ continue;
+ }
+
+ bare_rustc().target(target).print("sysroot").run();
+ }
+}
diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs
index d0cba72..db2a291 100644
--- a/tests/run-make/print-to-output/rmake.rs
+++ b/tests/run-make/print-to-output/rmake.rs
@@ -1,7 +1,6 @@
//! This checks the output of some `--print` options when
//! output to a file (instead of stdout)
-use std::ffi::OsString;
use std::path::PathBuf;
use run_make_support::{rfs, rustc, target};
@@ -44,10 +43,8 @@ fn check_(output: &str, includes: &[&str]) {
// --print={option}=PATH
let output = {
let tmp_path = PathBuf::from(format!("{}.txt", args.option));
- let mut print_arg = OsString::from(format!("--print={}=", args.option));
- print_arg.push(tmp_path.as_os_str());
- rustc().target(args.target).arg(print_arg).run();
+ rustc().target(args.target).print(&format!("{}={}", args.option, tmp_path.display())).run();
rfs::read_to_string(&tmp_path)
};
diff --git a/tests/run-make/profile/rmake.rs b/tests/run-make/profile/rmake.rs
index 8d41978..4c6f9c1 100644
--- a/tests/run-make/profile/rmake.rs
+++ b/tests/run-make/profile/rmake.rs
@@ -8,9 +8,10 @@
//@ ignore-cross-compile
//@ needs-profiler-support
-use run_make_support::{run, rustc};
use std::path::Path;
+use run_make_support::{run, rustc};
+
fn main() {
rustc().arg("-g").arg("-Zprofile").input("test.rs").run();
run("test");
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/Makefile b/tests/run-make/raw-dylib-alt-calling-convention/Makefile
deleted file mode 100644
index 14d23a5..0000000
--- a/tests/run-make/raw-dylib-alt-calling-convention/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
-
-# only-x86
-# only-windows
-
-include ../tools.mk
-
-all:
- $(RUSTC) --crate-type lib --crate-name raw_dylib_alt_calling_convention_test lib.rs
- $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
- $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
-ifdef IS_MSVC
- $(CC) "$(TMPDIR)"/extern.obj -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
-else
- $(CC) "$(TMPDIR)"/extern.obj -shared -o "$(TMPDIR)"/extern.dll
-endif
-
- "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
- $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt
-
-ifdef IS_MSVC
- "$(TMPDIR)"/driver true > "$(TMPDIR)"/output.msvc.txt
- $(RUSTC_TEST_OP) "$(TMPDIR)"/output.msvc.txt output.msvc.txt
-endif
diff --git a/tests/run-make/raw-dylib-alt-calling-convention/rmake.rs b/tests/run-make/raw-dylib-alt-calling-convention/rmake.rs
new file mode 100644
index 0000000..1a1622f
--- /dev/null
+++ b/tests/run-make/raw-dylib-alt-calling-convention/rmake.rs
@@ -0,0 +1,32 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// This test uses this feature alongside alternative calling conventions, checking that both
+// features are compatible and result in the expected output upon execution of the binary.
+// See https://github.com/rust-lang/rust/pull/84171
+
+//@ only-x86
+//@ only-windows
+
+use run_make_support::{build_native_dynamic_lib, diff, is_msvc, run, run_with_args, rustc};
+
+fn main() {
+ rustc()
+ .crate_type("lib")
+ .crate_name("raw_dylib_alt_calling_convention_test")
+ .input("lib.rs")
+ .run();
+ rustc().crate_type("bin").input("driver.rs").run();
+ build_native_dynamic_lib("extern");
+ let out = run("driver").stdout_utf8();
+ diff().expected_file("output.txt").actual_text("actual", out).normalize(r#"\r"#, "").run();
+ if is_msvc() {
+ let out_msvc = run_with_args("driver", &["true"]).stdout_utf8();
+ diff()
+ .expected_file("output.msvc.txt")
+ .actual_text("actual", out_msvc)
+ .normalize(r#"\r"#, "")
+ .run();
+ }
+}
diff --git a/tests/run-make/raw-dylib-c/Makefile b/tests/run-make/raw-dylib-c/Makefile
deleted file mode 100644
index af5c4a6..0000000
--- a/tests/run-make/raw-dylib-c/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
-
-# only-windows
-
-include ../tools.mk
-
-all:
- $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
- $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
- $(RUSTC) --crate-type bin --crate-name raw_dylib_test_bin lib.rs
- $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
- $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
-ifdef IS_MSVC
- $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll -noimplib
- $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll -noimplib
-else
- $(CC) "$(TMPDIR)"/extern_1.obj -shared -o "$(TMPDIR)"/extern_1.dll
- $(CC) "$(TMPDIR)"/extern_2.obj -shared -o "$(TMPDIR)"/extern_2.dll
-endif
- "$(TMPDIR)"/driver | tr -d '\r' > "$(TMPDIR)"/output.txt
- "$(TMPDIR)"/raw_dylib_test_bin > "$(TMPDIR)"/output_bin.txt
-
-ifdef RUSTC_BLESS_TEST
- cp "$(TMPDIR)"/output.txt output.txt
-else
- $(DIFF) output.txt "$(TMPDIR)"/output.txt
- $(DIFF) output.txt "$(TMPDIR)"/output_bin.txt
-endif
diff --git a/tests/run-make/raw-dylib-c/rmake.rs b/tests/run-make/raw-dylib-c/rmake.rs
new file mode 100644
index 0000000..3cfd8cb
--- /dev/null
+++ b/tests/run-make/raw-dylib-c/rmake.rs
@@ -0,0 +1,29 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// This test is the simplest of the raw-dylib tests, simply smoke-testing that the feature
+// can be used to build an executable binary with an expected output with native C files
+// compiling into dynamic libraries.
+// See https://github.com/rust-lang/rust/pull/86419
+
+//@ only-windows
+
+use run_make_support::{build_native_dynamic_lib, diff, run, rustc};
+
+fn main() {
+ rustc().crate_type("lib").crate_name("raw_dylib_test").input("lib.rs").run();
+ rustc().crate_type("bin").input("driver.rs").run();
+ rustc().crate_type("bin").crate_name("raw_dylib_test_bin").input("lib.rs").run();
+ build_native_dynamic_lib("extern_1");
+ build_native_dynamic_lib("extern_2");
+ let out_driver = run("driver").stdout_utf8();
+ let out_raw = run("raw_dylib_test_bin").stdout_utf8();
+
+ diff()
+ .expected_file("output.txt")
+ .actual_text("actual", out_driver)
+ .normalize(r#"\r"#, "")
+ .run();
+ diff().expected_file("output.txt").actual_text("actual", out_raw).normalize(r#"\r"#, "").run();
+}
diff --git a/tests/run-make/raw-dylib-import-name-type/Makefile b/tests/run-make/raw-dylib-import-name-type/Makefile
deleted file mode 100644
index 901d3e8..0000000
--- a/tests/run-make/raw-dylib-import-name-type/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
-
-# only-x86
-# only-windows
-
-include ../tools.mk
-
-all:
- $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
- $(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
-ifdef IS_MSVC
- $(CC) "$(TMPDIR)"/extern.obj extern.msvc.def -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
-else
- $(CC) "$(TMPDIR)"/extern.obj extern.gnu.def --no-leading-underscore -shared -o "$(TMPDIR)"/extern.dll
-endif
- "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
- $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt
diff --git a/tests/run-make/raw-dylib-import-name-type/rmake.rs b/tests/run-make/raw-dylib-import-name-type/rmake.rs
new file mode 100644
index 0000000..13a2c99
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/rmake.rs
@@ -0,0 +1,37 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// This test uses this feature alongside `import_name_type`, which allows for customization
+// of how Windows symbols will be named. A sanity check of this feature is done by comparison
+// with expected output.
+// See https://github.com/rust-lang/rust/pull/100732
+
+//@ only-x86
+//@ only-windows
+// Reason: this test specifically exercises a 32bit Windows calling convention.
+
+use run_make_support::{cc, diff, is_msvc, run, rustc};
+
+// NOTE: build_native_dynamic lib is not used, as the special `def` files
+// must be passed to the CC compiler.
+
+fn main() {
+ rustc().crate_type("bin").input("driver.rs").run();
+ if is_msvc() {
+ cc().arg("-c").out_exe("extern").input("extern.c").run();
+ cc().input("extern.obj")
+ .arg("extern.msvc.def")
+ .args(&["-link", "-dll", "-noimplib", "-out:extern.dll"])
+ .run();
+ } else {
+ cc().arg("-v").arg("-c").out_exe("extern.obj").input("extern.c").run();
+ cc().input("extern.obj")
+ .arg("extern.gnu.def")
+ .args(&["--no-leading-underscore", "-shared"])
+ .output("extern.dll")
+ .run();
+ };
+ let out = run("driver").stdout_utf8();
+ diff().expected_file("output.txt").actual_text("actual", out).normalize(r#"\r"#, "").run();
+}
diff --git a/tests/run-make/raw-dylib-link-ordinal/Makefile b/tests/run-make/raw-dylib-link-ordinal/Makefile
deleted file mode 100644
index 3cf1300..0000000
--- a/tests/run-make/raw-dylib-link-ordinal/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc
-
-# only-windows
-
-include ../tools.mk
-
-all:
- $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
- $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
- $(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
-ifdef IS_MSVC
- $(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
-else
- $(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
-endif
- "$(TMPDIR)"/driver | tr -d '\r' > "$(TMPDIR)"/output.txt
- $(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt
diff --git a/tests/run-make/raw-dylib-link-ordinal/rmake.rs b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
new file mode 100644
index 0000000..b52181a
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
@@ -0,0 +1,34 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// `#[link_ordinal(n)]` allows Rust to link against DLLs that export symbols by ordinal rather
+// than by name. As long as the ordinal matches, the name of the function in Rust is not
+// required to match the name of the corresponding function in the exporting DLL.
+// This test is a sanity check for this feature, done by comparing its output against expected
+// output.
+// See https://github.com/rust-lang/rust/pull/89025
+
+//@ only-windows
+
+use run_make_support::{cc, diff, is_msvc, run, rustc};
+
+// NOTE: build_native_dynamic lib is not used, as the special `def` files
+// must be passed to the CC compiler.
+
+fn main() {
+ rustc().crate_type("lib").crate_name("raw_dylib_test").input("lib.rs").run();
+ rustc().crate_type("bin").input("driver.rs").run();
+ if is_msvc() {
+ cc().arg("-c").out_exe("exporter").input("exporter.c").run();
+ cc().input("exporter.obj")
+ .arg("exporter.def")
+ .args(&["-link", "-dll", "-noimplib", "-out:exporter.dll"])
+ .run();
+ } else {
+ cc().arg("-v").arg("-c").out_exe("exporter.obj").input("exporter.c").run();
+ cc().input("exporter.obj").arg("exporter.def").arg("-shared").output("exporter.dll").run();
+ };
+ let out = run("driver").stdout_utf8();
+ diff().expected_file("output.txt").actual_text("actual", out).normalize(r#"\r"#, "").run();
+}
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile b/tests/run-make/raw-dylib-stdcall-ordinal/Makefile
deleted file mode 100644
index 70e4de6..0000000
--- a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")], #[link_ordinal], and alternative calling conventions on i686 windows.
-
-# only-x86
-# only-windows
-
-include ../tools.mk
-
-all:
- $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
- $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
- $(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
-ifdef IS_MSVC
- $(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
-else
- $(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
-endif
- "$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
- $(RUSTC_TEST_OP) "$(TMPDIR)"/actual_output.txt expected_output.txt
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs b/tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs
new file mode 100644
index 0000000..320ea15
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs
@@ -0,0 +1,41 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// Almost identical to `raw-dylib-link-ordinal`, but with the addition of calling conventions,
+// such as stdcall.
+// See https://github.com/rust-lang/rust/pull/90782
+
+//@ only-x86
+//@ only-windows
+// Reason: this test specifically exercises a 32bit Windows calling convention.
+
+use run_make_support::{cc, diff, is_msvc, run, rustc};
+
+// NOTE: build_native_dynamic lib is not used, as the special `def` files
+// must be passed to the CC compiler.
+
+fn main() {
+ rustc().crate_type("lib").crate_name("raw_dylib_test").input("lib.rs").run();
+ rustc().crate_type("bin").input("driver.rs").run();
+ if is_msvc() {
+ cc().arg("-c").out_exe("exporter").input("exporter.c").run();
+ cc().input("exporter.obj")
+ .arg("exporter-msvc.def")
+ .args(&["-link", "-dll", "-noimplib", "-out:exporter.dll"])
+ .run();
+ } else {
+ cc().arg("-v").arg("-c").out_exe("exporter.obj").input("exporter.c").run();
+ cc().input("exporter.obj")
+ .arg("exporter-gnu.def")
+ .arg("-shared")
+ .output("exporter.dll")
+ .run();
+ };
+ let out = run("driver").stdout_utf8();
+ diff()
+ .expected_file("expected_output.txt")
+ .actual_text("actual", out)
+ .normalize(r#"\r"#, "")
+ .run();
+}
diff --git a/tests/run-make/redundant-libs/Makefile b/tests/run-make/redundant-libs/Makefile
deleted file mode 100644
index 0a48b2b..0000000
--- a/tests/run-make/redundant-libs/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows-msvc
-
-# rustc will remove one of the two redundant references to foo below. Depending
-# on which one gets removed, we'll get a linker error on SOME platforms (like
-# Linux). On these platforms, when a library is referenced, the linker will
-# only pull in the symbols needed _at that point in time_. If a later library
-# depends on additional symbols from the library, they will not have been pulled
-# in, and you'll get undefined symbols errors.
-#
-# So in this example, we need to ensure that rustc keeps the _later_ reference
-# to foo, and not the former one.
-RUSTC_FLAGS = \
- -l static=bar \
- -l foo \
- -l static=baz \
- -l foo \
- --print link-args
-
-all: $(call DYLIB,foo) $(call STATICLIB,bar) $(call STATICLIB,baz)
- $(RUSTC) $(RUSTC_FLAGS) main.rs
- $(call RUN,main)
diff --git a/tests/run-make/redundant-libs/foo.c b/tests/run-make/redundant-libs/foo.c
index 339ee86..551b85d 100644
--- a/tests/run-make/redundant-libs/foo.c
+++ b/tests/run-make/redundant-libs/foo.c
@@ -1,2 +1,8 @@
-void foo1() {}
-void foo2() {}
+#ifdef _MSC_VER
+#define DllExport __declspec(dllexport)
+#else
+#define DllExport
+#endif
+
+DllExport void foo1() {}
+DllExport void foo2() {}
diff --git a/tests/run-make/redundant-libs/rmake.rs b/tests/run-make/redundant-libs/rmake.rs
new file mode 100644
index 0000000..e984dee
--- /dev/null
+++ b/tests/run-make/redundant-libs/rmake.rs
@@ -0,0 +1,26 @@
+// rustc will remove one of the two redundant references to foo below. Depending
+// on which one gets removed, we'll get a linker error on SOME platforms (like
+// Linux). On these platforms, when a library is referenced, the linker will
+// only pull in the symbols needed _at that point in time_. If a later library
+// depends on additional symbols from the library, they will not have been pulled
+// in, and you'll get undefined symbols errors.
+//
+// So in this example, we need to ensure that rustc keeps the _later_ reference
+// to foo, and not the former one.
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed
+
+use run_make_support::{build_native_dynamic_lib, build_native_static_lib, run, rustc};
+
+fn main() {
+ build_native_dynamic_lib("foo");
+ build_native_static_lib("bar");
+ build_native_static_lib("baz");
+ rustc()
+ .args(&["-lstatic=bar", "-lfoo", "-lstatic=baz", "-lfoo"])
+ .input("main.rs")
+ .print("link-args")
+ .run();
+ run("main");
+}
diff --git a/tests/run-make/relro-levels/rmake.rs b/tests/run-make/relro-levels/rmake.rs
index 56545eb..91d106a 100644
--- a/tests/run-make/relro-levels/rmake.rs
+++ b/tests/run-make/relro-levels/rmake.rs
@@ -2,8 +2,7 @@
//@ only-linux
-use run_make_support::llvm_readobj;
-use run_make_support::rustc;
+use run_make_support::{llvm_readobj, rustc};
fn compile(relro_level: &str) {
rustc().arg(format!("-Crelro-level={relro_level}")).input("hello.rs").run();
diff --git a/tests/run-make/repr128-dwarf/rmake.rs b/tests/run-make/repr128-dwarf/rmake.rs
index 824ca6e..2fd54c1 100644
--- a/tests/run-make/repr128-dwarf/rmake.rs
+++ b/tests/run-make/repr128-dwarf/rmake.rs
@@ -1,13 +1,14 @@
//@ ignore-windows
// This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit enums.
-use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian};
-use object::{Object, ObjectSection};
-use run_make_support::{gimli, object, rfs, rustc};
use std::collections::HashMap;
use std::path::PathBuf;
use std::rc::Rc;
+use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian};
+use object::{Object, ObjectSection};
+use run_make_support::{gimli, object, rfs, rustc};
+
fn main() {
let output = PathBuf::from("repr128");
rustc().input("main.rs").output(&output).arg("-Cdebuginfo=2").run();
diff --git a/tests/run-make/reproducible-build-2/Makefile b/tests/run-make/reproducible-build-2/Makefile
deleted file mode 100644
index 68fcac8..0000000
--- a/tests/run-make/reproducible-build-2/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-musl
-# ignore-windows
-# Objects are reproducible but their path is not.
-
-all: \
- fat_lto \
- sysroot
-
-fat_lto:
- rm -rf $(TMPDIR) && mkdir $(TMPDIR)
- $(RUSTC) reproducible-build-aux.rs
- $(RUSTC) reproducible-build.rs -C lto=fat
- cp $(TMPDIR)/reproducible-build $(TMPDIR)/reproducible-build-a
- $(RUSTC) reproducible-build.rs -C lto=fat
- cmp "$(TMPDIR)/reproducible-build-a" "$(TMPDIR)/reproducible-build" || exit 1
-
-sysroot:
- rm -rf $(TMPDIR) && mkdir $(TMPDIR)
- $(RUSTC) reproducible-build-aux.rs
- $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(shell $(RUSTC) --print sysroot) --remap-path-prefix=$(shell $(RUSTC) --print sysroot)=/sysroot
- cp -R $(shell $(RUSTC) --print sysroot) $(TMPDIR)/sysroot
- cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib
- $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(TMPDIR)/sysroot --remap-path-prefix=$(TMPDIR)/sysroot=/sysroot
- cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs
new file mode 100644
index 0000000..8b5825c
--- /dev/null
+++ b/tests/run-make/reproducible-build-2/rmake.rs
@@ -0,0 +1,47 @@
+// Builds with fat link-time-optimizations and the --sysroot flag used to be
+// non-deterministic - that means, compiling twice with no changes would create
+// slightly different outputs. This has been fixed by #63352 and #63505.
+// Test 1: Compile with fat-lto twice, check that both compilation outputs are identical.
+// Test 2: Compile with sysroot, then change the sysroot path from absolute to relative.
+// Outputs should be identical.
+// See https://github.com/rust-lang/rust/issues/34902
+
+//@ ignore-windows
+// Reasons:
+// 1. The object files are reproducible, but their paths are not, which causes
+// the first assertion in the test to fail.
+// 2. When the sysroot gets copied, some symlinks must be re-created,
+// which is a privileged action on Windows.
+
+use run_make_support::{rfs, rust_lib_name, rustc};
+
+fn main() {
+ // test 1: fat lto
+ rustc().input("reproducible-build-aux.rs").run();
+ rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run();
+ rfs::rename("reproducible-build", "reproducible-build-a");
+ rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run();
+ assert_eq!(rfs::read("reproducible-build"), rfs::read("reproducible-build-a"));
+
+ // test 2: sysroot
+ let sysroot = rustc().print("sysroot").run().stdout_utf8();
+ let sysroot = sysroot.trim();
+
+ rustc().input("reproducible-build-aux.rs").run();
+ rustc()
+ .input("reproducible-build.rs")
+ .crate_type("rlib")
+ .sysroot(&sysroot)
+ .arg(format!("--remap-path-prefix={sysroot}=/sysroot"))
+ .run();
+ rfs::copy_dir_all(&sysroot, "sysroot");
+ rfs::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo"));
+ rustc()
+ .input("reproducible-build.rs")
+ .crate_type("rlib")
+ .sysroot("sysroot")
+ .arg("--remap-path-prefix=/sysroot=/sysroot")
+ .run();
+
+ assert_eq!(rfs::read(rust_lib_name("reproducible_build")), rfs::read(rust_lib_name("foo")));
+}
diff --git a/tests/run-make/reset-codegen-1/rmake.rs b/tests/run-make/reset-codegen-1/rmake.rs
index cc6bb7d..118b3a6 100644
--- a/tests/run-make/reset-codegen-1/rmake.rs
+++ b/tests/run-make/reset-codegen-1/rmake.rs
@@ -7,9 +7,10 @@
//@ ignore-cross-compile
-use run_make_support::{bin_name, rfs, rustc};
use std::path::Path;
+use run_make_support::{bin_name, rustc};
+
fn compile(output_file: &str, emit: Option<&str>) {
let mut rustc = rustc();
let rustc = rustc.codegen_units(4).output(output_file).input("foo.rs");
diff --git a/tests/run-make/resolve-rename/rmake.rs b/tests/run-make/resolve-rename/rmake.rs
index 16ee7b0..21ec7f8 100644
--- a/tests/run-make/resolve-rename/rmake.rs
+++ b/tests/run-make/resolve-rename/rmake.rs
@@ -5,8 +5,7 @@
// the renamed library.
// See https://github.com/rust-lang/rust/pull/49253
-use run_make_support::rfs;
-use run_make_support::rustc;
+use run_make_support::{rfs, rustc};
fn main() {
rustc().extra_filename("-hash").input("foo.rs").run();
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
deleted file mode 100644
index d2a740b..0000000
--- a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-
-# Make sure -Zpacked_bundled_libs is compatible with verbatim.
-
-# We're using the llvm-nm instead of the system nm to ensure it is compatible
-# with the LLVM bitcode generated by rustc.
-# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm.
-ifndef IS_WINDOWS
-NM = "$(LLVM_BIN_DIR)"/llvm-nm
-else
-NM = nm
-endif
-
-all:
- # Build strange-named dep.
- $(RUSTC) native_dep.rs --crate-type=staticlib -o $(TMPDIR)/native_dep.ext
-
- $(RUSTC) rust_dep.rs --crate-type=rlib -Zpacked_bundled_libs
- $(NM) $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "U.*native_f1"
- $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) "native_dep.ext"
-
- # Make sure compiler doesn't use files, that it shouldn't know about.
- rm $(TMPDIR)/native_dep.ext
-
- $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib -Zpacked_bundled_libs
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
new file mode 100644
index 0000000..5a14609
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
@@ -0,0 +1,28 @@
+// `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler
+// only require a native library and no supplementary object files to compile.
+// This test simply checks that this flag can be passed alongside verbatim syntax
+// in rustc flags without a compilation failure or the removal of expected symbols.
+// See https://github.com/rust-lang/rust/pull/100101
+
+use run_make_support::{llvm_ar, llvm_nm, rfs, rust_lib_name, rustc};
+
+fn main() {
+ // Build a strangely named dependency.
+ rustc().input("native_dep.rs").crate_type("staticlib").output("native_dep.ext").run();
+
+ rustc().input("rust_dep.rs").crate_type("rlib").arg("-Zpacked_bundled_libs").run();
+ llvm_nm().input(rust_lib_name("rust_dep")).run().assert_stdout_contains_regex("U.*native_f1");
+ llvm_ar()
+ .arg("t")
+ .arg(rust_lib_name("rust_dep"))
+ .run()
+ .assert_stdout_contains("native_dep.ext");
+
+ // Ensure the compiler does not use files it should not be aware of.
+ rfs::remove_file("native_dep.ext");
+ rustc()
+ .input("main.rs")
+ .extern_("rust_dep", rust_lib_name("rust_dep"))
+ .arg("-Zpacked_bundled_libs")
+ .run();
+}
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs
index d152047..67e839b 100644
--- a/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs
+++ b/tests/run-make/rlib-format-packed-bundled-libs-3/rmake.rs
@@ -6,7 +6,7 @@
// See https://github.com/rust-lang/rust/pull/105601
use run_make_support::{
- build_native_static_lib, is_msvc, llvm_ar, regex, rfs, rust_lib_name, rustc, static_lib_name,
+ build_native_static_lib, llvm_ar, regex, rfs, rust_lib_name, rustc, static_lib_name,
};
//@ ignore-cross-compile
diff --git a/tests/run-make/run-in-tmpdir-self-test/rmake.rs b/tests/run-make/run-in-tmpdir-self-test/rmake.rs
index 83b99bf..dba036f 100644
--- a/tests/run-make/run-in-tmpdir-self-test/rmake.rs
+++ b/tests/run-make/run-in-tmpdir-self-test/rmake.rs
@@ -3,7 +3,7 @@
//! when returning from the closure.
use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
use run_make_support::{cwd, run_in_tmpdir};
diff --git a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs
index fc3dffd..2417a42 100644
--- a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs
+++ b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs
@@ -4,9 +4,10 @@
//@ ignore-nightly
//@ only-x86_64-unknown-linux-gnu
+use std::process::Output;
+
use run_make_support::regex::Regex;
use run_make_support::rustc;
-use std::process::Output;
fn main() {
// A regular compilation should not use rust-lld by default. We'll check that by asking the
diff --git a/tests/run-make/rust-lld-by-default-nightly/rmake.rs b/tests/run-make/rust-lld-by-default-nightly/rmake.rs
index f3ce9ad..02bbe822 100644
--- a/tests/run-make/rust-lld-by-default-nightly/rmake.rs
+++ b/tests/run-make/rust-lld-by-default-nightly/rmake.rs
@@ -8,7 +8,6 @@
use run_make_support::regex::Regex;
use run_make_support::rustc;
-use std::process::Output;
fn main() {
// A regular compilation should use rust-lld by default. We'll check that by asking the linker
diff --git a/tests/run-make/rust-lld-compress-debug-sections/main.rs b/tests/run-make/rust-lld-compress-debug-sections/main.rs
new file mode 100644
index 0000000..f328e4d
--- /dev/null
+++ b/tests/run-make/rust-lld-compress-debug-sections/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/rust-lld-compress-debug-sections/rmake.rs b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs
new file mode 100644
index 0000000..ea4997f
--- /dev/null
+++ b/tests/run-make/rust-lld-compress-debug-sections/rmake.rs
@@ -0,0 +1,39 @@
+// Checks the `compress-debug-sections` option on rust-lld.
+
+//@ needs-rust-lld
+//@ only-linux
+//@ ignore-cross-compile
+
+// FIXME: This test isn't comprehensive and isn't covering all possible combinations.
+
+use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc};
+
+fn check_compression(compression: &str, to_find: &str) {
+ run_in_tmpdir(|| {
+ let out = rustc()
+ .arg("-Zlinker-features=+lld")
+ .arg("-Clink-self-contained=+linker")
+ .arg("-Zunstable-options")
+ .arg("-Cdebuginfo=full")
+ .link_arg(&format!("-Wl,--compress-debug-sections={compression}"))
+ .input("main.rs")
+ .run_unchecked();
+ let stderr = out.stderr_utf8();
+ if stderr.is_empty() {
+ llvm_readobj().arg("-t").arg("main").run().assert_stdout_contains(to_find);
+ } else {
+ assert_contains(
+ stderr,
+ format!(
+ "LLVM was not built with LLVM_ENABLE_{to_find} \
+ or did not find {compression} at build time"
+ ),
+ );
+ }
+ });
+}
+
+fn main() {
+ check_compression("zlib", "ZLIB");
+ check_compression("zstd", "ZSTD");
+}
diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs
index f3dc227..a6f7c33 100644
--- a/tests/run-make/rust-lld-custom-target/rmake.rs
+++ b/tests/run-make/rust-lld-custom-target/rmake.rs
@@ -10,7 +10,6 @@
use run_make_support::regex::Regex;
use run_make_support::rustc;
-use std::process::Output;
fn main() {
// Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking
diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs
index 3eb6036..1f311af 100644
--- a/tests/run-make/rust-lld/rmake.rs
+++ b/tests/run-make/rust-lld/rmake.rs
@@ -2,14 +2,15 @@
// see https://github.com/rust-lang/compiler-team/issues/510 for more info
//@ needs-rust-lld
-//@ ignore-msvc
//@ ignore-s390x lld does not yet support s390x as target
use run_make_support::regex::Regex;
-use run_make_support::rustc;
-use std::process::Output;
+use run_make_support::{is_msvc, rustc};
fn main() {
+ // lld-link is used if msvc, otherwise a gnu-compatible lld is used.
+ let linker_version_flag = if is_msvc() { "--version" } else { "-Wl,-v" };
+
// Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
// asking the linker to display its version number with a link-arg.
let output = rustc()
@@ -17,7 +18,7 @@ fn main() {
.arg("-Zlinker-features=+lld")
.arg("-Clink-self-contained=+linker")
.arg("-Zunstable-options")
- .link_arg("-Wl,-v")
+ .link_arg(linker_version_flag)
.input("main.rs")
.run();
assert!(
@@ -26,10 +27,10 @@ fn main() {
output.stderr_utf8()
);
- // It should not be used when we explictly opt-out of lld.
+ // It should not be used when we explicitly opt-out of lld.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
- .link_arg("-Wl,-v")
+ .link_arg(linker_version_flag)
.arg("-Zlinker-features=-lld")
.input("main.rs")
.run();
@@ -43,7 +44,7 @@ fn main() {
// times to rustc.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
- .link_arg("-Wl,-v")
+ .link_arg(linker_version_flag)
.arg("-Clink-self-contained=+linker")
.arg("-Zunstable-options")
.arg("-Zlinker-features=-lld")
diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
similarity index 100%
rename from tests/run-make/issue-88756-default-output/output-default.stdout
rename to tests/run-make/rustdoc-default-output/output-default.stdout
diff --git a/tests/run-make/rustdoc-default-output/rmake.rs b/tests/run-make/rustdoc-default-output/rmake.rs
new file mode 100644
index 0000000..0672044
--- /dev/null
+++ b/tests/run-make/rustdoc-default-output/rmake.rs
@@ -0,0 +1,16 @@
+// Calling rustdoc with no arguments, which should bring up a help menu, used to
+// cause an error as rustdoc expects an input file. Fixed in #98331, this test
+// ensures the output of rustdoc's help menu is as expected.
+// See https://github.com/rust-lang/rust/issues/88756
+
+use run_make_support::{bare_rustdoc, diff};
+
+fn main() {
+ let out = bare_rustdoc().run().stdout_utf8();
+ diff()
+ .expected_file("output-default.stdout")
+ .actual_text("actual", out)
+ // replace the channel type in the URL with $CHANNEL
+ .normalize(r"nightly/|beta/|stable/|1\.[0-9]+\.[0-9]+/", "$$CHANNEL/")
+ .run();
+}
diff --git a/tests/run-make/rustdoc-determinism/rmake.rs b/tests/run-make/rustdoc-determinism/rmake.rs
index 2d4f357..aa80901 100644
--- a/tests/run-make/rustdoc-determinism/rmake.rs
+++ b/tests/run-make/rustdoc-determinism/rmake.rs
@@ -1,9 +1,10 @@
// Assert that the search index is generated deterministically, regardless of the
// order that crates are documented in.
-use run_make_support::{diff, rustdoc};
use std::path::Path;
+use run_make_support::{diff, rustdoc};
+
fn main() {
let foo_first = Path::new("foo_first");
rustdoc().input("foo.rs").output(&foo_first).run();
diff --git a/tests/run-make/rustdoc-io-error/rmake.rs b/tests/run-make/rustdoc-io-error/rmake.rs
index 69afea4..a5fae36 100644
--- a/tests/run-make/rustdoc-io-error/rmake.rs
+++ b/tests/run-make/rustdoc-io-error/rmake.rs
@@ -14,21 +14,20 @@
// `mkfs.ext4 -d`, as well as mounting a loop device for the rootfs.
//@ ignore-windows - the `set_readonly` functions doesn't work on folders.
-use run_make_support::{path, rustdoc};
-use std::fs;
+use run_make_support::{path, rfs, rustdoc};
fn main() {
let out_dir = path("rustdoc-io-error");
- let output = fs::create_dir(&out_dir).unwrap();
- let mut permissions = fs::metadata(&out_dir).unwrap().permissions();
+ rfs::create_dir(&out_dir);
+ let mut permissions = rfs::metadata(&out_dir).permissions();
let original_permissions = permissions.clone();
permissions.set_readonly(true);
- fs::set_permissions(&out_dir, permissions).unwrap();
+ rfs::set_permissions(&out_dir, permissions);
let output = rustdoc().input("foo.rs").output(&out_dir).env("RUST_BACKTRACE", "1").run_fail();
- fs::set_permissions(&out_dir, original_permissions).unwrap();
+ rfs::set_permissions(&out_dir, original_permissions);
output
.assert_exit_code(1)
diff --git a/tests/run-make/rustdoc-output-path/rmake.rs b/tests/run-make/rustdoc-output-path/rmake.rs
index 28e0fd9..3c1ccd3 100644
--- a/tests/run-make/rustdoc-output-path/rmake.rs
+++ b/tests/run-make/rustdoc-output-path/rmake.rs
@@ -1,8 +1,9 @@
// Checks that if the output folder doesn't exist, rustdoc will create it.
-use run_make_support::rustdoc;
use std::path::Path;
+use run_make_support::rustdoc;
+
fn main() {
let out_dir = Path::new("foo/bar/doc");
rustdoc().input("foo.rs").output(&out_dir).run();
diff --git a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
index bfe4a1d..b77df7a 100644
--- a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
+++ b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs
@@ -11,8 +11,7 @@ fn main() {
let dylib_name = rustc()
.crate_name(proc_crate_name)
.crate_type("dylib")
- .arg("--print")
- .arg("file-names")
+ .print("file-names")
.arg("-")
.run()
.stdout_utf8();
diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
index 3feee78..eca0704 100644
--- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
+++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs
@@ -1,6 +1,7 @@
-use run_make_support::{htmldocck, rfs, rustc, rustdoc, source_root};
use std::path::Path;
+use run_make_support::{htmldocck, rfs, rustc, rustdoc};
+
pub fn scrape(extra_args: &[&str]) {
let out_dir = Path::new("rustdoc");
let crate_name = "foobar";
diff --git a/tests/run-make/rustdoc-test-args/rmake.rs b/tests/run-make/rustdoc-test-args/rmake.rs
index 69dea83..fddb379 100644
--- a/tests/run-make/rustdoc-test-args/rmake.rs
+++ b/tests/run-make/rustdoc-test-args/rmake.rs
@@ -1,7 +1,8 @@
-use run_make_support::{rfs, rustdoc};
use std::iter;
use std::path::Path;
+use run_make_support::{rfs, rustdoc};
+
fn generate_a_lot_of_cfgs(path: &Path) {
let content = iter::repeat("--cfg=a\n").take(100_000).collect::<String>();
rfs::write(path, content.as_bytes());
diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs
index 981db35..8a961be 100644
--- a/tests/run-make/rustdoc-themes/rmake.rs
+++ b/tests/run-make/rustdoc-themes/rmake.rs
@@ -1,8 +1,9 @@
// Test that rustdoc will properly load in a theme file and display it in the theme selector.
-use run_make_support::{htmldocck, rfs, rustdoc, source_root};
use std::path::Path;
+use run_make_support::{htmldocck, rfs, rustdoc, source_root};
+
fn main() {
let out_dir = Path::new("rustdoc-themes");
let test_css = "test.css";
diff --git a/tests/run-make/rustdoc-verify-output-files/rmake.rs b/tests/run-make/rustdoc-verify-output-files/rmake.rs
index d1ff2e3..a4d4050 100644
--- a/tests/run-make/rustdoc-verify-output-files/rmake.rs
+++ b/tests/run-make/rustdoc-verify-output-files/rmake.rs
@@ -1,7 +1,6 @@
-use run_make_support::rfs;
use std::path::{Path, PathBuf};
-use run_make_support::{assert_dirs_are_equal, rustdoc};
+use run_make_support::{assert_dirs_are_equal, rfs, rustdoc};
#[derive(PartialEq)]
enum JsonOutput {
diff --git a/tests/run-make/sepcomp-cci-copies/rmake.rs b/tests/run-make/sepcomp-cci-copies/rmake.rs
index e244f54..a66cc28 100644
--- a/tests/run-make/sepcomp-cci-copies/rmake.rs
+++ b/tests/run-make/sepcomp-cci-copies/rmake.rs
@@ -4,10 +4,7 @@
// created for each source module (see `rustc_const_eval::monomorphize::partitioning`).
// See https://github.com/rust-lang/rust/pull/16367
-use run_make_support::{
- count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc,
- shallow_find_files,
-};
+use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc};
fn main() {
rustc().input("cci_lib.rs").run();
diff --git a/tests/run-make/sepcomp-inlining/rmake.rs b/tests/run-make/sepcomp-inlining/rmake.rs
index b7a6bed..ea4a4d2 100644
--- a/tests/run-make/sepcomp-inlining/rmake.rs
+++ b/tests/run-make/sepcomp-inlining/rmake.rs
@@ -5,10 +5,7 @@
// in only one compilation unit.
// See https://github.com/rust-lang/rust/pull/16367
-use run_make_support::{
- count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc,
- shallow_find_files,
-};
+use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc};
fn main() {
rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).arg("-Zinline-in-all-cgus").run();
diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs
index 9001757..4995804 100644
--- a/tests/run-make/sepcomp-separate/rmake.rs
+++ b/tests/run-make/sepcomp-separate/rmake.rs
@@ -3,10 +3,7 @@
// wind up in three different compilation units.
// See https://github.com/rust-lang/rust/pull/16367
-use run_make_support::{
- count_regex_matches_in_files_with_extension, cwd, has_extension, regex, rfs, rustc,
- shallow_find_files,
-};
+use run_make_support::{count_regex_matches_in_files_with_extension, regex, rustc};
fn main() {
rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).run();
diff --git a/tests/run-make/share-generics-dylib/Makefile b/tests/run-make/share-generics-dylib/Makefile
deleted file mode 100644
index 9d97eca..0000000
--- a/tests/run-make/share-generics-dylib/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# ignore-cross-compile
-# This test makes sure all generic instances get re-exported from Rust dylibs for use by
-# `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`)
-# which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is
-# supposed to re-export both these instances, and then there are `instance_user_a_rlib` and
-# `instance_user_b_rlib` which each rely on a specific instance to be available.
-#
-# In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does
-# not export both then we'll get an `undefined reference` error for one of the instances.
-#
-# This is regression test for https://github.com/rust-lang/rust/issues/67276.
-
-include ../tools.mk
-
-COMMON_ARGS=-Cprefer-dynamic -Zshare-generics=yes -Ccodegen-units=1 -Csymbol-mangling-version=v0
-
-all:
- $(RUSTC) instance_provider_a.rs $(COMMON_ARGS) --crate-type=rlib
- $(RUSTC) instance_provider_b.rs $(COMMON_ARGS) --crate-type=rlib
- $(RUSTC) instance_user_dylib.rs $(COMMON_ARGS) --crate-type=dylib
- $(RUSTC) instance_user_a_rlib.rs $(COMMON_ARGS) --crate-type=rlib
- $(RUSTC) instance_user_b_rlib.rs $(COMMON_ARGS) --crate-type=rlib
- $(RUSTC) linked_leaf.rs $(COMMON_ARGS) --crate-type=bin
diff --git a/tests/run-make/share-generics-dylib/rmake.rs b/tests/run-make/share-generics-dylib/rmake.rs
new file mode 100644
index 0000000..e0e647f
--- /dev/null
+++ b/tests/run-make/share-generics-dylib/rmake.rs
@@ -0,0 +1,30 @@
+// This test makes sure all generic instances get re-exported from Rust dylibs for use by
+// `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`)
+// which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is
+// supposed to re-export both these instances, and then there are `instance_user_a_rlib` and
+// `instance_user_b_rlib` which each rely on a specific instance to be available.
+//
+// In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does
+// not export both then we'll get an `undefined reference` error for one of the instances.
+//
+// This is regression test for https://github.com/rust-lang/rust/issues/67276.
+
+use run_make_support::rustc;
+
+fn main() {
+ compile("rlib", "instance_provider_a.rs");
+ compile("rlib", "instance_provider_b.rs");
+ compile("dylib", "instance_user_dylib.rs");
+ compile("rlib", "instance_user_a_rlib.rs");
+ compile("rlib", "instance_user_b_rlib.rs");
+ compile("bin", "linked_leaf.rs");
+}
+
+fn compile(crate_type: &str, input: &str) {
+ rustc()
+ .input(input)
+ .crate_type(crate_type)
+ .args(&["-Cprefer-dynamic", "-Zshare-generics=yes", "-Csymbol-mangling-version=v0"])
+ .codegen_units(1)
+ .run();
+}
diff --git a/tests/run-make/simd-ffi/Makefile b/tests/run-make/simd-ffi/Makefile
deleted file mode 100644
index 2973534..0000000
--- a/tests/run-make/simd-ffi/Makefile
+++ /dev/null
@@ -1,47 +0,0 @@
-include ../tools.mk
-
-TARGETS =
-ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm)
-# construct a fairly exhaustive list of platforms that we
-# support. These ones don't follow a pattern
-TARGETS += arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi
-endif
-
-ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86)
-X86_ARCHS = i686 x86_64
-else
-X86_ARCHS =
-endif
-
-# these ones do, each OS lists the architectures it supports
-LINUX=$(filter aarch64 mips,$(LLVM_COMPONENTS)) $(X86_ARCHS)
-ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips)
-LINUX += mipsel
-endif
-
-WINDOWS=$(X86_ARCHS)
-# fails with: failed to get iphonesimulator SDK path: no such file or directory
-#IOS=i386 aarch64 armv7
-DARWIN=$(X86_ARCHS)
-
-$(foreach arch,$(LINUX),$(eval TARGETS += $(arch)-unknown-linux-gnu))
-$(foreach arch,$(WINDOWS),$(eval TARGETS += $(arch)-pc-windows-gnu))
-#$(foreach arch,$(IOS),$(eval TARGETS += $(arch)-apple-ios))
-$(foreach arch,$(DARWIN),$(eval TARGETS += $(arch)-apple-darwin))
-
-all: $(TARGETS)
-
-define MK_TARGETS
-# compile the rust file to the given target, but only to asm and IR
-# form, to avoid having to have an appropriate linker.
-#
-# we need some features because the integer SIMD instructions are not
-# enabled by-default for i686 and ARM; these features will be invalid
-# on some platforms, but LLVM just prints a warning so that's fine for
-# now.
-$(1): simd.rs
- $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \
- -C target-feature='+neon,+sse2' -C extra-filename=-$(1)
-endef
-
-$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))
diff --git a/tests/run-make/simd-ffi/rmake.rs b/tests/run-make/simd-ffi/rmake.rs
new file mode 100644
index 0000000..04990c8
--- /dev/null
+++ b/tests/run-make/simd-ffi/rmake.rs
@@ -0,0 +1,63 @@
+// Using SIMD types in a program with foreign-function interfaces used to result in an ICE
+// (internal compiler error). Since this was fixed in #21233, it should be checked that
+// compilation of SIMD and FFI together should be successful on all the most common
+// architectures.
+// Note that this test does not check linking or binary execution.
+// See https://github.com/rust-lang/rust/pull/21233
+
+use run_make_support::{llvm_components_contain, rustc};
+
+fn main() {
+ let mut targets = Vec::new();
+ // arm-specific targets.
+ if llvm_components_contain("arm") {
+ targets.append(&mut vec![
+ "arm-linux-androideabi".to_owned(),
+ "arm-unknown-linux-gnueabihf".to_owned(),
+ "arm-unknown-linux-gnueabi".to_owned(),
+ ]);
+ }
+ let mut x86_archs = Vec::new();
+ if llvm_components_contain("x86") {
+ x86_archs.append(&mut vec!["i686", "x86_64"]);
+ }
+ // Linux has all x86 targets, plus aarch64 and mips.
+ let mut extra_targets = x86_archs.clone();
+ if llvm_components_contain("aarch64") {
+ extra_targets.push("aarch64");
+ }
+ if llvm_components_contain("mips") {
+ extra_targets.append(&mut vec!["mips", "mipsel"]);
+ }
+
+ for target in extra_targets {
+ let linux = format!("{target}-unknown-linux-gnu");
+ targets.push(linux);
+ }
+
+ // Windows and Darwin (OSX) only receive x86 targets.
+ let extra_targets = x86_archs.clone();
+ for target in extra_targets {
+ let windows = format!("{target}-pc-windows-gnu");
+ let darwin = format!("{target}-apple-darwin");
+ targets.push(windows);
+ targets.push(darwin);
+ }
+
+ for target in targets {
+ // compile the rust file to the given target, but only to asm and IR
+ // form, to avoid having to have an appropriate linker.
+ //
+ // we need some features because the integer SIMD instructions are not
+ // enabled by-default for i686 and ARM; these features will be invalid
+ // on some platforms, but LLVM just prints a warning so that's fine for
+ // now.
+ rustc()
+ .target(&target)
+ .emit("llvm-ir,asm")
+ .input("simd.rs")
+ .arg("-Ctarget-feature=+neon,+sse")
+ .arg(&format!("-Cextra-filename=-{target}"))
+ .run();
+ }
+}
diff --git a/tests/run-make/stable-symbol-names/Makefile b/tests/run-make/stable-symbol-names/Makefile
deleted file mode 100644
index bbfb8e3..0000000
--- a/tests/run-make/stable-symbol-names/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-include ../tools.mk
-
-# The following command will:
-# 1. dump the symbols of a library using `nm`
-# 2. extract only those lines that we are interested in via `grep`
-# 3. from those lines, extract just the symbol name via `sed`, which:
-# * always starts with "_ZN" and ends with "E" (`legacy` mangling)
-# * always starts with "_R" (`v0` mangling)
-# 4. sort those symbol names for deterministic comparison
-# 5. write the result into a file
-
-dump-symbols = nm "$(TMPDIR)/lib$(1).rlib" \
- | grep -E "$(2)" \
- | sed -E "s/.*(_ZN.*E|_R[a-zA-Z0-9_]*).*/\1/" \
- | sort \
- > "$(TMPDIR)/$(1)$(3).nm"
-
-# This test
-# - compiles each of the two crates 2 times and makes sure each time we get
-# exactly the same symbol names
-# - makes sure that both crates agree on the same symbol names for monomorphic
-# functions
-
-all:
- $(RUSTC) stable-symbol-names1.rs
- $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v1)
- rm $(TMPDIR)/libstable_symbol_names1.rlib
- $(RUSTC) stable-symbol-names1.rs
- $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v2)
- cmp "$(TMPDIR)/stable_symbol_names1_v1.nm" "$(TMPDIR)/stable_symbol_names1_v2.nm"
-
- $(RUSTC) stable-symbol-names2.rs
- $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v1)
- rm $(TMPDIR)/libstable_symbol_names2.rlib
- $(RUSTC) stable-symbol-names2.rs
- $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v2)
- cmp "$(TMPDIR)/stable_symbol_names2_v1.nm" "$(TMPDIR)/stable_symbol_names2_v2.nm"
-
- $(call dump-symbols,stable_symbol_names1,mono_,_cross)
- $(call dump-symbols,stable_symbol_names2,mono_,_cross)
- cmp "$(TMPDIR)/stable_symbol_names1_cross.nm" "$(TMPDIR)/stable_symbol_names2_cross.nm"
diff --git a/tests/run-make/stable-symbol-names/rmake.rs b/tests/run-make/stable-symbol-names/rmake.rs
new file mode 100644
index 0000000..402f411
--- /dev/null
+++ b/tests/run-make/stable-symbol-names/rmake.rs
@@ -0,0 +1,68 @@
+// A typo in rustc caused generic symbol names to be non-deterministic -
+// that is, it was possible to compile the same file twice with no changes
+// and get outputs with different symbol names.
+// This test compiles each of the two crates twice, and checks that each output
+// contains exactly the same symbol names.
+// Additionally, both crates should agree on the same symbol names for monomorphic
+// functions.
+// See https://github.com/rust-lang/rust/issues/32554
+
+use std::collections::HashSet;
+
+use run_make_support::{llvm_readobj, regex, rfs, rust_lib_name, rustc};
+
+static LEGACY_PATTERN: std::sync::OnceLock<regex::Regex> = std::sync::OnceLock::new();
+static V0_PATTERN: std::sync::OnceLock<regex::Regex> = std::sync::OnceLock::new();
+
+fn main() {
+ LEGACY_PATTERN.set(regex::Regex::new(r"_ZN.*E").unwrap()).unwrap();
+ V0_PATTERN.set(regex::Regex::new(r"_R[a-zA-Z0-9_]*").unwrap()).unwrap();
+ // test 1: first file
+ rustc().input("stable-symbol-names1.rs").run();
+ let sym1 = process_symbols("stable_symbol_names1", "generic_|mono_");
+ rfs::remove_file(rust_lib_name("stable_symbol_names1"));
+ rustc().input("stable-symbol-names1.rs").run();
+ let sym2 = process_symbols("stable_symbol_names1", "generic_|mono_");
+ assert_eq!(sym1, sym2);
+
+ // test 2: second file
+ rustc().input("stable-symbol-names2.rs").run();
+ let sym1 = process_symbols("stable_symbol_names2", "generic_|mono_");
+ rfs::remove_file(rust_lib_name("stable_symbol_names2"));
+ rustc().input("stable-symbol-names2.rs").run();
+ let sym2 = process_symbols("stable_symbol_names2", "generic_|mono_");
+ assert_eq!(sym1, sym2);
+
+ // test 3: crossed files
+ let sym1 = process_symbols("stable_symbol_names1", "mono_");
+ let sym2 = process_symbols("stable_symbol_names2", "mono_");
+ assert_eq!(sym1, sym2);
+}
+
+#[track_caller]
+fn process_symbols(path: &str, symbol: &str) -> Vec<String> {
+ // Dump all symbols.
+ let out = llvm_readobj().input(rust_lib_name(path)).symbols().run().stdout_utf8();
+ // Extract only lines containing `symbol`.
+ let symbol_regex = regex::Regex::new(symbol).unwrap();
+ let out = out.lines().filter(|&line| symbol_regex.find(line).is_some());
+
+ // HashSet - duplicates should be excluded!
+ let mut symbols: HashSet<String> = HashSet::new();
+ // From those lines, extract just the symbol name via `regex`, which:
+ // * always starts with "_ZN" and ends with "E" (`legacy` mangling)
+ // * always starts with "_R" (`v0` mangling)
+ for line in out {
+ if let Some(mat) = LEGACY_PATTERN.get().unwrap().find(line) {
+ symbols.insert(mat.as_str().to_string());
+ }
+ if let Some(mat) = V0_PATTERN.get().unwrap().find(line) {
+ symbols.insert(mat.as_str().to_string());
+ }
+ }
+
+ let mut symbols: Vec<String> = symbols.into_iter().collect();
+ // Sort those symbol names for deterministic comparison.
+ symbols.sort();
+ symbols
+}
diff --git a/tests/run-make/static-pie/rmake.rs b/tests/run-make/static-pie/rmake.rs
index 6a92f92..74f86bb 100644
--- a/tests/run-make/static-pie/rmake.rs
+++ b/tests/run-make/static-pie/rmake.rs
@@ -7,10 +7,8 @@
use std::process::Command;
-use run_make_support::llvm_readobj;
use run_make_support::regex::Regex;
-use run_make_support::rustc;
-use run_make_support::{cmd, run_with_args, target};
+use run_make_support::{cmd, llvm_readobj, run_with_args, rustc, target};
// Minimum major versions supporting -static-pie
const GCC_VERSION: u32 = 8;
diff --git a/tests/run-make/staticlib-dylib-linkage/Makefile b/tests/run-make/staticlib-dylib-linkage/Makefile
deleted file mode 100644
index a1e86a7..0000000
--- a/tests/run-make/staticlib-dylib-linkage/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-# ignore-msvc FIXME(bjorn3) can't figure out how to link with the MSVC toolchain
-# ignore-wasm wasm doesn't support dynamic libraries
-
-all:
- $(RUSTC) -C prefer-dynamic bar.rs
- $(RUSTC) foo.rs --crate-type staticlib --print native-static-libs \
- -Z staticlib-allow-rdylib-deps 2>&1 | grep 'note: native-static-libs: ' \
- | sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt
- cat $(TMPDIR)/libs.txt
-
-ifdef IS_MSVC
- $(CC) $(CFLAGS) /c foo.c /Fo:$(TMPDIR)/foo.o
- $(RUSTC_LINKER) $(TMPDIR)/foo.o $(TMPDIR)/foo.lib $$(cat $(TMPDIR)/libs.txt) $(call OUT_EXE,foo)
-else
- $(CC) $(CFLAGS) foo.c -L $(TMPDIR) -lfoo $$(cat $(TMPDIR)/libs.txt) -o $(call RUN_BINFILE,foo)
-endif
-
- $(call RUN,foo)
diff --git a/tests/run-make/staticlib-dylib-linkage/rmake.rs b/tests/run-make/staticlib-dylib-linkage/rmake.rs
new file mode 100644
index 0000000..8dd1ac0
--- /dev/null
+++ b/tests/run-make/staticlib-dylib-linkage/rmake.rs
@@ -0,0 +1,36 @@
+// A basic smoke test to check that rustc supports linking to a rust dylib with
+// --crate-type staticlib. bar is a dylib, on which foo is dependent - the native
+// static lib search paths are collected and used to compile foo.c, the final executable
+// which depends on both foo and bar.
+// See https://github.com/rust-lang/rust/pull/106560
+
+//@ ignore-cross-compile
+// Reason: the compiled binary is executed.
+//@ ignore-wasm
+// Reason: WASM does not support dynamic libraries
+
+use run_make_support::{cc, is_msvc, regex, run, rustc, static_lib_name};
+
+fn main() {
+ rustc().arg("-Cprefer-dynamic").input("bar.rs").run();
+ let libs = rustc()
+ .input("foo.rs")
+ .crate_type("staticlib")
+ .print("native-static-libs")
+ .arg("-Zstaticlib-allow-rdylib-deps")
+ .run()
+ .assert_stderr_contains("note: native-static-libs: ")
+ .stderr_utf8();
+ let re = regex::Regex::new(r#"note: native-static-libs:\s*(.+)"#).unwrap();
+ let libs = re.find(&libs).unwrap().as_str().trim();
+ // remove the note
+ let (_, native_link_args) = libs.split_once("note: native-static-libs: ").unwrap();
+ // divide the command-line arguments in a vec
+ let mut native_link_args = native_link_args.split(' ').collect::<Vec<&str>>();
+ if is_msvc() {
+ // For MSVC pass the arguments on to the linker.
+ native_link_args.insert(0, "-link");
+ }
+ cc().input("foo.c").input(static_lib_name("foo")).args(native_link_args).out_exe("foo").run();
+ run("foo");
+}
diff --git a/tests/run-make/stdin-rustc/rmake.rs b/tests/run-make/stdin-rustc/rmake.rs
index d599f813..68e9cf2 100644
--- a/tests/run-make/stdin-rustc/rmake.rs
+++ b/tests/run-make/stdin-rustc/rmake.rs
@@ -1,8 +1,9 @@
//! This test checks rustc `-` (stdin) support
-use run_make_support::{is_windows, rustc};
use std::path::PathBuf;
+use run_make_support::{is_windows, rustc};
+
const HELLO_WORLD: &str = r#"
fn main() {
println!("Hello world!");
diff --git a/tests/run-make/stdin-rustdoc/rmake.rs b/tests/run-make/stdin-rustdoc/rmake.rs
index a72fe1b..de47a24 100644
--- a/tests/run-make/stdin-rustdoc/rmake.rs
+++ b/tests/run-make/stdin-rustdoc/rmake.rs
@@ -1,8 +1,9 @@
//! This test checks rustdoc `-` (stdin) handling
-use run_make_support::rustdoc;
use std::path::PathBuf;
+use run_make_support::rustdoc;
+
static INPUT: &str = r#"
//! ```
//! dbg!(());
diff --git a/tests/run-make/suspicious-library/rmake.rs b/tests/run-make/suspicious-library/rmake.rs
index e789607..1dc9bc5 100644
--- a/tests/run-make/suspicious-library/rmake.rs
+++ b/tests/run-make/suspicious-library/rmake.rs
@@ -3,9 +3,10 @@
//@ ignore-cross-compile
-use run_make_support::{dynamic_lib_name, rustc};
use std::fs::File;
+use run_make_support::{dynamic_lib_name, rustc};
+
fn main() {
rustc().input("foo.rs").arg("-Cprefer-dynamic").run();
File::create(dynamic_lib_name("foo-something-special")).unwrap();
diff --git a/tests/run-make/symbol-visibility/Makefile b/tests/run-make/symbol-visibility/Makefile
deleted file mode 100644
index 9159af2..0000000
--- a/tests/run-make/symbol-visibility/Makefile
+++ /dev/null
@@ -1,123 +0,0 @@
-# ignore-cross-compile
-include ../tools.mk
-
-# ignore-windows-msvc
-
-NM=nm -D
-CDYLIB_NAME=liba_cdylib.so
-RDYLIB_NAME=liba_rust_dylib.so
-PROC_MACRO_NAME=liba_proc_macro.so
-EXE_NAME=an_executable
-COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.so
-
-ifeq ($(UNAME),Darwin)
-NM=nm -gU
-CDYLIB_NAME=liba_cdylib.dylib
-RDYLIB_NAME=liba_rust_dylib.dylib
-PROC_MACRO_NAME=liba_proc_macro.dylib
-EXE_NAME=an_executable
-COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib
-endif
-
-ifdef IS_WINDOWS
-NM=nm -g
-CDYLIB_NAME=liba_cdylib.dll.a
-RDYLIB_NAME=liba_rust_dylib.dll.a
-PROC_MACRO_NAME=liba_proc_macro.dll
-EXE_NAME=an_executable.exe
-COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a
-endif
-
-# `grep` regex for symbols produced by either `legacy` or `v0` mangling
-RE_ANY_RUST_SYMBOL="_ZN.*h.*E\|_R[a-zA-Z0-9_]+"
-
-all:
- $(RUSTC) -Zshare-generics=no an_rlib.rs
- $(RUSTC) -Zshare-generics=no a_cdylib.rs
- $(RUSTC) -Zshare-generics=no a_rust_dylib.rs
- $(RUSTC) -Zshare-generics=no a_proc_macro.rs
- $(RUSTC) -Zshare-generics=no an_executable.rs
- $(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib
-
- # Check that a cdylib exports its public #[no_mangle] functions
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
- # Check that a cdylib exports the public #[no_mangle] functions of dependencies
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- # Check that a cdylib DOES NOT export any public Rust functions
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
-
- # Check that a Rust dylib exports its monomorphic functions
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
- # Check that a Rust dylib does not export generics if -Zshare-generics=no
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "0" ]
-
-
- # Check that a Rust dylib exports the monomorphic functions from its dependencies
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ]
- # Check that a Rust dylib does not export generics if -Zshare-generics=no
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "0" ]
-
- # Check that a proc macro exports its public #[no_mangle] functions
- # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
- # Check that a proc macro exports the public #[no_mangle] functions of dependencies
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- # Check that a proc macro DOES NOT export any public Rust functions
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
-
-# FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
-ifndef IS_WINDOWS
- # Check that an executable does not export any dynamic symbols
- [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ]
- [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ]
-endif
-
-
- # Check the combined case, where we generate a cdylib and an rlib in the same
- # compilation session:
- # Check that a cdylib exports its public #[no_mangle] functions
- [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
- # Check that a cdylib exports the public #[no_mangle] functions of dependencies
- [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- # Check that a cdylib DOES NOT export any public Rust functions
- [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
-
-
- $(RUSTC) -Zshare-generics=yes an_rlib.rs
- $(RUSTC) -Zshare-generics=yes a_cdylib.rs
- $(RUSTC) -Zshare-generics=yes a_rust_dylib.rs
- $(RUSTC) -Zshare-generics=yes a_proc_macro.rs
- $(RUSTC) -Zshare-generics=yes an_executable.rs
-
- # Check that a cdylib exports its public #[no_mangle] functions
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
- # Check that a cdylib exports the public #[no_mangle] functions of dependencies
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- # Check that a cdylib DOES NOT export any public Rust functions
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
-
- # Check that a Rust dylib exports its monomorphic functions, including generics this time
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ]
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ]
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "1" ]
-
- # Check that a Rust dylib exports the monomorphic functions from its dependencies
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ]
- [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "1" ]
-
- # Check that a proc macro exports its public #[no_mangle] functions
- # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ]
- # Check that a proc macro exports the public #[no_mangle] functions of dependencies
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ]
- # Check that a proc macro DOES NOT export any public Rust functions
- [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ]
-
-ifndef IS_WINDOWS
- # Check that an executable does not export any dynamic symbols
- [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ]
- [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ]
-endif
diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs
new file mode 100644
index 0000000..f84e63e
--- /dev/null
+++ b/tests/run-make/symbol-visibility/rmake.rs
@@ -0,0 +1,167 @@
+// Dynamic libraries on Rust used to export a very high amount of symbols,
+// going as far as filling the output with mangled names and generic function
+// names. After the rework of #38117, this test checks that no mangled Rust symbols
+// are exported, and that generics are only shown if explicitely requested.
+// See https://github.com/rust-lang/rust/issues/37530
+
+use run_make_support::object::read::Object;
+use run_make_support::{bin_name, dynamic_lib_name, is_msvc, object, regex, rfs, rustc};
+
+fn main() {
+ let cdylib_name = dynamic_lib_name("a_cdylib");
+ let rdylib_name = dynamic_lib_name("a_rust_dylib");
+ let exe_name = bin_name("an_executable");
+ let combined_cdylib_name = dynamic_lib_name("combined_rlib_dylib");
+ rustc().arg("-Zshare-generics=no").input("an_rlib.rs").run();
+ rustc().arg("-Zshare-generics=no").input("a_cdylib.rs").run();
+ rustc().arg("-Zshare-generics=no").input("a_rust_dylib.rs").run();
+ rustc().arg("-Zshare-generics=no").input("a_proc_macro.rs").run();
+ rustc().arg("-Zshare-generics=no").input("an_executable.rs").run();
+ rustc()
+ .arg("-Zshare-generics=no")
+ .input("a_cdylib.rs")
+ .crate_name("combined_rlib_dylib")
+ .crate_type("rlib,cdylib")
+ .run();
+
+ // Check that a cdylib exports its public #[no_mangle] functions
+ symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true);
+ // Check that a cdylib exports the public #[no_mangle] functions of dependencies
+ symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
+ // Check that a cdylib DOES NOT export any public Rust functions
+ symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false);
+
+ // Check that a Rust dylib exports its monomorphic functions
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"),
+ true,
+ );
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),
+ true,
+ );
+ // Check that a Rust dylib does not export generics if -Zshare-generics=no
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),
+ false,
+ );
+
+ // Check that a Rust dylib exports the monomorphic functions from its dependencies
+ symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
+ symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true);
+ // Check that a Rust dylib does not export generics if -Zshare-generics=no
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_generic_function_from_rlib"),
+ false,
+ );
+
+ // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
+ if is_msvc() {
+ // Check that an executable does not export any dynamic symbols
+ symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false);
+ symbols_check(
+ &exe_name,
+ SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
+ false,
+ );
+ }
+
+ // Check the combined case, where we generate a cdylib and an rlib in the same
+ // compilation session:
+ // Check that a cdylib exports its public #[no_mangle] functions
+ symbols_check(
+ &combined_cdylib_name,
+ SymbolCheckType::StrSymbol("public_c_function_from_cdylib"),
+ true,
+ );
+ // Check that a cdylib exports the public #[no_mangle] functions of dependencies
+ symbols_check(
+ &combined_cdylib_name,
+ SymbolCheckType::StrSymbol("public_c_function_from_rlib"),
+ true,
+ );
+ // Check that a cdylib DOES NOT export any public Rust functions
+ symbols_check(&combined_cdylib_name, SymbolCheckType::AnyRustSymbol, false);
+
+ rustc().arg("-Zshare-generics=yes").input("an_rlib.rs").run();
+ rustc().arg("-Zshare-generics=yes").input("a_cdylib.rs").run();
+ rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run();
+ rustc().arg("-Zshare-generics=yes").input("an_executable.rs").run();
+
+ // Check that a cdylib exports its public #[no_mangle] functions
+ symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true);
+ // Check that a cdylib exports the public #[no_mangle] functions of dependencies
+ symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
+ // Check that a cdylib DOES NOT export any public Rust functions
+ symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false);
+
+ // Check that a Rust dylib exports its monomorphic functions, including generics this time
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"),
+ true,
+ );
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),
+ true,
+ );
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),
+ true,
+ );
+
+ // Check that a Rust dylib exports the monomorphic functions from its dependencies
+ symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
+ symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true);
+ symbols_check(
+ &rdylib_name,
+ SymbolCheckType::StrSymbol("public_generic_function_from_rlib"),
+ true,
+ );
+
+ // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032
+ if is_msvc() {
+ // Check that an executable does not export any dynamic symbols
+ symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false);
+ symbols_check(
+ &exe_name,
+ SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
+ false,
+ );
+ }
+}
+
+#[track_caller]
+fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) {
+ let binary_data = rfs::read(path);
+ let file = object::File::parse(&*binary_data).unwrap();
+ let mut found: u64 = 0;
+ for export in file.exports().unwrap() {
+ let name = std::str::from_utf8(export.name()).unwrap();
+ if has_symbol(name, symbol_check_type) {
+ found += 1;
+ }
+ }
+ assert_eq!(found, exists_once as u64);
+}
+
+fn has_symbol(name: &str, symbol_check_type: SymbolCheckType) -> bool {
+ if let SymbolCheckType::StrSymbol(expected) = symbol_check_type {
+ name.contains(expected)
+ } else {
+ let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap();
+ regex.is_match(name)
+ }
+}
+
+#[derive(Clone, Copy)]
+enum SymbolCheckType {
+ StrSymbol(&'static str),
+ AnyRustSymbol,
+}
diff --git a/tests/run-make/thumb-none-cortex-m/Makefile b/tests/run-make/thumb-none-cortex-m/Makefile
deleted file mode 100644
index e941fc4..0000000
--- a/tests/run-make/thumb-none-cortex-m/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-include ../tools.mk
-
-# How to run this
-# $ ./x.py clean
-# $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi tests/run-make
-
-# Supported targets:
-# - thumbv6m-none-eabi (Bare Cortex-M0, M0+, M1)
-# - thumbv7em-none-eabi (Bare Cortex-M4, M7)
-# - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
-# - thumbv7m-none-eabi (Bare Cortex-M3)
-
-# only-thumb
-
-# For cargo setting
-RUSTC := $(RUSTC_ORIGINAL)
-LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
-# We need to be outside of 'src' dir in order to run cargo
-WORK_DIR := $(TMPDIR)
-
-HERE := $(shell pwd)
-
-CRATE := cortex-m
-CRATE_URL := https://github.com/rust-embedded/cortex-m
-CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
-
-# Don't make lints fatal, but they need to at least warn or they break Cargo's target info parsing.
-export RUSTFLAGS := --cap-lints=warn
-
-all:
- env
- mkdir -p $(WORK_DIR)
- -cd $(WORK_DIR) && rm -rf $(CRATE)
- cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1)
- # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
- # These come from the top-level Rust workspace, that this crate is not a
- # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
- cd $(WORK_DIR) && cd $(CRATE) && env RUSTC_BOOTSTRAP=1 $(BOOTSTRAP_CARGO) build --target $(TARGET) -v
diff --git a/tests/run-make/thumb-none-cortex-m/rmake.rs b/tests/run-make/thumb-none-cortex-m/rmake.rs
new file mode 100644
index 0000000..0ddb91d
--- /dev/null
+++ b/tests/run-make/thumb-none-cortex-m/rmake.rs
@@ -0,0 +1,59 @@
+//! Test building of the `cortex-m` crate, a foundational crate in the embedded ecosystem
+//! for a collection of thumb targets. This is a smoke test that verifies that both cargo
+//! and rustc work in this case.
+//!
+//! How to run this
+//! $ ./x.py clean
+//! $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi tests/run-make
+//!
+//! Supported targets:
+//! - thumbv6m-none-eabi (Bare Cortex-M0, M0+, M1)
+//! - thumbv7em-none-eabi (Bare Cortex-M4, M7)
+//! - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
+//! - thumbv7m-none-eabi (Bare Cortex-M3)
+
+//@ only-thumb
+
+use std::path::PathBuf;
+
+use run_make_support::rfs::create_dir;
+use run_make_support::{cmd, env_var, target};
+
+const CRATE: &str = "cortex-m";
+const CRATE_URL: &str = "https://github.com/rust-embedded/cortex-m";
+const CRATE_SHA1: &str = "a448e9156e2cb1e556e5441fd65426952ef4b927"; // v0.5.0
+
+fn main() {
+ // FIXME: requires an internet connection https://github.com/rust-lang/rust/issues/128733
+ // See below link for git usage:
+ // https://stackoverflow.com/questions/3489173#14091182
+ cmd("git").args(["clone", CRATE_URL, CRATE]).run();
+ std::env::set_current_dir(CRATE).unwrap();
+ cmd("git").args(["reset", "--hard", CRATE_SHA1]).run();
+
+ let target_dir = PathBuf::from("target");
+ let manifest_path = PathBuf::from("Cargo.toml");
+
+ let path = env_var("PATH");
+ let rustc = env_var("RUSTC");
+ let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
+ // FIXME: extract bootstrap cargo invocations to a proper command
+ // https://github.com/rust-lang/rust/issues/128734
+ let mut cmd = cmd(bootstrap_cargo);
+ cmd.args(&[
+ "build",
+ "--manifest-path",
+ manifest_path.to_str().unwrap(),
+ "-Zbuild-std=core",
+ "--target",
+ &target(),
+ ])
+ .env("PATH", path)
+ .env("RUSTC", rustc)
+ .env("CARGO_TARGET_DIR", &target_dir)
+ // Don't make lints fatal, but they need to at least warn
+ // or they break Cargo's target info parsing.
+ .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes --cap-lints=warn");
+
+ cmd.run();
+}
diff --git a/tests/run-make/thumb-none-qemu/Makefile b/tests/run-make/thumb-none-qemu/Makefile
deleted file mode 100644
index eea6ca3..0000000
--- a/tests/run-make/thumb-none-qemu/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-include ../tools.mk
-
-# only-thumb
-
-# How to run this
-# $ ./x.py clean
-# $ ./x.py test --target thumbv7m-none-eabi tests/run-make
-
-# For cargo setting
-export RUSTC := $(RUSTC_ORIGINAL)
-export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
-# We need to be outside of 'src' dir in order to run cargo
-export WORK_DIR := $(TMPDIR)
-export HERE := $(shell pwd)
-
-## clean up unused env variables which might cause harm.
-unexport RUSTC_LINKER
-unexport RUSTC_BOOTSTRAP
-unexport RUST_BUILD_STAGE
-unexport RUST_TEST_THREADS
-unexport RUST_TEST_TMPDIR
-unexport AR
-unexport CC
-unexport CXX
-
-all:
- bash script.sh
diff --git a/tests/run-make/thumb-none-qemu/example/.cargo/config b/tests/run-make/thumb-none-qemu/example/.cargo/config.toml
similarity index 90%
rename from tests/run-make/thumb-none-qemu/example/.cargo/config
rename to tests/run-make/thumb-none-qemu/example/.cargo/config.toml
index 8b30310..7152e81 100644
--- a/tests/run-make/thumb-none-qemu/example/.cargo/config
+++ b/tests/run-make/thumb-none-qemu/example/.cargo/config.toml
@@ -1,6 +1,5 @@
[target.thumbv6m-none-eabi]
-# FIXME: Should be Cortex-M0, but Qemu used by CI is too old
-runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+runner = "qemu-system-arm -cpu cortex-m0 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.thumbv7m-none-eabi]
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
@@ -12,7 +11,7 @@
runner = "qemu-system-arm -cpu cortex-m4 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.thumbv8m.base-none-eabi]
-# FIXME: Should be the Cortex-M23, bt Qemu does not currently support it
+# FIXME: Should be the Cortex-M23, but Qemu does not currently support it
runner = "qemu-system-arm -cpu cortex-m33 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
[target.thumbv8m.main-none-eabi]
diff --git a/tests/run-make/thumb-none-qemu/example/src/main.rs b/tests/run-make/thumb-none-qemu/example/src/main.rs
index 2abfde8..4b8162c 100644
--- a/tests/run-make/thumb-none-qemu/example/src/main.rs
+++ b/tests/run-make/thumb-none-qemu/example/src/main.rs
@@ -1,11 +1,10 @@
#![no_main]
#![no_std]
use core::fmt::Write;
+
use cortex_m::asm;
use cortex_m_rt::entry;
-use cortex_m_semihosting as semihosting;
-
-use panic_halt as _;
+use {cortex_m_semihosting as semihosting, panic_halt as _};
#[entry]
fn main() -> ! {
diff --git a/tests/run-make/thumb-none-qemu/rmake.rs b/tests/run-make/thumb-none-qemu/rmake.rs
new file mode 100644
index 0000000..d0f42bc
--- /dev/null
+++ b/tests/run-make/thumb-none-qemu/rmake.rs
@@ -0,0 +1,62 @@
+//! This test runs a basic application for thumb targets, using the cortex-m crate.
+//!
+//! These targets are very bare-metal: the first instruction the core runs on
+//! power-on is already user code. The cortex-m-rt has to initialize the stack, .data,
+//! .bss, enable the FPU if present, etc.
+//!
+//! This test builds and runs the applications for various thumb targets using qemu.
+//!
+//! How to run this
+//! $ ./x.py clean
+//! $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi tests/run-make
+//!
+//! For supported targets, see `example/.cargo/config.toml`
+//!
+//! FIXME: https://github.com/rust-lang/rust/issues/128733 this test uses external
+//! dependencies, and needs an active internet connection
+//!
+//! FIXME: https://github.com/rust-lang/rust/issues/128734 extract bootstrap cargo
+//! to a proper command
+
+//@ only-thumb
+
+use std::path::PathBuf;
+
+use run_make_support::{cmd, env_var, path_helpers, target};
+
+const CRATE: &str = "example";
+
+fn main() {
+ std::env::set_current_dir(CRATE).unwrap();
+
+ let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
+ let path = env_var("PATH");
+ let rustc = env_var("RUSTC");
+
+ let target_dir = path_helpers::path("target");
+ let manifest_path = path_helpers::path("Cargo.toml");
+
+ let debug = {
+ let mut cmd = cmd(&bootstrap_cargo);
+ cmd.args(&["run", "--target", &target()])
+ .env("RUSTFLAGS", "-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x")
+ .env("CARGO_TARGET_DIR", &target_dir)
+ .env("PATH", &path)
+ .env("RUSTC", &rustc);
+ cmd.run()
+ };
+
+ debug.assert_stdout_contains("x = 42");
+
+ let release = {
+ let mut cmd = cmd(&bootstrap_cargo);
+ cmd.args(&["run", "--release", "--target", &target()])
+ .env("RUSTFLAGS", "-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x")
+ .env("CARGO_TARGET_DIR", &target_dir)
+ .env("PATH", &path)
+ .env("RUSTC", &rustc);
+ cmd.run()
+ };
+
+ release.assert_stdout_contains("x = 42");
+}
diff --git a/tests/run-make/thumb-none-qemu/script.sh b/tests/run-make/thumb-none-qemu/script.sh
deleted file mode 100644
index a8aa72a..0000000
--- a/tests/run-make/thumb-none-qemu/script.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-set -exuo pipefail
-
-CRATE=example
-
-env | sort
-mkdir -p $WORK_DIR
-pushd $WORK_DIR
- rm -rf $CRATE || echo OK
- cp -a $HERE/example .
- pushd $CRATE
- # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
- # These come from the top-level Rust workspace, that this crate is not a
- # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
- env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \
- $BOOTSTRAP_CARGO run --target $TARGET | grep "x = 42"
- env RUSTC_BOOTSTRAP=1 RUSTFLAGS="-C linker=arm-none-eabi-ld -C link-arg=-Tlink.x" \
- $BOOTSTRAP_CARGO run --target $TARGET --release | grep "x = 42"
- popd
-popd
diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs
index 56ef5c6..39f36b2 100644
--- a/tests/run-make/used/rmake.rs
+++ b/tests/run-make/used/rmake.rs
@@ -4,12 +4,10 @@
// It comes from #39987 which implements this RFC for the #[used] attribute:
// https://rust-lang.github.io/rfcs/2386-used.html
-//@ ignore-msvc
-
-use run_make_support::{cmd, rustc};
+use run_make_support::rustc;
+use run_make_support::symbols::any_symbol_contains;
fn main() {
rustc().opt_level("3").emit("obj").input("used.rs").run();
-
- cmd("nm").arg("used.o").run().assert_stdout_contains("FOO");
+ assert!(any_symbol_contains("used.o", &["FOO"]));
}
diff --git a/tests/run-make/used/used.rs b/tests/run-make/used/used.rs
index dca0a5e..133f812 100644
--- a/tests/run-make/used/used.rs
+++ b/tests/run-make/used/used.rs
@@ -2,5 +2,3 @@
#[used]
static FOO: u32 = 0;
-
-static BAR: u32 = 0;
diff --git a/tests/run-make/volatile-intrinsics/rmake.rs b/tests/run-make/volatile-intrinsics/rmake.rs
index 66bc6f9..1d19b65 100644
--- a/tests/run-make/volatile-intrinsics/rmake.rs
+++ b/tests/run-make/volatile-intrinsics/rmake.rs
@@ -1,7 +1,6 @@
//@ ignore-cross-compile
-use run_make_support::rfs;
-use run_make_support::{assert_contains, run, rustc};
+use run_make_support::{assert_contains, rfs, run, rustc};
fn main() {
// The tests must pass...
diff --git a/tests/run-make/wasm-custom-section/rmake.rs b/tests/run-make/wasm-custom-section/rmake.rs
index 756a72f..ff4c29a 100644
--- a/tests/run-make/wasm-custom-section/rmake.rs
+++ b/tests/run-make/wasm-custom-section/rmake.rs
@@ -1,8 +1,9 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::collections::HashMap;
+use run_make_support::{rfs, rustc, wasmparser};
+
fn main() {
rustc().input("foo.rs").target("wasm32-wasip1").run();
rustc().input("bar.rs").target("wasm32-wasip1").arg("-Clto").opt().run();
diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs
index 0be863f..063a4f2 100644
--- a/tests/run-make/wasm-custom-sections-opt/rmake.rs
+++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs
@@ -1,9 +1,10 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::collections::HashMap;
use std::path::Path;
+use run_make_support::{rfs, rustc, wasmparser};
+
fn main() {
rustc().input("foo.rs").target("wasm32-wasip1").opt().run();
diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs
index 9ea541a..4148cc2 100644
--- a/tests/run-make/wasm-export-all-symbols/rmake.rs
+++ b/tests/run-make/wasm-export-all-symbols/rmake.rs
@@ -1,8 +1,9 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::collections::HashMap;
use std::path::Path;
+
+use run_make_support::{rfs, rustc, wasmparser};
use wasmparser::ExternalKind::*;
fn main() {
diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs
index c240d47..3b74cb2 100644
--- a/tests/run-make/wasm-import-module/rmake.rs
+++ b/tests/run-make/wasm-import-module/rmake.rs
@@ -1,7 +1,8 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::collections::HashMap;
+
+use run_make_support::{rfs, rustc, wasmparser};
use wasmparser::TypeRef::Func;
fn main() {
diff --git a/tests/run-make/wasm-override-linker/rmake.rs b/tests/run-make/wasm-override-linker/rmake.rs
index 01bc08e..b04edc1 100644
--- a/tests/run-make/wasm-override-linker/rmake.rs
+++ b/tests/run-make/wasm-override-linker/rmake.rs
@@ -2,6 +2,10 @@
// $ RUSTBUILD_FORCE_CLANG_BASED_TESTS=1 ./x.py test tests/run-make/wasm-override-linker/
//@ needs-force-clang-based-tests
+// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets
+// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their
+// name.
+// However, this test does not run at all as its name does not contain "clang".
use run_make_support::{env_var, rustc, target};
diff --git a/tests/run-make/wasm-spurious-import/rmake.rs b/tests/run-make/wasm-spurious-import/rmake.rs
index 9cfd202..8fde8d2 100644
--- a/tests/run-make/wasm-spurious-import/rmake.rs
+++ b/tests/run-make/wasm-spurious-import/rmake.rs
@@ -1,8 +1,9 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::collections::HashMap;
+use run_make_support::{rfs, rustc, wasmparser};
+
fn main() {
rustc()
.input("main.rs")
diff --git a/tests/run-make/wasm-symbols-different-module/rmake.rs b/tests/run-make/wasm-symbols-different-module/rmake.rs
index 6b69f76..3cd459d 100644
--- a/tests/run-make/wasm-symbols-different-module/rmake.rs
+++ b/tests/run-make/wasm-symbols-different-module/rmake.rs
@@ -1,9 +1,10 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::collections::{HashMap, HashSet};
use std::path::Path;
+use run_make_support::{rfs, rustc, wasmparser};
+
fn main() {
test_file("foo.rs", &[("a", &["foo"]), ("b", &["foo"])]);
test_file("bar.rs", &[("m1", &["f", "g"]), ("m2", &["f"])]);
diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs
index ad31351..0b9c9c6 100644
--- a/tests/run-make/wasm-symbols-not-exported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs
@@ -1,8 +1,9 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::path::Path;
+use run_make_support::{rfs, rustc, wasmparser};
+
fn main() {
rustc().input("foo.rs").target("wasm32-wasip1").run();
verify_symbols(Path::new("foo.wasm"));
diff --git a/tests/run-make/wasm-symbols-not-imported/rmake.rs b/tests/run-make/wasm-symbols-not-imported/rmake.rs
index 36c600c..fc22e31 100644
--- a/tests/run-make/wasm-symbols-not-imported/rmake.rs
+++ b/tests/run-make/wasm-symbols-not-imported/rmake.rs
@@ -1,8 +1,9 @@
//@ only-wasm32-wasip1
-use run_make_support::{rfs, rustc, wasmparser};
use std::path::Path;
+use run_make_support::{rfs, rustc, wasmparser};
+
fn main() {
rustc().input("foo.rs").target("wasm32-wasip1").run();
verify_symbols(Path::new("foo.wasm"));
diff --git a/tests/run-make/weird-output-filenames/rmake.rs b/tests/run-make/weird-output-filenames/rmake.rs
index 3d1b5f4..9e451f7 100644
--- a/tests/run-make/weird-output-filenames/rmake.rs
+++ b/tests/run-make/weird-output-filenames/rmake.rs
@@ -1,6 +1,5 @@
use run_make_support::regex::Regex;
-use run_make_support::rfs;
-use run_make_support::{cwd, rustc};
+use run_make_support::{cwd, rfs, rustc};
fn main() {
let invalid_characters = [".foo.rs", ".foo.bar", "+foo+bar.rs"];
diff --git a/tests/run-make/windows-binary-no-external-deps/rmake.rs b/tests/run-make/windows-binary-no-external-deps/rmake.rs
index 61fdb20..1706d75 100644
--- a/tests/run-make/windows-binary-no-external-deps/rmake.rs
+++ b/tests/run-make/windows-binary-no-external-deps/rmake.rs
@@ -2,10 +2,11 @@
//! a "hello world" application by setting `PATH` to `C:\Windows\System32`.
//@ only-windows
-use run_make_support::{cwd, env_var, rustc};
use std::path::PathBuf;
use std::process::Command;
+use run_make_support::{cwd, env_var, rustc};
+
fn main() {
rustc().input("hello.rs").run();
diff --git a/tests/run-make/windows-ws2_32/rmake.rs b/tests/run-make/windows-ws2_32/rmake.rs
index 6457d74..1e426a8 100644
--- a/tests/run-make/windows-ws2_32/rmake.rs
+++ b/tests/run-make/windows-ws2_32/rmake.rs
@@ -2,7 +2,8 @@
// Tests that WS2_32.dll is not unnecessarily linked, see issue #85441
-use run_make_support::object::{self, read::Object};
+use run_make_support::object::read::Object;
+use run_make_support::object::{self};
use run_make_support::{rfs, rustc};
fn main() {
diff --git a/tests/run-make/zero-extend-abi-param-passing/param_passing.rs b/tests/run-make/zero-extend-abi-param-passing/param_passing.rs
index c11f3cc..addde6b 100644
--- a/tests/run-make/zero-extend-abi-param-passing/param_passing.rs
+++ b/tests/run-make/zero-extend-abi-param-passing/param_passing.rs
@@ -2,7 +2,7 @@
// LLVM optimization choices. See additional note below for an
// example.
-#[link(name = "bad")]
+#[link(name = "bad", kind = "static")]
extern "C" {
pub fn c_read_value(a: u32, b: u32, c: u32) -> u16;
}
diff --git a/tests/run-make/zero-extend-abi-param-passing/rmake.rs b/tests/run-make/zero-extend-abi-param-passing/rmake.rs
index aed27f7..96dbbd0 100644
--- a/tests/run-make/zero-extend-abi-param-passing/rmake.rs
+++ b/tests/run-make/zero-extend-abi-param-passing/rmake.rs
@@ -6,20 +6,13 @@
// while simultaneously interfacing with a C library and using the -O3 flag.
// See https://github.com/rust-lang/rust/issues/97463
-//@ ignore-msvc
-// Reason: the rustc compilation fails due to an unresolved external symbol
-
//@ ignore-cross-compile
// Reason: The compiled binary is executed.
-
-use run_make_support::{cc, is_msvc, llvm_ar, run, rustc, static_lib_name};
+use run_make_support::{build_native_static_lib_optimized, run, rustc};
fn main() {
- // The issue exercised by this test specifically needs needs `-O`
- // flags (like `-O3`) to reproduce. Thus, we call `cc()` instead of
- // the nicer `build_native_static_lib`.
- cc().arg("-c").arg("-O3").out_exe("bad.o").input("bad.c").run();
- llvm_ar().obj_to_ar().output_input(static_lib_name("bad"), "bad.o").run();
- rustc().input("param_passing.rs").arg("-lbad").opt_level("3").run();
+ // The issue exercised by this test specifically needs an optimized native static lib.
+ build_native_static_lib_optimized("bad");
+ rustc().input("param_passing.rs").opt_level("3").run();
run("param_passing");
}
diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml
new file mode 100644
index 0000000..4f037ec
--- /dev/null
+++ b/tests/rustdoc-gui/code-example-buttons.goml
@@ -0,0 +1,96 @@
+// This test ensures that code blocks buttons are displayed on hover and when you click on them.
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+include: "utils.goml"
+
+// First we check we "hover".
+move-cursor-to: ".example-wrap"
+assert-css: (".example-wrap .copy-button", { "visibility": "visible" })
+move-cursor-to: ".search-input"
+assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
+
+// Now we check the click.
+assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0)
+click: ".example-wrap"
+move-cursor-to: ".search-input"
+// It should have a new class and be visible.
+wait-for-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 1)
+wait-for-css: (".example-wrap:not(:hover) .button-holder.keep-visible", { "visibility": "visible" })
+// Clicking again will remove the class.
+click: ".example-wrap"
+move-cursor-to: ".search-input"
+assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0)
+assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
+
+// Clicking on the "copy code" button shouldn't make the buttons stick.
+click: ".example-wrap .copy-button"
+move-cursor-to: ".search-input"
+assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0)
+assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
+
+define-function: (
+ "check-buttons",
+ [theme, background, filter, filter_hover],
+ block {
+ call-function: ("switch-theme", {"theme": |theme|})
+
+ assert-css: (".example-wrap .test-arrow", {"visibility": "hidden"})
+ assert-css: (".example-wrap .copy-button", {"visibility": "hidden"})
+
+ move-cursor-to: ".example-wrap"
+ assert-css: (".example-wrap .test-arrow", {
+ "visibility": "visible",
+ "background-color": |background|,
+ "border-radius": "2px",
+ })
+ assert-css: (".example-wrap .test-arrow::before", {
+ "filter": |filter|,
+ })
+ assert-css: (".example-wrap .copy-button", {
+ "visibility": "visible",
+ "background-color": |background|,
+ "border-radius": "2px",
+ })
+ assert-css: (".example-wrap .copy-button::before", {
+ "filter": |filter|,
+ })
+
+ move-cursor-to: ".example-wrap .test-arrow"
+ assert-css: (".example-wrap .test-arrow:hover", {
+ "visibility": "visible",
+ "background-color": |background|,
+ "border-radius": "2px",
+ })
+ assert-css: (".example-wrap .test-arrow:hover::before", {
+ "filter": |filter_hover|,
+ })
+
+ move-cursor-to: ".example-wrap .copy-button"
+ assert-css: (".example-wrap .copy-button:hover", {
+ "visibility": "visible",
+ "background-color": |background|,
+ "border-radius": "2px",
+ })
+ assert-css: (".example-wrap .copy-button:hover::before", {
+ "filter": |filter_hover|,
+ })
+ },
+)
+
+call-function: ("check-buttons",{
+ "theme": "ayu",
+ "background": "#0f1419",
+ "filter": "invert(0.7)",
+ "filter_hover": "invert(1)",
+})
+call-function: ("check-buttons",{
+ "theme": "dark",
+ "background": "#353535",
+ "filter": "invert(0.5)",
+ "filter_hover": "invert(0.65)",
+})
+call-function: ("check-buttons",{
+ "theme": "light",
+ "background": "#fff",
+ "filter": "invert(0.5)",
+ "filter_hover": "invert(0.35)",
+})
diff --git a/tests/rustdoc-gui/copy-code.goml b/tests/rustdoc-gui/copy-code.goml
new file mode 100644
index 0000000..9cc717b
--- /dev/null
+++ b/tests/rustdoc-gui/copy-code.goml
@@ -0,0 +1,54 @@
+// Checks that the "copy code" button is not triggering JS error and its display
+// isn't broken.
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+
+define-function: (
+ "check-copy-button",
+ [],
+ block {
+ // First we ensure that there are no "copy code" currently existing.
+ assert-count: (".example-wrap .copy-button", 0)
+ move-cursor-to: ".example-wrap"
+ assert-count: (".example-wrap .copy-button", 1)
+ // We now ensure it's only displayed when the example is hovered.
+ assert-css: (".example-wrap .copy-button", { "visibility": "visible" })
+ move-cursor-to: ".search-input"
+ assert-css: (".example-wrap .copy-button", { "visibility": "hidden" })
+ // Checking that the copy button has the same size as the "copy path" button.
+ compare-elements-size: (
+ "#copy-path",
+ ".example-wrap:nth-of-type(1) .copy-button",
+ ["height", "width"],
+ )
+ },
+)
+
+call-function: ("check-copy-button", {})
+// Checking that the run button and the copy button have the same height and same width.
+compare-elements-size: (
+ ".example-wrap:nth-of-type(1) .test-arrow",
+ ".example-wrap:nth-of-type(1) .copy-button",
+ ["height", "width"],
+)
+// ... and the same y position.
+compare-elements-position: (
+ ".example-wrap:nth-of-type(1) .test-arrow",
+ ".example-wrap:nth-of-type(1) .copy-button",
+ ["y"],
+)
+store-size: (".example-wrap:nth-of-type(1) .copy-button", {
+ "height": copy_height,
+ "width": copy_width,
+})
+assert: |copy_height| > 0 && |copy_width| > 0
+
+// Checking same things for the copy button when there is no run button.
+go-to: "file://" + |DOC_PATH| + "/lib2/sub_mod/struct.Foo.html"
+call-function: ("check-copy-button", {})
+// Ensure there is no run button.
+assert-count: (".example-wrap .test-arrow", 0)
+// Check it's the same size without a run button.
+assert-size: (".example-wrap:nth-of-type(1) .copy-button", {
+ "height": |copy_height|,
+ "width": |copy_width|,
+})
diff --git a/tests/rustdoc-gui/duplicate-macro-reexport.goml b/tests/rustdoc-gui/duplicate-macro-reexport.goml
index 7d01c88..a838d99 100644
--- a/tests/rustdoc-gui/duplicate-macro-reexport.goml
+++ b/tests/rustdoc-gui/duplicate-macro-reexport.goml
@@ -4,11 +4,11 @@
wait-for: ".sidebar-elems .macro"
// Check there is only one macro named "a" listed in the sidebar.
assert-count: (
- "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='a']",
+ "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[normalize-space()='a']",
1,
)
// Check there is only one macro named "b" listed in the sidebar.
assert-count: (
- "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='b']",
+ "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[normalize-space()='b']",
1,
)
diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml
index 602b8d6..26e9bf5 100644
--- a/tests/rustdoc-gui/font-weight.goml
+++ b/tests/rustdoc-gui/font-weight.goml
@@ -1,8 +1,8 @@
// This test checks that the font weight is correctly applied.
go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
-assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='rust item-decl']//a[normalize-space()='Alias']", {"font-weight": "400"})
assert-css: (
- "//*[@class='structfield section-header']//a[text()='Alias']",
+ "//*[@class='structfield section-header']//a[normalize-space()='Alias']",
{"font-weight": "400"},
)
assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"})
diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml
index 1eb46e8..7a0194c 100644
--- a/tests/rustdoc-gui/item-info.goml
+++ b/tests/rustdoc-gui/item-info.goml
@@ -12,11 +12,11 @@
// test for <https://github.com/rust-lang/rust/issues/118615>.
set-window-size: (850, 800)
store-position: (
- "//*[@class='stab portability']//code[text()='Win32_System']",
+ "//*[@class='stab portability']//code[normalize-space()='Win32_System']",
{"x": first_line_x, "y": first_line_y},
)
store-position: (
- "//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']",
+ "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']",
{"x": second_line_x, "y": second_line_y},
)
assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272
diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml
index 0582bd2..a8363f2 100644
--- a/tests/rustdoc-gui/label-next-to-symbol.goml
+++ b/tests/rustdoc-gui/label-next-to-symbol.goml
@@ -23,11 +23,12 @@
// table like view
assert-css: (".desc.docblock-short", { "padding-left": "0px" })
compare-elements-position-near: (
- "//*[@class='item-name']//a[text()='replaced_function']",
+ "//*[@class='item-name']//a[normalize-space()='replaced_function']",
".item-name .stab.deprecated",
{"y": 2},
)
-compare-elements-position: (
+// "Unix" part is on second line
+compare-elements-position-false: (
".item-name .stab.deprecated",
".item-name .stab.portability",
["y"],
@@ -35,8 +36,8 @@
// Ensure no wrap
compare-elements-position: (
- "//*[@class='item-name']//a[text()='replaced_function']/..",
- "//*[@class='desc docblock-short'][text()='a thing with a label']",
+ "//*[@class='item-name']//a[normalize-space()='replaced_function']/..",
+ "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']",
["y"],
)
@@ -45,7 +46,7 @@
// staggered layout with 2em spacing
assert-css: (".desc.docblock-short", { "padding-left": "32px" })
compare-elements-position-near: (
- "//*[@class='item-name']//a[text()='replaced_function']",
+ "//*[@class='item-name']//a[normalize-space()='replaced_function']",
".item-name .stab.deprecated",
{"y": 2},
)
@@ -57,13 +58,13 @@
// Ensure wrap
compare-elements-position-false: (
- "//*[@class='item-name']//a[text()='replaced_function']/..",
- "//*[@class='desc docblock-short'][text()='a thing with a label']",
+ "//*[@class='item-name']//a[normalize-space()='replaced_function']/..",
+ "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']",
["y"],
)
compare-elements-position-false: (
".item-name .stab.deprecated",
- "//*[@class='desc docblock-short'][text()='a thing with a label']",
+ "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']",
["y"],
)
@@ -73,7 +74,7 @@
// This part of the tags should not be on the same line as the beginning since the width
// is too small for that.
compare-elements-position-false: (
- "//*[@class='stab portability']/code[text()='appservice-api-c']",
- "//*[@class='stab portability']/code[text()='server']",
+ "//*[@class='stab portability']/code[normalize-space()='appservice-api-c']",
+ "//*[@class='stab portability']/code[normalize-space()='server']",
["y"],
)
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index 6ee810c..e2a8a43 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -9,19 +9,19 @@
block {
// Checking they have the same y position.
compare-elements-position: (
- "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']",
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
["y"],
)
// Checking they don't have the same x position.
compare-elements-position-false: (
- "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']",
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
["x"],
)
// The `i` should be *after* the type.
assert-position: (
- "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']",
{"x": |x|},
)
assert-position: (
@@ -70,7 +70,7 @@
// Now only the `i` should be on the next line.
set-window-size: (1055, 600)
compare-elements-position-false: (
- "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']",
"//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
["y", "x"],
)
diff --git a/tests/rustdoc-gui/run-on-hover.goml b/tests/rustdoc-gui/run-on-hover.goml
deleted file mode 100644
index 087dd33..0000000
--- a/tests/rustdoc-gui/run-on-hover.goml
+++ /dev/null
@@ -1,54 +0,0 @@
-// Example code blocks sometimes have a "Run" button to run them on the
-// Playground. That button is hidden until the user hovers over the code block.
-// This test checks that it is hidden, and that it shows on hover. It also
-// checks for its color.
-include: "utils.goml"
-go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
-show-text: true
-
-define-function: (
- "check-run-button",
- [theme, color, background, hover_color, hover_background],
- block {
- call-function: ("switch-theme", {"theme": |theme|})
- assert-css: (".test-arrow", {"visibility": "hidden"})
- move-cursor-to: ".example-wrap"
- assert-css: (".test-arrow", {
- "visibility": "visible",
- "color": |color|,
- "background-color": |background|,
- "font-size": "22px",
- "border-radius": "5px",
- })
- move-cursor-to: ".test-arrow"
- assert-css: (".test-arrow:hover", {
- "visibility": "visible",
- "color": |hover_color|,
- "background-color": |hover_background|,
- "font-size": "22px",
- "border-radius": "5px",
- })
- },
-)
-
-call-function: ("check-run-button", {
- "theme": "ayu",
- "color": "#788797",
- "background": "rgba(57, 175, 215, 0.09)",
- "hover_color": "#c5c5c5",
- "hover_background": "rgba(57, 175, 215, 0.37)",
-})
-call-function: ("check-run-button", {
- "theme": "dark",
- "color": "#dedede",
- "background": "rgba(78, 139, 202, 0.2)",
- "hover_color": "#dedede",
- "hover_background": "rgb(78, 139, 202)",
-})
-call-function: ("check-run-button", {
- "theme": "light",
- "color": "#f5f5f5",
- "background": "rgba(78, 139, 202, 0.2)",
- "hover_color": "#f5f5f5",
- "hover_background": "rgb(78, 139, 202)",
-})
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index 9825f92..e8da43e 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -20,11 +20,11 @@
ALL,
)
assert-css: (
- "//*[@class='desc'][text()='Just a normal struct.']",
+ "//*[@class='desc'][normalize-space()='Just a normal struct.']",
{"color": |desc_color|},
)
assert-css: (
- "//*[@class='result-name']//*[text()='test_docs::']",
+ "//*[@class='result-name']//*[normalize-space()='test_docs::']",
{"color": |path_color|},
)
@@ -85,19 +85,19 @@
move-cursor-to: ".search-input"
focus: ".search-input" // To ensure the `<a>` container isn't focused or hovered.
assert-css: (
- "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a",
+ "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a",
{"color": |path_color|, "background-color": "transparent"},
ALL,
)
// Checking color and background on hover.
- move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']"
+ move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal struct.']"
assert-css: (
- "//*[@class='result-name']//*[text()='test_docs::']",
+ "//*[@class='result-name']//*[normalize-space()='test_docs::']",
{"color": |hover_path_color|},
)
assert-css: (
- "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a",
+ "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a",
{"color": |hover_path_color|, "background-color": |hover_background|},
)
}
diff --git a/tests/rustdoc-gui/search-result-impl-disambiguation.goml b/tests/rustdoc-gui/search-result-impl-disambiguation.goml
index 3e49ac3..bca52b4 100644
--- a/tests/rustdoc-gui/search-result-impl-disambiguation.goml
+++ b/tests/rustdoc-gui/search-result-impl-disambiguation.goml
@@ -41,3 +41,24 @@
"URL": "struct.ZyxwvutMethodDisambiguation.html#method.method_impl_disambiguation-1"
}, ENDS_WITH)
assert: "section:target"
+
+// Checks that, if a type has two methods with the same name,
+// and if it has multiple inherent impl blocks, that the numeric
+// impl block's disambiguator is also acted upon.
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=MultiImplBlockStruct->bool"
+wait-for: "#search-tabs"
+assert-count: ("a.result-method", 1)
+assert-attribute: ("a.result-method", {
+ "href": "../lib2/another_mod/struct.MultiImplBlockStruct.html#impl-MultiImplBlockStruct/method.second_fn"
+})
+click: "a.result-method"
+wait-for: "details:has(summary > #impl-MultiImplBlockStruct-1) > div section[id='method.second_fn']:target"
+
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=MultiImplBlockStruct->u32"
+wait-for: "#search-tabs"
+assert-count: ("a.result-method", 1)
+assert-attribute: ("a.result-method", {
+ "href": "../lib2/another_mod/struct.MultiImplBlockStruct.html#impl-MultiImplBlockTrait-for-MultiImplBlockStruct/method.second_fn"
+})
+click: "a.result-method"
+wait-for: "details:has(summary > #impl-MultiImplBlockTrait-for-MultiImplBlockStruct) > div section[id='method.second_fn-1']:target"
diff --git a/tests/rustdoc-gui/sidebar-macro-reexport.goml b/tests/rustdoc-gui/sidebar-macro-reexport.goml
index 0f7ef6c..cad2550 100644
--- a/tests/rustdoc-gui/sidebar-macro-reexport.goml
+++ b/tests/rustdoc-gui/sidebar-macro-reexport.goml
@@ -2,4 +2,4 @@
// displayed twice in the sidebar.
go-to: "file://" + |DOC_PATH| + "/test_docs/macro.repro.html"
wait-for: ".sidebar-elems .block.macro a"
-assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1)
+assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[normalize-space()='repro']", 1)
diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml
index b4ff483..4ada483 100644
--- a/tests/rustdoc-gui/sidebar-mobile.goml
+++ b/tests/rustdoc-gui/sidebar-mobile.goml
@@ -25,9 +25,12 @@
assert-css: (".sidebar", {"left": "0px"})
// Make sure the "struct Foo" header is hidden, since the mobile topbar already does it.
-assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='Foo']/parent::h2", {"display": "none"})
+assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[normalize-space()='Foo']/parent::h2", {"display": "none"})
// Make sure the global navigation is still here.
-assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In crate test_docs']/parent::h2", {"display": "block"})
+assert-css: (
+ "//nav[contains(@class, 'sidebar')]//h2/a[normalize-space()='In crate test_docs']/parent::h2",
+ {"display": "block"}
+)
// Click elsewhere.
click: "body"
diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml
index ef0b5ab..6afccf6 100644
--- a/tests/rustdoc-gui/sidebar-source-code.goml
+++ b/tests/rustdoc-gui/sidebar-source-code.goml
@@ -66,12 +66,12 @@
// We wait for the sidebar to be expanded.
wait-for-css: (".src-sidebar-expanded nav.sidebar", {"width": "300px"})
assert: "//*[@class='dir-entry' and @open]/*[text()='lib2']"
-assert: "//*[@class='dir-entry' and @open]/*[text()='another_folder']"
-assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']"
+assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='another_folder']"
+assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='sub_mod']"
// Only "another_folder" should be "open" in "lib2".
-assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']"
+assert: "//*[@class='dir-entry' and not(@open)]/*[normalize-space()='another_mod']"
// All other trees should be collapsed.
-assert-count: ("//*[@id='src-sidebar']/details[not(text()='lib2') and not(@open)]", 11)
+assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 11)
// We now switch to mobile mode.
set-window-size: (600, 600)
diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml
index 940851e..3508b26 100644
--- a/tests/rustdoc-gui/source-anchor-scroll.goml
+++ b/tests/rustdoc-gui/source-anchor-scroll.goml
@@ -11,7 +11,7 @@
assert-property: ("html", {"scrollTop": "123"})
click: '//a[text() = "bar" and @href="#28-36"]'
assert-property: ("html", {"scrollTop": "154"})
-click: '//a[text() = "sub_fn" and @href="#2-4"]'
+click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]'
assert-property: ("html", {"scrollTop": "51"})
// We now check that clicking on lines doesn't change the scroll
diff --git a/tests/rustdoc-gui/src/lib2/another_mod/mod.rs b/tests/rustdoc-gui/src/lib2/another_mod/mod.rs
index 9a4f007..77f83d2 100644
--- a/tests/rustdoc-gui/src/lib2/another_mod/mod.rs
+++ b/tests/rustdoc-gui/src/lib2/another_mod/mod.rs
@@ -1 +1,19 @@
-pub fn tadam() {}
+pub struct MultiImplBlockStruct;
+
+impl MultiImplBlockStruct {
+ pub fn first_fn() {}
+}
+
+impl MultiImplBlockStruct {
+ pub fn second_fn(self) -> bool { true }
+}
+
+pub trait MultiImplBlockTrait {
+ fn first_fn();
+ fn second_fn(self) -> u32;
+}
+
+impl MultiImplBlockTrait for MultiImplBlockStruct {
+ fn first_fn() {}
+ fn second_fn(self) -> u32 { 1 }
+}
diff --git a/tests/rustdoc-js/self-is-not-generic.js b/tests/rustdoc-js/self-is-not-generic.js
new file mode 100644
index 0000000..0fdf5b4
--- /dev/null
+++ b/tests/rustdoc-js/self-is-not-generic.js
@@ -0,0 +1,22 @@
+// exact-check
+
+const EXPECTED = [
+ {
+ 'query': 'A -> A',
+ 'others': [
+ { 'path': 'self_is_not_generic::Thing', 'name': 'from' }
+ ],
+ },
+ {
+ 'query': 'A -> B',
+ 'others': [
+ { 'path': 'self_is_not_generic::Thing', 'name': 'try_from' }
+ ],
+ },
+ {
+ 'query': 'Combine -> Combine',
+ 'others': [
+ { 'path': 'self_is_not_generic::Combine', 'name': 'combine' }
+ ],
+ }
+];
diff --git a/tests/rustdoc-js/self-is-not-generic.rs b/tests/rustdoc-js/self-is-not-generic.rs
new file mode 100644
index 0000000..d6a96ac
--- /dev/null
+++ b/tests/rustdoc-js/self-is-not-generic.rs
@@ -0,0 +1,11 @@
+pub trait Combine {
+ fn combine(&self, other: &Self) -> Self;
+}
+
+pub struct Thing;
+
+impl Combine for Thing {
+ fn combine(&self, other: &Self) -> Self {
+ Self
+ }
+}
diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
new file mode 100644
index 0000000..f02e38c
--- /dev/null
+++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+#![feature(impl_trait_in_assoc_type)]
+
+pub struct AlwaysTrue;
+
+/// impl IntoIterator
+impl IntoIterator for AlwaysTrue {
+ //@ set Item = '$.index[*][?(@.docs=="type Item")].id'
+ /// type Item
+ type Item = bool;
+
+ //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[*]' 1
+ //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.name' '"Iterator"'
+ //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[*]' 1
+ //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name' '"Item"'
+ //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive' '"bool"'
+
+ //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id'
+ /// type IntoIter
+ type IntoIter = impl Iterator<Item = bool>;
+
+ //@ set into_iter = '$.index[*][?(@.docs=="fn into_iter")].id'
+ /// fn into_iter
+ fn into_iter(self) -> Self::IntoIter {
+ std::iter::repeat(true)
+ }
+}
+
+//@ ismany '$.index[*][?(@.docs=="impl IntoIterator")].inner.impl.items[*]' $Item $IntoIter $into_iter
diff --git a/tests/rustdoc-json/impls/pub_for_hidden_private.rs b/tests/rustdoc-json/impls/pub_for_hidden_private.rs
new file mode 100644
index 0000000..261ffbf
--- /dev/null
+++ b/tests/rustdoc-json/impls/pub_for_hidden_private.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: --document-private-items --document-hidden-items
+
+pub trait TheTrait {}
+
+#[doc(hidden)]
+struct Value {}
+
+//@ has '$.index[*][?(@.docs=="THE IMPL")]'
+/// THE IMPL
+impl TheTrait for Value {}
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index e97db42..27394a6 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -15,6 +15,5 @@ mod usize {}
//@ is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
pub use i32 as my_i32;
-
//@ is "$.index[*].inner.import[?(@.name=='u32')].id" null
pub use u32;
diff --git a/tests/rustdoc-json/pub_mod_in_private_mod.rs b/tests/rustdoc-json/pub_mod_in_private_mod.rs
new file mode 100644
index 0000000..112ab9c
--- /dev/null
+++ b/tests/rustdoc-json/pub_mod_in_private_mod.rs
@@ -0,0 +1,6 @@
+// See https://github.com/rust-lang/rust/issues/101105
+
+//@ !has "$.index[*][?(@.name=='nucleus')]"
+mod corpus {
+ pub mod nucleus {}
+}
diff --git a/tests/rustdoc-json/the_smallest.rs b/tests/rustdoc-json/the_smallest.rs
new file mode 100644
index 0000000..2f6f91e
--- /dev/null
+++ b/tests/rustdoc-json/the_smallest.rs
@@ -0,0 +1,5 @@
+// This test asserts that `index` is not polluted with unrelated items.
+// See https://github.com/rust-lang/rust/issues/114039
+
+//@ count "$.index[*]" 1
+fn main() {}
diff --git a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
new file mode 100644
index 0000000..571bc94
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs
@@ -0,0 +1,12 @@
+//@ compile-flags:--test
+//@ check-pass
+#![allow(rustdoc::invalid_codeblock_attributes)]
+
+// https://github.com/rust-lang/rust/pull/124577#issuecomment-2276034737
+
+// Test that invalid langstrings don't get run.
+
+/// ```{rust,ignore}
+/// panic!();
+/// ```
+pub struct Foo;
diff --git a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout
new file mode 100644
index 0000000..e5c27be
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout
@@ -0,0 +1,5 @@
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+
diff --git a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr
index e23e0f0..2eebedb 100644
--- a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr
+++ b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr
@@ -4,7 +4,10 @@
LL | pub use inner::S;
| ^^^^^ you might be missing crate `inner`
|
- = help: consider adding `extern crate inner` to use the `inner` crate
+help: consider importing the `inner` crate
+ |
+LL + extern crate inner;
+ |
error: aborting due to 1 previous error
diff --git a/tests/rustdoc-ui/intra-doc/.gitattributes b/tests/rustdoc-ui/intra-doc/.gitattributes
index 6c125fa..0ac2e3c 100644
--- a/tests/rustdoc-ui/intra-doc/.gitattributes
+++ b/tests/rustdoc-ui/intra-doc/.gitattributes
@@ -1 +1 @@
-warning-crlf.rs eol=crlf
+warning-crlf.rs -text
diff --git a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
index a74e6b7..e689431 100644
--- a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
+++ b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr
@@ -4,7 +4,10 @@
LL | use unresolved_crate::module::Name;
| ^^^^^^^^^^^^^^^^ you might be missing crate `unresolved_crate`
|
- = help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate
+help: consider importing the `unresolved_crate` crate
+ |
+LL + extern crate unresolved_crate;
+ |
error: aborting due to 1 previous error
diff --git a/tests/rustdoc-ui/intra-doc/warning-crlf.rs b/tests/rustdoc-ui/intra-doc/warning-crlf.rs
index ab096b8..9d3a467 100644
--- a/tests/rustdoc-ui/intra-doc/warning-crlf.rs
+++ b/tests/rustdoc-ui/intra-doc/warning-crlf.rs
@@ -1,26 +1,26 @@
-// ignore-tidy-cr
-//@ check-pass
-
-// This file checks the spans of intra-link warnings in a file with CRLF line endings. The
-// .gitattributes file in this directory should enforce it.
-
-/// [error]
-pub struct A;
-//~^^ WARNING `error`
-
-///
-/// docs [error1]
-//~^ WARNING `error1`
-
-/// docs [error2]
-///
-pub struct B;
-//~^^^ WARNING `error2`
-
-/**
- * This is a multi-line comment.
- *
- * It also has an [error].
- */
-pub struct C;
-//~^^^ WARNING `error`
+// ignore-tidy-cr
+//@ check-pass
+
+// This file checks the spans of intra-link warnings in a file with CRLF line endings. The
+// .gitattributes file in this directory should enforce it.
+
+/// [error]
+pub struct A;
+//~^^ WARNING `error`
+
+///
+/// docs [error1]
+//~^ WARNING `error1`
+
+/// docs [error2]
+///
+pub struct B;
+//~^^^ WARNING `error2`
+
+/**
+ * This is a multi-line comment.
+ *
+ * It also has an [error].
+ */
+pub struct C;
+//~^^^ WARNING `error`
diff --git a/tests/rustdoc-ui/issues/issue-61732.stderr b/tests/rustdoc-ui/issues/issue-61732.stderr
index f49d53b..0aa7d55 100644
--- a/tests/rustdoc-ui/issues/issue-61732.stderr
+++ b/tests/rustdoc-ui/issues/issue-61732.stderr
@@ -4,7 +4,10 @@
LL | pub(in crate::r#mod) fn main() {}
| ^^^^^ you might be missing crate `r#mod`
|
- = help: consider adding `extern crate r#mod` to use the `r#mod` crate
+help: consider importing the `r#mod` crate
+ |
+LL + extern crate r#mod;
+ |
error: aborting due to 1 previous error
diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.rs b/tests/rustdoc-ui/issues/issue-81662-shortness.rs
index 02207d2..7df6326 100644
--- a/tests/rustdoc-ui/issues/issue-81662-shortness.rs
+++ b/tests/rustdoc-ui/issues/issue-81662-shortness.rs
@@ -1,6 +1,6 @@
//@ compile-flags:--test --error-format=short
//@ check-stdout
-//@ error-pattern:cannot find function `foo` in this scope
+//@ error-pattern:cannot find function `foo`
//@ normalize-stdout-test: "tests/rustdoc-ui/issues" -> "$$DIR"
//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
//@ failure-status: 101
diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout
index f32f51e..8fcc7ed 100644
--- a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout
+++ b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout
@@ -5,7 +5,7 @@
failures:
---- $DIR/issue-81662-shortness.rs - foo (line 8) stdout ----
-$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope
+$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope: not found in this scope
error: aborting due to 1 previous error
Couldn't compile the test.
diff --git a/tests/rustdoc-ui/remap-path-prefix-lint.rs b/tests/rustdoc-ui/remap-path-prefix-lint.rs
new file mode 100644
index 0000000..f27863e
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-lint.rs
@@ -0,0 +1,10 @@
+// Regression test for remapped paths in rustdoc errors
+// <https://github.com/rust-lang/rust/issues/69264>.
+
+//@ compile-flags:-Z unstable-options --remap-path-prefix={{src-base}}=remapped_path
+//@ rustc-env:RUST_BACKTRACE=0
+
+#![deny(rustdoc::invalid_html_tags)]
+
+/// </script>
+pub struct Bar;
diff --git a/tests/rustdoc-ui/remap-path-prefix-lint.stderr b/tests/rustdoc-ui/remap-path-prefix-lint.stderr
new file mode 100644
index 0000000..d7c1bb1
--- /dev/null
+++ b/tests/rustdoc-ui/remap-path-prefix-lint.stderr
@@ -0,0 +1,14 @@
+error: unopened HTML tag `script`
+ --> remapped_path/remap-path-prefix-lint.rs:9:5
+ |
+LL | /// </script>
+ | ^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> remapped_path/remap-path-prefix-lint.rs:7:9
+ |
+LL | #![deny(rustdoc::invalid_html_tags)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
new file mode 100644
index 0000000..5d08810
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
@@ -0,0 +1,2 @@
+//@ build-aux-docs
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
new file mode 100644
index 0000000..fab9ec4
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
@@ -0,0 +1,4 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
new file mode 100644
index 0000000..85c460a
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
@@ -0,0 +1,16 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+//@ has q/struct.Quebec.html
+//@ has s/struct.Sierra.html
+//@ has t/trait.Tango.html
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// We document multiple crates into the same output directory, which
+// merges the cross-crate information. Everything is available.
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
new file mode 100644
index 0000000..932a0b1
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
@@ -0,0 +1,5 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
new file mode 100644
index 0000000..c21a59c
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
@@ -0,0 +1,7 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
new file mode 100644
index 0000000..68bfc34
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
@@ -0,0 +1,24 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
+//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's'
+//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has q/struct.Quebec.html
+//@ has s/struct.Sierra.html
+//@ has t/trait.Tango.html
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
+
+// We document multiple crates into the same output directory, which
+// merges the cross-crate information. Everything is available.
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
new file mode 100644
index 0000000..abc580a
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
@@ -0,0 +1,2 @@
+//@ build-aux-docs
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
new file mode 100644
index 0000000..c93298f
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
@@ -0,0 +1,14 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+//@ has e/enum.Echo.html
+//@ has f/trait.Foxtrot.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
+
+// document two crates in the same way that cargo does. do not provide
+// --enable-index-page
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
new file mode 100644
index 0000000..a2a7033
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
@@ -0,0 +1,5 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
new file mode 100644
index 0000000..00f86cb
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
@@ -0,0 +1,21 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
+//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
+//@ has e/enum.Echo.html
+//@ has f/trait.Foxtrot.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
+
+// document two crates in the same way that cargo does, writing them both
+// into the same output directory
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
new file mode 100644
index 0000000..abc580a
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
@@ -0,0 +1,2 @@
+//@ build-aux-docs
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
new file mode 100644
index 0000000..ffee898
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
@@ -0,0 +1,20 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
+//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
+//@ has e/enum.Echo.html
+//@ has f/trait.Foxtrot.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
+
+// only declare --enable-index-page to the last rustdoc invocation
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
new file mode 100644
index 0000000..932a0b1
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
@@ -0,0 +1,5 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
new file mode 100644
index 0000000..2c0db2a
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
@@ -0,0 +1,7 @@
+//@ aux-build:s.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate s;
+pub type Romeo = s::Sierra;
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
new file mode 100644
index 0000000..355d3f1
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
@@ -0,0 +1,8 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
new file mode 100644
index 0000000..c21a59c
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
@@ -0,0 +1,7 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
new file mode 100644
index 0000000..bcb9464
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
@@ -0,0 +1,30 @@
+//@ aux-build:r.rs
+//@ aux-build:q.rs
+//@ aux-build:t.rs
+//@ aux-build:s.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html
+//@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
+//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r'
+//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's'
+//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has q/struct.Quebec.html
+//@ has r/type.Romeo.html
+//@ has s/struct.Sierra.html
+//@ has t/trait.Tango.html
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Quebec'
+//@ hasraw search-index.js 'Romeo'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Tango'
+//@ has type.impl/s/struct.Sierra.js
+//@ hasraw type.impl/s/struct.Sierra.js 'Tango'
+//@ hasraw type.impl/s/struct.Sierra.js 'Romeo'
+
+// document everything in the default mode
diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
new file mode 100644
index 0000000..c5e3dc0
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
@@ -0,0 +1,12 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
+//@ has q/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// there's nothing cross-crate going on here
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
new file mode 100644
index 0000000..d3e71fa
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
@@ -0,0 +1,6 @@
+//@ build-aux-docs
+//@ has q/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
+
+// there's nothing cross-crate going on here
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
new file mode 100644
index 0000000..5d08810
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
@@ -0,0 +1,2 @@
+//@ build-aux-docs
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
new file mode 100644
index 0000000..fab9ec4
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
@@ -0,0 +1,4 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs
new file mode 100644
index 0000000..0a4e5f6
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/transitive/s.rs
@@ -0,0 +1,6 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+// simple test to see if we support building transitive crates
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
new file mode 100644
index 0000000..abc580a
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
@@ -0,0 +1,2 @@
+//@ build-aux-docs
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs
new file mode 100644
index 0000000..9665af6
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/two/e.rs
@@ -0,0 +1,6 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+// simple test to assert that we can do a two-level aux-build
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
new file mode 100644
index 0000000..a7ab062
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
@@ -0,0 +1,10 @@
+//@ build-aux-docs
+//@ doc-flags:--scrape-examples-output-path=examples
+//@ doc-flags:--scrape-examples-target-crate=q
+//@ doc-flags:-Zunstable-options
+
+//@ has examples
+
+// where will --scrape-examples-output-path resolve the path to be?
+// should be the root output directory
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
new file mode 100644
index 0000000..f8c9adc
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
@@ -0,0 +1,3 @@
+//@ build-aux-docs
+//@ unique-doc-out-dir
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
new file mode 100644
index 0000000..9dcec21
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
@@ -0,0 +1,14 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+//@ has e/enum.Echo.html
+//@ !has f/trait.Foxtrot.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ !hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
+
+// test the fact that our test runner will document this crate somewhere
+// else
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/extremely_long_typename.extremely_long_typename.html b/tests/rustdoc/extremely_long_typename.extremely_long_typename.html
new file mode 100644
index 0000000..b20e598
--- /dev/null
+++ b/tests/rustdoc/extremely_long_typename.extremely_long_typename.html
@@ -0,0 +1 @@
+<li><div class="item-name"><a class="struct" href="struct.CreateSubscriptionPaymentSettingsPaymentMethodOptionsCustomerBalanceBankTransferEuBankTransfer.html" title="struct extremely_long_typename::CreateSubscriptionPaymentSettingsPaymentMethodOptionsCustomerBalanceBankTransferEuBankTransfer">Create<wbr />Subscription<wbr />Payment<wbr />Settings<wbr />Payment<wbr />Method<wbr />Options<wbr />Customer<wbr />Balance<wbr />Bank<wbr />Transfer<wbr />EuBank<wbr />Transfer</a></div></li>
\ No newline at end of file
diff --git a/tests/rustdoc/extremely_long_typename.rs b/tests/rustdoc/extremely_long_typename.rs
new file mode 100644
index 0000000..212afe2
--- /dev/null
+++ b/tests/rustdoc/extremely_long_typename.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+// Make sure that, if an extremely long type name is named,
+// the item table has it line wrapped.
+// There should be some reasonably-placed `<wbr>` tags in the snapshot file.
+
+// @snapshot extremely_long_typename "extremely_long_typename/index.html" '//ul[@class="item-table"]/li'
+pub struct CreateSubscriptionPaymentSettingsPaymentMethodOptionsCustomerBalanceBankTransferEuBankTransfer;
diff --git a/tests/rustdoc/item-desc-list-at-start.item-table.html b/tests/rustdoc/item-desc-list-at-start.item-table.html
index 72bde57..cff4f81 100644
--- a/tests/rustdoc/item-desc-list-at-start.item-table.html
+++ b/tests/rustdoc/item-desc-list-at-start.item-table.html
@@ -1 +1 @@
-<ul class="item-table"><li><div class="item-name"><a class="constant" href="constant.MY_CONSTANT.html" title="constant item_desc_list_at_start::MY_CONSTANT">MY_CONSTANT</a></div><div class="desc docblock-short">Groups: <code>SamplePatternSGIS</code>, <code>SamplePatternEXT</code></div></li></ul>
\ No newline at end of file
+<ul class="item-table"><li><div class="item-name"><a class="constant" href="constant.MY_CONSTANT.html" title="constant item_desc_list_at_start::MY_CONSTANT">MY_<wbr />CONSTANT</a></div><div class="desc docblock-short">Groups: <code>SamplePatternSGIS</code>, <code>SamplePatternEXT</code></div></li></ul>
\ No newline at end of file
diff --git a/tests/rustdoc/negative-impl-no-items.rs b/tests/rustdoc/negative-impl-no-items.rs
new file mode 100644
index 0000000..c628e54
--- /dev/null
+++ b/tests/rustdoc/negative-impl-no-items.rs
@@ -0,0 +1,26 @@
+// This test ensures that negative impls don't have items listed inside them.
+
+#![feature(negative_impls)]
+#![crate_name = "foo"]
+
+pub struct Thing;
+
+//@ has 'foo/struct.Thing.html'
+// We check the full path to ensure there is no `<details>` element.
+//@ has - '//div[@id="trait-implementations-list"]/section[@id="impl-Iterator-for-Thing"]/h3' \
+// 'impl !Iterator for Thing'
+impl !Iterator for Thing {}
+
+// This struct will allow us to compare both paths.
+pub struct Witness;
+
+//@ has 'foo/struct.Witness.html'
+//@ has - '//div[@id="trait-implementations-list"]/details//section[@id="impl-Iterator-for-Witness"]/h3' \
+// 'impl Iterator for Witness'
+impl Iterator for Witness {
+ type Item = u8;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ None
+ }
+}
diff --git a/tests/rustdoc/playground-arg.rs b/tests/rustdoc/playground-arg.rs
index 5875451..e10a310 100644
--- a/tests/rustdoc/playground-arg.rs
+++ b/tests/rustdoc/playground-arg.rs
@@ -10,4 +10,4 @@
pub fn dummy() {}
// ensure that `extern crate foo;` was inserted into code snips automatically:
-//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0A++++use+foo::dummy;%0A++++dummy();%0A%7D&edition=2015"]' "Run"
+//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0A%23%5Ballow(unused_extern_crates)%5D%0Aextern+crate+r%23foo;%0Afn+main()+%7B%0A++++use+foo::dummy;%0A++++dummy();%0A%7D&edition=2015"]' ""
diff --git a/tests/rustdoc/playground-syntax-error.rs b/tests/rustdoc/playground-syntax-error.rs
index f506714..d989570 100644
--- a/tests/rustdoc/playground-syntax-error.rs
+++ b/tests/rustdoc/playground-syntax-error.rs
@@ -17,5 +17,5 @@
pub fn bar() {}
//@ has foo/fn.bar.html
-//@ has - '//a[@class="test-arrow"]' "Run"
+//@ has - '//a[@class="test-arrow"]' ""
//@ has - '//*[@class="docblock"]' 'foo_recursive'
diff --git a/tests/rustdoc/playground.rs b/tests/rustdoc/playground.rs
index 7880f77..db2d166 100644
--- a/tests/rustdoc/playground.rs
+++ b/tests/rustdoc/playground.rs
@@ -22,6 +22,6 @@
//! }
//! ```
-//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
-//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' "Run"
-//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' "Run"
+//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
+//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&edition=2015"]' ""
+//@ matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn+main()+%7B%0A++++println!(%22Hello,+world!%22);%0A%7D&version=nightly&edition=2015"]' ""
diff --git a/tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs b/tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs
new file mode 100644
index 0000000..2846710
--- /dev/null
+++ b/tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs
@@ -0,0 +1,17 @@
+#![feature(impl_trait_in_assoc_type)]
+
+pub struct AlwaysTrue;
+
+//@ has impl_trait_in_assoc_type/struct.AlwaysTrue.html
+
+impl IntoIterator for AlwaysTrue {
+ type Item = bool;
+
+ //@ has - '//*[@id="associatedtype.IntoIter"]//h4[@class="code-header"]' \
+ // 'type IntoIter = impl Iterator<Item = bool>'
+ type IntoIter = impl Iterator<Item = bool>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ std::iter::repeat(true)
+ }
+}
diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/unsafe-extern-blocks.rs
index 22d3bee..829095f 100644
--- a/tests/rustdoc/unsafe-extern-blocks.rs
+++ b/tests/rustdoc/unsafe-extern-blocks.rs
@@ -1,6 +1,5 @@
// Test to ensure the feature is working as expected.
-#![feature(unsafe_extern_blocks)]
#![crate_name = "foo"]
// @has 'foo/index.html'
@@ -13,7 +12,7 @@
// @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1
// @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠'
-unsafe extern {
+unsafe extern "C" {
// @has 'foo/static.FOO.html'
// @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32'
pub safe static FOO: i32;
diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
index 33e10a0..c761b8e 100644
--- a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
@@ -1,5 +1,4 @@
//@ compile-flags: -Z unstable-options
-//@ ignore-stage1 (can be removed after beta bump, #[cfg(bootstrap)])
#![feature(rustc_private)]
#![deny(rustc::non_glob_import_of_type_ir_inherent)]
diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
index 84e3867..c5c10bb 100644
--- a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
@@ -1,5 +1,5 @@
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:9
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:16:9
|
LL | use rustc_type_ir::inherent::Predicate;
| ^^^^^^^^^^^^^^^^^^^^^^^^^---------
@@ -7,25 +7,25 @@
| help: try using a glob import instead: `*`
|
note: the lint level is defined here
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:4:9
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:3:9
|
LL | #![deny(rustc::non_glob_import_of_type_ir_inherent)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:35
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:35
|
LL | use rustc_type_ir::inherent::{AdtDef, Ty};
| ^^^^^^ help: try using a glob import instead: `*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:43
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:43
|
LL | use rustc_type_ir::inherent::{AdtDef, Ty};
| ^^ help: try using a glob import instead: `*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:21:9
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:20:9
|
LL | use rustc_type_ir::inherent::ParamEnv as _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^-------------
@@ -33,31 +33,31 @@
| help: try using a glob import instead: `*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:24:9
|
LL | use rustc_type_ir::inherent;
| ^^^^^^^^^^^^^^^^^^^^^^^- help: try using a glob import instead: `::*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:26:9
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
|
LL | use rustc_type_ir::inherent as inh;
| ^^^^^^^^^^^^^^^^^^^^^^^------- help: try using a glob import instead: `::*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:27:25
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:26:25
|
LL | use rustc_type_ir::{inherent as _};
| ^^^^^^^^----- help: try using a glob import instead: `::*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:33:35
|
LL | use rustc_type_ir::inherent::{self};
| ^^^^ help: try using a glob import instead: `*`
error: non-glob import of `rustc_type_ir::inherent`
- --> $DIR/non_glob_import_of_type_ir_inherent.rs:35:35
+ --> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
|
LL | use rustc_type_ir::inherent::{self as innate};
| ^^^^----------
diff --git a/tests/crashes/121444.rs b/tests/ui/abi/large-byval-align.rs
similarity index 68%
rename from tests/crashes/121444.rs
rename to tests/ui/abi/large-byval-align.rs
index a6373a5..e39170d 100644
--- a/tests/crashes/121444.rs
+++ b/tests/ui/abi/large-byval-align.rs
@@ -1,11 +1,13 @@
-//@ known-bug: #121444
//@ compile-flags: -Copt-level=0
-//@ edition:2021
//@ only-x86_64
//@ ignore-windows
+//@ min-llvm-version: 19
+//@ build-pass
+
#[repr(align(536870912))]
pub struct A(i64);
+#[allow(improper_ctypes_definitions)]
pub extern "C" fn foo(x: A) {}
fn main() {
diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs
index ba68cdd..46667ae 100644
--- a/tests/ui/asm/aarch64/type-check-2.rs
+++ b/tests/ui/asm/aarch64/type-check-2.rs
@@ -15,15 +15,6 @@ fn main() {
unsafe {
// Inputs must be initialized
- // Sym operands must point to a function or static
-
- const C: i32 = 0;
- static S: i32 = 0;
- asm!("{}", sym S);
- asm!("{}", sym main);
- asm!("{}", sym C);
- //~^ ERROR invalid `sym` operand
-
// Register operands must be Copy
asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
@@ -65,12 +56,3 @@ fn main() {
asm!("{}", in(reg) u);
}
}
-
-// Sym operands must point to a function or static
-
-const C: i32 = 0;
-static S: i32 = 0;
-global_asm!("{}", sym S);
-global_asm!("{}", sym main);
-global_asm!("{}", sym C);
-//~^ ERROR invalid `sym` operand
diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr
index d647f6a..b7723fc 100644
--- a/tests/ui/asm/aarch64/type-check-2.stderr
+++ b/tests/ui/asm/aarch64/type-check-2.stderr
@@ -1,29 +1,13 @@
-error: invalid `sym` operand
- --> $DIR/type-check-2.rs:75:19
- |
-LL | global_asm!("{}", sym C);
- | ^^^^^ is an `i32`
- |
- = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
- --> $DIR/type-check-2.rs:24:20
- |
-LL | asm!("{}", sym C);
- | ^^^^^ is an `i32`
- |
- = help: `sym` operands must refer to either a function or a static
-
error: arguments for inline assembly must be copyable
- --> $DIR/type-check-2.rs:29:31
+ --> $DIR/type-check-2.rs:20:31
|
LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `SimdNonCopy` does not implement the Copy trait
-error: cannot use value of type `{closure@$DIR/type-check-2.rs:41:28: 41:36}` for inline assembly
- --> $DIR/type-check-2.rs:41:28
+error: cannot use value of type `{closure@$DIR/type-check-2.rs:32:28: 32:36}` for inline assembly
+ --> $DIR/type-check-2.rs:32:28
|
LL | asm!("{}", in(reg) |x: i32| x);
| ^^^^^^^^^^
@@ -31,7 +15,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `Vec<i32>` for inline assembly
- --> $DIR/type-check-2.rs:43:28
+ --> $DIR/type-check-2.rs:34:28
|
LL | asm!("{}", in(reg) vec![0]);
| ^^^^^^^
@@ -40,7 +24,7 @@
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use value of type `(i32, i32, i32)` for inline assembly
- --> $DIR/type-check-2.rs:45:28
+ --> $DIR/type-check-2.rs:36:28
|
LL | asm!("{}", in(reg) (1, 2, 3));
| ^^^^^^^^^
@@ -48,7 +32,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `[i32; 3]` for inline assembly
- --> $DIR/type-check-2.rs:47:28
+ --> $DIR/type-check-2.rs:38:28
|
LL | asm!("{}", in(reg) [1, 2, 3]);
| ^^^^^^^^^
@@ -56,7 +40,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `fn() {main}` for inline assembly
- --> $DIR/type-check-2.rs:55:31
+ --> $DIR/type-check-2.rs:46:31
|
LL | asm!("{}", inout(reg) f);
| ^
@@ -64,12 +48,12 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `&mut i32` for inline assembly
- --> $DIR/type-check-2.rs:58:31
+ --> $DIR/type-check-2.rs:49:31
|
LL | asm!("{}", inout(reg) r);
| ^
|
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs
new file mode 100644
index 0000000..eff335f
--- /dev/null
+++ b/tests/ui/asm/invalid-const-operand.rs
@@ -0,0 +1,51 @@
+//@ needs-asm-support
+//@ ignore-nvptx64
+//@ ignore-spirv
+
+#![feature(asm_const)]
+
+use std::arch::{asm, global_asm};
+
+// Const operands must be integers and must be constants.
+
+global_asm!("{}", const 0);
+global_asm!("{}", const 0i32);
+global_asm!("{}", const 0i128);
+global_asm!("{}", const 0f32);
+//~^ ERROR invalid type for `const` operand
+global_asm!("{}", const 0 as *mut u8);
+//~^ ERROR invalid type for `const` operand
+
+fn main() {
+ unsafe {
+ // Const operands must be integers and must be constants.
+
+ asm!("{}", const 0);
+ asm!("{}", const 0i32);
+ asm!("{}", const 0i128);
+ asm!("{}", const 0f32);
+ //~^ ERROR invalid type for `const` operand
+ asm!("{}", const 0 as *mut u8);
+ //~^ ERROR invalid type for `const` operand
+ asm!("{}", const &0);
+ //~^ ERROR invalid type for `const` operand
+
+ // Constants must be... constant
+
+ let x = 0;
+ const fn const_foo(x: i32) -> i32 {
+ x
+ }
+ const fn const_bar<T>(x: T) -> T {
+ x
+ }
+ asm!("{}", const x);
+ //~^ ERROR attempt to use a non-constant value in a constant
+ asm!("{}", const const_foo(0));
+ asm!("{}", const const_foo(x));
+ //~^ ERROR attempt to use a non-constant value in a constant
+ asm!("{}", const const_bar(0));
+ asm!("{}", const const_bar(x));
+ //~^ ERROR attempt to use a non-constant value in a constant
+ }
+}
diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr
new file mode 100644
index 0000000..a6d742b
--- /dev/null
+++ b/tests/ui/asm/invalid-const-operand.stderr
@@ -0,0 +1,86 @@
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/invalid-const-operand.rs:42:26
+ |
+LL | asm!("{}", const x);
+ | ^ non-constant value
+ |
+help: consider using `const` instead of `let`
+ |
+LL | const x: /* Type */ = 0;
+ | ~~~~~ ++++++++++++
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/invalid-const-operand.rs:45:36
+ |
+LL | asm!("{}", const const_foo(x));
+ | ^ non-constant value
+ |
+help: consider using `const` instead of `let`
+ |
+LL | const x: /* Type */ = 0;
+ | ~~~~~ ++++++++++++
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/invalid-const-operand.rs:48:36
+ |
+LL | asm!("{}", const const_bar(x));
+ | ^ non-constant value
+ |
+help: consider using `const` instead of `let`
+ |
+LL | const x: /* Type */ = 0;
+ | ~~~~~ ++++++++++++
+
+error: invalid type for `const` operand
+ --> $DIR/invalid-const-operand.rs:14:19
+ |
+LL | global_asm!("{}", const 0f32);
+ | ^^^^^^----
+ | |
+ | is an `f32`
+ |
+ = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+ --> $DIR/invalid-const-operand.rs:16:19
+ |
+LL | global_asm!("{}", const 0 as *mut u8);
+ | ^^^^^^------------
+ | |
+ | is a `*mut u8`
+ |
+ = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+ --> $DIR/invalid-const-operand.rs:26:20
+ |
+LL | asm!("{}", const 0f32);
+ | ^^^^^^----
+ | |
+ | is an `f32`
+ |
+ = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+ --> $DIR/invalid-const-operand.rs:28:20
+ |
+LL | asm!("{}", const 0 as *mut u8);
+ | ^^^^^^------------
+ | |
+ | is a `*mut u8`
+ |
+ = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+ --> $DIR/invalid-const-operand.rs:30:20
+ |
+LL | asm!("{}", const &0);
+ | ^^^^^^--
+ | |
+ | is a `&i32`
+ |
+ = help: `const` operands must be of an integer type
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/invalid-sym-operand.rs b/tests/ui/asm/invalid-sym-operand.rs
new file mode 100644
index 0000000..2129c20
--- /dev/null
+++ b/tests/ui/asm/invalid-sym-operand.rs
@@ -0,0 +1,34 @@
+//@ needs-asm-support
+//@ ignore-nvptx64
+//@ ignore-spirv
+
+use std::arch::{asm, global_asm};
+
+// Sym operands must point to a function or static
+
+const C: i32 = 0;
+static S: i32 = 0;
+global_asm!("{}", sym S);
+global_asm!("{}", sym main);
+global_asm!("{}", sym C);
+//~^ ERROR invalid `sym` operand
+
+fn main() {
+ unsafe {
+ // Sym operands must point to a function or static
+
+ let x: u64 = 0;
+ const C: i32 = 0;
+ static S: i32 = 0;
+ asm!("{}", sym S);
+ asm!("{}", sym main);
+ asm!("{}", sym C);
+ //~^ ERROR invalid `sym` operand
+ asm!("{}", sym x);
+ //~^ ERROR invalid `sym` operand
+ }
+}
+
+unsafe fn generic<T>() {
+ asm!("{}", sym generic::<T>);
+}
diff --git a/tests/ui/asm/invalid-sym-operand.stderr b/tests/ui/asm/invalid-sym-operand.stderr
new file mode 100644
index 0000000..f0e6a17
--- /dev/null
+++ b/tests/ui/asm/invalid-sym-operand.stderr
@@ -0,0 +1,26 @@
+error: invalid `sym` operand
+ --> $DIR/invalid-sym-operand.rs:27:24
+ |
+LL | asm!("{}", sym x);
+ | ^ is a local variable
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+ --> $DIR/invalid-sym-operand.rs:13:19
+ |
+LL | global_asm!("{}", sym C);
+ | ^^^^^ is an `i32`
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: invalid `sym` operand
+ --> $DIR/invalid-sym-operand.rs:25:20
+ |
+LL | asm!("{}", sym C);
+ | ^^^^^ is an `i32`
+ |
+ = help: `sym` operands must refer to either a function or a static
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs
index 6d335ac..cb1e5c3 100644
--- a/tests/ui/asm/naked-functions.rs
+++ b/tests/ui/asm/naked-functions.rs
@@ -239,6 +239,9 @@ pub extern "C" fn valid_b() {
}
#[doc = "foo bar baz"]
+/// a doc comment
+// a normal comment
+#[doc(alias = "ADocAlias")]
#[naked]
pub unsafe extern "C" fn compatible_doc_attributes() {
asm!("", options(noreturn, raw));
diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs
index 9dec3a1..16ae0282 100644
--- a/tests/ui/asm/parse-error.rs
+++ b/tests/ui/asm/parse-error.rs
@@ -146,5 +146,16 @@ fn main() {
//~^ ERROR asm template must be a string literal
global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
//~^ ERROR asm template must be a string literal
-global_asm!("{}", label {});
-//~^ ERROR expected operand, options, or additional template string
+
+global_asm!("{}", in(reg));
+//~^ ERROR the `in` operand cannot be used with `global_asm!`
+global_asm!("{}", out(reg));
+//~^ ERROR the `out` operand cannot be used with `global_asm!`
+global_asm!("{}", lateout(reg));
+//~^ ERROR the `lateout` operand cannot be used with `global_asm!`
+global_asm!("{}", inout(reg));
+//~^ ERROR the `inout` operand cannot be used with `global_asm!`
+global_asm!("{}", inlateout(reg));
+//~^ ERROR the `inlateout` operand cannot be used with `global_asm!`
+global_asm!("{}", label(reg));
+//~^ ERROR the `label` operand cannot be used with `global_asm!`
diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr
index e9ecd71..f5f8d53 100644
--- a/tests/ui/asm/parse-error.stderr
+++ b/tests/ui/asm/parse-error.stderr
@@ -380,11 +380,41 @@
|
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: expected operand, options, or additional template string
- --> $DIR/parse-error.rs:149:19
+error: the `in` operand cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:150:19
|
-LL | global_asm!("{}", label {});
- | ^^^^^^^^ expected operand, options, or additional template string
+LL | global_asm!("{}", in(reg));
+ | ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `out` operand cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:152:19
+ |
+LL | global_asm!("{}", out(reg));
+ | ^^^ the `out` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `lateout` operand cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:154:19
+ |
+LL | global_asm!("{}", lateout(reg));
+ | ^^^^^^^ the `lateout` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `inout` operand cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:156:19
+ |
+LL | global_asm!("{}", inout(reg));
+ | ^^^^^ the `inout` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `inlateout` operand cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:158:19
+ |
+LL | global_asm!("{}", inlateout(reg));
+ | ^^^^^^^^^ the `inlateout` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `label` operand cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:160:19
+ |
+LL | global_asm!("{}", label(reg));
+ | ^^^^^ the `label` operand is not meaningful for global-scoped inline assembly, remove it
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:39:37
@@ -441,6 +471,6 @@
LL | const bar: /* Type */ = 0;
| ~~~~~ ++++++++++++
-error: aborting due to 67 previous errors
+error: aborting due to 72 previous errors
For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs
index b0f1362..22669dc 100644
--- a/tests/ui/asm/type-check-1.rs
+++ b/tests/ui/asm/type-check-1.rs
@@ -28,51 +28,5 @@ fn main() {
asm!("{}", inout(reg) v[..]);
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
//~| ERROR cannot use value of type `[u64]` for inline assembly
-
- // Constants must be... constant
-
- let x = 0;
- const fn const_foo(x: i32) -> i32 {
- x
- }
- const fn const_bar<T>(x: T) -> T {
- x
- }
- asm!("{}", const x);
- //~^ ERROR attempt to use a non-constant value in a constant
- asm!("{}", const const_foo(0));
- asm!("{}", const const_foo(x));
- //~^ ERROR attempt to use a non-constant value in a constant
- asm!("{}", const const_bar(0));
- asm!("{}", const const_bar(x));
- //~^ ERROR attempt to use a non-constant value in a constant
- asm!("{}", sym x);
- //~^ ERROR invalid `sym` operand
-
- // Const operands must be integers and must be constants.
-
- asm!("{}", const 0);
- asm!("{}", const 0i32);
- asm!("{}", const 0i128);
- asm!("{}", const 0f32);
- //~^ ERROR mismatched types
- asm!("{}", const 0 as *mut u8);
- //~^ ERROR mismatched types
- asm!("{}", const &0);
- //~^ ERROR mismatched types
}
}
-
-unsafe fn generic<T>() {
- asm!("{}", sym generic::<T>);
-}
-
-// Const operands must be integers and must be constants.
-
-global_asm!("{}", const 0);
-global_asm!("{}", const 0i32);
-global_asm!("{}", const 0i128);
-global_asm!("{}", const 0f32);
-//~^ ERROR mismatched types
-global_asm!("{}", const 0 as *mut u8);
-//~^ ERROR mismatched types
diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr
index 1852623..d47e6ae 100644
--- a/tests/ui/asm/type-check-1.stderr
+++ b/tests/ui/asm/type-check-1.stderr
@@ -1,44 +1,3 @@
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/type-check-1.rs:41:26
- |
-LL | asm!("{}", const x);
- | ^ non-constant value
- |
-help: consider using `const` instead of `let`
- |
-LL | const x: /* Type */ = 0;
- | ~~~~~ ++++++++++++
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/type-check-1.rs:44:36
- |
-LL | asm!("{}", const const_foo(x));
- | ^ non-constant value
- |
-help: consider using `const` instead of `let`
- |
-LL | const x: /* Type */ = 0;
- | ~~~~~ ++++++++++++
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/type-check-1.rs:47:36
- |
-LL | asm!("{}", const const_bar(x));
- | ^ non-constant value
- |
-help: consider using `const` instead of `let`
- |
-LL | const x: /* Type */ = 0;
- | ~~~~~ ++++++++++++
-
-error: invalid `sym` operand
- --> $DIR/type-check-1.rs:49:24
- |
-LL | asm!("{}", sym x);
- | ^ is a local variable
- |
- = help: `sym` operands must refer to either a function or a static
-
error: invalid asm output
--> $DIR/type-check-1.rs:14:29
|
@@ -102,49 +61,6 @@
|
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:57:26
- |
-LL | asm!("{}", const 0f32);
- | ^^^^ expected integer, found `f32`
+error: aborting due to 8 previous errors
-error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:59:26
- |
-LL | asm!("{}", const 0 as *mut u8);
- | ^^^^^^^^^^^^ expected integer, found `*mut u8`
- |
- = note: expected type `{integer}`
- found raw pointer `*mut u8`
-
-error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:61:26
- |
-LL | asm!("{}", const &0);
- | ^^ expected integer, found `&{integer}`
- |
-help: consider removing the borrow
- |
-LL - asm!("{}", const &0);
-LL + asm!("{}", const 0);
- |
-
-error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:75:25
- |
-LL | global_asm!("{}", const 0f32);
- | ^^^^ expected integer, found `f32`
-
-error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:77:25
- |
-LL | global_asm!("{}", const 0 as *mut u8);
- | ^^^^^^^^^^^^ expected integer, found `*mut u8`
- |
- = note: expected type `{integer}`
- found raw pointer `*mut u8`
-
-error: aborting due to 17 previous errors
-
-Some errors have detailed explanations: E0277, E0308, E0435.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs
index 4b5d59f..ff81196 100644
--- a/tests/ui/asm/x86_64/type-check-2.rs
+++ b/tests/ui/asm/x86_64/type-check-2.rs
@@ -27,17 +27,6 @@ fn main() {
asm!("{}", out(reg) v[0]);
asm!("{}", inout(reg) v[0]);
- // Sym operands must point to a function or static
-
- const C: i32 = 0;
- static S: i32 = 0;
- asm!("{}", sym S);
- asm!("{}", sym main);
- asm!("{}", sym C);
- //~^ ERROR invalid `sym` operand
- asm!("{}", sym x);
- //~^ ERROR invalid `sym` operand
-
// Register operands must be Copy
asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
@@ -79,12 +68,3 @@ fn main() {
asm!("{}", in(reg) u);
}
}
-
-// Sym operands must point to a function or static
-
-const C: i32 = 0;
-static S: i32 = 0;
-global_asm!("{}", sym S);
-global_asm!("{}", sym main);
-global_asm!("{}", sym C);
-//~^ ERROR invalid `sym` operand
diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr
index 6ae118b..c72e695 100644
--- a/tests/ui/asm/x86_64/type-check-2.stderr
+++ b/tests/ui/asm/x86_64/type-check-2.stderr
@@ -1,37 +1,13 @@
-error: invalid `sym` operand
- --> $DIR/type-check-2.rs:38:24
- |
-LL | asm!("{}", sym x);
- | ^ is a local variable
- |
- = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
- --> $DIR/type-check-2.rs:89:19
- |
-LL | global_asm!("{}", sym C);
- | ^^^^^ is an `i32`
- |
- = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
- --> $DIR/type-check-2.rs:36:20
- |
-LL | asm!("{}", sym C);
- | ^^^^^ is an `i32`
- |
- = help: `sym` operands must refer to either a function or a static
-
error: arguments for inline assembly must be copyable
- --> $DIR/type-check-2.rs:43:32
+ --> $DIR/type-check-2.rs:32:32
|
LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `SimdNonCopy` does not implement the Copy trait
-error: cannot use value of type `{closure@$DIR/type-check-2.rs:55:28: 55:36}` for inline assembly
- --> $DIR/type-check-2.rs:55:28
+error: cannot use value of type `{closure@$DIR/type-check-2.rs:44:28: 44:36}` for inline assembly
+ --> $DIR/type-check-2.rs:44:28
|
LL | asm!("{}", in(reg) |x: i32| x);
| ^^^^^^^^^^
@@ -39,7 +15,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `Vec<i32>` for inline assembly
- --> $DIR/type-check-2.rs:57:28
+ --> $DIR/type-check-2.rs:46:28
|
LL | asm!("{}", in(reg) vec![0]);
| ^^^^^^^
@@ -48,7 +24,7 @@
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use value of type `(i32, i32, i32)` for inline assembly
- --> $DIR/type-check-2.rs:59:28
+ --> $DIR/type-check-2.rs:48:28
|
LL | asm!("{}", in(reg) (1, 2, 3));
| ^^^^^^^^^
@@ -56,7 +32,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `[i32; 3]` for inline assembly
- --> $DIR/type-check-2.rs:61:28
+ --> $DIR/type-check-2.rs:50:28
|
LL | asm!("{}", in(reg) [1, 2, 3]);
| ^^^^^^^^^
@@ -64,7 +40,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `fn() {main}` for inline assembly
- --> $DIR/type-check-2.rs:69:31
+ --> $DIR/type-check-2.rs:58:31
|
LL | asm!("{}", inout(reg) f);
| ^
@@ -72,7 +48,7 @@
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `&mut i32` for inline assembly
- --> $DIR/type-check-2.rs:72:31
+ --> $DIR/type-check-2.rs:61:31
|
LL | asm!("{}", inout(reg) r);
| ^
@@ -121,7 +97,7 @@
LL | let mut v: Vec<u64> = vec![0, 1, 2];
| +++
-error: aborting due to 13 previous errors
+error: aborting due to 10 previous errors
Some errors have detailed explanations: E0381, E0596.
For more information about an error, try `rustc --explain E0381`.
diff --git a/tests/ui/associated-type-bounds/name-same-as-generic-type-issue-128249.rs b/tests/ui/associated-type-bounds/name-same-as-generic-type-issue-128249.rs
new file mode 100644
index 0000000..f5f8fa5
--- /dev/null
+++ b/tests/ui/associated-type-bounds/name-same-as-generic-type-issue-128249.rs
@@ -0,0 +1,15 @@
+trait Trait<Type> {
+ type Type;
+
+ fn one(&self, val: impl Trait<Type: Default>);
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
+
+ fn two<T: Trait<Type: Default>>(&self) -> T;
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
+
+ fn three<T>(&self) -> T where
+ T: Trait<Type: Default>,;
+ //~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/name-same-as-generic-type-issue-128249.stderr b/tests/ui/associated-type-bounds/name-same-as-generic-type-issue-128249.stderr
new file mode 100644
index 0000000..06ab060
--- /dev/null
+++ b/tests/ui/associated-type-bounds/name-same-as-generic-type-issue-128249.stderr
@@ -0,0 +1,51 @@
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
+ --> $DIR/name-same-as-generic-type-issue-128249.rs:4:30
+ |
+LL | fn one(&self, val: impl Trait<Type: Default>);
+ | ^^^^^ expected 1 generic argument
+ |
+note: trait defined here, with 1 generic parameter: `Type`
+ --> $DIR/name-same-as-generic-type-issue-128249.rs:1:7
+ |
+LL | trait Trait<Type> {
+ | ^^^^^ ----
+help: add missing generic argument
+ |
+LL | fn one(&self, val: impl Trait<Type, Type: Default>);
+ | +++++
+
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
+ --> $DIR/name-same-as-generic-type-issue-128249.rs:7:15
+ |
+LL | fn two<T: Trait<Type: Default>>(&self) -> T;
+ | ^^^^^ expected 1 generic argument
+ |
+note: trait defined here, with 1 generic parameter: `Type`
+ --> $DIR/name-same-as-generic-type-issue-128249.rs:1:7
+ |
+LL | trait Trait<Type> {
+ | ^^^^^ ----
+help: add missing generic argument
+ |
+LL | fn two<T: Trait<Type, Type: Default>>(&self) -> T;
+ | +++++
+
+error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
+ --> $DIR/name-same-as-generic-type-issue-128249.rs:11:12
+ |
+LL | T: Trait<Type: Default>,;
+ | ^^^^^ expected 1 generic argument
+ |
+note: trait defined here, with 1 generic parameter: `Type`
+ --> $DIR/name-same-as-generic-type-issue-128249.rs:1:7
+ |
+LL | trait Trait<Type> {
+ | ^^^^^ ----
+help: add missing generic argument
+ |
+LL | T: Trait<Type, Type: Default>,;
+ | +++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/associated-types/associated-types-outlives.stderr b/tests/ui/associated-types/associated-types-outlives.stderr
index 1164869..bd6022f 100644
--- a/tests/ui/associated-types/associated-types-outlives.stderr
+++ b/tests/ui/associated-types/associated-types-outlives.stderr
@@ -18,7 +18,7 @@
| ^ consider constraining this type parameter with `Clone`
...
LL | 's: loop { y = denormalise(&x); break }
- | -- you could clone this value
+ | - you could clone this value
error: aborting due to 1 previous error
diff --git a/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
new file mode 100644
index 0000000..8b2de57
--- /dev/null
+++ b/tests/ui/async-await/async-closures/box-deref-in-debuginfo.rs
@@ -0,0 +1,35 @@
+//@ aux-build:block-on.rs
+//@ edition:2021
+//@ run-pass
+
+#![feature(async_closure)]
+
+extern crate block_on;
+
+pub trait Trait {
+ fn callback(&mut self);
+}
+impl Trait for (i32,) {
+ fn callback(&mut self) {
+ println!("hi {}", self.0);
+ self.0 += 1;
+ }
+}
+
+async fn call_once(f: impl async FnOnce()) {
+ f().await;
+}
+
+async fn run(mut loader: Box<dyn Trait>) {
+ let f = async move || {
+ loader.callback();
+ loader.callback();
+ };
+ call_once(f).await;
+}
+
+fn main() {
+ block_on::block_on(async {
+ run(Box::new((42,))).await;
+ });
+}
diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.rs b/tests/ui/async-await/async-closures/fn-exception-target-features.rs
new file mode 100644
index 0000000..de62fc8
--- /dev/null
+++ b/tests/ui/async-await/async-closures/fn-exception-target-features.rs
@@ -0,0 +1,17 @@
+//@ edition: 2021
+//@ only-x86_64
+
+#![feature(async_closure, target_feature_11)]
+// `target_feature_11` just to test safe functions w/ target features.
+
+use std::pin::Pin;
+use std::future::Future;
+
+#[target_feature(enable = "sse2")]
+fn target_feature() -> Pin<Box<dyn Future<Output = ()> + 'static>> { todo!() }
+
+fn test(f: impl async Fn()) {}
+
+fn main() {
+ test(target_feature); //~ ERROR the trait bound
+}
diff --git a/tests/ui/async-await/async-closures/fn-exception-target-features.stderr b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr
new file mode 100644
index 0000000..396167f
--- /dev/null
+++ b/tests/ui/async-await/async-closures/fn-exception-target-features.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}: AsyncFn<()>` is not satisfied
+ --> $DIR/fn-exception-target-features.rs:16:10
+ |
+LL | test(target_feature);
+ | ---- ^^^^^^^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {target_feature}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `test`
+ --> $DIR/fn-exception-target-features.rs:13:17
+ |
+LL | fn test(f: impl async Fn()) {}
+ | ^^^^^^^^^^ required by this bound in `test`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-closures/fn-exception.rs b/tests/ui/async-await/async-closures/fn-exception.rs
new file mode 100644
index 0000000..0e06ebf
--- /dev/null
+++ b/tests/ui/async-await/async-closures/fn-exception.rs
@@ -0,0 +1,21 @@
+//@ edition: 2021
+
+#![feature(async_closure)]
+
+use std::pin::Pin;
+use std::future::Future;
+
+unsafe extern "Rust" {
+ pub unsafe fn unsafety() -> Pin<Box<dyn Future<Output = ()> + 'static>>;
+}
+
+unsafe extern "C" {
+ pub safe fn abi() -> Pin<Box<dyn Future<Output = ()> + 'static>>;
+}
+
+fn test(f: impl async Fn()) {}
+
+fn main() {
+ test(unsafety); //~ ERROR the trait bound
+ test(abi); //~ ERROR the trait bound
+}
diff --git a/tests/ui/async-await/async-closures/fn-exception.stderr b/tests/ui/async-await/async-closures/fn-exception.stderr
new file mode 100644
index 0000000..bacd079
--- /dev/null
+++ b/tests/ui/async-await/async-closures/fn-exception.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the trait bound `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}: AsyncFn<()>` is not satisfied
+ --> $DIR/fn-exception.rs:19:10
+ |
+LL | test(unsafety);
+ | ---- ^^^^^^^^ the trait `AsyncFn<()>` is not implemented for fn item `unsafe fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {unsafety}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `test`
+ --> $DIR/fn-exception.rs:16:17
+ |
+LL | fn test(f: impl async Fn()) {}
+ | ^^^^^^^^^^ required by this bound in `test`
+
+error[E0277]: the trait bound `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}: AsyncFn<()>` is not satisfied
+ --> $DIR/fn-exception.rs:20:10
+ |
+LL | test(abi);
+ | ---- ^^^ the trait `AsyncFn<()>` is not implemented for fn item `extern "C" fn() -> Pin<Box<(dyn Future<Output = ()> + 'static)>> {abi}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `test`
+ --> $DIR/fn-exception.rs:16:17
+ |
+LL | fn test(f: impl async Fn()) {}
+ | ^^^^^^^^^^ required by this bound in `test`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
new file mode 100644
index 0000000..cd9d98d
--- /dev/null
+++ b/tests/ui/async-await/async-closures/non-copy-arg-does-not-force-inner-move.rs
@@ -0,0 +1,17 @@
+//@ aux-build:block-on.rs
+//@ edition:2021
+//@ build-pass
+
+#![feature(async_closure)]
+
+extern crate block_on;
+
+fn wrapper(f: impl Fn(String)) -> impl async Fn(String) {
+ async move |s| f(s)
+}
+
+fn main() {
+ block_on::block_on(async {
+ wrapper(|who| println!("Hello, {who}!"))(String::from("world")).await;
+ });
+}
diff --git a/tests/ui/async-await/for-await-consumes-iter.rs b/tests/ui/async-await/for-await-consumes-iter.rs
index 38dfe46..7ea88c1 100644
--- a/tests/ui/async-await/for-await-consumes-iter.rs
+++ b/tests/ui/async-await/for-await-consumes-iter.rs
@@ -1,5 +1,5 @@
//@ edition: 2021
-#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker)]
+#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker)]
use std::future::Future;
diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs
index e09e843..b4fba6b 100644
--- a/tests/ui/async-await/for-await-passthrough.rs
+++ b/tests/ui/async-await/for-await-passthrough.rs
@@ -1,7 +1,7 @@
//@ run-pass
//@ edition: 2024
//@ compile-flags: -Zunstable-options
-#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker,
+#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker,
gen_blocks)]
async gen fn async_iter() -> i32 {
diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs
index acd9f01..b4af38a 100644
--- a/tests/ui/async-await/for-await.rs
+++ b/tests/ui/async-await/for-await.rs
@@ -1,6 +1,6 @@
//@ run-pass
//@ edition: 2021
-#![feature(async_iterator, async_iter_from_iter, const_waker, async_for_loop, noop_waker)]
+#![feature(async_iterator, async_iter_from_iter, async_for_loop, noop_waker)]
use std::future::Future;
diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs
index d3d1284..a5c81a9 100644
--- a/tests/ui/async-await/in-trait/generics-mismatch.rs
+++ b/tests/ui/async-await/in-trait/generics-mismatch.rs
@@ -6,7 +6,7 @@ trait Foo {
impl Foo for () {
async fn foo<const N: usize>() {}
- //~^ ERROR: method `foo` has an incompatible generic parameter for trait `Foo` [E0053]
+ //~^ ERROR: associated function `foo` has an incompatible generic parameter for trait `Foo` [E0053]
}
fn main() {}
diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr
index c0357dc..cb0f95e 100644
--- a/tests/ui/async-await/in-trait/generics-mismatch.stderr
+++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr
@@ -1,4 +1,4 @@
-error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo`
+error[E0053]: associated function `foo` has an incompatible generic parameter for trait `Foo`
--> $DIR/generics-mismatch.rs:8:18
|
LL | trait Foo {
diff --git a/tests/ui/async-await/unreachable-lint-2.rs b/tests/ui/async-await/unreachable-lint-2.rs
new file mode 100644
index 0000000..137cb32
--- /dev/null
+++ b/tests/ui/async-await/unreachable-lint-2.rs
@@ -0,0 +1,15 @@
+//@ edition:2018
+
+#![deny(unreachable_code)]
+
+async fn foo() {
+ endless().await;
+ println!("this is unreachable!");
+ //~^ ERROR unreachable statement
+}
+
+async fn endless() -> ! {
+ loop {}
+}
+
+fn main() { }
diff --git a/tests/ui/async-await/unreachable-lint-2.stderr b/tests/ui/async-await/unreachable-lint-2.stderr
new file mode 100644
index 0000000..cbebc99
--- /dev/null
+++ b/tests/ui/async-await/unreachable-lint-2.stderr
@@ -0,0 +1,17 @@
+error: unreachable statement
+ --> $DIR/unreachable-lint-2.rs:7:5
+ |
+LL | endless().await;
+ | ----- any code following this expression is unreachable
+LL | println!("this is unreachable!");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
+ |
+note: the lint level is defined here
+ --> $DIR/unreachable-lint-2.rs:3:9
+ |
+LL | #![deny(unreachable_code)]
+ | ^^^^^^^^^^^^^^^^
+ = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/check-builtin-attr-ice.rs b/tests/ui/attributes/check-builtin-attr-ice.rs
new file mode 100644
index 0000000..9ef5890
--- /dev/null
+++ b/tests/ui/attributes/check-builtin-attr-ice.rs
@@ -0,0 +1,58 @@
+//! Regression test for #128622.
+//!
+//! PR #128581 introduced an assertion that all builtin attributes are actually checked via
+//! `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes.
+//! Unfortunately, the check had correctness problems.
+//!
+//! The match on attribute path segments looked like
+//!
+//! ```rs,ignore
+//! [sym::should_panic] => /* check is implemented */
+//! match BUILTIN_ATTRIBUTE_MAP.get(name) {
+//! // checked below
+//! Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {}
+//! Some(_) => {
+//! if !name.as_str().starts_with("rustc_") {
+//! span_bug!(
+//! attr.span,
+//! "builtin attribute {name:?} not handled by `CheckAttrVisitor`"
+//! )
+//! }
+//! }
+//! None => (),
+//! }
+//! ```
+//!
+//! However, it failed to account for edge cases such as an attribute whose:
+//!
+//! 1. path segments *starts* with a builtin attribute such as `should_panic`
+//! 2. which does not start with `rustc_`, and
+//! 3. is also an `AttributeType::Normal` attribute upon registration with the builtin attribute map
+//!
+//! These conditions when all satisfied cause the span bug to be issued for e.g.
+//! `#[should_panic::skip]` because the `[sym::should_panic]` arm is not matched (since it's
+//! `[sym::should_panic, sym::skip]`).
+//!
+//! This test checks that the span bug is not fired for such cases.
+//!
+//! issue: rust-lang/rust#128622
+
+// Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately.
+
+struct Foo {
+ #[should_panic::skip]
+ //~^ ERROR failed to resolve
+ pub field: u8,
+
+ #[should_panic::a::b::c]
+ //~^ ERROR failed to resolve
+ pub field2: u8,
+}
+
+fn foo() {}
+
+fn main() {
+ #[deny::skip]
+ //~^ ERROR failed to resolve
+ foo();
+}
diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr
new file mode 100644
index 0000000..5a27da5
--- /dev/null
+++ b/tests/ui/attributes/check-builtin-attr-ice.stderr
@@ -0,0 +1,21 @@
+error[E0433]: failed to resolve: use of undeclared crate or module `should_panic`
+ --> $DIR/check-builtin-attr-ice.rs:43:7
+ |
+LL | #[should_panic::skip]
+ | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `should_panic`
+ --> $DIR/check-builtin-attr-ice.rs:47:7
+ |
+LL | #[should_panic::a::b::c]
+ | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `deny`
+ --> $DIR/check-builtin-attr-ice.rs:55:7
+ |
+LL | #[deny::skip]
+ | ^^^^ use of undeclared crate or module `deny`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/attributes/check-cfg_attr-ice.rs b/tests/ui/attributes/check-cfg_attr-ice.rs
new file mode 100644
index 0000000..5bf8baa
--- /dev/null
+++ b/tests/ui/attributes/check-cfg_attr-ice.rs
@@ -0,0 +1,68 @@
+//! I missed a `cfg_attr` match in #128581, it should have had the same treatment as `cfg`. If
+//! an invalid attribute starting with `cfg_attr` is passed, then it would trigger an ICE because
+//! it was not considered "checked" (e.g. `#[cfg_attr::skip]` or `#[cfg_attr::no_such_thing]`).
+//!
+//! This test is not exhaustive, there's too many possible positions to check, instead it just does
+//! a basic smoke test in a few select positions to make sure we don't ICE for e.g.
+//! `#[cfg_attr::no_such_thing]`.
+//!
+//! issue: rust-lang/rust#128716
+#![crate_type = "lib"]
+
+#[cfg_attr::no_such_thing]
+//~^ ERROR failed to resolve
+mod we_are_no_strangers_to_love {}
+
+#[cfg_attr::no_such_thing]
+//~^ ERROR failed to resolve
+struct YouKnowTheRules {
+ #[cfg_attr::no_such_thing]
+ //~^ ERROR failed to resolve
+ and_so_do_i: u8,
+}
+
+#[cfg_attr::no_such_thing]
+//~^ ERROR failed to resolve
+fn a_full_commitment() {
+ #[cfg_attr::no_such_thing]
+ //~^ ERROR failed to resolve
+ let is_what_i_am_thinking_of = ();
+}
+
+#[cfg_attr::no_such_thing]
+//~^ ERROR failed to resolve
+union AnyOtherGuy {
+ owo: ()
+}
+struct This;
+
+#[cfg_attr(FALSE, doc = "you wouldn't get this")]
+impl From<AnyOtherGuy> for This {
+ #[cfg_attr::no_such_thing]
+ //~^ ERROR failed to resolve
+ fn from(#[cfg_attr::no_such_thing] any_other_guy: AnyOtherGuy) -> This {
+ //~^ ERROR failed to resolve
+ #[cfg_attr::no_such_thing]
+ //~^ ERROR attributes on expressions are experimental
+ //~| ERROR failed to resolve
+ unreachable!()
+ }
+}
+
+#[cfg_attr::no_such_thing]
+//~^ ERROR failed to resolve
+enum NeverGonna {
+ #[cfg_attr::no_such_thing]
+ //~^ ERROR failed to resolve
+ GiveYouUp(#[cfg_attr::no_such_thing] u8),
+ //~^ ERROR failed to resolve
+ LetYouDown {
+ #![cfg_attr::no_such_thing]
+ //~^ ERROR an inner attribute is not permitted in this context
+ never_gonna: (),
+ round_around: (),
+ #[cfg_attr::no_such_thing]
+ //~^ ERROR failed to resolve
+ and_desert_you: (),
+ },
+}
diff --git a/tests/ui/attributes/check-cfg_attr-ice.stderr b/tests/ui/attributes/check-cfg_attr-ice.stderr
new file mode 100644
index 0000000..dbdf325
--- /dev/null
+++ b/tests/ui/attributes/check-cfg_attr-ice.stderr
@@ -0,0 +1,101 @@
+error: an inner attribute is not permitted in this context
+ --> $DIR/check-cfg_attr-ice.rs:60:9
+ |
+LL | #![cfg_attr::no_such_thing]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+ = note: outer attributes, like `#[test]`, annotate the item following them
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/check-cfg_attr-ice.rs:45:9
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:52:3
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:55:7
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:57:17
+ |
+LL | GiveYouUp(#[cfg_attr::no_such_thing] u8),
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:64:11
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:41:7
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:43:15
+ |
+LL | fn from(#[cfg_attr::no_such_thing] any_other_guy: AnyOtherGuy) -> This {
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:45:11
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:32:3
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:24:3
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:27:7
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:16:3
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:19:7
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr`
+ --> $DIR/check-cfg_attr-ice.rs:12:3
+ |
+LL | #[cfg_attr::no_such_thing]
+ | ^^^^^^^^ use of undeclared crate or module `cfg_attr`
+
+error: aborting due to 15 previous errors
+
+Some errors have detailed explanations: E0433, E0658.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/tests/ui/attributes/field-attributes-vis-unresolved.stderr b/tests/ui/attributes/field-attributes-vis-unresolved.stderr
index 819cd85..f8610c0 100644
--- a/tests/ui/attributes/field-attributes-vis-unresolved.stderr
+++ b/tests/ui/attributes/field-attributes-vis-unresolved.stderr
@@ -4,7 +4,10 @@
LL | pub(in nonexistent) field: u8
| ^^^^^^^^^^^ you might be missing crate `nonexistent`
|
- = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
+help: consider importing the `nonexistent` crate
+ |
+LL + extern crate nonexistent;
+ |
error[E0433]: failed to resolve: you might be missing crate `nonexistent`
--> $DIR/field-attributes-vis-unresolved.rs:22:12
@@ -12,7 +15,10 @@
LL | pub(in nonexistent) u8
| ^^^^^^^^^^^ you might be missing crate `nonexistent`
|
- = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
+help: consider importing the `nonexistent` crate
+ |
+LL + extern crate nonexistent;
+ |
error: aborting due to 2 previous errors
diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs
new file mode 100644
index 0000000..82b7a22
--- /dev/null
+++ b/tests/ui/attributes/no-sanitize.rs
@@ -0,0 +1,34 @@
+#![feature(no_sanitize)]
+#![feature(stmt_expr_attributes)]
+#![deny(unused_attributes)]
+#![allow(dead_code)]
+
+fn invalid() {
+ #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
+ {
+ 1
+ };
+}
+
+#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
+type InvalidTy = ();
+
+#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
+mod invalid_module {}
+
+fn main() {
+ let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
+ (|| 1);
+}
+
+#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
+struct F;
+
+#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition
+impl F {
+ #[no_sanitize(memory)]
+ fn valid(&self) {}
+}
+
+#[no_sanitize(memory)]
+fn valid() {}
diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr
new file mode 100644
index 0000000..f742ba0
--- /dev/null
+++ b/tests/ui/attributes/no-sanitize.stderr
@@ -0,0 +1,55 @@
+error: attribute should be applied to a function definition
+ --> $DIR/no-sanitize.rs:7:5
+ |
+LL | #[no_sanitize(memory)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | / {
+LL | | 1
+LL | | };
+ | |_____- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/no-sanitize.rs:13:1
+ |
+LL | #[no_sanitize(memory)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | type InvalidTy = ();
+ | -------------------- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/no-sanitize.rs:16:1
+ |
+LL | #[no_sanitize(memory)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | mod invalid_module {}
+ | --------------------- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/no-sanitize.rs:20:13
+ |
+LL | let _ = #[no_sanitize(memory)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | (|| 1);
+ | ------ not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/no-sanitize.rs:24:1
+ |
+LL | #[no_sanitize(memory)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | struct F;
+ | --------- not a function definition
+
+error: attribute should be applied to a function definition
+ --> $DIR/no-sanitize.rs:27:1
+ |
+LL | #[no_sanitize(memory)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | / impl F {
+LL | | #[no_sanitize(memory)]
+LL | | fn valid(&self) {}
+LL | | }
+ | |_- not a function definition
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/attributes/optimize.rs b/tests/ui/attributes/optimize.rs
new file mode 100644
index 0000000..b018061
--- /dev/null
+++ b/tests/ui/attributes/optimize.rs
@@ -0,0 +1,28 @@
+#![feature(optimize_attribute)]
+#![feature(stmt_expr_attributes)]
+#![deny(unused_attributes)]
+#![allow(dead_code)]
+
+#[optimize(speed)] //~ ERROR attribute should be applied to function or closure
+struct F;
+
+fn invalid() {
+ #[optimize(speed)] //~ ERROR attribute should be applied to function or closure
+ {
+ 1
+ };
+}
+
+#[optimize(speed)]
+fn valid() {}
+
+#[optimize(speed)]
+mod valid_module {}
+
+#[optimize(speed)]
+impl F {}
+
+fn main() {
+ let _ = #[optimize(speed)]
+ (|| 1);
+}
diff --git a/tests/ui/attributes/optimize.stderr b/tests/ui/attributes/optimize.stderr
new file mode 100644
index 0000000..3c445d7
--- /dev/null
+++ b/tests/ui/attributes/optimize.stderr
@@ -0,0 +1,20 @@
+error: attribute should be applied to function or closure
+ --> $DIR/optimize.rs:6:1
+ |
+LL | #[optimize(speed)]
+ | ^^^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/optimize.rs:3:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: attribute should be applied to function or closure
+ --> $DIR/optimize.rs:10:5
+ |
+LL | #[optimize(speed)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
index 774ce86..b8edb4a 100644
--- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
+++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
@@ -1,6 +1,15 @@
#![feature(unsafe_attributes)]
-#[derive(unsafe(Debug))] //~ ERROR: traits in `#[derive(...)]` don't accept `unsafe(...)`
+#[derive(unsafe(Debug))]
+//~^ ERROR: expected identifier, found keyword `unsafe`
+//~| ERROR: traits in `#[derive(...)]` don't accept arguments
+//~| ERROR: expected identifier, found keyword `unsafe`
+//~| ERROR: expected identifier, found keyword `unsafe`
+//~| ERROR: cannot find derive macro `r#unsafe` in this scope
+//~| ERROR: cannot find derive macro `r#unsafe` in this scope
struct Foo;
+#[unsafe(derive(Debug))] //~ ERROR: is not an unsafe attribute
+struct Bar;
+
fn main() {}
diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
index fc0daf1..c40a551 100644
--- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
+++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
@@ -1,8 +1,65 @@
-error: traits in `#[derive(...)]` don't accept `unsafe(...)`
+error: expected identifier, found keyword `unsafe`
+ --> $DIR/derive-unsafe-attributes.rs:3:10
+ |
+LL | #[derive(unsafe(Debug))]
+ | ^^^^^^ expected identifier, found keyword
+ |
+help: escape `unsafe` to use it as an identifier
+ |
+LL | #[derive(r#unsafe(Debug))]
+ | ++
+
+error: traits in `#[derive(...)]` don't accept arguments
+ --> $DIR/derive-unsafe-attributes.rs:3:16
+ |
+LL | #[derive(unsafe(Debug))]
+ | ^^^^^^^ help: remove the arguments
+
+error: `derive` is not an unsafe attribute
+ --> $DIR/derive-unsafe-attributes.rs:12:3
+ |
+LL | #[unsafe(derive(Debug))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: expected identifier, found keyword `unsafe`
+ --> $DIR/derive-unsafe-attributes.rs:3:10
+ |
+LL | #[derive(unsafe(Debug))]
+ | ^^^^^^ expected identifier, found keyword
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: escape `unsafe` to use it as an identifier
+ |
+LL | #[derive(r#unsafe(Debug))]
+ | ++
+
+error: expected identifier, found keyword `unsafe`
+ --> $DIR/derive-unsafe-attributes.rs:3:10
+ |
+LL | #[derive(unsafe(Debug))]
+ | ^^^^^^ expected identifier, found keyword
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: escape `unsafe` to use it as an identifier
+ |
+LL | #[derive(r#unsafe(Debug))]
+ | ++
+
+error: cannot find derive macro `r#unsafe` in this scope
--> $DIR/derive-unsafe-attributes.rs:3:10
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^
-error: aborting due to 1 previous error
+error: cannot find derive macro `r#unsafe` in this scope
+ --> $DIR/derive-unsafe-attributes.rs:3:10
+ |
+LL | #[derive(unsafe(Debug))]
+ | ^^^^^^
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 7 previous errors
diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
index ea82bac..950b263 100644
--- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
+++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
@@ -13,7 +13,7 @@
--> $DIR/double-unsafe-attributes.rs:3:3
|
LL | #[unsafe(unsafe(no_mangle))]
- | ^^^^^^
+ | ^^^^^^ this is not an unsafe attribute
|
= note: extraneous unsafe is not allowed in attributes
diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs
new file mode 100644
index 0000000..0181add
--- /dev/null
+++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs
@@ -0,0 +1,31 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+#![feature(unsafe_attributes)]
+
+#[unsafe(cfg(any()))] //~ ERROR: is not an unsafe attribute
+fn a() {}
+
+#[unsafe(cfg_attr(any(), allow(dead_code)))] //~ ERROR: is not an unsafe attribute
+fn b() {}
+
+#[unsafe(test)] //~ ERROR: is not an unsafe attribute
+fn aa() {}
+
+#[unsafe(ignore = "test")] //~ ERROR: is not an unsafe attribute
+fn bb() {}
+
+#[unsafe(should_panic(expected = "test"))] //~ ERROR: is not an unsafe attribute
+fn cc() {}
+
+#[unsafe(macro_use)] //~ ERROR: is not an unsafe attribute
+mod inner {
+ #[unsafe(macro_export)] //~ ERROR: is not an unsafe attribute
+ macro_rules! m {
+ () => {};
+ }
+}
+
+#[unsafe(used)] //~ ERROR: is not an unsafe attribute
+static FOO: usize = 0;
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr
new file mode 100644
index 0000000..f39074b
--- /dev/null
+++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr
@@ -0,0 +1,66 @@
+error: `cfg` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:5:3
+ |
+LL | #[unsafe(cfg(any()))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `cfg_attr` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:8:3
+ |
+LL | #[unsafe(cfg_attr(any(), allow(dead_code)))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `test` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:11:3
+ |
+LL | #[unsafe(test)]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `ignore` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:14:3
+ |
+LL | #[unsafe(ignore = "test")]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `should_panic` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:17:3
+ |
+LL | #[unsafe(should_panic(expected = "test"))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `macro_use` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:20:3
+ |
+LL | #[unsafe(macro_use)]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `macro_export` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:22:7
+ |
+LL | #[unsafe(macro_export)]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `used` is not an unsafe attribute
+ --> $DIR/extraneous-unsafe-attributes.rs:28:3
+ |
+LL | #[unsafe(used)]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs
new file mode 100644
index 0000000..f29a5b3
--- /dev/null
+++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs
@@ -0,0 +1,37 @@
+#![feature(unsafe_attributes)]
+
+#[unsafe(proc_macro)]
+//~^ ERROR: is not an unsafe attribute
+//~| ERROR attribute is only usable with crates of the `proc-macro` crate type
+pub fn a() {}
+
+
+#[unsafe(proc_macro_derive(Foo))]
+//~^ ERROR: is not an unsafe attribute
+//~| ERROR attribute is only usable with crates of the `proc-macro` crate type
+pub fn b() {}
+
+#[proc_macro_derive(unsafe(Foo))]
+//~^ ERROR attribute is only usable with crates of the `proc-macro` crate type
+//~| ERROR: expected identifier, found keyword `unsafe`
+pub fn c() {}
+
+#[unsafe(proc_macro_attribute)]
+//~^ ERROR: is not an unsafe attribute
+//~| ERROR attribute is only usable with crates of the `proc-macro` crate type
+pub fn d() {}
+
+#[unsafe(allow(dead_code))]
+//~^ ERROR: is not an unsafe attribute
+pub fn e() {}
+
+#[unsafe(allow(unsafe(dead_code)))]
+//~^ ERROR: is not an unsafe attribute
+//~| ERROR: malformed lint attribute input
+//~| ERROR: malformed lint attribute input
+//~| ERROR: expected identifier, found keyword `unsafe`
+//~| ERROR: malformed lint attribute input
+//~| ERROR: malformed lint attribute input
+pub fn f() {}
+
+fn main() {}
diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr
new file mode 100644
index 0000000..79d34d4
--- /dev/null
+++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr
@@ -0,0 +1,119 @@
+error[E0452]: malformed lint attribute input
+ --> $DIR/proc-unsafe-attributes.rs:28:16
+ |
+LL | #[unsafe(allow(unsafe(dead_code)))]
+ | ^^^^^^^^^^^^^^^^^ bad attribute argument
+
+error[E0452]: malformed lint attribute input
+ --> $DIR/proc-unsafe-attributes.rs:28:16
+ |
+LL | #[unsafe(allow(unsafe(dead_code)))]
+ | ^^^^^^^^^^^^^^^^^ bad attribute argument
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: `proc_macro` is not an unsafe attribute
+ --> $DIR/proc-unsafe-attributes.rs:3:3
+ |
+LL | #[unsafe(proc_macro)]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `proc_macro_derive` is not an unsafe attribute
+ --> $DIR/proc-unsafe-attributes.rs:9:3
+ |
+LL | #[unsafe(proc_macro_derive(Foo))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: expected identifier, found keyword `unsafe`
+ --> $DIR/proc-unsafe-attributes.rs:14:21
+ |
+LL | #[proc_macro_derive(unsafe(Foo))]
+ | ^^^^^^ expected identifier, found keyword
+ |
+help: escape `unsafe` to use it as an identifier
+ |
+LL | #[proc_macro_derive(r#unsafe(Foo))]
+ | ++
+
+error: `proc_macro_attribute` is not an unsafe attribute
+ --> $DIR/proc-unsafe-attributes.rs:19:3
+ |
+LL | #[unsafe(proc_macro_attribute)]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `allow` is not an unsafe attribute
+ --> $DIR/proc-unsafe-attributes.rs:24:3
+ |
+LL | #[unsafe(allow(dead_code))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: `allow` is not an unsafe attribute
+ --> $DIR/proc-unsafe-attributes.rs:28:3
+ |
+LL | #[unsafe(allow(unsafe(dead_code)))]
+ | ^^^^^^ this is not an unsafe attribute
+ |
+ = note: extraneous unsafe is not allowed in attributes
+
+error: expected identifier, found keyword `unsafe`
+ --> $DIR/proc-unsafe-attributes.rs:28:16
+ |
+LL | #[unsafe(allow(unsafe(dead_code)))]
+ | ^^^^^^ expected identifier, found keyword
+ |
+help: escape `unsafe` to use it as an identifier
+ |
+LL | #[unsafe(allow(r#unsafe(dead_code)))]
+ | ++
+
+error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
+ --> $DIR/proc-unsafe-attributes.rs:3:1
+ |
+LL | #[unsafe(proc_macro)]
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+ --> $DIR/proc-unsafe-attributes.rs:9:1
+ |
+LL | #[unsafe(proc_macro_derive(Foo))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
+ --> $DIR/proc-unsafe-attributes.rs:14:1
+ |
+LL | #[proc_macro_derive(unsafe(Foo))]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type
+ --> $DIR/proc-unsafe-attributes.rs:19:1
+ |
+LL | #[unsafe(proc_macro_attribute)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0452]: malformed lint attribute input
+ --> $DIR/proc-unsafe-attributes.rs:28:16
+ |
+LL | #[unsafe(allow(unsafe(dead_code)))]
+ | ^^^^^^^^^^^^^^^^^ bad attribute argument
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0452]: malformed lint attribute input
+ --> $DIR/proc-unsafe-attributes.rs:28:16
+ |
+LL | #[unsafe(allow(unsafe(dead_code)))]
+ | ^^^^^^^^^^^^^^^^^ bad attribute argument
+ |
+ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0452`.
diff --git a/tests/ui/attributes/unsafe/unsafe-attributes.rs b/tests/ui/attributes/unsafe/unsafe-attributes.rs
index e7620a1..33a412a 100644
--- a/tests/ui/attributes/unsafe/unsafe-attributes.rs
+++ b/tests/ui/attributes/unsafe/unsafe-attributes.rs
@@ -4,4 +4,10 @@
#[unsafe(no_mangle)]
fn a() {}
+#[unsafe(export_name = "foo")]
+fn b() {}
+
+#[cfg_attr(any(), unsafe(no_mangle))]
+static VAR2: u32 = 1;
+
fn main() {}
diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
index 0602af3..584b0ea 100644
--- a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
+++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
@@ -2,7 +2,7 @@
--> $DIR/unsafe-safe-attribute.rs:3:3
|
LL | #[unsafe(repr(C))]
- | ^^^^^^
+ | ^^^^^^ this is not an unsafe attribute
|
= note: extraneous unsafe is not allowed in attributes
diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr
index 584dacf4..26b5e4e 100644
--- a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr
+++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr
@@ -2,7 +2,7 @@
--> $DIR/unsafe-safe-attribute_diagnostic.rs:3:3
|
LL | #[unsafe(diagnostic::on_unimplemented(
- | ^^^^^^
+ | ^^^^^^ this is not an unsafe attribute
|
= note: extraneous unsafe is not allowed in attributes
diff --git a/tests/ui/augmented-assignments.rs b/tests/ui/augmented-assignments.rs
index 8b263e0..440a4a7 100644
--- a/tests/ui/augmented-assignments.rs
+++ b/tests/ui/augmented-assignments.rs
@@ -17,7 +17,6 @@ fn main() {
x;
//~^ ERROR cannot move out of `x` because it is borrowed
//~| move out of `x` occurs here
- //~| HELP consider cloning
let y = Int(2);
//~^ HELP consider changing this to be mutable
diff --git a/tests/ui/augmented-assignments.stderr b/tests/ui/augmented-assignments.stderr
index 6b2900d..a4b75cb 100644
--- a/tests/ui/augmented-assignments.stderr
+++ b/tests/ui/augmented-assignments.stderr
@@ -8,14 +8,9 @@
...
LL | x;
| ^ move out of `x` occurs here
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | x.clone();
- | ++++++++
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
- --> $DIR/augmented-assignments.rs:25:5
+ --> $DIR/augmented-assignments.rs:24:5
|
LL | y
| ^ cannot borrow as mutable
diff --git a/tests/ui/backtrace/synchronized-panic-handler.rs b/tests/ui/backtrace/synchronized-panic-handler.rs
index 00eb249..29431ae 100644
--- a/tests/ui/backtrace/synchronized-panic-handler.rs
+++ b/tests/ui/backtrace/synchronized-panic-handler.rs
@@ -3,6 +3,7 @@
//@ edition:2021
//@ exec-env:RUST_BACKTRACE=0
//@ needs-threads
+//@ needs-unwind
use std::thread;
const PANIC_MESSAGE: &str = "oops oh no woe is me";
diff --git a/tests/ui/backtrace/synchronized-panic-handler.run.stderr b/tests/ui/backtrace/synchronized-panic-handler.run.stderr
index b7c815a..8a06d00 100644
--- a/tests/ui/backtrace/synchronized-panic-handler.run.stderr
+++ b/tests/ui/backtrace/synchronized-panic-handler.run.stderr
@@ -1,5 +1,5 @@
-thread '<unnamed>' panicked at $DIR/synchronized-panic-handler.rs:10:5:
+thread '<unnamed>' panicked at $DIR/synchronized-panic-handler.rs:11:5:
oops oh no woe is me
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-thread '<unnamed>' panicked at $DIR/synchronized-panic-handler.rs:10:5:
+thread '<unnamed>' panicked at $DIR/synchronized-panic-handler.rs:11:5:
oops oh no woe is me
diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr
index 83c2759..45c7f11 100644
--- a/tests/ui/binop/binop-move-semantics.stderr
+++ b/tests/ui/binop/binop-move-semantics.stderr
@@ -65,7 +65,7 @@
LL | fn move_borrowed<T: Add<Output=()>>(x: T, mut y: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
- | -- you could clone this value
+ | - you could clone this value
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/binop-move-semantics.rs:23:5
@@ -88,7 +88,7 @@
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
LL | let n = &mut y;
- | ------ you could clone this value
+ | - you could clone this value
error[E0507]: cannot move out of `*m` which is behind a mutable reference
--> $DIR/binop-move-semantics.rs:30:5
diff --git a/tests/ui/borrowck/borrow-tuple-fields.stderr b/tests/ui/borrowck/borrow-tuple-fields.stderr
index 8ea7a9a..277c335cf 100644
--- a/tests/ui/borrowck/borrow-tuple-fields.stderr
+++ b/tests/ui/borrowck/borrow-tuple-fields.stderr
@@ -13,9 +13,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let r = &x.0;
-LL + let r = x.0.clone();
- |
+LL | let r = &x.0.clone();
+ | ++++++++
error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
--> $DIR/borrow-tuple-fields.rs:18:13
@@ -51,9 +50,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let r = &x.0;
-LL + let r = x.0.clone();
- |
+LL | let r = &x.0.clone();
+ | ++++++++
error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
--> $DIR/borrow-tuple-fields.rs:33:13
diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
index b96949f..5e7eee0 100644
--- a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
+++ b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
@@ -14,7 +14,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - &*a,
-LL + a.clone(),
+LL + &a.clone(),
|
error[E0505]: cannot move out of `a` because it is borrowed
@@ -32,7 +32,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - &*a,
-LL + a.clone(),
+LL + &a.clone(),
|
error: aborting due to 2 previous errors
diff --git a/tests/ui/borrowck/borrowck-field-sensitivity.stderr b/tests/ui/borrowck/borrowck-field-sensitivity.stderr
index ea552ff..b30dd14 100644
--- a/tests/ui/borrowck/borrowck-field-sensitivity.stderr
+++ b/tests/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -52,9 +52,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let p = &x.b;
-LL + let p = x.b.clone();
- |
+LL | let p = &x.b.clone();
+ | ++++++++
error[E0505]: cannot move out of `x.b` because it is borrowed
--> $DIR/borrowck-field-sensitivity.rs:41:14
@@ -70,9 +69,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let p = &x.b;
-LL + let p = x.b.clone();
- |
+LL | let p = &x.b.clone();
+ | ++++++++
error[E0499]: cannot borrow `x.a` as mutable more than once at a time
--> $DIR/borrowck-field-sensitivity.rs:48:13
diff --git a/tests/ui/borrowck/borrowck-issue-48962.stderr b/tests/ui/borrowck/borrowck-issue-48962.stderr
index 6e821a4..ee174f6 100644
--- a/tests/ui/borrowck/borrowck-issue-48962.stderr
+++ b/tests/ui/borrowck/borrowck-issue-48962.stderr
@@ -17,11 +17,6 @@
| --- value moved here
LL | src.0 = 66;
| ^^^^^^^^^^ value used here after move
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | {src.clone()};
- | ++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
index 370ae05..d9af5cf 100644
--- a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
+++ b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
@@ -16,9 +16,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let w = &v;
-LL + let w = v.clone();
- |
+LL | let w = &v.clone();
+ | ++++++++
error[E0505]: cannot move out of `v` because it is borrowed
--> $DIR/borrowck-loan-blocks-move-cc.rs:24:19
@@ -38,9 +37,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let w = &v;
-LL + let w = v.clone();
- |
+LL | let w = &v.clone();
+ | ++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
index 8a8005d..1698035 100644
--- a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
+++ b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
@@ -12,9 +12,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let w = &v;
-LL + let w = v.clone();
- |
+LL | let w = &v.clone();
+ | ++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
index a23a203..b78c374 100644
--- a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
+++ b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
@@ -13,9 +13,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let b = &a;
-LL + let b = a.clone();
- |
+LL | let b = &a.clone();
+ | ++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
index acf4269..4b9351b 100644
--- a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
+++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
@@ -14,7 +14,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - let p: &isize = &*t0; // Freezes `*t0`
-LL + let p: &isize = t0.clone(); // Freezes `*t0`
+LL + let p: &isize = &t0.clone(); // Freezes `*t0`
|
error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
index cc6c3bd..b5dc01f 100644
--- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr
+++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
@@ -17,7 +17,7 @@
| ^^^^^^^^ consider implementing `Clone` for this type
...
LL | let pb = &a;
- | -- you could clone this value
+ | - you could clone this value
error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/borrowck-multiple-captures.stderr b/tests/ui/borrowck/borrowck-multiple-captures.stderr
index fdac4c2..01b648e 100644
--- a/tests/ui/borrowck/borrowck-multiple-captures.stderr
+++ b/tests/ui/borrowck/borrowck-multiple-captures.stderr
@@ -17,9 +17,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let p1 = &x1;
-LL + let p1 = x1.clone();
- |
+LL | let p1 = &x1.clone();
+ | ++++++++
error[E0505]: cannot move out of `x2` because it is borrowed
--> $DIR/borrowck-multiple-captures.rs:12:19
@@ -39,9 +38,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let p2 = &x2;
-LL + let p2 = x2.clone();
- |
+LL | let p2 = &x2.clone();
+ | ++++++++
error[E0382]: use of moved value: `x1`
--> $DIR/borrowck-multiple-captures.rs:27:19
@@ -108,9 +106,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let p = &x;
-LL + let p = x.clone();
- |
+LL | let p = &x.clone();
+ | ++++++++
error[E0382]: use of moved value: `x`
--> $DIR/borrowck-multiple-captures.rs:52:14
diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
index 7f8cc74a..3366853 100644
--- a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
@@ -11,6 +11,11 @@
...
LL | use_mut(rs);
| -- borrow later used here
+ |
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL | let rs = &mut s.clone();
+ | ++++++++
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/borrowck-overloaded-index-move-index.rs:53:7
@@ -25,6 +30,11 @@
...
LL | use_mut(rs);
| -- borrow later used here
+ |
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL | let rs = &mut s.clone();
+ | ++++++++
error[E0382]: use of moved value: `s`
--> $DIR/borrowck-overloaded-index-move-index.rs:53:7
diff --git a/tests/ui/borrowck/borrowck-unary-move.stderr b/tests/ui/borrowck/borrowck-unary-move.stderr
index 598ecb5..0aec6d4 100644
--- a/tests/ui/borrowck/borrowck-unary-move.stderr
+++ b/tests/ui/borrowck/borrowck-unary-move.stderr
@@ -13,7 +13,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - let y = &*x;
-LL + let y = x.clone();
+LL + let y = &x.clone();
|
error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr
index 19f0405..d5d2129 100644
--- a/tests/ui/borrowck/clone-on-ref.stderr
+++ b/tests/ui/borrowck/clone-on-ref.stderr
@@ -38,7 +38,7 @@
LL | fn bar<T: std::fmt::Display>(x: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let a = &x;
- | -- you could clone this value
+ | - you could clone this value
help: consider further restricting this bound
|
LL | fn bar<T: std::fmt::Display + Clone>(x: T) {
@@ -66,7 +66,7 @@
| ^^^^^^^^ consider implementing `Clone` for this type
LL | fn qux(x: A) {
LL | let a = &x;
- | -- you could clone this value
+ | - you could clone this value
help: consider annotating `A` with `#[derive(Clone)]`
|
LL + #[derive(Clone)]
diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr
index a894fa6..7fec81b 100644
--- a/tests/ui/borrowck/issue-101119.stderr
+++ b/tests/ui/borrowck/issue-101119.stderr
@@ -18,14 +18,6 @@
| ------------ ^^^^^^^^^^ this parameter takes ownership of the value
| |
| in this function
-note: if `State` implemented `Clone`, you could clone the value
- --> $DIR/issue-101119.rs:1:1
- |
-LL | struct State;
- | ^^^^^^^^^^^^ consider implementing `Clone` for this type
-...
-LL | fill_segment(state);
- | ----- you could clone this value
error: aborting due to 1 previous error
diff --git a/tests/ui/btreemap/btreemap_dropck.stderr b/tests/ui/btreemap/btreemap_dropck.stderr
index 873f8cf..e8f1455 100644
--- a/tests/ui/btreemap/btreemap_dropck.stderr
+++ b/tests/ui/btreemap/btreemap_dropck.stderr
@@ -12,9 +12,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]);
-LL + let _map = BTreeMap::from_iter([((), PrintOnDrop(s.clone()))]);
- |
+LL | let _map = BTreeMap::from_iter([((), PrintOnDrop(&s.clone()))]);
+ | ++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/cast/dyn-tails-need-normalization.rs b/tests/ui/cast/dyn-tails-need-normalization.rs
new file mode 100644
index 0000000..719e0e8
--- /dev/null
+++ b/tests/ui/cast/dyn-tails-need-normalization.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+
+trait Trait {
+ type Associated;
+}
+
+impl Trait for i32 {
+ type Associated = i64;
+}
+
+trait Generic<T> {}
+
+type TraitObject = dyn Generic<<i32 as Trait>::Associated>;
+
+struct Wrap(TraitObject);
+
+fn cast(x: *mut TraitObject) {
+ x as *mut Wrap;
+}
+
+fn main() {}
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr
similarity index 90%
rename from tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
rename to tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr
index d1d598e..5a5b4bf 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr
@@ -1,5 +1,5 @@
error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:21:17
+ --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17
|
LL | fn m<'a>() {
| -- lifetime `'a` defined here
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr
similarity index 90%
copy from tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
copy to tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr
index d1d598e..5a5b4bf 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr
@@ -1,5 +1,5 @@
error: lifetime may not live long enough
- --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:21:17
+ --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17
|
LL | fn m<'a>() {
| -- lifetime `'a` defined here
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
index cdd55e2..f968dca 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
@@ -1,3 +1,6 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
//@ check-fail
//
// Make sure we can't trick the compiler by using a projection.
diff --git a/tests/ui/cfg/disallowed-cli-cfgs-allow.rs b/tests/ui/cfg/disallowed-cli-cfgs-allow.rs
new file mode 100644
index 0000000..0a9b074
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs-allow.rs
@@ -0,0 +1,4 @@
+//@ check-pass
+//@ compile-flags: --cfg unix -Aexplicit_builtin_cfgs_in_flags
+
+fn main() {}
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.debug_assertions_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.debug_assertions_.stderr
new file mode 100644
index 0000000..ec3e15b
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.debug_assertions_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg debug_assertions` flag
+ |
+ = note: config `debug_assertions` is only supposed to be controlled by `-C debug-assertions`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.overflow_checks_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.overflow_checks_.stderr
new file mode 100644
index 0000000..ba8ed3f
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.overflow_checks_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg overflow_checks` flag
+ |
+ = note: config `overflow_checks` is only supposed to be controlled by `-C overflow-checks`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.panic_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.panic_.stderr
new file mode 100644
index 0000000..5b37569
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.panic_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg panic="abort"` flag
+ |
+ = note: config `panic` is only supposed to be controlled by `-C panic`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.proc_macro_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.proc_macro_.stderr
new file mode 100644
index 0000000..c2e2990
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.proc_macro_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg proc_macro` flag
+ |
+ = note: config `proc_macro` is only supposed to be controlled by `--crate-type proc-macro`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.relocation_model_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.relocation_model_.stderr
new file mode 100644
index 0000000..65ada55
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.relocation_model_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg relocation_model="a"` flag
+ |
+ = note: config `relocation_model` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs
new file mode 100644
index 0000000..714c01f
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.rs
@@ -0,0 +1,35 @@
+//@ check-fail
+//@ revisions: overflow_checks_ debug_assertions_ ub_checks_ sanitize_
+//@ revisions: sanitizer_cfi_generalize_pointers_ sanitizer_cfi_normalize_integers_
+//@ revisions: proc_macro_ panic_ target_feature_ unix_ windows_ target_abi_
+//@ revisions: target_arch_ target_endian_ target_env_ target_family_ target_os_
+//@ revisions: target_pointer_width_ target_vendor_ target_has_atomic_
+//@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_
+//@ revisions: target_thread_local_ relocation_model_
+
+//@ [overflow_checks_]compile-flags: --cfg overflow_checks
+//@ [debug_assertions_]compile-flags: --cfg debug_assertions
+//@ [ub_checks_]compile-flags: --cfg ub_checks
+//@ [sanitize_]compile-flags: --cfg sanitize="cfi"
+//@ [sanitizer_cfi_generalize_pointers_]compile-flags: --cfg sanitizer_cfi_generalize_pointers
+//@ [sanitizer_cfi_normalize_integers_]compile-flags: --cfg sanitizer_cfi_normalize_integers
+//@ [proc_macro_]compile-flags: --cfg proc_macro
+//@ [panic_]compile-flags: --cfg panic="abort"
+//@ [target_feature_]compile-flags: --cfg target_feature="sse3"
+//@ [unix_]compile-flags: --cfg unix
+//@ [windows_]compile-flags: --cfg windows
+//@ [target_abi_]compile-flags: --cfg target_abi="gnu"
+//@ [target_arch_]compile-flags: --cfg target_arch="arm"
+//@ [target_endian_]compile-flags: --cfg target_endian="little"
+//@ [target_env_]compile-flags: --cfg target_env
+//@ [target_family_]compile-flags: --cfg target_family="unix"
+//@ [target_os_]compile-flags: --cfg target_os="linux"
+//@ [target_pointer_width_]compile-flags: --cfg target_pointer_width="32"
+//@ [target_vendor_]compile-flags: --cfg target_vendor
+//@ [target_has_atomic_]compile-flags: --cfg target_has_atomic="32"
+//@ [target_has_atomic_equal_alignment_]compile-flags: --cfg target_has_atomic_equal_alignment="32"
+//@ [target_has_atomic_load_store_]compile-flags: --cfg target_has_atomic_load_store="32"
+//@ [target_thread_local_]compile-flags: --cfg target_thread_local
+//@ [relocation_model_]compile-flags: --cfg relocation_model="a"
+
+fn main() {}
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.sanitize_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.sanitize_.stderr
new file mode 100644
index 0000000..b1f3b19
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.sanitize_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg sanitize="cfi"` flag
+ |
+ = note: config `sanitize` is only supposed to be controlled by `-Z sanitizer`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.sanitizer_cfi_generalize_pointers_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.sanitizer_cfi_generalize_pointers_.stderr
new file mode 100644
index 0000000..49106f9
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.sanitizer_cfi_generalize_pointers_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg sanitizer_cfi_generalize_pointers` flag
+ |
+ = note: config `sanitizer_cfi_generalize_pointers` is only supposed to be controlled by `-Z sanitizer=cfi`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.sanitizer_cfi_normalize_integers_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.sanitizer_cfi_normalize_integers_.stderr
new file mode 100644
index 0000000..f9bb9e7
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.sanitizer_cfi_normalize_integers_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg sanitizer_cfi_normalize_integers` flag
+ |
+ = note: config `sanitizer_cfi_normalize_integers` is only supposed to be controlled by `-Z sanitizer=cfi`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_abi_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_abi_.stderr
new file mode 100644
index 0000000..f5c0911
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_abi_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_abi="gnu"` flag
+ |
+ = note: config `target_abi` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_arch_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_arch_.stderr
new file mode 100644
index 0000000..7f616e7
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_arch_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_arch="arm"` flag
+ |
+ = note: config `target_arch` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_endian_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_endian_.stderr
new file mode 100644
index 0000000..755f370
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_endian_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_endian="little"` flag
+ |
+ = note: config `target_endian` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_env_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_env_.stderr
new file mode 100644
index 0000000..ccd027d
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_env_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_env` flag
+ |
+ = note: config `target_env` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_family_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_family_.stderr
new file mode 100644
index 0000000..e376e4e
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_family_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_family="unix"` flag
+ |
+ = note: config `target_family` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_feature_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_feature_.stderr
new file mode 100644
index 0000000..457cca6
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_feature_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_feature="sse3"` flag
+ |
+ = note: config `target_feature` is only supposed to be controlled by `-C target-feature`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_.stderr
new file mode 100644
index 0000000..1607411
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_atomic="32"` flag
+ |
+ = note: config `target_has_atomic` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_equal_alignment_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_equal_alignment_.stderr
new file mode 100644
index 0000000..096490a
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_equal_alignment_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_atomic_equal_alignment="32"` flag
+ |
+ = note: config `target_has_atomic_equal_alignment` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_load_store_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_load_store_.stderr
new file mode 100644
index 0000000..5253987
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_has_atomic_load_store_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_has_atomic_load_store="32"` flag
+ |
+ = note: config `target_has_atomic_load_store` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_os_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_os_.stderr
new file mode 100644
index 0000000..ba2c967
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_os_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_os="linux"` flag
+ |
+ = note: config `target_os` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_pointer_width_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_pointer_width_.stderr
new file mode 100644
index 0000000..983313b
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_pointer_width_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_pointer_width="32"` flag
+ |
+ = note: config `target_pointer_width` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_thread_local_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_thread_local_.stderr
new file mode 100644
index 0000000..4f66ea1
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_thread_local_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_thread_local` flag
+ |
+ = note: config `target_thread_local` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_vendor_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_vendor_.stderr
new file mode 100644
index 0000000..e8f3259
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.target_vendor_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg target_vendor` flag
+ |
+ = note: config `target_vendor` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.test_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.test_.stderr
new file mode 100644
index 0000000..96b5beb
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.test_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg test` flag
+ |
+ = note: config `test` is only supposed to be controlled by `--test`
+ = note: see <https://github.com/rust-lang/rust/issues/xxxxx> for more information
+ = note: `#[deny(unexpected_builtin_cfgs)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.ub_checks_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.ub_checks_.stderr
new file mode 100644
index 0000000..e61e5ac
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.ub_checks_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg ub_checks` flag
+ |
+ = note: config `ub_checks` is only supposed to be controlled by `-Z ub-checks`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.unix_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.unix_.stderr
new file mode 100644
index 0000000..f3c6bb0
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.unix_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg unix` flag
+ |
+ = note: config `unix` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cfg/disallowed-cli-cfgs.windows_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.windows_.stderr
new file mode 100644
index 0000000..171a3f9
--- /dev/null
+++ b/tests/ui/cfg/disallowed-cli-cfgs.windows_.stderr
@@ -0,0 +1,8 @@
+error: unexpected `--cfg windows` flag
+ |
+ = note: config `windows` is only supposed to be controlled by `--target`
+ = note: manually setting a built-in cfg can and does create incoherent behaviors
+ = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 57cbe17..520cffc 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -251,7 +251,7 @@
LL | cfg!(target_feature = "zebra");
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 199 more
+ = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: 27 warnings emitted
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 00abb5f..d780e04 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -165,7 +165,7 @@
LL | target_feature = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
+ = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs
index 52ed008..74f37b5 100644
--- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs
+++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs
@@ -1,10 +1,9 @@
// Test precise capture of a multi-variant enum (when remaining variants are
// visibly uninhabited).
-//@ revisions: min_exhaustive_patterns exhaustive_patterns
+//@ revisions: normal exhaustive_patterns
//@ edition:2021
//@ run-pass
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
-#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
#![feature(never_type)]
pub fn main() {
diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.svg b/tests/ui/codemap_tests/huge_multispan_highlight.svg
index 7b6dbb1..1205817 100644
--- a/tests/ui/codemap_tests/huge_multispan_highlight.svg
+++ b/tests/ui/codemap_tests/huge_multispan_highlight.svg
@@ -1,4 +1,4 @@
-<svg width="740px" height="848px" xmlns="http://www.w3.org/2000/svg">
+<svg width="818px" height="848px" xmlns="http://www.w3.org/2000/svg">
<style>
.fg { fill: #AAAAAA }
.bg { background: #000000 }
diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr
index 6c56a91..634a10b 100644
--- a/tests/ui/coherence/normalize-for-errors.next.stderr
+++ b/tests/ui/coherence/normalize-for-errors.next.stderr
@@ -7,6 +7,7 @@
LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)`
|
+ = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs
index 2288118..4188389 100644
--- a/tests/ui/coherence/normalize-for-errors.rs
+++ b/tests/ui/coherence/normalize-for-errors.rs
@@ -18,5 +18,6 @@ impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
//~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>,
//~| NOTE conflicting implementation for `(Box<(MyType,)>,
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
+//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
fn main() {}
diff --git a/tests/ui/coherence/re-rebalance-coherence.rs b/tests/ui/coherence/re-rebalance-coherence.rs
index 5383a63..9c176d5 100644
--- a/tests/ui/coherence/re-rebalance-coherence.rs
+++ b/tests/ui/coherence/re-rebalance-coherence.rs
@@ -4,7 +4,6 @@
extern crate re_rebalance_coherence_lib as lib;
use lib::*;
-#[allow(dead_code)]
struct Oracle;
impl Backend for Oracle {}
impl<'a, T:'a, Tab> QueryFragment<Oracle> for BatchInsert<'a, T, Tab> {}
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr
new file mode 100644
index 0000000..fb01cf1
--- /dev/null
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
+ --> $DIR/super-trait-knowable-1.rs:16:1
+ |
+LL | impl<T, U: Sub<T>> Overlap<T> for U {}
+ | ----------------------------------- first implementation here
+LL | impl<T> Overlap<T> for () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+ |
+ = note: downstream crates may implement trait `Sub<_>` for type `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
new file mode 100644
index 0000000..80df8c1
--- /dev/null
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs
@@ -0,0 +1,19 @@
+// Added in #124532. While `(): Super` is knowable, `(): Sub<?t>` is not.
+//
+// We therefore elaborate super trait bounds in the implicit negative
+// overlap check.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+trait Super {}
+trait Sub<T>: Super {}
+
+trait Overlap<T> {}
+impl<T, U: Sub<T>> Overlap<T> for U {}
+impl<T> Overlap<T> for () {}
+//[current]~^ ERROR conflicting implementations
+
+fn main() {}
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
new file mode 100644
index 0000000..d1f2e8d
--- /dev/null
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs
@@ -0,0 +1,33 @@
+// A regression test for pyella-0.1.5 which broke when
+// enabling the new solver in coherence.
+//
+// `Tensor: TensorValue` is knowable while `Tensor: TensorOp<?t2>`
+// may be implemented downstream. We previously didn't check the
+// super trait bound in coherence, causing these impls to overlap.
+//
+// However, we did fail to normalize `<Tensor as TensorValue::Unmasked`
+// which caused the old solver to emit a `Tensor: TensorValue` goal in
+// `fn normalize_to_error` which then failed, causing this test to pass.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+
+pub trait TensorValue {
+ type Unmasked;
+}
+
+trait TensorCompare<T> {}
+pub trait TensorOp<T>: TensorValue {}
+
+pub struct Tensor;
+impl<T2> TensorCompare<T2> for Tensor {}
+impl<T1, T2> TensorCompare<T2> for T1
+where
+ T1: TensorOp<T2>,
+ T1::Unmasked: Sized,
+{}
+
+
+fn main() {}
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr
new file mode 100644
index 0000000..542edb8
--- /dev/null
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr
@@ -0,0 +1,13 @@
+error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()`
+ --> $DIR/super-trait-knowable-3.rs:19:1
+ |
+LL | impl<T, U: Bound<W<T>>> Overlap<T> for U {}
+ | ---------------------------------------- first implementation here
+LL | impl<T> Overlap<T> for () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+ |
+ = note: downstream crates may implement trait `Sub<_>` for type `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
new file mode 100644
index 0000000..295d7ac
--- /dev/null
+++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs
@@ -0,0 +1,22 @@
+// Unlike in `super-trait-knowable-1.rs`, the knowable
+// super trait bound is in a nested goal so this would not
+// compile if we were to only elaborate root goals.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+trait Super {}
+trait Sub<T>: Super {}
+
+struct W<T>(T);
+trait Bound<T> {}
+impl<T: Sub<U>, U> Bound<W<U>> for T {}
+
+trait Overlap<T> {}
+impl<T, U: Bound<W<T>>> Overlap<T> for U {}
+impl<T> Overlap<T> for () {}
+//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()`
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs
new file mode 100644
index 0000000..311f507
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs
@@ -0,0 +1,28 @@
+// This ensures we don't ICE in situations like rust-lang/rust#126272.
+
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+use std::marker::ConstParamTy;
+
+#[derive(Debug, PartialEq, Eq, ConstParamTy)]
+//~^ ERROR the trait `ConstParamTy_`
+//~| ERROR the trait `ConstParamTy_`
+struct Foo {
+ nested: &'static Bar<dyn std::fmt::Debug>,
+ //~^ ERROR the size for values
+ //~| ERROR the size for values
+ //~| ERROR binary operation `==` cannot
+ //~| ERROR the trait bound `dyn Debug: Eq`
+ //~| ERROR the size for values
+}
+
+#[derive(Debug, PartialEq, Eq, ConstParamTy)]
+struct Bar<T>(T);
+
+struct Test<const F: Foo>;
+
+fn main() {
+ let x: Test<{ Foo { nested: &Bar(4) } }> = Test;
+ //~^ ERROR the size for values
+}
diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
new file mode 100644
index 0000000..1c30aa6
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr
@@ -0,0 +1,160 @@
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+ |
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | ^^^^^^^^^^^^
+...
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ----------------------------------------- this field does not implement `ConstParamTy_`
+ |
+ = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | ^^^^^^^^^^^^
+...
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ----------------------------------------- this field does not implement `ConstParamTy_`
+ |
+note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Eq`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+ |
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): Sized`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+ |
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` requires that `(dyn Debug + 'static): UnsizedConstParamTy`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:13
+ |
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | ----- in this derive macro expansion
+...
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`, which is required by `&&'static Bar<(dyn Debug + 'static)>: Debug`
+ = help: the trait `Debug` is implemented for `Bar<T>`
+note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:20:10
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | ^^^^^
+LL | struct Bar<T>(T);
+ | - unsatisfied trait bound introduced in this `derive` macro
+ = note: 2 redundant requirements hidden
+ = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug`
+ = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug`
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0369]: binary operation `==` cannot be applied to type `&Bar<dyn Debug>`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | --------- in this derive macro expansion
+...
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the trait bound `dyn Debug: Eq` is not satisfied
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | -- in this derive macro expansion
+...
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `dyn Debug`, which is required by `&'static Bar<dyn Debug>: Eq`
+ |
+ = help: the trait `Eq` is implemented for `Bar<T>`
+note: required for `Bar<dyn Debug>` to implement `Eq`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:20:28
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | ^^ unsatisfied trait bound introduced in this `derive` macro
+ = note: 1 redundant requirement hidden
+ = note: required for `&'static Bar<dyn Debug>` to implement `Eq`
+note: required by a bound in `AssertParamIsEq`
+ --> $SRC_DIR/core/src/cmp.rs:LL:COL
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5
+ |
+LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)]
+ | -- in this derive macro expansion
+...
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `dyn Debug`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+ = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:26:33
+ |
+LL | let x: Test<{ Foo { nested: &Bar(4) } }> = Test;
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/unsizing-wfcheck-issue-126272.rs:21:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0204, E0277, E0369.
+For more information about an error, try `rustc --explain E0204`.
diff --git a/tests/ui/const-generics/cross_crate_complex.rs b/tests/ui/const-generics/cross_crate_complex.rs
index b44d889..d13b69a 100644
--- a/tests/ui/const-generics/cross_crate_complex.rs
+++ b/tests/ui/const-generics/cross_crate_complex.rs
@@ -11,7 +11,6 @@ async fn foo() {
async_in_foo(async_out_foo::<4>().await).await;
}
-#[allow(dead_code)]
struct Faz<const N: usize>;
impl<const N: usize> Foo<N> for Faz<N> {}
diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs
index 5c93232..9eb33ac 100644
--- a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs
+++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.rs
@@ -3,7 +3,7 @@ fn foo<U>() {}
}
impl Trait for () {
fn foo<const M: u64>() {}
- //~^ error: method `foo` has an incompatible generic parameter for trait
+ //~^ error: associated function `foo` has an incompatible generic parameter for trait
}
trait Other {
@@ -11,7 +11,7 @@ fn bar<const M: u8>() {}
}
impl Other for () {
fn bar<T>() {}
- //~^ error: method `bar` has an incompatible generic parameter for trait
+ //~^ error: associated function `bar` has an incompatible generic parameter for trait
}
trait Uwu {
@@ -19,7 +19,7 @@ fn baz<const N: u32>() {}
}
impl Uwu for () {
fn baz<const N: i32>() {}
- //~^ error: method `baz` has an incompatible generic parameter for trait
+ //~^ error: associated function `baz` has an incompatible generic parameter for trait
}
trait Aaaaaa {
@@ -27,7 +27,7 @@ fn bbbb<const N: u32, T>() {}
}
impl Aaaaaa for () {
fn bbbb<T, const N: u32>() {}
- //~^ error: method `bbbb` has an incompatible generic parameter for trait
+ //~^ error: associated function `bbbb` has an incompatible generic parameter for trait
}
trait Names {
@@ -35,7 +35,7 @@ fn abcd<T, const N: u32>() {}
}
impl Names for () {
fn abcd<const N: u32, T>() {}
- //~^ error: method `abcd` has an incompatible generic parameter for trait
+ //~^ error: associated function `abcd` has an incompatible generic parameter for trait
}
fn main() {}
diff --git a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr
index 3455f2c..7ec162e 100644
--- a/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr
+++ b/tests/ui/const-generics/defaults/mismatched_ty_const_in_trait_impl.stderr
@@ -1,4 +1,4 @@
-error[E0053]: method `foo` has an incompatible generic parameter for trait `Trait`
+error[E0053]: associated function `foo` has an incompatible generic parameter for trait `Trait`
--> $DIR/mismatched_ty_const_in_trait_impl.rs:5:12
|
LL | trait Trait {
@@ -11,7 +11,7 @@
LL | fn foo<const M: u64>() {}
| ^^^^^^^^^^^^ found const parameter of type `u64`
-error[E0053]: method `bar` has an incompatible generic parameter for trait `Other`
+error[E0053]: associated function `bar` has an incompatible generic parameter for trait `Other`
--> $DIR/mismatched_ty_const_in_trait_impl.rs:13:12
|
LL | trait Other {
@@ -24,7 +24,7 @@
LL | fn bar<T>() {}
| ^ found type parameter
-error[E0053]: method `baz` has an incompatible generic parameter for trait `Uwu`
+error[E0053]: associated function `baz` has an incompatible generic parameter for trait `Uwu`
--> $DIR/mismatched_ty_const_in_trait_impl.rs:21:12
|
LL | trait Uwu {
@@ -37,7 +37,7 @@
LL | fn baz<const N: i32>() {}
| ^^^^^^^^^^^^ found const parameter of type `i32`
-error[E0053]: method `bbbb` has an incompatible generic parameter for trait `Aaaaaa`
+error[E0053]: associated function `bbbb` has an incompatible generic parameter for trait `Aaaaaa`
--> $DIR/mismatched_ty_const_in_trait_impl.rs:29:13
|
LL | trait Aaaaaa {
@@ -50,7 +50,7 @@
LL | fn bbbb<T, const N: u32>() {}
| ^ found type parameter
-error[E0053]: method `abcd` has an incompatible generic parameter for trait `Names`
+error[E0053]: associated function `abcd` has an incompatible generic parameter for trait `Names`
--> $DIR/mismatched_ty_const_in_trait_impl.rs:37:13
|
LL | trait Names {
diff --git a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs
index 4bf2fa7..c231875 100644
--- a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs
+++ b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs
@@ -2,7 +2,6 @@
//@ run-pass
-#[allow(dead_code)]
#[repr(C)]
pub struct Loaf<T: Sized, const N: usize = 1> {
head: [T; N],
diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs
index 50a6102..5d2198f 100644
--- a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs
+++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs
@@ -16,8 +16,7 @@ impl BlockCipher for BarCipher {
const BLOCK_SIZE: usize = 32;
}
-#[allow(dead_code)]
-pub struct Block<C>(C);
+pub struct Block<C>(#[allow(dead_code)] C);
pub fn test<C: BlockCipher, const M: usize>()
where
diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs
index 4ba696f..9f20cf0 100644
--- a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs
+++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs
@@ -9,9 +9,10 @@ fn bug<const N: Nat>(&self)
where
for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
//~^ ERROR only lifetime parameters can be used in this context
- //~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
- //~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
- //~^^^^ ERROR failed to resolve: use of undeclared type `COT`
+ //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+ //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+ //~| ERROR failed to resolve: use of undeclared type `COT`
+ //~| ERROR the name `N` is already used for a generic parameter in this item's generic parameters
{
}
diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr
index ee0ec38..6037e68 100644
--- a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr
@@ -6,6 +6,15 @@
|
= note: associated functions are those in `impl` or `trait` definitions
+error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:15
+ |
+LL | fn bug<const N: Nat>(&self)
+ | - first use of `N`
+...
+LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
+ | ^ already used
+
error[E0412]: cannot find type `Nat` in this scope
--> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:17
|
@@ -40,7 +49,7 @@
LL | for<const N: usize = 3, T = u32> [(); COT::BYTES]:,
| ^^^ use of undeclared type `COT`
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
-Some errors have detailed explanations: E0412, E0433, E0658.
-For more information about an error, try `rustc --explain E0412`.
+Some errors have detailed explanations: E0403, E0412, E0433, E0658.
+For more information about an error, try `rustc --explain E0403`.
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr
index 09b618f..1c97ead 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr
@@ -4,10 +4,6 @@
LL | Combination::<0>.and::<_>().and::<_>();
| ^^^ cannot infer type of the type parameter `M` declared on the method `and`
|
-help: consider specifying the generic argument
- |
-LL | Combination::<0>.and::<_>().and::<_>();
- | ~~~~~
error: aborting due to 1 previous error
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
index 8d59235..0152959 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
@@ -1,4 +1,4 @@
-error: internal compiler error: compiler/rustc_const_eval/src/interpret/step.rs:LL:CC: SizeOf MIR operator called for unsized type dyn Debug
+error: internal compiler error: compiler/rustc_const_eval/src/interpret/operator.rs:LL:CC: unsized type for `NullaryOp::SizeOf`
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
Box<dyn Any>
diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs
index 77cce66..5323046 100644
--- a/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs
+++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.rs
@@ -17,6 +17,7 @@ pub fn new() -> Self {
a: [0.; N],
b: [0.; complex_maths(N)],
//~^ ERROR: unconstrained generic constant
+ //~| ERROR: unconstrained generic constant
}
}
}
diff --git a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr
index a2680ea..88fc68a 100644
--- a/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/no_where_clause.stderr
@@ -10,6 +10,17 @@
| +++++++++++++++++++++++++++++
error: unconstrained generic constant
+ --> $DIR/no_where_clause.rs:18:10
+ |
+LL | b: [0.; complex_maths(N)],
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: try adding a `where` bound
+ |
+LL | pub fn new() -> Self where [(); complex_maths(N)]: {
+ | +++++++++++++++++++++++++++++
+
+error: unconstrained generic constant
--> $DIR/no_where_clause.rs:18:15
|
LL | b: [0.; complex_maths(N)],
@@ -20,5 +31,5 @@
LL | pub fn new() -> Self where [(); complex_maths(N)]: {
| +++++++++++++++++++++++++++++
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs
index ab68c6b..8d064f3 100644
--- a/tests/ui/const-generics/issues/issue-86535-2.rs
+++ b/tests/ui/const-generics/issues/issue-86535-2.rs
@@ -9,7 +9,6 @@ fn foo()
[(); Self::ASSOC_C]:;
}
-#[allow(dead_code)]
struct Bar<const N: &'static ()>;
impl<const N: &'static ()> Foo for Bar<N> {
const ASSOC_C: usize = 3;
diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs
index 9aaf7dd..62454f4 100644
--- a/tests/ui/const-generics/issues/issue-86535.rs
+++ b/tests/ui/const-generics/issues/issue-86535.rs
@@ -2,7 +2,6 @@
#![feature(adt_const_params, unsized_const_params, generic_const_exprs)]
#![allow(incomplete_features, unused_variables)]
-#[allow(dead_code)]
struct F<const S: &'static str>;
impl<const S: &'static str> X for F<{ S }> {
const W: usize = 3;
diff --git a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs
index 35c41ae..419d605 100644
--- a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs
+++ b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs
@@ -6,7 +6,6 @@
use std::mem::MaybeUninit;
-#[allow(dead_code)]
#[repr(transparent)]
pub struct MaybeUninitWrapper<const N: usize>(MaybeUninit<[u64; N]>);
diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr
index eb41a25..fad078a 100644
--- a/tests/ui/const-ptr/forbidden_slices.stderr
+++ b/tests/ui/const-ptr/forbidden_slices.stderr
@@ -118,7 +118,7 @@
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: ALLOC10 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+ = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC10 which is only 4 bytes from the end of the allocation
|
note: inside `std::ptr::const_ptr::<impl *const u32>::add`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -177,7 +177,7 @@
error[E0080]: could not evaluate static initializer
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: ALLOC11 has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+ = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC11+0x1 which is only 7 bytes from the end of the allocation
|
note: inside `std::ptr::const_ptr::<impl *const u64>::add`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr
index 7634ba2..7f35496 100644
--- a/tests/ui/const-ptr/out_of_bounds_read.stderr
+++ b/tests/ui/const-ptr/out_of_bounds_read.stderr
@@ -1,7 +1,7 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
- = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+ = note: memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
|
note: inside `std::ptr::read::<u32>`
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -14,7 +14,7 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
- = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+ = note: memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
|
note: inside `std::ptr::read::<u32>`
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -29,7 +29,7 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
- = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+ = note: memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
|
note: inside `std::ptr::read::<u32>`
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr
index 9e49706..7f83dee 100644
--- a/tests/ui/consts/const-compare-bytes-ub.stderr
+++ b/tests/ui/consts/const-compare-bytes-ub.stderr
@@ -2,31 +2,31 @@
--> $DIR/const-compare-bytes-ub.rs:10:9
|
LL | compare_bytes(0 as *const u8, 2 as *const u8, 1)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got a null pointer
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:14:9
|
LL | compare_bytes(1 as *const u8, 0 as *const u8, 1)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:18:9
|
LL | compare_bytes(1 as *const u8, 2 as *const u8, 1)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:22:9
|
LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 which is only 3 bytes from the end of the allocation
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:26:9
|
LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC1 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 which is only 3 bytes from the end of the allocation
error[E0080]: evaluation of constant value failed
--> $DIR/const-compare-bytes-ub.rs:30:9
diff --git a/tests/ui/consts/const-deref-ptr.stderr b/tests/ui/consts/const-deref-ptr.stderr
index b102b4d..070685e 100644
--- a/tests/ui/consts/const-deref-ptr.stderr
+++ b/tests/ui/consts/const-deref-ptr.stderr
@@ -2,7 +2,7 @@
--> $DIR/const-deref-ptr.rs:4:29
|
LL | static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0xdeadbeef[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got 0xdeadbeef[noalloc] which is a dangling pointer (it has no provenance)
error: aborting due to 1 previous error
diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr
index e6cd25e..b0c8646 100644
--- a/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr
+++ b/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr
@@ -2,13 +2,13 @@
--> $DIR/const_raw_ptr_ops2.rs:7:26
|
LL | const Z2: i32 = unsafe { *(42 as *const i32) };
- | ^^^^^^^^^^^^^^^^^^^ memory access failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/const_raw_ptr_ops2.rs:9:26
|
LL | const Z3: i32 = unsafe { *(44 as *const i32) };
- | ^^^^^^^^^^^^^^^^^^^ memory access failed: 0x2c[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x2c[noalloc] which is a dangling pointer (it has no provenance)
error: aborting due to 2 previous errors
diff --git a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr
index b878c8d..bd6dafb 100644
--- a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr
+++ b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr
@@ -2,7 +2,7 @@
--> $DIR/nonnull_as_ref_ub.rs:4:29
|
LL | const _: () = assert!(42 == *unsafe { NON_NULL.as_ref() });
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
error: aborting due to 1 previous error
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index d7d24f3..27c85cc 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -436,17 +436,27 @@
╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
}
-error[E0080]: evaluation of constant value failed
- --> $DIR/raw-bytes.rs:196:62
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/raw-bytes.rs:196:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 8, align: 4) {
+ ╾ALLOC_ID╼ 00 00 00 00 │ ╾──╼....
+ }
-error[E0080]: evaluation of constant value failed
- --> $DIR/raw-bytes.rs:199:65
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/raw-bytes.rs:199:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC32 as vtable pointer but it does not point to a vtable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 8, align: 4) {
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──╼╾──╼
+ }
error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:204:1
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index 22679ac..2b0ce99 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -436,17 +436,27 @@
╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
}
-error[E0080]: evaluation of constant value failed
- --> $DIR/raw-bytes.rs:196:62
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/raw-bytes.rs:196:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 16, align: 8) {
+ ╾ALLOC_ID╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
+ }
-error[E0080]: evaluation of constant value failed
- --> $DIR/raw-bytes.rs:199:65
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/raw-bytes.rs:199:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC32 as vtable pointer but it does not point to a vtable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 16, align: 8) {
+ ╾ALLOC_ID╼ ╾ALLOC_ID╼ │ ╾──────╼╾──────╼
+ }
error[E0080]: it is undefined behavior to use this value
--> $DIR/raw-bytes.rs:204:1
diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs
index de1a81b..0df732d 100644
--- a/tests/ui/consts/const-eval/raw-bytes.rs
+++ b/tests/ui/consts/const-eval/raw-bytes.rs
@@ -194,10 +194,10 @@ impl Trait for bool {}
//~| expected a boolean
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| null pointer
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| vtable
// Uninhabited types
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs
index 47105de..5aced5b 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.rs
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs
@@ -39,7 +39,7 @@
let mem = [0u32; 1];
let ptr = mem.as_ptr().cast::<u64>();
let _val = *ptr; //~ERROR: evaluation of constant value failed
- //~^NOTE: size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+ //~^NOTE: expected a pointer to 8 bytes of memory
};
fn main() {}
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
index cba06fd..aeb4672 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
@@ -35,7 +35,7 @@
--> $DIR/raw-pointer-ub.rs:41:16
|
LL | let _val = *ptr;
- | ^^^^ memory access failed: ALLOC0 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+ | ^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got ALLOC0 which is only 4 bytes from the end of the allocation
error: aborting due to 5 previous errors
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
index 439ccb2..5c47cbf 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
@@ -1,20 +1,8 @@
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-incorrect-vtable.rs:19:14
- |
-LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC8 as vtable pointer but it does not point to a vtable
-
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-incorrect-vtable.rs:24:14
- |
-LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC9 as vtable pointer but it does not point to a vtable
-
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:33:1
+ --> $DIR/ub-incorrect-vtable.rs:18:1
|
-LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC1<imm>, but expected a vtable pointer
+LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
@@ -22,10 +10,10 @@
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:38:1
+ --> $DIR/ub-incorrect-vtable.rs:23:1
|
-LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC3<imm>, but expected a vtable pointer
+LL | const INVALID_VTABLE_SIZE: &dyn Trait =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
@@ -33,10 +21,10 @@
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:44:1
+ --> $DIR/ub-incorrect-vtable.rs:33:1
|
-LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
+LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
@@ -44,6 +32,28 @@
}
error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-incorrect-vtable.rs:38:1
+ |
+LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 8, align: 4) {
+ ╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼ │ ╾──╼╾──╼
+ }
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-incorrect-vtable.rs:44:1
+ |
+LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 8, align: 4) {
+ ╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼ │ ╾──╼╾──╼
+ }
+
+error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-incorrect-vtable.rs:91:1
|
LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
@@ -51,7 +61,7 @@
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 8, align: 4) {
- ╾ALLOC6<imm>╼ ╾ALLOC7╼ │ ╾──╼╾──╼
+ ╾ALLOC10<imm>╼ ╾ALLOC11╼ │ ╾──╼╾──╼
}
error: aborting due to 6 previous errors
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
index 89bf959..f400073 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
@@ -1,20 +1,8 @@
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-incorrect-vtable.rs:19:14
- |
-LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC8 as vtable pointer but it does not point to a vtable
-
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-incorrect-vtable.rs:24:14
- |
-LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC9 as vtable pointer but it does not point to a vtable
-
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:33:1
+ --> $DIR/ub-incorrect-vtable.rs:18:1
|
-LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC1<imm>, but expected a vtable pointer
+LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
@@ -22,10 +10,10 @@
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:38:1
+ --> $DIR/ub-incorrect-vtable.rs:23:1
|
-LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC3<imm>, but expected a vtable pointer
+LL | const INVALID_VTABLE_SIZE: &dyn Trait =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
@@ -33,10 +21,10 @@
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:44:1
+ --> $DIR/ub-incorrect-vtable.rs:33:1
|
-LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
+LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
@@ -44,6 +32,28 @@
}
error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-incorrect-vtable.rs:38:1
+ |
+LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 16, align: 8) {
+ ╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼ │ ╾──────╼╾──────╼
+ }
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-incorrect-vtable.rs:44:1
+ |
+LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: 16, align: 8) {
+ ╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼ │ ╾──────╼╾──────╼
+ }
+
+error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-incorrect-vtable.rs:91:1
|
LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
@@ -51,7 +61,7 @@
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: 16, align: 8) {
- ╾ALLOC6<imm>╼ ╾ALLOC7╼ │ ╾──────╼╾──────╼
+ ╾ALLOC10<imm>╼ ╾ALLOC11╼ │ ╾──────╼╾──────╼
}
error: aborting due to 6 previous errors
diff --git a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs
index 4325495..8058f76 100644
--- a/tests/ui/consts/const-eval/ub-incorrect-vtable.rs
+++ b/tests/ui/consts/const-eval/ub-incorrect-vtable.rs
@@ -17,12 +17,12 @@ trait Trait {}
const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-//~^ ERROR evaluation of constant value failed
+//~^^ ERROR it is undefined behavior to use this value
//~| vtable
const INVALID_VTABLE_SIZE: &dyn Trait =
unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-//~^ ERROR evaluation of constant value failed
+//~^^ ERROR it is undefined behavior to use this value
//~| vtable
#[repr(transparent)]
diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr
index ab0fb2a..0e4926e 100644
--- a/tests/ui/consts/const-eval/ub-nonnull.stderr
+++ b/tests/ui/consts/const-eval/ub-nonnull.stderr
@@ -13,7 +13,7 @@
--> $DIR/ub-nonnull.rs:20:29
|
LL | let out_of_bounds_ptr = &ptr[255];
- | ^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC1 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 255 bytes of memory, but got ALLOC1 which is only 1 byte from the end of the allocation
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-nonnull.rs:24:1
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs
index 3956146..991d442 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs
@@ -123,13 +123,13 @@ impl Trait for bool {}
//~^ ERROR it is undefined behavior to use this value
//~| vtable
const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| vtable
const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| vtable
const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| vtable
const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
//~^ ERROR it is undefined behavior to use this value
@@ -142,10 +142,10 @@ impl Trait for bool {}
// # raw trait object
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| null pointer
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-//~^ ERROR evaluation of constant value failed
+//~^ ERROR it is undefined behavior to use this value
//~| vtable
const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw
// Officially blessed way to get the vtable
@@ -154,12 +154,12 @@ impl Trait for bool {}
static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
- //~^ ERROR could not evaluate static initializer
+ //~^^ ERROR it is undefined behavior to use this value
//~| null pointer
};
static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
- //~^ ERROR could not evaluate static initializer
+ //~^^ ERROR it is undefined behavior to use this value
//~| vtable
};
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
index 4fe7442..92f0029 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -218,29 +218,44 @@
HEX_DUMP
}
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:125:57
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:125:1
|
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC20 as vtable pointer but it does not point to a vtable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC17<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:128:57
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:128:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC21 as vtable pointer but it does not point to a vtable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC19<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:131:56
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:131:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC22 as vtable pointer but it does not point to a vtable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC21<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-wide-ptr.rs:134:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17<imm>, but expected a vtable pointer
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC23<imm>, but expected a vtable pointer
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -258,29 +273,49 @@
HEX_DUMP
}
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:144:62
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:144:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
-error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:147:65
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:147:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC23 as vtable pointer but it does not point to a vtable
-
-error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:156:5
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC28<imm>, but expected a vtable pointer
|
-LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
-error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:161:5
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:155:1
|
-LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using ALLOC24 as vtable pointer but it does not point to a vtable
+LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/ub-wide-ptr.rs:160:1
+ |
+LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC31<imm>, but expected a vtable pointer
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+ = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
+ HEX_DUMP
+ }
error: aborting due to 29 previous errors
diff --git a/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs b/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs
index 5628ae1..f413031 100644
--- a/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs
+++ b/tests/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs
@@ -1,8 +1,8 @@
//@ run-pass
-
+#![allow(unreachable_patterns)]
#![allow(dead_code)]
-enum Empty { }
+enum Empty {}
enum Test1 {
A(u8),
B(Empty),
diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs
index 4183dc0..e3f43ce 100644
--- a/tests/ui/consts/copy-intrinsic.rs
+++ b/tests/ui/consts/copy-intrinsic.rs
@@ -27,7 +27,7 @@
copy_nonoverlapping(0x100 as *const i32, dangle, 0);
// Non-zero-sized copy is not.
copy_nonoverlapping(0x100 as *const i32, dangle, 1); //~ ERROR evaluation of constant value failed [E0080]
- //~| 0x100[noalloc] is a dangling pointer
+ //~| got 0x100[noalloc] which is a dangling pointer
};
const COPY_OOB_2: () = unsafe {
let x = 0i32;
@@ -36,7 +36,7 @@
copy_nonoverlapping(dangle, 0x100 as *mut i32, 0);
// Non-zero-sized copy is not.
copy_nonoverlapping(dangle, 0x100 as *mut i32, 1); //~ ERROR evaluation of constant value failed [E0080]
- //~| offset 40 is out-of-bounds
+ //~| +0x28 which is at or beyond the end of the allocation
};
const COPY_SIZE_OVERFLOW: () = unsafe {
diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr
index d34e61c..2dbb471 100644
--- a/tests/ui/consts/copy-intrinsic.stderr
+++ b/tests/ui/consts/copy-intrinsic.stderr
@@ -2,13 +2,13 @@
--> $DIR/copy-intrinsic.rs:29:5
|
LL | copy_nonoverlapping(0x100 as *const i32, dangle, 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x100[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
--> $DIR/copy-intrinsic.rs:38:5
|
LL | copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 40 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
error[E0080]: evaluation of constant value failed
--> $DIR/copy-intrinsic.rs:45:5
diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs
index 1506c21..7efc5dd 100644
--- a/tests/ui/consts/offset_from_ub.rs
+++ b/tests/ui/consts/offset_from_ub.rs
@@ -1,3 +1,4 @@
+//@ normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes"
#![feature(const_ptr_sub_ptr)]
#![feature(core_intrinsics)]
@@ -36,7 +37,7 @@ struct Struct {
let ptr1 = 8 as *const u8;
let ptr2 = 16 as *const u8;
unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
- //~| different pointers without provenance
+ //~| dangling pointer
};
const OUT_OF_BOUNDS_1: isize = {
@@ -45,7 +46,7 @@ struct Struct {
let end_ptr = (start_ptr).wrapping_add(length);
// First ptr is out of bounds
unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed
- //~| pointer to 10 bytes starting at offset 0 is out-of-bounds
+ //~| expected a pointer to 10 bytes of memory
};
const OUT_OF_BOUNDS_2: isize = {
@@ -54,7 +55,7 @@ struct Struct {
let end_ptr = (start_ptr).wrapping_add(length);
// Second ptr is out of bounds
unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed
- //~| pointer to 10 bytes starting at offset 0 is out-of-bounds
+ //~| expected a pointer to the end of 10 bytes of memory
};
pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr
index 7b62312..ac4597f 100644
--- a/tests/ui/consts/offset_from_ub.stderr
+++ b/tests/ui/consts/offset_from_ub.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:18:27
+ --> $DIR/offset_from_ub.rs:19:27
|
LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
@@ -12,67 +12,67 @@
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `NOT_PTR`
- --> $DIR/offset_from_ub.rs:24:14
+ --> $DIR/offset_from_ub.rs:25:14
|
LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:31:14
+ --> $DIR/offset_from_ub.rs:32:14
|
LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:38:14
+ --> $DIR/offset_from_ub.rs:39:14
|
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got 0x8[noalloc] which is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:47:14
+ --> $DIR/offset_from_ub.rs:48:14
|
LL | unsafe { ptr_offset_from(end_ptr, start_ptr) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC0 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got ALLOC0 which is only $BYTES bytes from the end of the allocation
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:56:14
+ --> $DIR/offset_from_ub.rs:57:14
|
LL | unsafe { ptr_offset_from(start_ptr, end_ptr) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC1 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC1+0xa which does not have enough space to the beginning of the allocation
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:65:14
+ --> $DIR/offset_from_ub.rs:66:14
|
LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:72:14
+ --> $DIR/offset_from_ub.rs:73:14
|
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:78:14
+ --> $DIR/offset_from_ub.rs:79:14
|
LL | unsafe { ptr_offset_from(ptr1, ptr2) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:86:14
+ --> $DIR/offset_from_ub.rs:87:14
|
LL | unsafe { ptr_offset_from(ptr1, ptr2) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:93:14
+ --> $DIR/offset_from_ub.rs:94:14
|
LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:100:14
+ --> $DIR/offset_from_ub.rs:101:14
|
LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second
@@ -80,12 +80,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+ = note: out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got a null pointer
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `OFFSET_VERY_FAR1`
- --> $DIR/offset_from_ub.rs:109:14
+ --> $DIR/offset_from_ub.rs:110:14
|
LL | unsafe { ptr2.offset_from(ptr1) }
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -93,12 +93,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+ = note: `ptr_offset_from` called when first pointer is too far before second
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `OFFSET_VERY_FAR2`
- --> $DIR/offset_from_ub.rs:115:14
+ --> $DIR/offset_from_ub.rs:116:14
|
LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs
index ebc7019..5026d9a 100644
--- a/tests/ui/consts/offset_ub.rs
+++ b/tests/ui/consts/offset_ub.rs
@@ -1,7 +1,8 @@
use std::ptr;
-
+//@ normalize-stderr-test: "0xf+" -> "0xf..f"
//@ normalize-stderr-test: "0x7f+" -> "0x7f..f"
+//@ normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes"
pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE
diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr
index 89371f0..779cb96 100644
--- a/tests/ui/consts/offset_ub.stderr
+++ b/tests/ui/consts/offset_ub.stderr
@@ -1,12 +1,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: overflowing in-bounds pointer arithmetic
+ = note: out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC0 which is at the beginning of the allocation
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `BEFORE_START`
- --> $DIR/offset_ub.rs:7:46
+ --> $DIR/offset_ub.rs:8:46
|
LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -14,12 +14,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
+ = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC1 which is only 1 byte from the end of the allocation
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `AFTER_END`
- --> $DIR/offset_ub.rs:8:43
+ --> $DIR/offset_ub.rs:9:43
|
LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -27,12 +27,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: ALLOC1 has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
+ = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC2 which is only $BYTES bytes from the end of the allocation
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `AFTER_ARRAY`
- --> $DIR/offset_ub.rs:9:45
+ --> $DIR/offset_ub.rs:10:45
|
LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,12 +40,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: overflowing in-bounds pointer arithmetic
+ = note: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
|
note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `OVERFLOW`
- --> $DIR/offset_ub.rs:11:43
+ --> $DIR/offset_ub.rs:12:43
|
LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,12 +53,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: overflowing in-bounds pointer arithmetic
+ = note: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
|
note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `UNDERFLOW`
- --> $DIR/offset_ub.rs:12:44
+ --> $DIR/offset_ub.rs:13:44
|
LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,12 +66,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: overflowing in-bounds pointer arithmetic
+ = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0xf..f[noalloc] which is a dangling pointer (it has no provenance)
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `OVERFLOW_ADDRESS_SPACE`
- --> $DIR/offset_ub.rs:13:56
+ --> $DIR/offset_ub.rs:14:56
|
LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -79,12 +79,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: overflowing in-bounds pointer arithmetic
+ = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `UNDERFLOW_ADDRESS_SPACE`
- --> $DIR/offset_ub.rs:14:57
+ --> $DIR/offset_ub.rs:15:57
|
LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,12 +92,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: ALLOC2 has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
+ = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC3-0x2 which points to before the beginning of the allocation
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `NEGATIVE_OFFSET`
- --> $DIR/offset_ub.rs:15:49
+ --> $DIR/offset_ub.rs:16:49
|
LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -105,12 +105,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: ALLOC3 has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+ = note: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC4 which is at or beyond the end of the allocation of size $BYTES bytes
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `ZERO_SIZED_ALLOC`
- --> $DIR/offset_ub.rs:17:50
+ --> $DIR/offset_ub.rs:18:50
|
LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,12 +118,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+ = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
|
note: inside `std::ptr::mut_ptr::<impl *mut u8>::offset`
--> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
note: inside `DANGLING`
- --> $DIR/offset_ub.rs:18:42
+ --> $DIR/offset_ub.rs:19:42
|
LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,12 +131,12 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
+ = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got 0xf..f[noalloc] which is a dangling pointer (it has no provenance)
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
note: inside `UNDERFLOW_ABS`
- --> $DIR/offset_ub.rs:21:47
+ --> $DIR/offset_ub.rs:22:47
|
LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr
index 64fa2be..15123a4 100644
--- a/tests/ui/coroutine/gen_block.none.stderr
+++ b/tests/ui/coroutine/gen_block.none.stderr
@@ -73,7 +73,6 @@
= note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
= help: add `#![feature(coroutines)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
--> $DIR/gen_block.rs:16:16
@@ -95,7 +94,6 @@
= note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
= help: add `#![feature(coroutines)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 11 previous errors
diff --git a/tests/ui/coroutine/invalid_attr_usage.rs b/tests/ui/coroutine/invalid_attr_usage.rs
new file mode 100644
index 0000000..995a3aa
--- /dev/null
+++ b/tests/ui/coroutine/invalid_attr_usage.rs
@@ -0,0 +1,11 @@
+//! The `coroutine` attribute is only allowed on closures.
+
+#![feature(coroutines)]
+
+#[coroutine]
+//~^ ERROR: attribute should be applied to closures
+struct Foo;
+
+#[coroutine]
+//~^ ERROR: attribute should be applied to closures
+fn main() {}
diff --git a/tests/ui/coroutine/invalid_attr_usage.stderr b/tests/ui/coroutine/invalid_attr_usage.stderr
new file mode 100644
index 0000000..316a011
--- /dev/null
+++ b/tests/ui/coroutine/invalid_attr_usage.stderr
@@ -0,0 +1,14 @@
+error: attribute should be applied to closures
+ --> $DIR/invalid_attr_usage.rs:5:1
+ |
+LL | #[coroutine]
+ | ^^^^^^^^^^^^
+
+error: attribute should be applied to closures
+ --> $DIR/invalid_attr_usage.rs:9:1
+ |
+LL | #[coroutine]
+ | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/delegation/explicit-paths.rs b/tests/ui/delegation/explicit-paths.rs
index d42e305..3b0454e 100644
--- a/tests/ui/delegation/explicit-paths.rs
+++ b/tests/ui/delegation/explicit-paths.rs
@@ -22,9 +22,7 @@ mod fn_to_other {
use super::*;
reuse Trait::foo1;
- //~^ ERROR delegation to a trait method from a free function is not supported yet
reuse <S as Trait>::foo2;
- //~^ ERROR delegation to a trait method from a free function is not supported yet
reuse to_reuse::foo3;
reuse S::foo4;
//~^ ERROR cannot find function `foo4` in `S`
diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr
index b5afe19..8098ea8 100644
--- a/tests/ui/delegation/explicit-paths.stderr
+++ b/tests/ui/delegation/explicit-paths.stderr
@@ -1,5 +1,5 @@
error[E0407]: method `foo3` is not a member of trait `Trait`
- --> $DIR/explicit-paths.rs:51:9
+ --> $DIR/explicit-paths.rs:49:9
|
LL | reuse to_reuse::foo3;
| ^^^^^^^^^^^^^^^^----^
@@ -8,7 +8,7 @@
| not a member of trait `Trait`
error[E0407]: method `foo4` is not a member of trait `Trait`
- --> $DIR/explicit-paths.rs:53:9
+ --> $DIR/explicit-paths.rs:51:9
|
LL | reuse F::foo4 { &self.0 }
| ^^^^^^^^^----^^^^^^^^^^^^
@@ -17,49 +17,49 @@
| not a member of trait `Trait`
error[E0425]: cannot find function `foo4` in `S`
- --> $DIR/explicit-paths.rs:29:14
+ --> $DIR/explicit-paths.rs:27:14
|
LL | reuse S::foo4;
| ^^^^ not found in `S`
error[E0425]: cannot find function `foo4` in `F`
- --> $DIR/explicit-paths.rs:40:18
+ --> $DIR/explicit-paths.rs:38:18
|
LL | reuse F::foo4 { &self.0 }
| ^^^^ not found in `F`
|
note: function `fn_to_other::foo4` exists but is inaccessible
- --> $DIR/explicit-paths.rs:29:5
+ --> $DIR/explicit-paths.rs:27:5
|
LL | reuse S::foo4;
| ^^^^^^^^^^^^^^ not accessible
error[E0425]: cannot find function `foo4` in `F`
- --> $DIR/explicit-paths.rs:53:18
+ --> $DIR/explicit-paths.rs:51:18
|
LL | reuse F::foo4 { &self.0 }
| ^^^^ not found in `F`
|
note: function `fn_to_other::foo4` exists but is inaccessible
- --> $DIR/explicit-paths.rs:29:5
+ --> $DIR/explicit-paths.rs:27:5
|
LL | reuse S::foo4;
| ^^^^^^^^^^^^^^ not accessible
error[E0425]: cannot find function `foo4` in `F`
- --> $DIR/explicit-paths.rs:67:18
+ --> $DIR/explicit-paths.rs:65:18
|
LL | reuse F::foo4 { &F }
| ^^^^ not found in `F`
|
note: function `fn_to_other::foo4` exists but is inaccessible
- --> $DIR/explicit-paths.rs:29:5
+ --> $DIR/explicit-paths.rs:27:5
|
LL | reuse S::foo4;
| ^^^^^^^^^^^^^^ not accessible
error[E0119]: conflicting implementations of trait `Trait` for type `S`
- --> $DIR/explicit-paths.rs:76:5
+ --> $DIR/explicit-paths.rs:74:5
|
LL | impl Trait for S {
| ---------------- first implementation here
@@ -67,26 +67,8 @@
LL | impl Trait for S {
| ^^^^^^^^^^^^^^^^ conflicting implementation for `S`
-error: delegation to a trait method from a free function is not supported yet
- --> $DIR/explicit-paths.rs:24:18
- |
-LL | fn foo1(&self, x: i32) -> i32 { x }
- | ----------------------------- callee defined here
-...
-LL | reuse Trait::foo1;
- | ^^^^
-
-error: delegation to a trait method from a free function is not supported yet
- --> $DIR/explicit-paths.rs:26:25
- |
-LL | fn foo2(x: i32) -> i32 { x }
- | ---------------------- callee defined here
-...
-LL | reuse <S as Trait>::foo2;
- | ^^^^
-
error[E0308]: mismatched types
- --> $DIR/explicit-paths.rs:63:36
+ --> $DIR/explicit-paths.rs:61:36
|
LL | trait Trait2 : Trait {
| -------------------- found this type parameter
@@ -104,7 +86,7 @@
| ^^^^ -----
error[E0277]: the trait bound `S2: Trait` is not satisfied
- --> $DIR/explicit-paths.rs:78:16
+ --> $DIR/explicit-paths.rs:76:16
|
LL | reuse <S2 as Trait>::foo1;
| ^^ the trait `Trait` is not implemented for `S2`
@@ -114,7 +96,7 @@
S
error[E0308]: mismatched types
- --> $DIR/explicit-paths.rs:78:30
+ --> $DIR/explicit-paths.rs:76:30
|
LL | reuse <S2 as Trait>::foo1;
| ^^^^
@@ -130,7 +112,7 @@
LL | fn foo1(&self, x: i32) -> i32 { x }
| ^^^^ -----
-error: aborting due to 12 previous errors
+error: aborting due to 10 previous errors
Some errors have detailed explanations: E0119, E0277, E0308, E0407, E0425.
For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs b/tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs
new file mode 100644
index 0000000..625bbdd
--- /dev/null
+++ b/tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs
@@ -0,0 +1,28 @@
+//@ run-pass
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+ pub fn types<T, U>(x: U, y: T) -> (T, U) {
+ (y, x)
+ }
+ pub fn late<'a, 'b>(x: &'a u8, y: &'b u8) -> u8 {
+ *x + *y
+ }
+ pub fn early<'a: 'a>(x: &'a str) -> &'a str {
+ x
+ }
+}
+
+reuse to_reuse::types;
+reuse to_reuse::late;
+reuse to_reuse::early;
+
+fn main() {
+ assert_eq!(types(0, "str"), ("str", 0));
+ assert_eq!(late(&1u8, &2u8), 3);
+ {
+ let s: &'static str = "hello world";
+ assert_eq!(early::<'static>(s), "hello world");
+ }
+}
diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.rs b/tests/ui/delegation/generics/free-fn-to-free-fn.rs
new file mode 100644
index 0000000..3741ad6
--- /dev/null
+++ b/tests/ui/delegation/generics/free-fn-to-free-fn.rs
@@ -0,0 +1,27 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod to_reuse {
+ pub fn consts<const N: i32>() -> i32 {
+ N
+ }
+ pub fn late<'a>(x: &'a u8) -> u8 {
+ *x
+ }
+ pub fn bounds<T: Clone>(_: T) {}
+}
+
+// FIXME(fn_delegation): this is supposed to work eventually
+reuse to_reuse::consts;
+//~^ ERROR type annotations needed
+reuse to_reuse::late;
+reuse to_reuse::bounds;
+
+fn main() {
+ late::<'static>(&0u8);
+ //~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+
+ struct S;
+ bounds(S);
+ //~^ ERROR the trait bound `S: Clone` is not satisfied
+}
diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.stderr b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr
new file mode 100644
index 0000000..5ba56ce
--- /dev/null
+++ b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr
@@ -0,0 +1,54 @@
+error[E0284]: type annotations needed
+ --> $DIR/free-fn-to-free-fn.rs:15:17
+ |
+LL | reuse to_reuse::consts;
+ | ^^^^^^ cannot infer the value of the const parameter `N` declared on the function `consts`
+ |
+note: required by a const generic parameter in `to_reuse::consts`
+ --> $DIR/free-fn-to-free-fn.rs:5:19
+ |
+LL | pub fn consts<const N: i32>() -> i32 {
+ | ^^^^^^^^^^^^ required by this const generic parameter in `consts`
+help: consider specifying the generic argument
+ |
+LL | reuse to_reuse::consts::<N>;
+ | +++++
+
+error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+ --> $DIR/free-fn-to-free-fn.rs:21:12
+ |
+LL | late::<'static>(&0u8);
+ | ^^^^^^^
+ |
+note: the late bound lifetime parameter is introduced here
+ --> $DIR/free-fn-to-free-fn.rs:8:17
+ |
+LL | pub fn late<'a>(x: &'a u8) -> u8 {
+ | ^^
+
+error[E0277]: the trait bound `S: Clone` is not satisfied
+ --> $DIR/free-fn-to-free-fn.rs:25:12
+ |
+LL | bounds(S);
+ | ------ ^ the trait `Clone` is not implemented for `S`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `bounds`
+ --> $DIR/free-fn-to-free-fn.rs:11:22
+ |
+LL | pub fn bounds<T: Clone>(_: T) {}
+ | ^^^^^ required by this bound in `bounds`
+...
+LL | reuse to_reuse::bounds;
+ | ------ required by a bound in this function
+help: consider annotating `S` with `#[derive(Clone)]`
+ |
+LL + #[derive(Clone)]
+LL | struct S;
+ |
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0284, E0794.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs b/tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs
new file mode 100644
index 0000000..f7b7c09
--- /dev/null
+++ b/tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs
@@ -0,0 +1,30 @@
+//@ run-pass
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod types {
+ pub trait Trait<T> {
+ fn foo<U>(&self, x: U, y: T) -> (T, U) {(y, x)}
+ }
+ impl<T> Trait<T> for u8 {}
+}
+
+mod types_and_lifetimes {
+ pub trait Trait<'a, T> {
+ fn foo<'b, U>(&self, _: &'b U, _: &'a T) -> bool {
+ true
+ }
+ }
+ impl<'a, T> Trait<'a, T> for u8 {}
+}
+
+reuse types::Trait::foo as types;
+reuse types_and_lifetimes::Trait::foo as types_and_lifetimes;
+
+fn main() {
+ assert_eq!(types(&2, "str", 1), (1, "str"));
+
+ struct T;
+ struct U;
+ assert_eq!(types_and_lifetimes::<u8, T, U>(&1, &U, &T), true);
+}
diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.rs b/tests/ui/delegation/generics/free-fn-to-trait-method.rs
new file mode 100644
index 0000000..70be1a4
--- /dev/null
+++ b/tests/ui/delegation/generics/free-fn-to-trait-method.rs
@@ -0,0 +1,56 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+mod default_param {
+ pub trait Trait<T = u32> {
+ fn foo(&self, _: T) {}
+ }
+
+ impl<T> Trait<T> for u8 {}
+}
+
+mod types_and_lifetimes {
+ pub trait Trait<'a, T> {
+ fn foo<'b: 'b>(&'a self, x: &'b T) {
+ loop {}
+ }
+ }
+ impl<'a, T> Trait<'a, T> for u8 {}
+}
+
+mod bounds {
+ pub trait Trait<T> {
+ fn foo<U: Clone>(&self, t: T, u: U) where T: Copy {}
+ }
+
+ impl<T> Trait<T> for u8 {}
+}
+
+mod generic_arguments {
+ trait Trait<T> {
+ fn foo<U>(&self, _: U, _: T) {}
+ }
+
+ impl<T> Trait<T> for u8 {}
+
+ reuse Trait::<_>::foo::<i32> as generic_arguments1;
+ //~^ ERROR mismatched types
+ reuse <u8 as Trait<_>>::foo as generic_arguments2;
+ //~^ ERROR mismatched types
+ reuse <_ as Trait<_>>::foo as generic_arguments3; // OK
+}
+
+reuse default_param::Trait::foo as default_param;
+reuse types_and_lifetimes::Trait::foo as types_and_lifetimes;
+reuse bounds::Trait::foo as bounds;
+
+fn main() {
+ default_param(&0u8, "hello world"); // OK, default params are not substituted
+ types_and_lifetimes::<'static, 'static, _, _>(&0u8, &0u16); // OK, lifetimes go first
+
+ struct S;
+ struct U;
+ bounds(&0u8, S, U);
+ //~^ ERROR the trait bound `S: Copy` is not satisfied
+ //~| ERROR the trait bound `U: Clone` is not satisfied
+}
diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.stderr b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr
new file mode 100644
index 0000000..d8299d0
--- /dev/null
+++ b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr
@@ -0,0 +1,88 @@
+error[E0308]: mismatched types
+ --> $DIR/free-fn-to-trait-method.rs:36:23
+ |
+LL | fn foo<U>(&self, _: U, _: T) {}
+ | - found this type parameter
+...
+LL | reuse Trait::<_>::foo::<i32> as generic_arguments1;
+ | ^^^
+ | |
+ | expected `i32`, found type parameter `U`
+ | arguments to this function are incorrect
+ |
+ = note: expected type `i32`
+ found type parameter `U`
+note: method defined here
+ --> $DIR/free-fn-to-trait-method.rs:31:12
+ |
+LL | fn foo<U>(&self, _: U, _: T) {}
+ | ^^^ ----
+
+error[E0308]: mismatched types
+ --> $DIR/free-fn-to-trait-method.rs:38:29
+ |
+LL | trait Trait<T> {
+ | -------------- found this type parameter
+...
+LL | reuse <u8 as Trait<_>>::foo as generic_arguments2;
+ | ^^^
+ | |
+ | expected `&u8`, found `&Self`
+ | arguments to this function are incorrect
+ |
+ = note: expected reference `&u8`
+ found reference `&Self`
+note: method defined here
+ --> $DIR/free-fn-to-trait-method.rs:31:12
+ |
+LL | fn foo<U>(&self, _: U, _: T) {}
+ | ^^^ -----
+
+error[E0277]: the trait bound `S: Copy` is not satisfied
+ --> $DIR/free-fn-to-trait-method.rs:53:18
+ |
+LL | bounds(&0u8, S, U);
+ | ------ ^ the trait `Copy` is not implemented for `S`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `bounds`
+ --> $DIR/free-fn-to-trait-method.rs:23:54
+ |
+LL | fn foo<U: Clone>(&self, t: T, u: U) where T: Copy {}
+ | ^^^^ required by this bound in `bounds`
+...
+LL | reuse bounds::Trait::foo as bounds;
+ | ------ required by a bound in this function
+help: consider annotating `S` with `#[derive(Copy)]`
+ |
+LL + #[derive(Copy)]
+LL | struct S;
+ |
+
+error[E0277]: the trait bound `U: Clone` is not satisfied
+ --> $DIR/free-fn-to-trait-method.rs:53:21
+ |
+LL | bounds(&0u8, S, U);
+ | ------ ^ the trait `Clone` is not implemented for `U`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `bounds`
+ --> $DIR/free-fn-to-trait-method.rs:23:19
+ |
+LL | fn foo<U: Clone>(&self, t: T, u: U) where T: Copy {}
+ | ^^^^^ required by this bound in `bounds`
+...
+LL | reuse bounds::Trait::foo as bounds;
+ | ------ required by a bound in this function
+help: consider annotating `U` with `#[derive(Clone)]`
+ |
+LL + #[derive(Clone)]
+LL | struct U;
+ |
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs
index 82a9605..3bfae8f 100644
--- a/tests/ui/delegation/ice-issue-124347.rs
+++ b/tests/ui/delegation/ice-issue-124347.rs
@@ -6,7 +6,8 @@ trait Trait {
//~^ ERROR recursive delegation is not supported yet
}
+// FIXME(fn_delegation): `recursive delegation` error should be emitted here
reuse foo;
-//~^ ERROR recursive delegation is not supported yet
+//~^ ERROR cycle detected when computing generics of `foo`
fn main() {}
diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr
index 5a3f452..87dd75f 100644
--- a/tests/ui/delegation/ice-issue-124347.stderr
+++ b/tests/ui/delegation/ice-issue-124347.stderr
@@ -4,11 +4,20 @@
LL | reuse Trait::foo { &self.0 }
| ^^^ callee defined here
-error: recursive delegation is not supported yet
- --> $DIR/ice-issue-124347.rs:9:7
+error[E0391]: cycle detected when computing generics of `foo`
+ --> $DIR/ice-issue-124347.rs:10:7
|
LL | reuse foo;
- | ^^^ callee defined here
+ | ^^^
+ |
+ = note: ...which immediately requires computing generics of `foo` again
+note: cycle used when checking that `foo` is well-formed
+ --> $DIR/ice-issue-124347.rs:10:7
+ |
+LL | reuse foo;
+ | ^^^
+ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs
index 25d7a4c..d5ac68e 100644
--- a/tests/ui/delegation/not-supported.rs
+++ b/tests/ui/delegation/not-supported.rs
@@ -1,4 +1,6 @@
+#![feature(const_trait_impl)]
#![feature(c_variadic)]
+#![feature(effects)]
#![feature(fn_delegation)]
#![allow(incomplete_features)]
@@ -14,9 +16,9 @@ fn foo2<T>(&self, x: T) -> T { x }
fn foo3<'a: 'a>(_: &'a u32) {}
reuse GenericTrait::bar;
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
reuse GenericTrait::bar1;
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
}
struct F;
@@ -27,37 +29,37 @@ impl<T> GenericTrait<T> for F {}
impl<T> GenericTrait<T> for S {
reuse <F as GenericTrait<T>>::bar { &self.0 }
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
reuse GenericTrait::<T>::bar1;
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
}
impl GenericTrait<()> for () {
reuse GenericTrait::bar { &F }
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
reuse GenericTrait::bar1;
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
}
impl Trait for &S {
reuse Trait::foo;
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
}
impl Trait for S {
reuse Trait::foo1 { &self.0 }
reuse Trait::foo2 { &self.0 }
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
//~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
reuse <F as Trait>::foo3;
- //~^ ERROR delegation with early bound generics is not supported yet
- //~| ERROR lifetime parameters or bounds on method `foo3` do not match the trait declaration
+ //~^ ERROR early bound generics are not supported for associated delegation items
+ //~| ERROR lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
}
struct GenericS<T>(T);
impl<T> Trait for GenericS<T> {
reuse Trait::foo { &self.0 }
- //~^ ERROR delegation with early bound generics is not supported yet
+ //~^ ERROR early bound generics are not supported for associated delegation items
}
}
@@ -68,13 +70,10 @@ impl Trait for () {}
mod to_reuse {
use super::Trait;
- pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
pub fn opaque_ret() -> impl Trait { unimplemented!() }
//~^ warn: this function depends on never type fallback being `()`
//~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
}
- reuse to_reuse::opaque_arg;
- //~^ ERROR delegation with early bound generics is not supported yet
trait ToReuse {
fn opaque_ret() -> impl Trait { unimplemented!() }
@@ -104,4 +103,14 @@ pub fn foo() {}
//~^ ERROR recursive delegation is not supported yet
}
+mod effects {
+ #[const_trait]
+ trait Trait {
+ fn foo();
+ }
+
+ reuse Trait::foo;
+ //~^ ERROR delegation to a function with effect parameter is not supported yet
+}
+
fn main() {}
diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr
index 4ce01fd..14d6b37 100644
--- a/tests/ui/delegation/not-supported.stderr
+++ b/tests/ui/delegation/not-supported.stderr
@@ -1,5 +1,10 @@
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:16:29
+error: using `#![feature(effects)]` without enabling next trait solver globally
+ |
+ = note: the next trait solver must be enabled globally for the effects feature to work correctly
+ = help: use `-Znext-solver` to enable
+
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:18:29
|
LL | fn bar(&self, x: T) -> T { x }
| ------------------------ callee defined here
@@ -7,8 +12,8 @@
LL | reuse GenericTrait::bar;
| ^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:18:29
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:20:29
|
LL | fn bar1() {}
| --------- callee defined here
@@ -16,8 +21,8 @@
LL | reuse GenericTrait::bar1;
| ^^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:29:39
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:31:39
|
LL | fn bar(&self, x: T) -> T { x }
| ------------------------ callee defined here
@@ -25,8 +30,8 @@
LL | reuse <F as GenericTrait<T>>::bar { &self.0 }
| ^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:31:34
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:33:34
|
LL | fn bar1() {}
| --------- callee defined here
@@ -34,8 +39,8 @@
LL | reuse GenericTrait::<T>::bar1;
| ^^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:36:29
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:38:29
|
LL | fn bar(&self, x: T) -> T { x }
| ------------------------ callee defined here
@@ -43,8 +48,8 @@
LL | reuse GenericTrait::bar { &F }
| ^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:38:29
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:40:29
|
LL | fn bar1() {}
| --------- callee defined here
@@ -52,8 +57,8 @@
LL | reuse GenericTrait::bar1;
| ^^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:43:22
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:45:22
|
LL | fn foo(&self, x: i32) -> i32 { x }
| ---------------------------- callee defined here
@@ -62,7 +67,7 @@
| ^^^
error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter
- --> $DIR/not-supported.rs:49:22
+ --> $DIR/not-supported.rs:51:22
|
LL | fn foo2<T>(&self, x: T) -> T { x }
| - expected 1 type parameter
@@ -70,8 +75,8 @@
LL | reuse Trait::foo2 { &self.0 }
| ^^^^ found 0 type parameters
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:52:29
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:54:29
|
LL | fn foo3<'a: 'a>(_: &'a u32) {}
| --------------------------- callee defined here
@@ -79,17 +84,26 @@
LL | reuse <F as Trait>::foo3;
| ^^^^
-error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration
- --> $DIR/not-supported.rs:52:29
+error[E0195]: lifetime parameters or bounds on associated function `foo3` do not match the trait declaration
+ --> $DIR/not-supported.rs:54:29
|
LL | fn foo3<'a: 'a>(_: &'a u32) {}
- | -------- lifetimes in impl do not match this method in trait
+ | -------- lifetimes in impl do not match this associated function in trait
...
LL | reuse <F as Trait>::foo3;
- | ^^^^ lifetimes do not match method in trait
+ | ^^^^ lifetimes do not match associated function in trait
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:59:22
+error: delegation to a function with effect parameter is not supported yet
+ --> $DIR/not-supported.rs:112:18
+ |
+LL | fn foo();
+ | --------- callee defined here
+...
+LL | reuse Trait::foo;
+ | ^^^
+
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:61:22
|
LL | fn foo(&self, x: i32) -> i32 { x }
| ---------------------------- callee defined here
@@ -97,8 +111,8 @@
LL | reuse Trait::foo { &self.0 }
| ^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:49:22
+error: early bound generics are not supported for associated delegation items
+ --> $DIR/not-supported.rs:51:22
|
LL | fn foo2<T>(&self, x: T) -> T { x }
| ---------------------------- callee defined here
@@ -106,17 +120,8 @@
LL | reuse Trait::foo2 { &self.0 }
| ^^^^
-error: delegation with early bound generics is not supported yet
- --> $DIR/not-supported.rs:76:21
- |
-LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 }
- | --------------------------------------- callee defined here
-...
-LL | reuse to_reuse::opaque_arg;
- | ^^^^^^^^^^
-
warning: this function depends on never type fallback being `()`
- --> $DIR/not-supported.rs:80:9
+ --> $DIR/not-supported.rs:79:9
|
LL | fn opaque_ret() -> impl Trait { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -125,33 +130,33 @@
= note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: opaque::Trait` will fail
- --> $DIR/not-supported.rs:80:28
+ --> $DIR/not-supported.rs:79:28
|
LL | fn opaque_ret() -> impl Trait { unimplemented!() }
| ^^^^^^^^^^
= note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>::{synthetic#0}`
- --> $DIR/not-supported.rs:87:25
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`
+ --> $DIR/not-supported.rs:86:25
|
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
|
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
- --> $DIR/not-supported.rs:87:25
+ --> $DIR/not-supported.rs:86:25
|
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
- = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:86:5: 86:24>` is well-formed
- --> $DIR/not-supported.rs:86:5
+ = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:85:5: 85:24>` is well-formed
+ --> $DIR/not-supported.rs:85:5
|
LL | impl ToReuse for u8 {
| ^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
warning: this function depends on never type fallback being `()`
- --> $DIR/not-supported.rs:72:9
+ --> $DIR/not-supported.rs:73:9
|
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -160,32 +165,32 @@
= note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
= help: specify the types explicitly
note: in edition 2024, the requirement `!: opaque::Trait` will fail
- --> $DIR/not-supported.rs:72:32
+ --> $DIR/not-supported.rs:73:32
|
LL | pub fn opaque_ret() -> impl Trait { unimplemented!() }
| ^^^^^^^^^^
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>::{synthetic#0}`
- --> $DIR/not-supported.rs:90:24
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`
+ --> $DIR/not-supported.rs:89:24
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
|
note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process...
- --> $DIR/not-supported.rs:90:24
+ --> $DIR/not-supported.rs:89:24
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
- = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>::{synthetic#0}`, completing the cycle
-note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:89:5: 89:25>` is well-formed
- --> $DIR/not-supported.rs:89:5
+ = note: ...which again requires computing type of `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>::{synthetic#0}`, completing the cycle
+note: cycle used when checking that `opaque::<impl at $DIR/not-supported.rs:88:5: 88:25>` is well-formed
+ --> $DIR/not-supported.rs:88:5
|
LL | impl ToReuse for u16 {
| ^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: recursive delegation is not supported yet
- --> $DIR/not-supported.rs:103:22
+ --> $DIR/not-supported.rs:102:22
|
LL | pub reuse to_reuse2::foo;
| --- callee defined here
@@ -193,7 +198,7 @@
LL | reuse to_reuse1::foo;
| ^^^
-error: aborting due to 16 previous errors; 2 warnings emitted
+error: aborting due to 17 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0049, E0195, E0391.
For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs
index fd7ea94..f766ca7 100644
--- a/tests/ui/delegation/target-expr.rs
+++ b/tests/ui/delegation/target-expr.rs
@@ -14,9 +14,7 @@ fn foo(x: i32) -> i32 { x }
fn bar<T: Default>(_: T) {
reuse Trait::static_method {
- //~^ ERROR delegation to a trait method from a free function is not supported yet
- //~| ERROR delegation with early bound generics is not supported yet
- //~| ERROR mismatched types
+ //~^ ERROR mismatched types
let _ = T::Default();
//~^ ERROR can't use generic parameters from outer item
}
@@ -25,7 +23,6 @@ fn bar<T: Default>(_: T) {
fn main() {
let y = 0;
reuse <S as Trait>::static_method {
- //~^ ERROR delegation to a trait method from a free function is not supported yet
let x = y;
//~^ ERROR can't capture dynamic environment in a fn item
foo(self);
diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr
index b30f0c4..f5556bf 100644
--- a/tests/ui/delegation/target-expr.stderr
+++ b/tests/ui/delegation/target-expr.stderr
@@ -1,16 +1,16 @@
error[E0401]: can't use generic parameters from outer item
- --> $DIR/target-expr.rs:20:17
+ --> $DIR/target-expr.rs:18:17
|
LL | fn bar<T: Default>(_: T) {
| - type parameter from outer item
LL | reuse Trait::static_method {
| - help: try introducing a local generic parameter here: `T,`
-...
+LL |
LL | let _ = T::Default();
| ^^^^^^^^^^ use of generic parameter from outer item
error[E0434]: can't capture dynamic environment in a fn item
- --> $DIR/target-expr.rs:29:17
+ --> $DIR/target-expr.rs:26:17
|
LL | let x = y;
| ^
@@ -18,7 +18,7 @@
= help: use the `|| { ... }` closure form instead
error[E0424]: expected value, found module `self`
- --> $DIR/target-expr.rs:36:5
+ --> $DIR/target-expr.rs:33:5
|
LL | fn main() {
| ---- this function can't have a `self` parameter
@@ -27,58 +27,29 @@
| ^^^^ `self` value is a keyword only available in methods with a `self` parameter
error[E0425]: cannot find value `x` in this scope
- --> $DIR/target-expr.rs:38:13
+ --> $DIR/target-expr.rs:35:13
|
LL | let z = x;
| ^
|
help: the binding `x` is available in a different scope in the same function
- --> $DIR/target-expr.rs:29:13
+ --> $DIR/target-expr.rs:26:13
|
LL | let x = y;
| ^
-error: delegation with early bound generics is not supported yet
- --> $DIR/target-expr.rs:16:18
- |
-LL | fn static_method(x: i32) -> i32 { x }
- | ------------------------------- callee defined here
-...
-LL | reuse Trait::static_method {
- | ^^^^^^^^^^^^^
-
-error: delegation to a trait method from a free function is not supported yet
- --> $DIR/target-expr.rs:16:18
- |
-LL | fn static_method(x: i32) -> i32 { x }
- | ------------------------------- callee defined here
-...
-LL | reuse Trait::static_method {
- | ^^^^^^^^^^^^^
-
-error: delegation to a trait method from a free function is not supported yet
- --> $DIR/target-expr.rs:27:25
- |
-LL | fn static_method(x: i32) -> i32 { x }
- | ------------------------------- callee defined here
-...
-LL | reuse <S as Trait>::static_method {
- | ^^^^^^^^^^^^^
-
error[E0308]: mismatched types
--> $DIR/target-expr.rs:16:32
|
LL | reuse Trait::static_method {
| ________________________________^
LL | |
-LL | |
-LL | |
LL | | let _ = T::Default();
LL | |
LL | | }
| |_____^ expected `i32`, found `()`
-error: aborting due to 8 previous errors
+error: aborting due to 5 previous errors
Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434.
For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
index 885dacc..6ab1fb7 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
@@ -1,9 +1,9 @@
#![forbid(dead_code)]
#[derive(Debug)]
-pub struct Whatever { //~ ERROR struct `Whatever` is never constructed
+pub struct Whatever {
pub field0: (),
- field1: (),
+ field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read
field2: (),
field3: (),
field4: (),
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
index e10d28a..e9b757b 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
@@ -1,9 +1,19 @@
-error: struct `Whatever` is never constructed
- --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12
+error: fields `field1`, `field2`, `field3`, and `field4` are never read
+ --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
|
LL | pub struct Whatever {
- | ^^^^^^^^
+ | -------- fields in this struct
+LL | pub field0: (),
+LL | field1: (),
+ | ^^^^^^
+LL | field2: (),
+ | ^^^^^^
+LL | field3: (),
+ | ^^^^^^
+LL | field4: (),
+ | ^^^^^^
|
+ = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
note: the lint level is defined here
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
|
diff --git a/tests/ui/derives/deriving-with-repr-packed.rs b/tests/ui/derives/deriving-with-repr-packed.rs
index 58be451..d17b528 100644
--- a/tests/ui/derives/deriving-with-repr-packed.rs
+++ b/tests/ui/derives/deriving-with-repr-packed.rs
@@ -22,25 +22,22 @@
struct X(Y);
//~^ ERROR cannot move out of `self` which is behind a shared reference
-// This is currently allowed, but will be phased out at some point. From
-// `zerovec` within icu4x-0.9.0.
#[derive(Debug)]
#[repr(packed)]
struct FlexZeroSlice {
width: u8,
data: [u8],
- //~^ WARNING byte slice in a packed struct that derives a built-in trait
- //~^^ this was previously accepted
+ //~^ ERROR cannot move
+ //~| ERROR cannot move
}
-// Again, currently allowed, but will be phased out.
#[derive(Debug)]
#[repr(packed)]
struct WithStr {
width: u8,
data: str,
- //~^ WARNING string slice in a packed struct that derives a built-in trait
- //~^^ this was previously accepted
+ //~^ ERROR cannot move
+ //~| ERROR cannot move
}
fn main() {}
diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr
index a8523d2..321ffb2 100644
--- a/tests/ui/derives/deriving-with-repr-packed.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed.stderr
@@ -1,32 +1,3 @@
-warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-with-repr-packed.rs:31:5
- |
-LL | #[derive(Debug)]
- | ----- in this derive macro expansion
-...
-LL | data: [u8],
- | ^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
- = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: string slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-with-repr-packed.rs:41:5
- |
-LL | #[derive(Debug)]
- | ----- in this derive macro expansion
-...
-LL | data: str,
- | ^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
error[E0507]: cannot move out of `self` which is behind a shared reference
--> $DIR/deriving-with-repr-packed.rs:22:10
|
@@ -47,38 +18,43 @@
= note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 1 previous error; 2 warnings emitted
+error[E0161]: cannot move a value of type `[u8]`
+ --> $DIR/deriving-with-repr-packed.rs:29:5
+ |
+LL | data: [u8],
+ | ^^^^^^^^^^ the size of `[u8]` cannot be statically determined
-For more information about this error, try `rustc --explain E0507`.
-Future incompatibility report: Future breakage diagnostic:
-warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-with-repr-packed.rs:31:5
+error[E0507]: cannot move out of `self.data` which is behind a shared reference
+ --> $DIR/deriving-with-repr-packed.rs:29:5
|
LL | #[derive(Debug)]
| ----- in this derive macro expansion
...
LL | data: [u8],
- | ^^^^^^^^^^
+ | ^^^^^^^^^^ move occurs because `self.data` has type `[u8]`, which does not implement the `Copy` trait
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
- = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-Future breakage diagnostic:
-warning: string slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-with-repr-packed.rs:41:5
+error[E0161]: cannot move a value of type `str`
+ --> $DIR/deriving-with-repr-packed.rs:38:5
+ |
+LL | data: str,
+ | ^^^^^^^^^ the size of `str` cannot be statically determined
+
+error[E0507]: cannot move out of `self.data` which is behind a shared reference
+ --> $DIR/deriving-with-repr-packed.rs:38:5
|
LL | #[derive(Debug)]
| ----- in this derive macro expansion
...
LL | data: str,
- | ^^^^^^^^^
+ | ^^^^^^^^^ move occurs because `self.data` has type `str`, which does not implement the `Copy` trait
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
- = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+ = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs
index 6fa4f74..eab2b4f 100644
--- a/tests/ui/deriving/deriving-all-codegen.rs
+++ b/tests/ui/deriving/deriving-all-codegen.rs
@@ -73,16 +73,6 @@ impl Copy for PackedManualCopy {}
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
struct Unsized([u32]);
-// A packed struct with an unsized `[u8]` field. This is currently allowed, but
-// causes a warning and will be phased out at some point.
-#[derive(Debug, Hash)]
-#[repr(packed)]
-struct PackedUnsizedU8([u8]);
-//~^ WARNING byte slice in a packed struct that derives a built-in trait
-//~^^ WARNING byte slice in a packed struct that derives a built-in trait
-//~^^^ this was previously accepted
-//~^^^^ this was previously accepted
-
trait Trait {
type A;
}
diff --git a/tests/ui/deriving/deriving-all-codegen.stderr b/tests/ui/deriving/deriving-all-codegen.stderr
deleted file mode 100644
index 503f0ca..0000000
--- a/tests/ui/deriving/deriving-all-codegen.stderr
+++ /dev/null
@@ -1,63 +0,0 @@
-warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-all-codegen.rs:80:24
- |
-LL | #[derive(Debug, Hash)]
- | ----- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
- = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-all-codegen.rs:80:24
- |
-LL | #[derive(Debug, Hash)]
- | ---- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-all-codegen.rs:80:24
- |
-LL | #[derive(Debug, Hash)]
- | ----- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
- = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-warning: byte slice in a packed struct that derives a built-in trait
- --> $DIR/deriving-all-codegen.rs:80:24
- |
-LL | #[derive(Debug, Hash)]
- | ---- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
- | ^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #107457 <https://github.com/rust-lang/rust/issues/107457>
- = help: consider implementing the trait by hand, or remove the `packed` attribute
- = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
- = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index 6b69b57..6503c87 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -516,26 +516,6 @@
}
}
-// A packed struct with an unsized `[u8]` field. This is currently allowed, but
-// causes a warning and will be phased out at some point.
-#[repr(packed)]
-struct PackedUnsizedU8([u8]);
-#[automatically_derived]
-impl ::core::fmt::Debug for PackedUnsizedU8 {
- #[inline]
- fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- ::core::fmt::Formatter::debug_tuple_field1_finish(f,
- "PackedUnsizedU8", &&self.0)
- }
-}
-#[automatically_derived]
-impl ::core::hash::Hash for PackedUnsizedU8 {
- #[inline]
- fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
- ::core::hash::Hash::hash(&self.0, state)
- }
-}
-
trait Trait {
type A;
}
diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.rs b/tests/ui/deriving/deriving-smart-pointer-expanded.rs
new file mode 100644
index 0000000..b78258c
--- /dev/null
+++ b/tests/ui/deriving/deriving-smart-pointer-expanded.rs
@@ -0,0 +1,22 @@
+//@ check-pass
+//@ compile-flags: -Zunpretty=expanded
+#![feature(derive_smart_pointer)]
+use std::marker::SmartPointer;
+
+pub trait MyTrait<T: ?Sized> {}
+
+#[derive(SmartPointer)]
+#[repr(transparent)]
+struct MyPointer<'a, #[pointee] T: ?Sized> {
+ ptr: &'a T,
+}
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct MyPointer2<'a, Y, Z: MyTrait<T>, #[pointee] T: ?Sized + MyTrait<T>, X: MyTrait<T> = ()>
+where
+ Y: MyTrait<T>,
+{
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout
new file mode 100644
index 0000000..3c7e719
--- /dev/null
+++ b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout
@@ -0,0 +1,44 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ check-pass
+//@ compile-flags: -Zunpretty=expanded
+#![feature(derive_smart_pointer)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+use std::marker::SmartPointer;
+
+pub trait MyTrait<T: ?Sized> {}
+
+#[repr(transparent)]
+struct MyPointer<'a, #[pointee] T: ?Sized> {
+ ptr: &'a T,
+}
+#[automatically_derived]
+impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
+ ::core::ops::DispatchFromDyn<MyPointer<'a, __S>> for MyPointer<'a, T> {
+}
+#[automatically_derived]
+impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
+ ::core::ops::CoerceUnsized<MyPointer<'a, __S>> for MyPointer<'a, T> {
+}
+
+#[repr(transparent)]
+pub struct MyPointer2<'a, Y, Z: MyTrait<T>, #[pointee] T: ?Sized + MyTrait<T>,
+ X: MyTrait<T> = ()> where Y: MyTrait<T> {
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+#[automatically_derived]
+impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> +
+ ::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait<T> +
+ MyTrait<__S>> ::core::ops::DispatchFromDyn<MyPointer2<'a, Y, Z, __S, X>>
+ for MyPointer2<'a, Y, Z, T, X> where Y: MyTrait<T>, Y: MyTrait<__S> {
+}
+#[automatically_derived]
+impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> +
+ ::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait<T> +
+ MyTrait<__S>> ::core::ops::CoerceUnsized<MyPointer2<'a, Y, Z, __S, X>> for
+ MyPointer2<'a, Y, Z, T, X> where Y: MyTrait<T>, Y: MyTrait<__S> {
+}
diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs
index bfb4e86..04f52a15 100644
--- a/tests/ui/deriving/deriving-smart-pointer-neg.rs
+++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs
@@ -1,5 +1,6 @@
#![feature(derive_smart_pointer, arbitrary_self_types)]
+extern crate core;
use std::marker::SmartPointer;
#[derive(SmartPointer)]
@@ -35,6 +36,13 @@ struct NotTransparent<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
+#[derive(SmartPointer)]
+#[repr(transparent)]
+struct NoMaybeSized<'a, #[pointee] T> {
+ //~^ ERROR: `derive(SmartPointer)` requires T to be marked `?Sized`
+ ptr: &'a T,
+}
+
// However, reordering attributes should work nevertheless.
#[repr(transparent)]
#[derive(SmartPointer)]
@@ -42,4 +50,26 @@ struct ThisIsAPossibleSmartPointer<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
+// Also, these paths to Sized should work
+#[derive(SmartPointer)]
+#[repr(transparent)]
+struct StdSized<'a, #[pointee] T: ?std::marker::Sized> {
+ ptr: &'a T,
+}
+#[derive(SmartPointer)]
+#[repr(transparent)]
+struct CoreSized<'a, #[pointee] T: ?core::marker::Sized> {
+ ptr: &'a T,
+}
+#[derive(SmartPointer)]
+#[repr(transparent)]
+struct GlobalStdSized<'a, #[pointee] T: ?::std::marker::Sized> {
+ ptr: &'a T,
+}
+#[derive(SmartPointer)]
+#[repr(transparent)]
+struct GlobalCoreSized<'a, #[pointee] T: ?::core::marker::Sized> {
+ ptr: &'a T,
+}
+
fn main() {}
diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr
index d994a6e..8b0f91d 100644
--- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr
+++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr
@@ -1,5 +1,5 @@
error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
- --> $DIR/deriving-smart-pointer-neg.rs:5:10
+ --> $DIR/deriving-smart-pointer-neg.rs:6:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@@ -7,7 +7,7 @@
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits
- --> $DIR/deriving-smart-pointer-neg.rs:11:10
+ --> $DIR/deriving-smart-pointer-neg.rs:12:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@@ -15,7 +15,7 @@
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `SmartPointer` can only be derived on `struct`s with at least one field
- --> $DIR/deriving-smart-pointer-neg.rs:18:10
+ --> $DIR/deriving-smart-pointer-neg.rs:19:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@@ -23,7 +23,7 @@
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `SmartPointer` can only be derived on `struct`s with at least one field
- --> $DIR/deriving-smart-pointer-neg.rs:25:10
+ --> $DIR/deriving-smart-pointer-neg.rs:26:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@@ -31,15 +31,21 @@
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
- --> $DIR/deriving-smart-pointer-neg.rs:32:10
+ --> $DIR/deriving-smart-pointer-neg.rs:33:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
|
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
+error: `derive(SmartPointer)` requires T to be marked `?Sized`
+ --> $DIR/deriving-smart-pointer-neg.rs:41:36
+ |
+LL | struct NoMaybeSized<'a, #[pointee] T> {
+ | ^
+
error[E0392]: lifetime parameter `'a` is never used
- --> $DIR/deriving-smart-pointer-neg.rs:21:16
+ --> $DIR/deriving-smart-pointer-neg.rs:22:16
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^^ unused lifetime parameter
@@ -47,7 +53,7 @@
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
error[E0392]: type parameter `T` is never used
- --> $DIR/deriving-smart-pointer-neg.rs:21:31
+ --> $DIR/deriving-smart-pointer-neg.rs:22:31
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^ unused type parameter
@@ -55,7 +61,7 @@
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
error[E0392]: lifetime parameter `'a` is never used
- --> $DIR/deriving-smart-pointer-neg.rs:28:20
+ --> $DIR/deriving-smart-pointer-neg.rs:29:20
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^^ unused lifetime parameter
@@ -63,13 +69,13 @@
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
error[E0392]: type parameter `T` is never used
- --> $DIR/deriving-smart-pointer-neg.rs:28:35
+ --> $DIR/deriving-smart-pointer-neg.rs:29:35
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^ unused type parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/deriving/smart-pointer-bounds-issue-127647.rs b/tests/ui/deriving/smart-pointer-bounds-issue-127647.rs
new file mode 100644
index 0000000..4cae1b3
--- /dev/null
+++ b/tests/ui/deriving/smart-pointer-bounds-issue-127647.rs
@@ -0,0 +1,78 @@
+//@ check-pass
+
+#![feature(derive_smart_pointer)]
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct Ptr<'a, #[pointee] T: OnDrop + ?Sized, X> {
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+
+pub trait OnDrop {
+ fn on_drop(&mut self);
+}
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct Ptr2<'a, #[pointee] T: ?Sized, X>
+where
+ T: OnDrop,
+{
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+
+pub trait MyTrait<T: ?Sized> {}
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct Ptr3<'a, #[pointee] T: ?Sized, X>
+where
+ T: MyTrait<T>,
+{
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct Ptr4<'a, #[pointee] T: MyTrait<T> + ?Sized, X> {
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct Ptr5<'a, #[pointee] T: ?Sized, X>
+where
+ Ptr5Companion<T>: MyTrait<T>,
+ Ptr5Companion2: MyTrait<T>,
+{
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+
+pub struct Ptr5Companion<T: ?Sized>(core::marker::PhantomData<T>);
+pub struct Ptr5Companion2;
+
+#[derive(core::marker::SmartPointer)]
+#[repr(transparent)]
+pub struct Ptr6<'a, #[pointee] T: ?Sized, X: MyTrait<T> = (), const PARAM: usize = 0> {
+ data: &'a mut T,
+ x: core::marker::PhantomData<X>,
+}
+
+// a reduced example from https://lore.kernel.org/all/20240402-linked-list-v1-1-b1c59ba7ae3b@google.com/
+#[repr(transparent)]
+#[derive(core::marker::SmartPointer)]
+pub struct ListArc<#[pointee] T, const ID: u64 = 0>
+where
+ T: ListArcSafe<ID> + ?Sized,
+{
+ arc: *const T,
+}
+
+pub trait ListArcSafe<const ID: u64> {}
+
+fn main() {}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs
new file mode 100644
index 0000000..5548fa2
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.rs
@@ -0,0 +1,21 @@
+#![allow(unknown_or_malformed_diagnostic_attributes)]
+
+trait Foo {}
+
+#[diagnostic::do_not_recommend]
+impl<A> Foo for (A,) {}
+
+#[diagnostic::do_not_recommend]
+impl<A, B> Foo for (A, B) {}
+
+#[diagnostic::do_not_recommend]
+impl<A, B, C> Foo for (A, B, C) {}
+
+impl Foo for i32 {}
+
+fn check(a: impl Foo) {}
+
+fn main() {
+ check(());
+ //~^ ERROR the trait bound `(): Foo` is not satisfied
+}
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr
new file mode 100644
index 0000000..e56af28
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `(): Foo` is not satisfied
+ --> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:11
+ |
+LL | check(());
+ | ----- ^^ the trait `Foo` is not implemented for `()`
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the following other types implement trait `Foo`:
+ (A, B)
+ (A, B, C)
+ (A,)
+note: required by a bound in `check`
+ --> $DIR/do_not_apply_attribute_without_feature_flag.rs:16:18
+ |
+LL | fn check(a: impl Foo) {}
+ | ^^^ required by this bound in `check`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/dropck/drop-with-active-borrows-1.stderr b/tests/ui/dropck/drop-with-active-borrows-1.stderr
index 7d16332..229514c 100644
--- a/tests/ui/dropck/drop-with-active-borrows-1.stderr
+++ b/tests/ui/dropck/drop-with-active-borrows-1.stderr
@@ -9,11 +9,6 @@
| ^ move out of `a` occurs here
LL | for s in &b {
| -- borrow later used here
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | let b: Vec<&str> = a.clone().lines().collect();
- | ++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/dropck/dropck-empty-array.rs b/tests/ui/dropck/dropck-empty-array.rs
new file mode 100644
index 0000000..f3eca6a
--- /dev/null
+++ b/tests/ui/dropck/dropck-empty-array.rs
@@ -0,0 +1,23 @@
+//@ run-pass
+
+#[allow(dead_code)]
+struct Struct<'s>(&'s str);
+
+impl<'s> Drop for Struct<'s> {
+ fn drop(&mut self) {}
+}
+
+fn to_array_zero<T>(_: T) -> [T; 0] {
+ []
+}
+
+pub fn array_zero_in_tuple() {
+ let mut x = ([], String::new());
+ {
+ let s = String::from("temporary");
+ let p = Struct(&s);
+ x.0 = to_array_zero(p);
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/enum-discriminant/issue-61696.rs b/tests/ui/enum-discriminant/issue-61696.rs
index d200b44..e93fd0e 100644
--- a/tests/ui/enum-discriminant/issue-61696.rs
+++ b/tests/ui/enum-discriminant/issue-61696.rs
@@ -1,4 +1,5 @@
//@ run-pass
+#![allow(unreachable_patterns)]
pub enum Infallible {}
diff --git a/tests/ui/enum-discriminant/niche.rs b/tests/ui/enum-discriminant/niche.rs
index 15d227f..f9c4a13 100644
--- a/tests/ui/enum-discriminant/niche.rs
+++ b/tests/ui/enum-discriminant/niche.rs
@@ -1,4 +1,5 @@
//@ run-pass
+#![allow(unreachable_patterns)]
//! Make sure that we read and write enum discriminants correctly for corner cases caused
//! by layout optimizations.
diff --git a/tests/ui/error-codes/E0049.stderr b/tests/ui/error-codes/E0049.stderr
index c0cd31f..83a30aa 100644
--- a/tests/ui/error-codes/E0049.stderr
+++ b/tests/ui/error-codes/E0049.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
+error[E0049]: associated function `foo` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/E0049.rs:8:11
|
LL | fn foo<T: Default>(x: T) -> Self;
@@ -7,7 +7,7 @@
LL | fn foo(x: bool) -> Self { Bar }
| ^ found 0 type parameters
-error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters
+error[E0049]: associated function `fuzz` has 0 type parameters but its trait declaration has 2 type parameters
--> $DIR/E0049.rs:18:12
|
LL | fn fuzz<A: Default, B>(x: A, y: B) -> Self;
diff --git a/tests/ui/error-codes/E0195.rs b/tests/ui/error-codes/E0195.rs
index f712ee4..a7e51df 100644
--- a/tests/ui/error-codes/E0195.rs
+++ b/tests/ui/error-codes/E0195.rs
@@ -1,13 +1,13 @@
trait Trait {
fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
- //~^ NOTE lifetimes in impl do not match this method in trait
+ //~^ NOTE lifetimes in impl do not match this associated function in trait
}
struct Foo;
impl Trait for Foo {
fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
- //~^ NOTE lifetimes do not match method in trait
+ //~^ NOTE lifetimes do not match associated function in trait
}
}
diff --git a/tests/ui/error-codes/E0195.stderr b/tests/ui/error-codes/E0195.stderr
index b88064b..9767dee 100644
--- a/tests/ui/error-codes/E0195.stderr
+++ b/tests/ui/error-codes/E0195.stderr
@@ -1,11 +1,11 @@
-error[E0195]: lifetime parameters or bounds on method `bar` do not match the trait declaration
+error[E0195]: lifetime parameters or bounds on associated function `bar` do not match the trait declaration
--> $DIR/E0195.rs:9:11
|
LL | fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
- | ---------- lifetimes in impl do not match this method in trait
+ | ---------- lifetimes in impl do not match this associated function in trait
...
LL | fn bar<'a,'b>(x: &'a str, y: &'b str) {
- | ^^^^^^^ lifetimes do not match method in trait
+ | ^^^^^^^ lifetimes do not match associated function in trait
error: aborting due to 1 previous error
diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr
index fc08395..381eca5 100644
--- a/tests/ui/error-codes/E0283.stderr
+++ b/tests/ui/error-codes/E0283.stderr
@@ -7,10 +7,12 @@
LL | let cont: u32 = Coroutine::create();
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
-help: use a fully-qualified path to a specific available implementation
+help: use a fully-qualified path to one of the available implementations
|
-LL | let cont: u32 = </* self type */ as Coroutine>::create();
- | +++++++++++++++++++ +
+LL | let cont: u32 = <Impl as Coroutine>::create();
+ | ++++++++ +
+LL | let cont: u32 = <AnotherImpl as Coroutine>::create();
+ | +++++++++++++++ +
error[E0283]: type annotations needed
--> $DIR/E0283.rs:35:24
diff --git a/tests/ui/error-codes/E0396-fixed.stderr b/tests/ui/error-codes/E0396-fixed.stderr
index 2f8ea79..c14f494 100644
--- a/tests/ui/error-codes/E0396-fixed.stderr
+++ b/tests/ui/error-codes/E0396-fixed.stderr
@@ -2,7 +2,7 @@
--> $DIR/E0396-fixed.rs:5:28
|
LL | const VALUE: u8 = unsafe { *REG_ADDR };
- | ^^^^^^^^^ memory access failed: 0x5f3759df[noalloc] is a dangling pointer (it has no provenance)
+ | ^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x5f3759df[noalloc] which is a dangling pointer (it has no provenance)
error: aborting due to 1 previous error
diff --git a/tests/ui/error-codes/E0432.stderr b/tests/ui/error-codes/E0432.stderr
index a0b17e3..36fefc9 100644
--- a/tests/ui/error-codes/E0432.stderr
+++ b/tests/ui/error-codes/E0432.stderr
@@ -4,7 +4,10 @@
LL | use something::Foo;
| ^^^^^^^^^ you might be missing crate `something`
|
- = help: consider adding `extern crate something` to use the `something` crate
+help: consider importing the `something` crate
+ |
+LL + extern crate something;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr
index 343bca9..5826695 100644
--- a/tests/ui/error-codes/E0504.stderr
+++ b/tests/ui/error-codes/E0504.stderr
@@ -21,7 +21,7 @@
| ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let fancy_ref = &fancy_num;
- | ---------- you could clone this value
+ | --------- you could clone this value
error: aborting due to 1 previous error
diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr
index 266df9e..3f2913e 100644
--- a/tests/ui/error-codes/E0505.stderr
+++ b/tests/ui/error-codes/E0505.stderr
@@ -18,7 +18,7 @@
| ^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let _ref_to_val: &Value = &x;
- | -- you could clone this value
+ | - you could clone this value
error: aborting due to 1 previous error
diff --git a/tests/ui/error-codes/E0790.stderr b/tests/ui/error-codes/E0790.stderr
index 6338a10..106554b 100644
--- a/tests/ui/error-codes/E0790.stderr
+++ b/tests/ui/error-codes/E0790.stderr
@@ -63,10 +63,12 @@
LL | MyTrait2::my_fn();
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
-help: use a fully-qualified path to a specific available implementation
+help: use a fully-qualified path to one of the available implementations
|
-LL | </* self type */ as MyTrait2>::my_fn();
- | +++++++++++++++++++ +
+LL | <Impl1 as MyTrait2>::my_fn();
+ | +++++++++ +
+LL | <Impl2 as MyTrait2>::my_fn();
+ | +++++++++ +
error: aborting due to 5 previous errors
diff --git a/tests/ui/extern/extern-types-field-offset.run.stderr b/tests/ui/extern/extern-types-field-offset.run.stderr
index 1b04b86..f140739 100644
--- a/tests/ui/extern/extern-types-field-offset.run.stderr
+++ b/tests/ui/extern/extern-types-field-offset.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL:
+thread 'main' panicked at core/src/panicking.rs:$LINE:$COL:
attempted to compute the size or alignment of extern type `Opaque`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused non-unwinding panic. aborting.
diff --git a/tests/ui/extern/extern-types-size_of_val.align.run.stderr b/tests/ui/extern/extern-types-size_of_val.align.run.stderr
index 20c4d87..faad1aa 100644
--- a/tests/ui/extern/extern-types-size_of_val.align.run.stderr
+++ b/tests/ui/extern/extern-types-size_of_val.align.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL:
+thread 'main' panicked at core/src/panicking.rs:$LINE:$COL:
attempted to compute the size or alignment of extern type `A`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused non-unwinding panic. aborting.
diff --git a/tests/ui/extern/extern-types-size_of_val.size.run.stderr b/tests/ui/extern/extern-types-size_of_val.size.run.stderr
index 20c4d87..faad1aa 100644
--- a/tests/ui/extern/extern-types-size_of_val.size.run.stderr
+++ b/tests/ui/extern/extern-types-size_of_val.size.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL:
+thread 'main' panicked at core/src/panicking.rs:$LINE:$COL:
attempted to compute the size or alignment of extern type `A`
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused non-unwinding panic. aborting.
diff --git a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
index 65e7737..032d7ad 100644
--- a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
+++ b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr
@@ -47,7 +47,6 @@
= note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
= help: add `#![feature(coroutines)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
--> $DIR/feature-gate-coroutines.rs:5:5
@@ -69,7 +68,6 @@
= note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
= help: add `#![feature(coroutines)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
- = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks
--> $DIR/feature-gate-coroutines.rs:10:16
diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
deleted file mode 100644
index 308de26..0000000
--- a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
- --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8
- |
-LL | fn avg<T=i32>(_: T) {}
- | ^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
- = note: `#[deny(invalid_type_param_default)]` on by default
-
-error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
- --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6
- |
-LL | impl<T=i32> S<T> {}
- | ^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs
index f0cc9ea..7989159 100644
--- a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.rs
@@ -5,5 +5,5 @@ fn foo() -> Result<u32, !> {
}
fn main() {
- let Ok(_x) = foo(); //~ ERROR refutable pattern in local binding
+ let Ok(_x) = &foo(); //~ ERROR refutable pattern in local binding
}
diff --git a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index d34f257..4836ffe 100644
--- a/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/tests/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -1,16 +1,16 @@
error[E0005]: refutable pattern in local binding
--> $DIR/feature-gate-exhaustive-patterns.rs:8:9
|
-LL | let Ok(_x) = foo();
- | ^^^^^^ pattern `Err(_)` not covered
+LL | let Ok(_x) = &foo();
+ | ^^^^^^ pattern `&Err(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
- = note: the matched value is of type `Result<u32, !>`
+ = note: the matched value is of type `&Result<u32, !>`
help: you might want to use `let else` to handle the variant that isn't matched
|
-LL | let Ok(_x) = foo() else { todo!() };
- | ++++++++++++++++
+LL | let Ok(_x) = &foo() else { todo!() };
+ | ++++++++++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
index 1f2f7ee..cc9efeb 100644
--- a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
+++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
@@ -1,5 +1,3 @@
-#![feature(offset_of_nested)]
-
use std::mem::offset_of;
enum Alpha {
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
index fc7dd79..8a73abc 100644
--- a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
+++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
@@ -1,5 +1,5 @@
error[E0573]: expected type, found variant `Alpha::One`
- --> $DIR/feature-gate-offset-of-enum.rs:11:16
+ --> $DIR/feature-gate-offset-of-enum.rs:9:16
|
LL | offset_of!(Alpha::One, 0);
| ^^^^^^^^^^
@@ -8,7 +8,7 @@
| help: try using the variant's enum: `Alpha`
error[E0658]: using enums in offset_of is experimental
- --> $DIR/feature-gate-offset-of-enum.rs:12:23
+ --> $DIR/feature-gate-offset-of-enum.rs:10:23
|
LL | offset_of!(Alpha, One);
| ^^^
@@ -18,13 +18,13 @@
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0795]: `One` is an enum variant; expected field at end of `offset_of`
- --> $DIR/feature-gate-offset-of-enum.rs:12:23
+ --> $DIR/feature-gate-offset-of-enum.rs:10:23
|
LL | offset_of!(Alpha, One);
| ^^^ enum variant
error[E0658]: using enums in offset_of is experimental
- --> $DIR/feature-gate-offset-of-enum.rs:14:23
+ --> $DIR/feature-gate-offset-of-enum.rs:12:23
|
LL | offset_of!(Alpha, Two.0);
| ^^^
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs
deleted file mode 100644
index c4eb472..0000000
--- a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![feature(offset_of_enum)]
-
-use std::mem::offset_of;
-
-struct S {
- a: u8,
- b: (u8, u8),
- c: T,
-}
-
-struct T {
- t: &'static str,
-}
-
-enum Alpha {
- One(u8),
- Two(u8),
-}
-
-fn main() {
- offset_of!(Alpha, Two.0); //~ ERROR only a single ident or integer is stable as the field in offset_of
- offset_of!(S, a);
- offset_of!((u8, S), 1);
- offset_of!((u32, (S, T)), 1.1); //~ ERROR only a single ident or integer is stable as the field in offset_of
- offset_of!(S, b.0); //~ ERROR only a single ident or integer is stable as the field in offset_of
- offset_of!((S, ()), 0.c); //~ ERROR only a single ident or integer is stable as the field in offset_of
- offset_of!(S, c.t); //~ ERROR only a single ident or integer is stable as the field in offset_of
-}
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
deleted file mode 100644
index f367fc9..0000000
--- a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
+++ /dev/null
@@ -1,60 +0,0 @@
-error[E0658]: only a single ident or integer is stable as the field in offset_of
- --> $DIR/feature-gate-offset-of-nested.rs:21:27
- |
-LL | offset_of!(Alpha, Two.0);
- | ^
- |
- = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
- = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: only a single ident or integer is stable as the field in offset_of
- --> $DIR/feature-gate-offset-of-nested.rs:24:33
- |
-LL | offset_of!((u32, (S, T)), 1.1);
- | _____----------------------------^-
- | | |
- | | in this macro invocation
-LL | | offset_of!(S, b.0);
-LL | | offset_of!((S, ()), 0.c);
-LL | | offset_of!(S, c.t);
-... |
- |
- = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
- = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
- = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0658]: only a single ident or integer is stable as the field in offset_of
- --> $DIR/feature-gate-offset-of-nested.rs:25:21
- |
-LL | offset_of!(S, b.0);
- | ^
- |
- = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
- = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: only a single ident or integer is stable as the field in offset_of
- --> $DIR/feature-gate-offset-of-nested.rs:26:27
- |
-LL | offset_of!((S, ()), 0.c);
- | ^
- |
- = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
- = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: only a single ident or integer is stable as the field in offset_of
- --> $DIR/feature-gate-offset-of-nested.rs:27:21
- |
-LL | offset_of!(S, c.t);
- | ^
- |
- = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
- = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs
new file mode 100644
index 0000000..176a40e
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs
@@ -0,0 +1,6 @@
+//@ only-x86_64
+#[target_feature(enable = "sha512")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr
new file mode 100644
index 0000000..da9eea0
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the target feature `sha512` is currently unstable
+ --> $DIR/feature-gate-sha512_sm_x86.rs:2:18
+ |
+LL | #[target_feature(enable = "sha512")]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #126624 <https://github.com/rust-lang/rust/issues/126624> for more information
+ = help: add `#![feature(sha512_sm_x86)]` to the crate attributes to enable
+ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
deleted file mode 100644
index 3ea62e8..0000000
--- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-unsafe extern "C" {
- //~^ ERROR extern block cannot be declared unsafe
-}
-
-// We can't gate `unsafe extern` blocks themselves since they were previously
-// allowed, but we should gate the `safe` soft keyword.
-#[cfg(any())]
-unsafe extern "C" {
- safe fn foo();
- //~^ ERROR `unsafe extern {}` blocks and `safe` keyword are experimental
-}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
deleted file mode 100644
index 5653494..0000000
--- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: extern block cannot be declared unsafe
- --> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1
- |
-LL | unsafe extern "C" {
- | ^^^^^^
- |
- = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
- = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental
- --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5
- |
-LL | safe fn foo();
- | ^^^^
- |
- = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
- = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/version_check.rs b/tests/ui/feature-gates/version_check.rs
new file mode 100644
index 0000000..e212dc7
--- /dev/null
+++ b/tests/ui/feature-gates/version_check.rs
@@ -0,0 +1,17 @@
+//@ run-pass
+//@ only-linux
+//@ only-x86
+// FIXME: this should be more like //@ needs-subprocesses
+use std::process::Command;
+
+fn main() {
+ let signalled_version = "Ceci n'est pas une rustc";
+ let version = Command::new(std::env::var_os("RUSTC").unwrap())
+ .env("RUSTC_OVERRIDE_VERSION_STRING", signalled_version)
+ .arg("--version")
+ .output()
+ .unwrap()
+ .stdout;
+ let version = std::str::from_utf8(&version).unwrap().strip_prefix("rustc ").unwrap().trim_end();
+ assert_eq!(version, signalled_version);
+}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
index b8ec2e3..4e64ed6 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
@@ -13,9 +13,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let y = f(&x, ());
-LL + let y = f(x.clone(), ());
- |
+LL | let y = f(&x.clone(), ());
+ | ++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs
index a7489f6..38be325 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs
@@ -5,6 +5,7 @@
// if the `T: 'a` bound gets implied we would probably get ub here again
impl<'a, T> Trait<'a> for T {
//~^ ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
type Type = ();
}
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
index 382ab86..b2aa1ab 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
@@ -16,8 +16,21 @@
LL | impl<'a, T: 'a> Trait<'a> for T {
| ++++
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:27
+ |
+LL | impl<'a, T> Trait<'a> for T {
+ | -- ^ ...so that the type `T` will meet its required lifetime bounds
+ | |
+ | the parameter type `T` must be valid for the lifetime `'a` as defined here...
+ |
+help: consider adding an explicit lifetime bound
+ |
+LL | impl<'a, T: 'a> Trait<'a> for T {
+ | ++++
+
error[E0505]: cannot move out of `x` because it is borrowed
- --> $DIR/implied-bounds-unnorm-associated-type-5.rs:21:10
+ --> $DIR/implied-bounds-unnorm-associated-type-5.rs:22:10
|
LL | let x = String::from("Hello World!");
| - binding `x` declared here
@@ -30,11 +43,10 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let y = f(&x, ());
-LL + let y = f(x.clone(), ());
- |
+LL | let y = f(&x.clone(), ());
+ | ++++++++
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
Some errors have detailed explanations: E0309, E0505.
For more information about an error, try `rustc --explain E0309`.
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
index ce97d85..2a74313 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
@@ -13,9 +13,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let y = f(&x, ());
-LL + let y = f(x.clone(), ());
- |
+LL | let y = f(&x.clone(), ());
+ | ++++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
index 2854931..946cb1a 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
+++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.rs
@@ -8,7 +8,7 @@ impl<T> X for T { //~ ERROR: not all trait items implemented
fn foo<'a, T1: X<Y = T1>>(t : T1) -> T1::Y<'a> {
//~^ ERROR missing generics for associated type
//~^^ ERROR missing generics for associated type
- //~| ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+ //~| ERROR associated function `foo` has 1 type parameter but its trait declaration has 0 type parameters
t
}
}
diff --git a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
index 6a600ae..72c2bdc 100644
--- a/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
+++ b/tests/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated function `foo` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/gat-trait-path-missing-lifetime.rs:8:10
|
LL | fn foo<'a>(t : Self::Y<'a>) -> Self::Y<'a> { t }
diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs
index e58b6f6..b33fda8 100644
--- a/tests/ui/generic-associated-types/issue-71176.rs
+++ b/tests/ui/generic-associated-types/issue-71176.rs
@@ -16,6 +16,6 @@ struct Holder<B> {
fn main() {
Holder {
- inner: Box::new(()),
+ inner: Box::new(()), //~ ERROR: the trait `Provider` cannot be made into an object
};
}
diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr
index a1913bb..9f83c16 100644
--- a/tests/ui/generic-associated-types/issue-71176.stderr
+++ b/tests/ui/generic-associated-types/issue-71176.stderr
@@ -64,7 +64,23 @@
= help: consider moving `A` to another trait
= help: only type `()` implements the trait, consider using it directly instead
-error: aborting due to 4 previous errors
+error[E0038]: the trait `Provider` cannot be made into an object
+ --> $DIR/issue-71176.rs:19:16
+ |
+LL | inner: Box::new(()),
+ | ^^^^^^^^^^^^ `Provider` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-71176.rs:2:10
+ |
+LL | trait Provider {
+ | -------- this trait cannot be made into an object...
+LL | type A<'a>;
+ | ^ ...because it contains the generic associated type `A`
+ = help: consider moving `A` to another trait
+ = help: only type `()` implements the trait, consider using it directly instead
+
+error: aborting due to 5 previous errors
Some errors have detailed explanations: E0038, E0107.
For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed
index ff69016..703d3c1 100644
--- a/tests/ui/generic-associated-types/missing-bounds.fixed
+++ b/tests/ui/generic-associated-types/missing-bounds.fixed
@@ -2,7 +2,6 @@
use std::ops::Add;
-#[allow(dead_code)]
struct A<B>(B);
impl<B> Add for A<B> where B: Add<Output = B> {
@@ -13,7 +12,6 @@
}
}
-#[allow(dead_code)]
struct C<B>(B);
impl<B: Add<Output = B>> Add for C<B> {
@@ -24,7 +22,6 @@
}
}
-#[allow(dead_code)]
struct D<B>(B);
impl<B: std::ops::Add<Output = B>> Add for D<B> {
@@ -35,7 +32,6 @@
}
}
-#[allow(dead_code)]
struct E<B>(B);
impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> {
diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs
index 1f83356..f40b422 100644
--- a/tests/ui/generic-associated-types/missing-bounds.rs
+++ b/tests/ui/generic-associated-types/missing-bounds.rs
@@ -2,7 +2,6 @@
use std::ops::Add;
-#[allow(dead_code)]
struct A<B>(B);
impl<B> Add for A<B> where B: Add {
@@ -13,7 +12,6 @@ fn add(self, rhs: Self) -> Self {
}
}
-#[allow(dead_code)]
struct C<B>(B);
impl<B: Add> Add for C<B> {
@@ -24,7 +22,6 @@ fn add(self, rhs: Self) -> Self {
}
}
-#[allow(dead_code)]
struct D<B>(B);
impl<B> Add for D<B> {
@@ -35,7 +32,6 @@ fn add(self, rhs: Self) -> Self {
}
}
-#[allow(dead_code)]
struct E<B>(B);
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr
index 0f0dc24..1d7d80d 100644
--- a/tests/ui/generic-associated-types/missing-bounds.stderr
+++ b/tests/ui/generic-associated-types/missing-bounds.stderr
@@ -1,5 +1,5 @@
error: equality constraints are not yet supported in `where` clauses
- --> $DIR/missing-bounds.rs:41:33
+ --> $DIR/missing-bounds.rs:37:33
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
@@ -11,7 +11,7 @@
| ~~~~~~~~~~~~~~~~~~
error[E0308]: mismatched types
- --> $DIR/missing-bounds.rs:12:11
+ --> $DIR/missing-bounds.rs:11:11
|
LL | impl<B> Add for A<B> where B: Add {
| - expected this type parameter
@@ -24,14 +24,14 @@
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
- --> $DIR/missing-bounds.rs:12:9
+ --> $DIR/missing-bounds.rs:11:9
|
LL | A(self.0 + rhs.0)
| ^^--------------^
| |
| this argument influences the type of `A`
note: tuple struct defined here
- --> $DIR/missing-bounds.rs:6:8
+ --> $DIR/missing-bounds.rs:5:8
|
LL | struct A<B>(B);
| ^
@@ -41,7 +41,7 @@
| ++++++++++++
error[E0308]: mismatched types
- --> $DIR/missing-bounds.rs:23:14
+ --> $DIR/missing-bounds.rs:21:14
|
LL | impl<B: Add> Add for C<B> {
| - expected this type parameter
@@ -54,7 +54,7 @@
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
note: tuple struct defined here
- --> $DIR/missing-bounds.rs:17:8
+ --> $DIR/missing-bounds.rs:15:8
|
LL | struct C<B>(B);
| ^
@@ -64,7 +64,7 @@
| ++++++++++++
error[E0369]: cannot add `B` to `B`
- --> $DIR/missing-bounds.rs:34:21
+ --> $DIR/missing-bounds.rs:31:21
|
LL | Self(self.0 + rhs.0)
| ------ ^ ----- B
@@ -77,7 +77,7 @@
| +++++++++++++++++++++++++++
error[E0308]: mismatched types
- --> $DIR/missing-bounds.rs:46:14
+ --> $DIR/missing-bounds.rs:42:14
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
| - expected this type parameter
@@ -90,7 +90,7 @@
= note: expected type parameter `B`
found associated type `<B as Add>::Output`
note: tuple struct defined here
- --> $DIR/missing-bounds.rs:39:8
+ --> $DIR/missing-bounds.rs:35:8
|
LL | struct E<B>(B);
| ^
diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr
index 5c1778b..bfed4cd 100644
--- a/tests/ui/hygiene/panic-location.run.stderr
+++ b/tests/ui/hygiene/panic-location.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at library/alloc/src/raw_vec.rs:LL:CC:
+thread 'main' panicked at alloc/src/raw_vec.rs:LL:CC:
capacity overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
index 3c4499f..886fc1d 100644
--- a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed
@@ -1,8 +1,6 @@
//@ run-rustfix
-#[allow(dead_code)]
struct S<T>(T);
-#[allow(dead_code)]
struct S2;
impl<T: Default> Default for S<T> {
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
index ac07832..f327199 100644
--- a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs
@@ -1,8 +1,6 @@
//@ run-rustfix
-#[allow(dead_code)]
struct S<T>(T);
-#[allow(dead_code)]
struct S2;
impl<T: Default> impl Default for S<T> {
diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
index 91c7da5..5aafc8b 100644
--- a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
+++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr
@@ -1,23 +1,23 @@
error: unexpected `impl` keyword
- --> $DIR/extra-impl-in-trait-impl.rs:8:18
+ --> $DIR/extra-impl-in-trait-impl.rs:6:18
|
LL | impl<T: Default> impl Default for S<T> {
| ^^^^^ help: remove the extra `impl`
|
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
- --> $DIR/extra-impl-in-trait-impl.rs:8:18
+ --> $DIR/extra-impl-in-trait-impl.rs:6:18
|
LL | impl<T: Default> impl Default for S<T> {
| ^^^^^^^^^^^^
error: unexpected `impl` keyword
- --> $DIR/extra-impl-in-trait-impl.rs:14:6
+ --> $DIR/extra-impl-in-trait-impl.rs:12:6
|
LL | impl impl Default for S2 {
| ^^^^^ help: remove the extra `impl`
|
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
- --> $DIR/extra-impl-in-trait-impl.rs:14:6
+ --> $DIR/extra-impl-in-trait-impl.rs:12:6
|
LL | impl impl Default for S2 {
| ^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs
new file mode 100644
index 0000000..d7b6243
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs
@@ -0,0 +1,29 @@
+#![feature(precise_capturing)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+ fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32>;
+}
+
+trait ErasedMyTrait {
+ fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32)
+ -> Pin<Box<dyn Future<Output = i32> + 'dynosaur>>
+ where
+ 'life0: 'dynosaur,
+ 'life1: 'dynosaur;
+}
+
+struct DynMyTrait<T: ErasedMyTrait> {
+ ptr: T,
+}
+
+impl<T: ErasedMyTrait> MyTrait for DynMyTrait<T> {
+ fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
+ self.ptr.foo(x)
+ //~^ ERROR hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr
new file mode 100644
index 0000000..92ef66c
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr
@@ -0,0 +1,13 @@
+error[E0700]: hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
+ --> $DIR/cannot-capture-intersection.rs:24:9
+ |
+LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
+ | ------------------------- opaque type defined here
+LL | self.ptr.foo(x)
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: hidden type `Pin<Box<dyn Future<Output = i32>>>` captures lifetime `'_`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
index d9fac02..0477de3 100644
--- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
+++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
@@ -6,7 +6,7 @@ trait Foo {
impl Foo for S {
fn bar() -> impl Sized {}
- //~^ ERROR method `bar` has 0 type parameters but its trait declaration has 1 type parameter
+ //~^ ERROR associated function `bar` has 0 type parameters but its trait declaration has 1 type parameter
}
fn main() {
diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
index eed4c07..ca67db4 100644
--- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
+++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter
+error[E0049]: associated function `bar` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/trait-more-generics-than-impl.rs:8:11
|
LL | fn bar<T>() -> impl Sized;
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index 4d4ba58..b7cee7d 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -2,17 +2,12 @@
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
- | -- ------------------ opaque type defined here
- | |
- | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+ | ------------------ opaque type defined here
...
LL | if condition() { a } else { b }
| ^
|
-help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
- |
-LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
- | ++++
+ = note: hidden type `Ordinary<'_>` captures lifetime `'_`
error: aborting due to 1 previous error
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index 060eaa7..d1190da 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -2,17 +2,12 @@
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
- | -- ------------------ opaque type defined here
- | |
- | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+ | ------------------ opaque type defined here
...
LL | if condition() { a } else { b }
| ^
|
-help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
- |
-LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
- | ++++
+ = note: hidden type `Ordinary<'_>` captures lifetime `'_`
error: aborting due to 1 previous error
diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index f0d259d..1fb69db 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -433,3 +433,25 @@
Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0599, E0658, E0666.
For more information about an error, try `rustc --explain E0053`.
+Future incompatibility report: Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/where-allowed.rs:239:7
+ |
+LL | impl <T = impl Debug> T {}
+ | ^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
+Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/where-allowed.rs:246:36
+ |
+LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
+ | ^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.stderr
index 59b000a..dd35627 100644
--- a/tests/ui/imports/import-from-missing-star-2.stderr
+++ b/tests/ui/imports/import-from-missing-star-2.stderr
@@ -4,7 +4,10 @@
LL | use spam::*;
| ^^^^ you might be missing crate `spam`
|
- = help: consider adding `extern crate spam` to use the `spam` crate
+help: consider importing the `spam` crate
+ |
+LL + extern crate spam;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/import-from-missing-star-3.stderr b/tests/ui/imports/import-from-missing-star-3.stderr
index 23df6b3..1e2412b 100644
--- a/tests/ui/imports/import-from-missing-star-3.stderr
+++ b/tests/ui/imports/import-from-missing-star-3.stderr
@@ -4,7 +4,10 @@
LL | use spam::*;
| ^^^^ you might be missing crate `spam`
|
- = help: consider adding `extern crate spam` to use the `spam` crate
+help: consider importing the `spam` crate
+ |
+LL + extern crate spam;
+ |
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-3.rs:27:13
@@ -12,7 +15,10 @@
LL | use spam::*;
| ^^^^ you might be missing crate `spam`
|
- = help: consider adding `extern crate spam` to use the `spam` crate
+help: consider importing the `spam` crate
+ |
+LL + extern crate spam;
+ |
error: aborting due to 2 previous errors
diff --git a/tests/ui/imports/import-from-missing-star.stderr b/tests/ui/imports/import-from-missing-star.stderr
index b311527..c9bb9ba 100644
--- a/tests/ui/imports/import-from-missing-star.stderr
+++ b/tests/ui/imports/import-from-missing-star.stderr
@@ -4,7 +4,10 @@
LL | use spam::*;
| ^^^^ you might be missing crate `spam`
|
- = help: consider adding `extern crate spam` to use the `spam` crate
+help: consider importing the `spam` crate
+ |
+LL + extern crate spam;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr
index 06260ef..157b5b6 100644
--- a/tests/ui/imports/import3.stderr
+++ b/tests/ui/imports/import3.stderr
@@ -4,7 +4,10 @@
LL | use main::bar;
| ^^^^ you might be missing crate `main`
|
- = help: consider adding `extern crate main` to use the `main` crate
+help: consider importing the `main` crate
+ |
+LL + extern crate main;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr
index fe06edd..e66528e 100644
--- a/tests/ui/imports/issue-109343.stderr
+++ b/tests/ui/imports/issue-109343.stderr
@@ -4,7 +4,10 @@
LL | pub use unresolved::f;
| ^^^^^^^^^^ you might be missing crate `unresolved`
|
- = help: consider adding `extern crate unresolved` to use the `unresolved` crate
+help: consider importing the `unresolved` crate
+ |
+LL + extern crate unresolved;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/issue-1697.rs b/tests/ui/imports/issue-1697.rs
index 8ec48d4..0192376 100644
--- a/tests/ui/imports/issue-1697.rs
+++ b/tests/ui/imports/issue-1697.rs
@@ -3,6 +3,6 @@
use unresolved::*;
//~^ ERROR unresolved import `unresolved` [E0432]
//~| NOTE you might be missing crate `unresolved`
-//~| HELP consider adding `extern crate unresolved` to use the `unresolved` crate
+//~| HELP consider importing the `unresolved` crate
fn main() {}
diff --git a/tests/ui/imports/issue-1697.stderr b/tests/ui/imports/issue-1697.stderr
index df2957b..ec0d94b 100644
--- a/tests/ui/imports/issue-1697.stderr
+++ b/tests/ui/imports/issue-1697.stderr
@@ -4,7 +4,10 @@
LL | use unresolved::*;
| ^^^^^^^^^^ you might be missing crate `unresolved`
|
- = help: consider adding `extern crate unresolved` to use the `unresolved` crate
+help: consider importing the `unresolved` crate
+ |
+LL + extern crate unresolved;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/issue-33464.stderr b/tests/ui/imports/issue-33464.stderr
index 17cc0e4..28fbcee 100644
--- a/tests/ui/imports/issue-33464.stderr
+++ b/tests/ui/imports/issue-33464.stderr
@@ -4,7 +4,10 @@
LL | use abc::one_el;
| ^^^ you might be missing crate `abc`
|
- = help: consider adding `extern crate abc` to use the `abc` crate
+help: consider importing the `abc` crate
+ |
+LL + extern crate abc;
+ |
error[E0432]: unresolved import `abc`
--> $DIR/issue-33464.rs:5:5
@@ -12,7 +15,10 @@
LL | use abc::{a, bbb, cccccc};
| ^^^ you might be missing crate `abc`
|
- = help: consider adding `extern crate abc` to use the `abc` crate
+help: consider importing the `abc` crate
+ |
+LL + extern crate abc;
+ |
error[E0432]: unresolved import `a_very_long_name`
--> $DIR/issue-33464.rs:7:5
@@ -20,7 +26,10 @@
LL | use a_very_long_name::{el, el2};
| ^^^^^^^^^^^^^^^^ you might be missing crate `a_very_long_name`
|
- = help: consider adding `extern crate a_very_long_name` to use the `a_very_long_name` crate
+help: consider importing the `a_very_long_name` crate
+ |
+LL + extern crate a_very_long_name;
+ |
error: aborting due to 3 previous errors
diff --git a/tests/ui/imports/issue-36881.stderr b/tests/ui/imports/issue-36881.stderr
index 3c136df..004836e 100644
--- a/tests/ui/imports/issue-36881.stderr
+++ b/tests/ui/imports/issue-36881.stderr
@@ -4,7 +4,10 @@
LL | use issue_36881_aux::Foo;
| ^^^^^^^^^^^^^^^ you might be missing crate `issue_36881_aux`
|
- = help: consider adding `extern crate issue_36881_aux` to use the `issue_36881_aux` crate
+help: consider importing the `issue_36881_aux` crate
+ |
+LL + extern crate issue_36881_aux;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr
index 3602070..02c2c80 100644
--- a/tests/ui/imports/issue-37887.stderr
+++ b/tests/ui/imports/issue-37887.stderr
@@ -4,7 +4,10 @@
LL | use test::*;
| ^^^^ you might be missing crate `test`
|
- = help: consider adding `extern crate test` to use the `test` crate
+help: consider importing the `test` crate
+ |
+LL + extern crate test;
+ |
error[E0658]: use of unstable library feature 'test'
--> $DIR/issue-37887.rs:2:5
diff --git a/tests/ui/imports/issue-53269.stderr b/tests/ui/imports/issue-53269.stderr
index 317b3c6..d25d85b 100644
--- a/tests/ui/imports/issue-53269.stderr
+++ b/tests/ui/imports/issue-53269.stderr
@@ -4,7 +4,10 @@
LL | use nonexistent_module::mac;
| ^^^^^^^^^^^^^^^^^^ you might be missing crate `nonexistent_module`
|
- = help: consider adding `extern crate nonexistent_module` to use the `nonexistent_module` crate
+help: consider importing the `nonexistent_module` crate
+ |
+LL + extern crate nonexistent_module;
+ |
error[E0659]: `mac` is ambiguous
--> $DIR/issue-53269.rs:8:5
diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr
index e9126e6..9c99b6a 100644
--- a/tests/ui/imports/issue-55457.stderr
+++ b/tests/ui/imports/issue-55457.stderr
@@ -13,7 +13,10 @@
LL | use non_existent::non_existent;
| ^^^^^^^^^^^^ you might be missing crate `non_existent`
|
- = help: consider adding `extern crate non_existent` to use the `non_existent` crate
+help: consider importing the `non_existent` crate
+ |
+LL + extern crate non_existent;
+ |
error: aborting due to 2 previous errors
diff --git a/tests/ui/imports/issue-55884-2.stderr b/tests/ui/imports/issue-55884-2.stderr
index 8a9d5f2..0d4f01a 100644
--- a/tests/ui/imports/issue-55884-2.stderr
+++ b/tests/ui/imports/issue-55884-2.stderr
@@ -24,10 +24,6 @@
|
LL | pub struct ParseOptions {}
| ^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly
-help: import `ParseOptions` through the re-export
- |
-LL | pub use parser::ParseOptions;
- | ~~~~~~~~~~~~~~~~~~~~
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/issue-81413.stderr b/tests/ui/imports/issue-81413.stderr
index 321b369..aa1246c 100644
--- a/tests/ui/imports/issue-81413.stderr
+++ b/tests/ui/imports/issue-81413.stderr
@@ -4,7 +4,10 @@
LL | pub use doesnt_exist::*;
| ^^^^^^^^^^^^ you might be missing crate `doesnt_exist`
|
- = help: consider adding `extern crate doesnt_exist` to use the `doesnt_exist` crate
+help: consider importing the `doesnt_exist` crate
+ |
+LL + extern crate doesnt_exist;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs
index f1de064..0064eaa 100644
--- a/tests/ui/imports/redundant-import-extern-prelude.rs
+++ b/tests/ui/imports/redundant-import-extern-prelude.rs
@@ -1,16 +1,17 @@
-//@ check-pass
// Check that we detect imports that are redundant due to the extern prelude
// and that we emit a reasonable diagnostic.
// issue: rust-lang/rust#121915
+//~^^^ NOTE the item `aux_issue_121915` is already defined by the extern prelude
// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
//@ compile-flags: --extern aux_issue_121915 --edition 2018
//@ aux-build: aux-issue-121915.rs
-#[deny(unused_imports)]
+#[deny(redundant_imports)]
+//~^ NOTE the lint level is defined here
fn main() {
use aux_issue_121915;
- //FIXME(unused_imports): ~^ ERROR the item `aux_issue_121915` is imported redundantly
+ //~^ ERROR the item `aux_issue_121915` is imported redundantly
aux_issue_121915::item();
}
diff --git a/tests/ui/imports/redundant-import-extern-prelude.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr
new file mode 100644
index 0000000..6d2518c
--- /dev/null
+++ b/tests/ui/imports/redundant-import-extern-prelude.stderr
@@ -0,0 +1,14 @@
+error: the item `aux_issue_121915` is imported redundantly
+ --> $DIR/redundant-import-extern-prelude.rs:14:9
+ |
+LL | use aux_issue_121915;
+ | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude
+ |
+note: the lint level is defined here
+ --> $DIR/redundant-import-extern-prelude.rs:11:8
+ |
+LL | #[deny(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs
index be3b820..dc499bc 100644
--- a/tests/ui/imports/redundant-import-issue-121915-2015.rs
+++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs
@@ -1,12 +1,11 @@
-//@ check-pass
//@ compile-flags: --extern aux_issue_121915 --edition 2015
//@ aux-build: aux-issue-121915.rs
extern crate aux_issue_121915;
-#[deny(unused_imports)]
+#[deny(redundant_imports)]
fn main() {
use aux_issue_121915;
- //FIXME(unused_imports): ~^ ERROR the item `aux_issue_121915` is imported redundantly
+ //~^ ERROR the item `aux_issue_121915` is imported redundantly
aux_issue_121915::item();
}
diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr
new file mode 100644
index 0000000..f4e9f60
--- /dev/null
+++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr
@@ -0,0 +1,17 @@
+error: the item `aux_issue_121915` is imported redundantly
+ --> $DIR/redundant-import-issue-121915-2015.rs:8:9
+ |
+LL | extern crate aux_issue_121915;
+ | ------------------------------ the item `aux_issue_121915` is already imported here
+...
+LL | use aux_issue_121915;
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/redundant-import-issue-121915-2015.rs:6:8
+ |
+LL | #[deny(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.rs b/tests/ui/imports/redundant-import-lang-prelude-attr.rs
index 59cd570..f7ee918 100644
--- a/tests/ui/imports/redundant-import-lang-prelude-attr.rs
+++ b/tests/ui/imports/redundant-import-lang-prelude-attr.rs
@@ -1,6 +1,6 @@
-//@ check-pass
// Check that we detect imports (of built-in attributes) that are redundant due to
// the language prelude and that we emit a reasonable diagnostic.
+//~^^ NOTE the item `allow` is already defined by the extern prelude
// Note that we use the term "extern prelude" in the label even though "language prelude"
// would be more correct. However, it's not worth special-casing this.
@@ -9,9 +9,10 @@
//@ edition: 2018
-#![deny(unused_imports)]
+#![deny(redundant_imports)]
+//~^ NOTE the lint level is defined here
-use allow; //FIXME(unused_imports): ~ ERROR the item `allow` is imported redundantly
+use allow; //~ ERROR the item `allow` is imported redundantly
#[allow(unused)]
fn main() {}
diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.stderr b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr
new file mode 100644
index 0000000..f0016f5
--- /dev/null
+++ b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr
@@ -0,0 +1,14 @@
+error: the item `allow` is imported redundantly
+ --> $DIR/redundant-import-lang-prelude-attr.rs:15:5
+ |
+LL | use allow;
+ | ^^^^^ the item `allow` is already defined by the extern prelude
+ |
+note: the lint level is defined here
+ --> $DIR/redundant-import-lang-prelude-attr.rs:12:9
+ |
+LL | #![deny(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/redundant-import-lang-prelude.rs b/tests/ui/imports/redundant-import-lang-prelude.rs
index 53d3b70..3f95ffb 100644
--- a/tests/ui/imports/redundant-import-lang-prelude.rs
+++ b/tests/ui/imports/redundant-import-lang-prelude.rs
@@ -1,16 +1,17 @@
-//@ check-pass
// Check that we detect imports that are redundant due to the language prelude
// and that we emit a reasonable diagnostic.
+//~^^ NOTE the item `u8` is already defined by the extern prelude
// Note that we use the term "extern prelude" in the label even though "language prelude"
// would be more correct. However, it's not worth special-casing this.
// See also the discussion in <https://github.com/rust-lang/rust/pull/122954>.
-#![deny(unused_imports)]
+#![deny(redundant_imports)]
+//~^ NOTE the lint level is defined here
use std::primitive::u8;
-//FIXME(unused_imports): ~^ ERROR the item `u8` is imported redundantly
+//~^ ERROR the item `u8` is imported redundantly
const _: u8 = 0;
diff --git a/tests/ui/imports/redundant-import-lang-prelude.stderr b/tests/ui/imports/redundant-import-lang-prelude.stderr
new file mode 100644
index 0000000..4fd5763
--- /dev/null
+++ b/tests/ui/imports/redundant-import-lang-prelude.stderr
@@ -0,0 +1,14 @@
+error: the item `u8` is imported redundantly
+ --> $DIR/redundant-import-lang-prelude.rs:13:5
+ |
+LL | use std::primitive::u8;
+ | ^^^^^^^^^^^^^^^^^^ the item `u8` is already defined by the extern prelude
+ |
+note: the lint level is defined here
+ --> $DIR/redundant-import-lang-prelude.rs:10:9
+ |
+LL | #![deny(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs
index 2bb8283..ee3ceb6 100644
--- a/tests/ui/imports/suggest-remove-issue-121315.rs
+++ b/tests/ui/imports/suggest-remove-issue-121315.rs
@@ -1,20 +1,19 @@
//@ compile-flags: --edition 2021
-
-#![deny(unused_imports)]
+#![deny(unused_imports, redundant_imports)]
#![allow(dead_code)]
fn test0() {
// Test remove FlatUnused
use std::convert::TryFrom;
- //FIXME(unused_imports): ~^ ERROR the item `TryFrom` is imported redundantly
+ //~^ ERROR the item `TryFrom` is imported redundantly
let _ = u32::try_from(5i32);
}
fn test1() {
// FIXME(yukang) Test remove NestedFullUnused
use std::convert::{TryFrom, TryInto};
- //FIXME(unused_imports): ~^ ERROR the item `TryFrom` is imported redundantly
- //FIXME(unused_imports): ~| ERROR the item `TryInto` is imported redundantly
+ //~^ ERROR the item `TryFrom` is imported redundantly
+ //~| ERROR the item `TryInto` is imported redundantly
let _ = u32::try_from(5i32);
let _a: i32 = u32::try_into(5u32).unwrap();
@@ -24,7 +23,7 @@ fn test2() {
// FIXME(yukang): Test remove both redundant and unused
use std::convert::{AsMut, Into};
//~^ ERROR unused import: `AsMut`
- //FIXME(unused_imports): ~| ERROR the item `Into` is imported redundantly
+ //~| ERROR the item `Into` is imported redundantly
let _a: u32 = (5u8).into();
}
diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr
index 5701514..5d0bf9b 100644
--- a/tests/ui/imports/suggest-remove-issue-121315.stderr
+++ b/tests/ui/imports/suggest-remove-issue-121315.stderr
@@ -1,20 +1,62 @@
+error: the item `TryFrom` is imported redundantly
+ --> $DIR/suggest-remove-issue-121315.rs:7:9
+ |
+LL | use std::convert::TryFrom;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `TryFrom` is already defined here
+ |
+note: the lint level is defined here
+ --> $DIR/suggest-remove-issue-121315.rs:2:25
+ |
+LL | #![deny(unused_imports, redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: the item `TryFrom` is imported redundantly
+ --> $DIR/suggest-remove-issue-121315.rs:14:24
+ |
+LL | use std::convert::{TryFrom, TryInto};
+ | ^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `TryFrom` is already defined here
+
+error: the item `TryInto` is imported redundantly
+ --> $DIR/suggest-remove-issue-121315.rs:14:33
+ |
+LL | use std::convert::{TryFrom, TryInto};
+ | ^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `TryInto` is already defined here
+
error: unused import: `AsMut`
- --> $DIR/suggest-remove-issue-121315.rs:25:24
+ --> $DIR/suggest-remove-issue-121315.rs:24:24
|
LL | use std::convert::{AsMut, Into};
| ^^^^^
|
note: the lint level is defined here
- --> $DIR/suggest-remove-issue-121315.rs:3:9
+ --> $DIR/suggest-remove-issue-121315.rs:2:9
|
-LL | #![deny(unused_imports)]
+LL | #![deny(unused_imports, redundant_imports)]
| ^^^^^^^^^^^^^^
+error: the item `Into` is imported redundantly
+ --> $DIR/suggest-remove-issue-121315.rs:24:31
+ |
+LL | use std::convert::{AsMut, Into};
+ | ^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `Into` is already defined here
+
error: unused import: `From`
- --> $DIR/suggest-remove-issue-121315.rs:34:24
+ --> $DIR/suggest-remove-issue-121315.rs:33:24
|
LL | use std::convert::{From, Infallible};
| ^^^^
-error: aborting due to 2 previous errors
+error: aborting due to 6 previous errors
diff --git a/tests/ui/imports/tool-mod-child.stderr b/tests/ui/imports/tool-mod-child.stderr
index 764256e..ec110cc 100644
--- a/tests/ui/imports/tool-mod-child.stderr
+++ b/tests/ui/imports/tool-mod-child.stderr
@@ -4,7 +4,10 @@
LL | use clippy::a::b;
| ^^^^^^ you might be missing crate `clippy`
|
- = help: consider adding `extern crate clippy` to use the `clippy` crate
+help: consider importing the `clippy` crate
+ |
+LL + extern crate clippy;
+ |
error[E0432]: unresolved import `clippy`
--> $DIR/tool-mod-child.rs:1:5
@@ -12,7 +15,10 @@
LL | use clippy::a;
| ^^^^^^ you might be missing crate `clippy`
|
- = help: consider adding `extern crate clippy` to use the `clippy` crate
+help: consider importing the `clippy` crate
+ |
+LL + extern crate clippy;
+ |
error[E0433]: failed to resolve: you might be missing crate `rustdoc`
--> $DIR/tool-mod-child.rs:5:5
@@ -20,7 +26,10 @@
LL | use rustdoc::a::b;
| ^^^^^^^ you might be missing crate `rustdoc`
|
- = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate
+help: consider importing the `rustdoc` crate
+ |
+LL + extern crate rustdoc;
+ |
error[E0432]: unresolved import `rustdoc`
--> $DIR/tool-mod-child.rs:4:5
@@ -28,7 +37,10 @@
LL | use rustdoc::a;
| ^^^^^^^ you might be missing crate `rustdoc`
|
- = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate
+help: consider importing the `rustdoc` crate
+ |
+LL + extern crate rustdoc;
+ |
error: aborting due to 4 previous errors
diff --git a/tests/ui/imports/unresolved-imports-used.stderr b/tests/ui/imports/unresolved-imports-used.stderr
index 1cbc235..4bf02ff 100644
--- a/tests/ui/imports/unresolved-imports-used.stderr
+++ b/tests/ui/imports/unresolved-imports-used.stderr
@@ -16,7 +16,10 @@
LL | use foo::bar;
| ^^^ you might be missing crate `foo`
|
- = help: consider adding `extern crate foo` to use the `foo` crate
+help: consider importing the `foo` crate
+ |
+LL + extern crate foo;
+ |
error[E0432]: unresolved import `baz`
--> $DIR/unresolved-imports-used.rs:12:5
@@ -24,7 +27,10 @@
LL | use baz::*;
| ^^^ you might be missing crate `baz`
|
- = help: consider adding `extern crate baz` to use the `baz` crate
+help: consider importing the `baz` crate
+ |
+LL + extern crate baz;
+ |
error[E0432]: unresolved import `foo2`
--> $DIR/unresolved-imports-used.rs:14:5
@@ -32,7 +38,10 @@
LL | use foo2::bar2;
| ^^^^ you might be missing crate `foo2`
|
- = help: consider adding `extern crate foo2` to use the `foo2` crate
+help: consider importing the `foo2` crate
+ |
+LL + extern crate foo2;
+ |
error[E0432]: unresolved import `baz2`
--> $DIR/unresolved-imports-used.rs:15:5
@@ -40,7 +49,10 @@
LL | use baz2::*;
| ^^^^ you might be missing crate `baz2`
|
- = help: consider adding `extern crate baz2` to use the `baz2` crate
+help: consider importing the `baz2` crate
+ |
+LL + extern crate baz2;
+ |
error[E0603]: function `quz` is private
--> $DIR/unresolved-imports-used.rs:9:10
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs
new file mode 100644
index 0000000..830a639
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs
@@ -0,0 +1,24 @@
+// issue#121613
+
+#![feature(more_qualified_paths)]
+
+struct S {}
+
+struct Foo;
+
+trait A {
+ type Assoc;
+}
+
+impl A for Foo {
+ type Assoc = S;
+}
+
+fn f() {}
+
+fn main() {
+ <Foo as A>::Assoc {};
+ f(|a, b| a.cmp(b));
+ //~^ ERROR: type annotations needed
+ //~| ERROR: this function takes 0 arguments but 1 argument was supplied
+}
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr
new file mode 100644
index 0000000..10056bd
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr
@@ -0,0 +1,32 @@
+error[E0282]: type annotations needed
+ --> $DIR/incompat-call-after-qualified-path-0.rs:21:6
+ |
+LL | f(|a, b| a.cmp(b));
+ | ^ - type must be known at this point
+ |
+help: consider giving this closure parameter an explicit type
+ |
+LL | f(|a: /* Type */, b| a.cmp(b));
+ | ++++++++++++
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+ --> $DIR/incompat-call-after-qualified-path-0.rs:21:3
+ |
+LL | f(|a, b| a.cmp(b));
+ | ^ --------------- unexpected argument
+ |
+note: function defined here
+ --> $DIR/incompat-call-after-qualified-path-0.rs:17:4
+ |
+LL | fn f() {}
+ | ^
+help: remove the extra argument
+ |
+LL - f(|a, b| a.cmp(b));
+LL + f();
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0282.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs
new file mode 100644
index 0000000..6b78633
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs
@@ -0,0 +1,28 @@
+// issue#121613
+
+#![feature(more_qualified_paths)]
+
+struct S<T> {
+ a: T
+}
+
+struct Foo;
+
+trait A {
+ type Assoc<T>;
+}
+
+impl A for Foo {
+ type Assoc<T> = S<T>;
+}
+
+fn f() {}
+
+fn main() {
+ <Foo as A>::Assoc::<i32> {
+ a: 1
+ };
+ f(|a, b| a.cmp(b));
+ //~^ ERROR: type annotations needed
+ //~| ERROR: this function takes 0 arguments but 1 argument was supplied
+}
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr
new file mode 100644
index 0000000..632a9b9
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr
@@ -0,0 +1,32 @@
+error[E0282]: type annotations needed
+ --> $DIR/incompat-call-after-qualified-path-1.rs:25:6
+ |
+LL | f(|a, b| a.cmp(b));
+ | ^ - type must be known at this point
+ |
+help: consider giving this closure parameter an explicit type
+ |
+LL | f(|a: /* Type */, b| a.cmp(b));
+ | ++++++++++++
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+ --> $DIR/incompat-call-after-qualified-path-1.rs:25:3
+ |
+LL | f(|a, b| a.cmp(b));
+ | ^ --------------- unexpected argument
+ |
+note: function defined here
+ --> $DIR/incompat-call-after-qualified-path-1.rs:19:4
+ |
+LL | fn f() {}
+ | ^
+help: remove the extra argument
+ |
+LL - f(|a, b| a.cmp(b));
+LL + f();
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0282.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/inline-const/using-late-bound-from-closure.rs b/tests/ui/inline-const/using-late-bound-from-closure.rs
new file mode 100644
index 0000000..2b12b2e
--- /dev/null
+++ b/tests/ui/inline-const/using-late-bound-from-closure.rs
@@ -0,0 +1,16 @@
+// Test for ICE: cannot convert ReLateParam to a region vid
+// https://github.com/rust-lang/rust/issues/125873
+
+#![feature(closure_lifetime_binder)]
+fn foo() {
+ let a = for<'a> |b: &'a ()| -> &'a () {
+ const {
+ let awd = ();
+ let _: &'a () = &awd;
+ //~^ `awd` does not live long enough
+ };
+ b
+ };
+}
+
+fn main() {}
diff --git a/tests/ui/inline-const/using-late-bound-from-closure.stderr b/tests/ui/inline-const/using-late-bound-from-closure.stderr
new file mode 100644
index 0000000..d6e1579
--- /dev/null
+++ b/tests/ui/inline-const/using-late-bound-from-closure.stderr
@@ -0,0 +1,19 @@
+error[E0597]: `awd` does not live long enough
+ --> $DIR/using-late-bound-from-closure.rs:9:29
+ |
+LL | let a = for<'a> |b: &'a ()| -> &'a () {
+ | -- lifetime `'a` defined here
+LL | const {
+LL | let awd = ();
+ | --- binding `awd` declared here
+LL | let _: &'a () = &awd;
+ | ------ ^^^^ borrowed value does not live long enough
+ | |
+ | type annotation requires that `awd` is borrowed for `'a`
+LL |
+LL | };
+ | - `awd` dropped here while still borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
index 0e894ef..ab46fd7 100644
--- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
+++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
@@ -10,7 +10,7 @@
const RAW_EQ_PTR: bool = unsafe {
std::intrinsics::raw_eq(&(&0), &(&1))
//~^ ERROR evaluation of constant value failed
-//~| `raw_eq` on bytes with provenance
+//~| unable to turn pointer into integer
};
pub fn main() {
diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
index 317466e..af16c2b 100644
--- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
+++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
@@ -8,7 +8,10 @@
--> $DIR/intrinsic-raw_eq-const-bad.rs:11:5
|
LL | std::intrinsics::raw_eq(&(&0), &(&1))
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
+ |
+ = help: this code performed an operation that depends on the underlying bytes representing a pointer
+ = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error: aborting due to 2 previous errors
diff --git a/tests/ui/issues/issue-19380.rs b/tests/ui/issues/issue-19380.rs
index fce737c..8b3fe4d 100644
--- a/tests/ui/issues/issue-19380.rs
+++ b/tests/ui/issues/issue-19380.rs
@@ -15,5 +15,6 @@ struct Bar {
const FOO : Foo = Foo;
const BAR : Bar = Bar { foos: &[&FOO]};
//~^ ERROR E0038
+//~| ERROR E0038
fn main() { }
diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr
index f6244d9..1d7aa6b 100644
--- a/tests/ui/issues/issue-19380.stderr
+++ b/tests/ui/issues/issue-19380.stderr
@@ -45,6 +45,29 @@
LL | fn qiz() where Self: Sized;
| +++++++++++++++++
-error: aborting due to 2 previous errors
+error[E0038]: the trait `Qiz` cannot be made into an object
+ --> $DIR/issue-19380.rs:16:31
+ |
+LL | const BAR : Bar = Bar { foos: &[&FOO]};
+ | ^^^^^^^ `Qiz` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-19380.rs:2:6
+ |
+LL | trait Qiz {
+ | --- this trait cannot be made into an object...
+LL | fn qiz();
+ | ^^^ ...because associated function `qiz` has no `self` parameter
+ = help: only type `Foo` implements the trait, consider using it directly instead
+help: consider turning `qiz` into a method by giving it a `&self` argument
+ |
+LL | fn qiz(&self);
+ | +++++
+help: alternatively, consider constraining `qiz` so it does not apply to trait objects
+ |
+LL | fn qiz() where Self: Sized;
+ | +++++++++++++++++
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs
index 3391ea4..e0723e0 100644
--- a/tests/ui/issues/issue-26812.rs
+++ b/tests/ui/issues/issue-26812.rs
@@ -1,6 +1,6 @@
-#![feature(default_type_parameter_fallback)]
-
fn avg<T=T::Item>(_: T) {}
//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+//~| ERROR defaults for type parameters
+//~| WARN previously accepted
fn main() {}
diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr
index c2a3d4b..4a18b23 100644
--- a/tests/ui/issues/issue-26812.stderr
+++ b/tests/ui/issues/issue-26812.stderr
@@ -1,9 +1,30 @@
error[E0128]: generic parameters with a default cannot use forward declared identifiers
- --> $DIR/issue-26812.rs:3:10
+ --> $DIR/issue-26812.rs:1:10
|
LL | fn avg<T=T::Item>(_: T) {}
| ^^^^^^^ defaulted generic parameters cannot be forward declared
-error: aborting due to 1 previous error
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/issue-26812.rs:1:8
+ |
+LL | fn avg<T=T::Item>(_: T) {}
+ | ^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0128`.
+Future incompatibility report: Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/issue-26812.rs:1:8
+ |
+LL | fn avg<T=T::Item>(_: T) {}
+ | ^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
diff --git a/tests/ui/issues/issue-48728.stderr b/tests/ui/issues/issue-48728.current.stderr
similarity index 95%
rename from tests/ui/issues/issue-48728.stderr
rename to tests/ui/issues/issue-48728.current.stderr
index 6b4247f..2a1b4ff 100644
--- a/tests/ui/issues/issue-48728.stderr
+++ b/tests/ui/issues/issue-48728.current.stderr
@@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Clone` for type `Node<[_]>`
- --> $DIR/issue-48728.rs:4:10
+ --> $DIR/issue-48728.rs:9:10
|
LL | #[derive(Clone)]
| ^^^^^ conflicting implementation for `Node<[_]>`
diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs
index cbdc10b..7ef05f4 100644
--- a/tests/ui/issues/issue-48728.rs
+++ b/tests/ui/issues/issue-48728.rs
@@ -1,7 +1,12 @@
// Regression test for #48728, an ICE that occurred computing
// coherence "help" information.
-#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone`
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone`
struct Node<T: ?Sized>(Box<T>);
impl<T: Clone + ?Sized> Clone for Node<[T]> {
diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/issues/issue-5708.rs
index 89ea9fb..ce9ef78 100644
--- a/tests/ui/issues/issue-5708.rs
+++ b/tests/ui/issues/issue-5708.rs
@@ -44,7 +44,6 @@ pub trait MyTrait<T> {
fn dummy(&self, t: T) -> T { panic!() }
}
-#[allow(dead_code)]
pub struct MyContainer<'a, T:'a> {
foos: Vec<&'a (dyn MyTrait<T>+'a)> ,
}
diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.stderr b/tests/ui/json/json-bom-plus-crlf-multifile.stderr
index 2ed26f9..9c88a7e 100644
--- a/tests/ui/json/json-bom-plus-crlf-multifile.stderr
+++ b/tests/ui/json/json-bom-plus-crlf-multifile.stderr
@@ -24,7 +24,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":623,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":613,"byte_end":619,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":623,"byte_end":623,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":623,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":613,"byte_end":619,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":623,"byte_end":623,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types: expected `String`, found integer
"}
{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -52,7 +52,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":683,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":673,"byte_end":679,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":683,"byte_end":683,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":683,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":673,"byte_end":679,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":683,"byte_end":683,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types: expected `String`, found integer
"}
{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -80,7 +80,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":747,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":736,"byte_end":742,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":747,"byte_end":747,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":747,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":736,"byte_end":742,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":747,"byte_end":747,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types: expected `String`, found integer
"}
{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -108,7 +108,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":802,"byte_end":810,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":793,"byte_end":799,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":802,"byte_end":810,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":793,"byte_end":799,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types: expected `String`, found `()`
"}
{"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr
index b5e6f65..cd1e366 100644
--- a/tests/ui/json/json-bom-plus-crlf.stderr
+++ b/tests/ui/json/json-bom-plus-crlf.stderr
@@ -24,7 +24,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":608,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":598,"byte_end":604,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":608,"byte_end":608,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":608,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":598,"byte_end":604,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":608,"byte_end":608,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types: expected `String`, found integer
"}
{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -52,7 +52,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":668,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":658,"byte_end":664,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":668,"byte_end":668,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":668,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":658,"byte_end":664,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":668,"byte_end":668,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types: expected `String`, found integer
"}
{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -80,7 +80,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":732,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":721,"byte_end":727,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":732,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":732,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":721,"byte_end":727,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":732,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types: expected `String`, found integer
"}
{"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type.
@@ -108,7 +108,7 @@
expected an expression of a different type. It can occur in several cases, the
most common being when calling a function and passing an argument which has a
different type than the matching type in the function declaration.
-"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":787,"byte_end":795,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":778,"byte_end":784,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types
+"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":787,"byte_end":795,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":778,"byte_end":784,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types: expected `String`, found `()`
"}
{"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors
"}
diff --git a/tests/ui/json/json-short.stderr b/tests/ui/json/json-short.stderr
index a3d579c..8a4a55e 100644
--- a/tests/ui/json/json-short.stderr
+++ b/tests/ui/json/json-short.stderr
@@ -13,7 +13,7 @@
[Rust Book][rust-book] to get started.
[rust-book]: https://doc.rust-lang.org/book/
-"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":63,"byte_end":63,"line_start":1,"line_end":1,"column_start":64,"column_end":64,"is_primary":true,"text":[{"text":"//@ compile-flags: --json=diagnostic-short --error-format=json","highlight_start":64,"highlight_end":64}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:64: error[E0601]: `main` function not found in crate `json_short`
+"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":63,"byte_end":63,"line_start":1,"line_end":1,"column_start":64,"column_end":64,"is_primary":true,"text":[{"text":"//@ compile-flags: --json=diagnostic-short --error-format=json","highlight_start":64,"highlight_end":64}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:64: error[E0601]: `main` function not found in crate `json_short`: consider adding a `main` function to `$DIR/json-short.rs`
"}
{"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 1 previous error
"}
diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
index a647ca2..f23f855 100644
--- a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
+++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr
@@ -15,7 +15,10 @@
LL | use extern::foo;
| ^^^^^^ you might be missing crate `r#extern`
|
- = help: consider adding `extern crate r#extern` to use the `r#extern` crate
+help: consider importing the `r#extern` crate
+ |
+LL + extern crate r#extern;
+ |
error: aborting due to 2 previous errors
diff --git a/tests/ui/lifetimes/elided-lint-in-mod.rs b/tests/ui/lifetimes/elided-lint-in-mod.rs
new file mode 100644
index 0000000..afe85cb
--- /dev/null
+++ b/tests/ui/lifetimes/elided-lint-in-mod.rs
@@ -0,0 +1,11 @@
+struct Foo<'a>(&'a ());
+
+fn test(_: Foo) {}
+
+#[deny(elided_lifetimes_in_paths)]
+mod w {
+ fn test2(_: super::Foo) {}
+ //~^ ERROR hidden lifetime parameters in types are deprecated
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/elided-lint-in-mod.stderr b/tests/ui/lifetimes/elided-lint-in-mod.stderr
new file mode 100644
index 0000000..1fee180
--- /dev/null
+++ b/tests/ui/lifetimes/elided-lint-in-mod.stderr
@@ -0,0 +1,20 @@
+error: hidden lifetime parameters in types are deprecated
+ --> $DIR/elided-lint-in-mod.rs:7:24
+ |
+LL | fn test2(_: super::Foo) {}
+ | -------^^^
+ | |
+ | expected lifetime parameter
+ |
+note: the lint level is defined here
+ --> $DIR/elided-lint-in-mod.rs:5:8
+ |
+LL | #[deny(elided_lifetimes_in_paths)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+help: indicate the anonymous lifetime
+ |
+LL | fn test2(_: super::Foo<'_>) {}
+ | ++++
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index e446345..ebf6f6c 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -72,3 +72,14 @@
Some errors have detailed explanations: E0106, E0214, E0308, E0770.
For more information about an error, try `rustc --explain E0106`.
+Future incompatibility report: Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/unusual-rib-combinations.rs:15:6
+ |
+LL | fn c<T = u8()>() {}
+ | ^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
diff --git a/tests/ui/lint/command-line-lint-group-forbid.stderr b/tests/ui/lint/command-line-lint-group-forbid.stderr
index 7b527e7..ec9b6ca 100644
--- a/tests/ui/lint/command-line-lint-group-forbid.stderr
+++ b/tests/ui/lint/command-line-lint-group-forbid.stderr
@@ -5,7 +5,6 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_inappropriate_camel_casing`
|
= note: `-F non-snake-case` implied by `-F bad-style`
- = help: to override `-F bad-style` add `#[allow(non_snake_case)]`
error: aborting due to 1 previous error
diff --git a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs
deleted file mode 100644
index 8cd1524..0000000
--- a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-//@ check-pass
-
-mod ffi {
- use super::*;
-
- extern "C" {
- pub fn DomPromise_AddRef(promise: *const Promise);
- pub fn DomPromise_Release(promise: *const Promise);
- }
-}
-
-#[repr(C)]
-#[allow(unused)]
-pub struct Promise {
- private: [u8; 0],
- __nosync: ::std::marker::PhantomData<::std::rc::Rc<u8>>,
-}
-
-pub unsafe trait RefCounted {
- unsafe fn addref(&self);
- unsafe fn release(&self);
-}
-
-unsafe impl RefCounted for Promise {
- unsafe fn addref(&self) {
- ffi::DomPromise_AddRef(self)
- }
- unsafe fn release(&self) {
- ffi::DomPromise_Release(self)
- }
-}
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/issue-59003.rs b/tests/ui/lint/dead-code/issue-59003.rs
index 319cf2d..e3dcaca 100644
--- a/tests/ui/lint/dead-code/issue-59003.rs
+++ b/tests/ui/lint/dead-code/issue-59003.rs
@@ -4,8 +4,8 @@
#![deny(dead_code)]
-#[allow(dead_code)]
struct Foo {
+ #[allow(dead_code)]
inner: u32,
}
diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs
index 3386dfa..ddcafed 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-1.rs
+++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs
@@ -46,10 +46,11 @@ struct UsedStruct1 {
impl SemiUsedStruct {
fn la_la_la() {}
}
-struct StructUsedAsField; //~ ERROR struct `StructUsedAsField` is never constructed
+struct StructUsedAsField;
pub struct StructUsedInEnum;
struct StructUsedInGeneric;
-pub struct PubStruct2 { //~ ERROR struct `PubStruct2` is never constructed
+pub struct PubStruct2 {
+ #[allow(dead_code)]
struct_used_as_field: *const StructUsedAsField
}
diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr
index b0163df..eb728b5b 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-1.stderr
+++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr
@@ -22,26 +22,14 @@
LL | struct PrivStruct;
| ^^^^^^^^^^
-error: struct `StructUsedAsField` is never constructed
- --> $DIR/lint-dead-code-1.rs:49:8
- |
-LL | struct StructUsedAsField;
- | ^^^^^^^^^^^^^^^^^
-
-error: struct `PubStruct2` is never constructed
- --> $DIR/lint-dead-code-1.rs:52:12
- |
-LL | pub struct PubStruct2 {
- | ^^^^^^^^^^
-
error: enum `priv_enum` is never used
- --> $DIR/lint-dead-code-1.rs:63:6
+ --> $DIR/lint-dead-code-1.rs:64:6
|
LL | enum priv_enum { foo2, bar2 }
| ^^^^^^^^^
error: variant `bar3` is never constructed
- --> $DIR/lint-dead-code-1.rs:66:5
+ --> $DIR/lint-dead-code-1.rs:67:5
|
LL | enum used_enum {
| --------- variant in this enum
@@ -50,25 +38,25 @@
| ^^^^
error: function `priv_fn` is never used
- --> $DIR/lint-dead-code-1.rs:87:4
+ --> $DIR/lint-dead-code-1.rs:88:4
|
LL | fn priv_fn() {
| ^^^^^^^
error: function `foo` is never used
- --> $DIR/lint-dead-code-1.rs:92:4
+ --> $DIR/lint-dead-code-1.rs:93:4
|
LL | fn foo() {
| ^^^
error: function `bar` is never used
- --> $DIR/lint-dead-code-1.rs:97:4
+ --> $DIR/lint-dead-code-1.rs:98:4
|
LL | fn bar() {
| ^^^
error: function `baz` is never used
- --> $DIR/lint-dead-code-1.rs:101:4
+ --> $DIR/lint-dead-code-1.rs:102:4
|
LL | fn baz() -> impl Copy {
| ^^^
@@ -79,5 +67,5 @@
LL | pub struct Bar;
| ^^^
-error: aborting due to 12 previous errors
+error: aborting due to 10 previous errors
diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs
deleted file mode 100644
index 2577743..0000000
--- a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![deny(dead_code)]
-
-struct Foo(u8); //~ ERROR struct `Foo` is never constructed
-
-enum Bar { //~ ERROR enum `Bar` is never used
- Var1(u8),
- Var2(u8),
-}
-
-pub trait Tr1 {
- fn f1() -> Self;
-}
-
-impl Tr1 for Foo {
- fn f1() -> Foo {
- let f = Foo(0);
- let Foo(tag) = f;
- Foo(tag)
- }
-}
-
-impl Tr1 for Bar {
- fn f1() -> Bar {
- let b = Bar::Var1(0);
- let b = if let Bar::Var1(_) = b {
- Bar::Var1(0)
- } else {
- Bar::Var2(0)
- };
- match b {
- Bar::Var1(_) => Bar::Var2(0),
- Bar::Var2(_) => Bar::Var1(0),
- }
- }
-}
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr
deleted file mode 100644
index 7c1a4b4..0000000
--- a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: struct `Foo` is never constructed
- --> $DIR/lint-unused-adt-appeared-in-pattern.rs:3:8
- |
-LL | struct Foo(u8);
- | ^^^
- |
-note: the lint level is defined here
- --> $DIR/lint-unused-adt-appeared-in-pattern.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: enum `Bar` is never used
- --> $DIR/lint-unused-adt-appeared-in-pattern.rs:5:6
- |
-LL | enum Bar {
- | ^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs
deleted file mode 100644
index 43a2e43..0000000
--- a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-//@ check-pass
-
-#![deny(dead_code)]
-
-#[repr(u8)]
-#[derive(Copy, Clone, Debug)]
-pub enum RecordField {
- Target = 1,
- Level,
- Module,
- File,
- Line,
- NumArgs,
-}
-
-unsafe trait Pod {}
-
-#[repr(transparent)]
-struct RecordFieldWrapper(RecordField);
-
-unsafe impl Pod for RecordFieldWrapper {}
-
-fn try_read<T: Pod>(buf: &[u8]) -> T {
- unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const T) }
-}
-
-pub fn foo(buf: &[u8]) -> RecordField {
- let RecordFieldWrapper(tag) = try_read(buf);
- tag
-}
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
index 61babde..8cb242f 100644
--- a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
+++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
@@ -1,6 +1,5 @@
//@ check-pass
-#![feature(offset_of_nested)]
#![deny(dead_code)]
// This struct contains a projection that can only be normalized after getting the field type.
diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs
index 5269426..89e9fd9 100644
--- a/tests/ui/lint/dead-code/offset-of.rs
+++ b/tests/ui/lint/dead-code/offset-of.rs
@@ -1,4 +1,3 @@
-#![feature(offset_of_nested)]
#![deny(dead_code)]
use std::mem::offset_of;
diff --git a/tests/ui/lint/dead-code/offset-of.stderr b/tests/ui/lint/dead-code/offset-of.stderr
index ed29164..4a903a9 100644
--- a/tests/ui/lint/dead-code/offset-of.stderr
+++ b/tests/ui/lint/dead-code/offset-of.stderr
@@ -1,5 +1,5 @@
error: field `b` is never read
- --> $DIR/offset-of.rs:8:5
+ --> $DIR/offset-of.rs:7:5
|
LL | struct Alpha {
| ----- field in this struct
@@ -8,13 +8,13 @@
| ^
|
note: the lint level is defined here
- --> $DIR/offset-of.rs:2:9
+ --> $DIR/offset-of.rs:1:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^
error: field `a` is never read
- --> $DIR/offset-of.rs:13:5
+ --> $DIR/offset-of.rs:12:5
|
LL | struct Beta {
| ---- field in this struct
@@ -22,7 +22,7 @@
| ^
error: field `a` is never read
- --> $DIR/offset-of.rs:18:5
+ --> $DIR/offset-of.rs:17:5
|
LL | struct Gamma {
| ----- field in this struct
@@ -30,7 +30,7 @@
| ^
error: field `b` is never read
- --> $DIR/offset-of.rs:24:5
+ --> $DIR/offset-of.rs:23:5
|
LL | struct Delta {
| ----- field in this struct
@@ -39,7 +39,7 @@
| ^
error: field `a` is never read
- --> $DIR/offset-of.rs:35:5
+ --> $DIR/offset-of.rs:34:5
|
LL | struct Project<T: Trait> {
| ------- field in this struct
diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs
index 658cc3d..5b755d6 100644
--- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs
+++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs
@@ -1,9 +1,8 @@
#![deny(dead_code)]
struct T1; //~ ERROR struct `T1` is never constructed
-struct T2; //~ ERROR struct `T2` is never constructed
-pub struct T3(i32); //~ ERROR struct `T3` is never constructed
-pub struct T4(i32); //~ ERROR field `0` is never read
+pub struct T2(i32); //~ ERROR field `0` is never read
+struct T3;
trait Trait1 { //~ ERROR trait `Trait1` is never used
const UNUSED: i32;
@@ -12,13 +11,13 @@ fn unused(&self) {}
}
pub trait Trait2 {
- const MAY_USED: i32;
- fn may_used(&self) {}
+ const USED: i32;
+ fn used(&self) {}
}
pub trait Trait3 {
- const MAY_USED: i32;
- fn may_used() -> Self;
+ const USED: i32;
+ fn construct_self() -> Self;
}
impl Trait1 for T1 {
@@ -31,34 +30,23 @@ fn construct_self() -> Self {
impl Trait1 for T2 {
const UNUSED: i32 = 0;
fn construct_self() -> Self {
- Self
+ T2(0)
}
}
impl Trait2 for T1 {
- const MAY_USED: i32 = 0;
+ const USED: i32 = 0;
}
impl Trait2 for T2 {
- const MAY_USED: i32 = 0;
+ const USED: i32 = 0;
}
-impl Trait2 for T3 {
- const MAY_USED: i32 = 0;
-}
-
-impl Trait3 for T2 {
- const MAY_USED: i32 = 0;
- fn may_used() -> Self {
+impl Trait3 for T3 {
+ const USED: i32 = 0;
+ fn construct_self() -> Self {
Self
}
}
-impl Trait3 for T4 {
- const MAY_USED: i32 = 0;
- fn may_used() -> Self {
- T4(0)
- }
-}
-
fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr
index 08c7a5c..2441a3f 100644
--- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr
+++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr
@@ -10,22 +10,10 @@
LL | #![deny(dead_code)]
| ^^^^^^^^^
-error: struct `T2` is never constructed
- --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:8
- |
-LL | struct T2;
- | ^^
-
-error: struct `T3` is never constructed
- --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:5:12
- |
-LL | pub struct T3(i32);
- | ^^
-
error: field `0` is never read
- --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:6:15
+ --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:15
|
-LL | pub struct T4(i32);
+LL | pub struct T2(i32);
| -- ^^^
| |
| field in this struct
@@ -33,10 +21,10 @@
= help: consider removing this field
error: trait `Trait1` is never used
- --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:8:7
+ --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7
|
LL | trait Trait1 {
| ^^^^^^
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
diff --git a/tests/ui/lint/dead-code/unused-assoc-const.rs b/tests/ui/lint/dead-code/unused-assoc-const.rs
deleted file mode 100644
index 36e8315..0000000
--- a/tests/ui/lint/dead-code/unused-assoc-const.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-#![deny(dead_code)]
-
-trait Trait {
- const UNUSED_CONST: i32; //~ ERROR associated constant `UNUSED_CONST` is never used
- const USED_CONST: i32;
-
- fn foo(&self) {}
-}
-
-pub struct T(());
-
-impl Trait for T {
- const UNUSED_CONST: i32 = 0;
- const USED_CONST: i32 = 1;
-}
-
-fn main() {
- T(()).foo();
- T::USED_CONST;
-}
diff --git a/tests/ui/lint/dead-code/unused-assoc-const.stderr b/tests/ui/lint/dead-code/unused-assoc-const.stderr
deleted file mode 100644
index 78296d7..0000000
--- a/tests/ui/lint/dead-code/unused-assoc-const.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error: associated constant `UNUSED_CONST` is never used
- --> $DIR/unused-assoc-const.rs:4:11
- |
-LL | trait Trait {
- | ----- associated constant in this trait
-LL | const UNUSED_CONST: i32;
- | ^^^^^^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/unused-assoc-const.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs
deleted file mode 100644
index 46065dc..0000000
--- a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-#![deny(dead_code)]
-
-struct Foo; //~ ERROR struct `Foo` is never constructed
-
-trait Trait { //~ ERROR trait `Trait` is never used
- fn foo(&self) {}
-}
-
-impl Trait for Foo {}
-
-impl Trait for [Foo] {}
-impl<const N: usize> Trait for [Foo; N] {}
-
-impl Trait for *const Foo {}
-impl Trait for *mut Foo {}
-
-impl Trait for &Foo {}
-impl Trait for &&Foo {}
-impl Trait for &mut Foo {}
-
-impl Trait for [&Foo] {}
-impl Trait for &[Foo] {}
-impl Trait for &*const Foo {}
-
-pub trait Trait2 {
- fn foo(&self) {}
-}
-
-impl Trait2 for Foo {}
-
-impl Trait2 for [Foo] {}
-impl<const N: usize> Trait2 for [Foo; N] {}
-
-impl Trait2 for *const Foo {}
-impl Trait2 for *mut Foo {}
-
-impl Trait2 for &Foo {}
-impl Trait2 for &&Foo {}
-impl Trait2 for &mut Foo {}
-
-impl Trait2 for [&Foo] {}
-impl Trait2 for &[Foo] {}
-impl Trait2 for &*const Foo {}
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr
deleted file mode 100644
index e61fc40..0000000
--- a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: struct `Foo` is never constructed
- --> $DIR/unused-impl-for-non-adts.rs:3:8
- |
-LL | struct Foo;
- | ^^^
- |
-note: the lint level is defined here
- --> $DIR/unused-impl-for-non-adts.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: trait `Trait` is never used
- --> $DIR/unused-impl-for-non-adts.rs:5:7
- |
-LL | trait Trait {
- | ^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/lint/dead-code/unused-pub-struct.rs b/tests/ui/lint/dead-code/unused-pub-struct.rs
deleted file mode 100644
index aaf4dd6..0000000
--- a/tests/ui/lint/dead-code/unused-pub-struct.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-#![deny(dead_code)]
-
-pub struct NotLint1(());
-pub struct NotLint2(std::marker::PhantomData<i32>);
-
-pub struct NeverConstructed(i32); //~ ERROR struct `NeverConstructed` is never constructed
-
-impl NeverConstructed {
- pub fn not_construct_self(&self) {}
-}
-
-impl Clone for NeverConstructed {
- fn clone(&self) -> NeverConstructed {
- NeverConstructed(0)
- }
-}
-
-pub trait Trait {
- fn not_construct_self(&self);
-}
-
-impl Trait for NeverConstructed {
- fn not_construct_self(&self) {
- self.0;
- }
-}
-
-pub struct Constructed(i32);
-
-impl Constructed {
- pub fn construct_self() -> Self {
- Constructed(0)
- }
-}
-
-impl Clone for Constructed {
- fn clone(&self) -> Constructed {
- Constructed(0)
- }
-}
-
-impl Trait for Constructed {
- fn not_construct_self(&self) {
- self.0;
- }
-}
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-pub-struct.stderr b/tests/ui/lint/dead-code/unused-pub-struct.stderr
deleted file mode 100644
index 3667ddb..0000000
--- a/tests/ui/lint/dead-code/unused-pub-struct.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: struct `NeverConstructed` is never constructed
- --> $DIR/unused-pub-struct.rs:6:12
- |
-LL | pub struct NeverConstructed(i32);
- | ^^^^^^^^^^^^^^^^
- |
-note: the lint level is defined here
- --> $DIR/unused-pub-struct.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs
index f20b7cb..330ad32 100644
--- a/tests/ui/lint/dead-code/unused-struct-derive-default.rs
+++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs
@@ -22,5 +22,4 @@ pub struct T2 {
fn main() {
let _x: Used = Default::default();
- let _e: E = Default::default();
}
diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr
index 7422f9a..bbb0bd7 100644
--- a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr
+++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr
@@ -4,6 +4,7 @@
LL | struct T;
| ^
|
+ = note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis
note: the lint level is defined here
--> $DIR/unused-struct-derive-default.rs:1:9
|
diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs
deleted file mode 100644
index e8116d8..0000000
--- a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![deny(dead_code)]
-
-struct T1; //~ ERROR struct `T1` is never constructed
-
-trait Foo { type Unused; } //~ ERROR trait `Foo` is never used
-impl Foo for T1 { type Unused = Self; }
-
-pub trait Bar { type Used; }
-impl Bar for T1 { type Used = Self; }
-
-fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr
deleted file mode 100644
index ab73c64..0000000
--- a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error: struct `T1` is never constructed
- --> $DIR/unused-trait-with-assoc-ty.rs:3:8
- |
-LL | struct T1;
- | ^^
- |
-note: the lint level is defined here
- --> $DIR/unused-trait-with-assoc-ty.rs:1:9
- |
-LL | #![deny(dead_code)]
- | ^^^^^^^^^
-
-error: trait `Foo` is never used
- --> $DIR/unused-trait-with-assoc-ty.rs:5:7
- |
-LL | trait Foo { type Unused; }
- | ^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr
index 01c2ed8..d1b764b 100644
--- a/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr
+++ b/tests/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr
@@ -7,7 +7,6 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility`
- = help: to override `--force-warn rust-2021-compatibility` add `#[allow(ellipsis_inclusive_range_patterns)]`
warning: 1 warning emitted
diff --git a/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr b/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr
index e925a19..dc7b1b7 100644
--- a/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allow-warnings.stderr
@@ -5,7 +5,6 @@
| ^^^^^^^^ help: convert the identifier to snake case: `function`
|
= note: `--force-warn non-snake-case` implied by `--force-warn nonstandard-style`
- = help: to override `--force-warn nonstandard-style` add `#[allow(non_snake_case)]`
warning: 1 warning emitted
diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
index a74cda2..dc85e8c 100644
--- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
@@ -7,7 +7,6 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
- = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]`
help: if this is an object-safe trait, use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
index c9472a3..55cfad8 100644
--- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
@@ -7,7 +7,6 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
- = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]`
help: if this is an object-safe trait, use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
index 558d5cb..b7bf0c4 100644
--- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
+++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
@@ -7,7 +7,6 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
- = help: to override `--force-warn rust-2018-idioms` add `#[allow(bare_trait_objects)]`
help: if this is an object-safe trait, use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/tests/ui/lint/group-forbid-always-trumps-cli.stderr b/tests/ui/lint/group-forbid-always-trumps-cli.stderr
index 21674eb..ed1242e 100644
--- a/tests/ui/lint/group-forbid-always-trumps-cli.stderr
+++ b/tests/ui/lint/group-forbid-always-trumps-cli.stderr
@@ -5,7 +5,6 @@
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
= note: `-F unused-variables` implied by `-F unused`
- = help: to override `-F unused` add `#[allow(unused_variables)]`
error: aborting due to 1 previous error
diff --git a/tests/ui/lint/lint-unnecessary-parens.fixed b/tests/ui/lint/lint-unnecessary-parens.fixed
index 760897c..089aa1b 100644
--- a/tests/ui/lint/lint-unnecessary-parens.fixed
+++ b/tests/ui/lint/lint-unnecessary-parens.fixed
@@ -1,6 +1,7 @@
//@ run-rustfix
#![deny(unused_parens)]
+#![feature(raw_ref_op)]
#![allow(while_true)] // for rustfix
#[derive(Eq, PartialEq)]
@@ -125,4 +126,11 @@
// FIXME: false positive. This parenthesis is required.
unit! {} - One //~ ERROR unnecessary parentheses around block return value
};
+
+ // Do *not* lint around `&raw` (but do lint when `&` creates a reference).
+ let mut x = 0;
+ let _r = &x; //~ ERROR unnecessary parentheses
+ let _r = &mut x; //~ ERROR unnecessary parentheses
+ let _r = (&raw const x);
+ let _r = (&raw mut x);
}
diff --git a/tests/ui/lint/lint-unnecessary-parens.rs b/tests/ui/lint/lint-unnecessary-parens.rs
index 7cbaac8..dc77ee0 100644
--- a/tests/ui/lint/lint-unnecessary-parens.rs
+++ b/tests/ui/lint/lint-unnecessary-parens.rs
@@ -1,6 +1,7 @@
//@ run-rustfix
#![deny(unused_parens)]
+#![feature(raw_ref_op)]
#![allow(while_true)] // for rustfix
#[derive(Eq, PartialEq)]
@@ -125,4 +126,11 @@ fn main() {
// FIXME: false positive. This parenthesis is required.
(unit! {} - One) //~ ERROR unnecessary parentheses around block return value
};
+
+ // Do *not* lint around `&raw` (but do lint when `&` creates a reference).
+ let mut x = 0;
+ let _r = (&x); //~ ERROR unnecessary parentheses
+ let _r = (&mut x); //~ ERROR unnecessary parentheses
+ let _r = (&raw const x);
+ let _r = (&raw mut x);
}
diff --git a/tests/ui/lint/lint-unnecessary-parens.stderr b/tests/ui/lint/lint-unnecessary-parens.stderr
index 755dd5f..c942243 100644
--- a/tests/ui/lint/lint-unnecessary-parens.stderr
+++ b/tests/ui/lint/lint-unnecessary-parens.stderr
@@ -1,5 +1,5 @@
error: unnecessary parentheses around `return` value
- --> $DIR/lint-unnecessary-parens.rs:13:12
+ --> $DIR/lint-unnecessary-parens.rs:14:12
|
LL | return (1);
| ^ ^
@@ -16,7 +16,7 @@
|
error: unnecessary parentheses around `return` value
- --> $DIR/lint-unnecessary-parens.rs:16:12
+ --> $DIR/lint-unnecessary-parens.rs:17:12
|
LL | return (X { y });
| ^ ^
@@ -28,7 +28,7 @@
|
error: unnecessary parentheses around type
- --> $DIR/lint-unnecessary-parens.rs:19:46
+ --> $DIR/lint-unnecessary-parens.rs:20:46
|
LL | pub fn unused_parens_around_return_type() -> (u32) {
| ^ ^
@@ -40,7 +40,7 @@
|
error: unnecessary parentheses around block return value
- --> $DIR/lint-unnecessary-parens.rs:25:9
+ --> $DIR/lint-unnecessary-parens.rs:26:9
|
LL | (5)
| ^ ^
@@ -52,7 +52,7 @@
|
error: unnecessary parentheses around block return value
- --> $DIR/lint-unnecessary-parens.rs:27:5
+ --> $DIR/lint-unnecessary-parens.rs:28:5
|
LL | (5)
| ^ ^
@@ -64,7 +64,7 @@
|
error: unnecessary parentheses around `if` condition
- --> $DIR/lint-unnecessary-parens.rs:39:7
+ --> $DIR/lint-unnecessary-parens.rs:40:7
|
LL | if(true) {}
| ^ ^
@@ -76,7 +76,7 @@
|
error: unnecessary parentheses around `while` condition
- --> $DIR/lint-unnecessary-parens.rs:40:10
+ --> $DIR/lint-unnecessary-parens.rs:41:10
|
LL | while(true) {}
| ^ ^
@@ -88,7 +88,7 @@
|
error: unnecessary parentheses around `for` iterator expression
- --> $DIR/lint-unnecessary-parens.rs:41:13
+ --> $DIR/lint-unnecessary-parens.rs:42:13
|
LL | for _ in(e) {}
| ^ ^
@@ -100,7 +100,7 @@
|
error: unnecessary parentheses around `match` scrutinee expression
- --> $DIR/lint-unnecessary-parens.rs:42:10
+ --> $DIR/lint-unnecessary-parens.rs:43:10
|
LL | match(1) { _ => ()}
| ^ ^
@@ -112,7 +112,7 @@
|
error: unnecessary parentheses around `return` value
- --> $DIR/lint-unnecessary-parens.rs:43:11
+ --> $DIR/lint-unnecessary-parens.rs:44:11
|
LL | return(1);
| ^ ^
@@ -124,7 +124,7 @@
|
error: unnecessary parentheses around assigned value
- --> $DIR/lint-unnecessary-parens.rs:74:31
+ --> $DIR/lint-unnecessary-parens.rs:75:31
|
LL | pub const CONST_ITEM: usize = (10);
| ^ ^
@@ -136,7 +136,7 @@
|
error: unnecessary parentheses around assigned value
- --> $DIR/lint-unnecessary-parens.rs:75:33
+ --> $DIR/lint-unnecessary-parens.rs:76:33
|
LL | pub static STATIC_ITEM: usize = (10);
| ^ ^
@@ -148,7 +148,7 @@
|
error: unnecessary parentheses around function argument
- --> $DIR/lint-unnecessary-parens.rs:79:9
+ --> $DIR/lint-unnecessary-parens.rs:80:9
|
LL | bar((true));
| ^ ^
@@ -160,7 +160,7 @@
|
error: unnecessary parentheses around `if` condition
- --> $DIR/lint-unnecessary-parens.rs:81:8
+ --> $DIR/lint-unnecessary-parens.rs:82:8
|
LL | if (true) {}
| ^ ^
@@ -172,7 +172,7 @@
|
error: unnecessary parentheses around `while` condition
- --> $DIR/lint-unnecessary-parens.rs:82:11
+ --> $DIR/lint-unnecessary-parens.rs:83:11
|
LL | while (true) {}
| ^ ^
@@ -184,7 +184,7 @@
|
error: unnecessary parentheses around `match` scrutinee expression
- --> $DIR/lint-unnecessary-parens.rs:83:11
+ --> $DIR/lint-unnecessary-parens.rs:84:11
|
LL | match (true) {
| ^ ^
@@ -196,7 +196,7 @@
|
error: unnecessary parentheses around `let` scrutinee expression
- --> $DIR/lint-unnecessary-parens.rs:86:16
+ --> $DIR/lint-unnecessary-parens.rs:87:16
|
LL | if let 1 = (1) {}
| ^ ^
@@ -208,7 +208,7 @@
|
error: unnecessary parentheses around `let` scrutinee expression
- --> $DIR/lint-unnecessary-parens.rs:87:19
+ --> $DIR/lint-unnecessary-parens.rs:88:19
|
LL | while let 1 = (2) {}
| ^ ^
@@ -220,7 +220,7 @@
|
error: unnecessary parentheses around method argument
- --> $DIR/lint-unnecessary-parens.rs:103:24
+ --> $DIR/lint-unnecessary-parens.rs:104:24
|
LL | X { y: false }.foo((true));
| ^ ^
@@ -232,7 +232,7 @@
|
error: unnecessary parentheses around assigned value
- --> $DIR/lint-unnecessary-parens.rs:105:18
+ --> $DIR/lint-unnecessary-parens.rs:106:18
|
LL | let mut _a = (0);
| ^ ^
@@ -244,7 +244,7 @@
|
error: unnecessary parentheses around assigned value
- --> $DIR/lint-unnecessary-parens.rs:106:10
+ --> $DIR/lint-unnecessary-parens.rs:107:10
|
LL | _a = (0);
| ^ ^
@@ -256,7 +256,7 @@
|
error: unnecessary parentheses around assigned value
- --> $DIR/lint-unnecessary-parens.rs:107:11
+ --> $DIR/lint-unnecessary-parens.rs:108:11
|
LL | _a += (1);
| ^ ^
@@ -268,7 +268,7 @@
|
error: unnecessary parentheses around pattern
- --> $DIR/lint-unnecessary-parens.rs:109:8
+ --> $DIR/lint-unnecessary-parens.rs:110:8
|
LL | let(mut _a) = 3;
| ^ ^
@@ -280,7 +280,7 @@
|
error: unnecessary parentheses around pattern
- --> $DIR/lint-unnecessary-parens.rs:110:9
+ --> $DIR/lint-unnecessary-parens.rs:111:9
|
LL | let (mut _a) = 3;
| ^ ^
@@ -292,7 +292,7 @@
|
error: unnecessary parentheses around pattern
- --> $DIR/lint-unnecessary-parens.rs:111:8
+ --> $DIR/lint-unnecessary-parens.rs:112:8
|
LL | let( mut _a) = 3;
| ^^ ^
@@ -304,7 +304,7 @@
|
error: unnecessary parentheses around pattern
- --> $DIR/lint-unnecessary-parens.rs:113:8
+ --> $DIR/lint-unnecessary-parens.rs:114:8
|
LL | let(_a) = 3;
| ^ ^
@@ -316,7 +316,7 @@
|
error: unnecessary parentheses around pattern
- --> $DIR/lint-unnecessary-parens.rs:114:9
+ --> $DIR/lint-unnecessary-parens.rs:115:9
|
LL | let (_a) = 3;
| ^ ^
@@ -328,7 +328,7 @@
|
error: unnecessary parentheses around pattern
- --> $DIR/lint-unnecessary-parens.rs:115:8
+ --> $DIR/lint-unnecessary-parens.rs:116:8
|
LL | let( _a) = 3;
| ^^ ^
@@ -340,7 +340,7 @@
|
error: unnecessary parentheses around block return value
- --> $DIR/lint-unnecessary-parens.rs:121:9
+ --> $DIR/lint-unnecessary-parens.rs:122:9
|
LL | (unit!() - One)
| ^ ^
@@ -352,7 +352,7 @@
|
error: unnecessary parentheses around block return value
- --> $DIR/lint-unnecessary-parens.rs:123:9
+ --> $DIR/lint-unnecessary-parens.rs:124:9
|
LL | (unit![] - One)
| ^ ^
@@ -364,7 +364,7 @@
|
error: unnecessary parentheses around block return value
- --> $DIR/lint-unnecessary-parens.rs:126:9
+ --> $DIR/lint-unnecessary-parens.rs:127:9
|
LL | (unit! {} - One)
| ^ ^
@@ -375,5 +375,29 @@
LL + unit! {} - One
|
-error: aborting due to 31 previous errors
+error: unnecessary parentheses around assigned value
+ --> $DIR/lint-unnecessary-parens.rs:132:14
+ |
+LL | let _r = (&x);
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _r = (&x);
+LL + let _r = &x;
+ |
+
+error: unnecessary parentheses around assigned value
+ --> $DIR/lint-unnecessary-parens.rs:133:14
+ |
+LL | let _r = (&mut x);
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _r = (&mut x);
+LL + let _r = &mut x;
+ |
+
+error: aborting due to 33 previous errors
diff --git a/tests/ui/lint/negative_literals.rs b/tests/ui/lint/negative_literals.rs
index 048fcd6..5964bbb 100644
--- a/tests/ui/lint/negative_literals.rs
+++ b/tests/ui/lint/negative_literals.rs
@@ -1,5 +1,7 @@
//@ check-fail
+#![deny(ambiguous_negative_literals)]
+
fn main() {
let _ = -1i32.abs();
//~^ ERROR `-` has lower precedence than method calls
diff --git a/tests/ui/lint/negative_literals.stderr b/tests/ui/lint/negative_literals.stderr
index df000a7..b0323cc 100644
--- a/tests/ui/lint/negative_literals.stderr
+++ b/tests/ui/lint/negative_literals.stderr
@@ -1,11 +1,15 @@
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:4:13
+ --> $DIR/negative_literals.rs:6:13
|
LL | let _ = -1i32.abs();
| ^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
- = note: `#[deny(ambiguous_negative_literals)]` on by default
+note: the lint level is defined here
+ --> $DIR/negative_literals.rs:3:9
+ |
+LL | #![deny(ambiguous_negative_literals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1i32).abs();
@@ -16,7 +20,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:6:13
+ --> $DIR/negative_literals.rs:8:13
|
LL | let _ = -1f32.abs();
| ^^^^^^^^^^^
@@ -32,7 +36,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:8:13
+ --> $DIR/negative_literals.rs:10:13
|
LL | let _ = -1f64.asin();
| ^^^^^^^^^^^^
@@ -48,7 +52,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:10:13
+ --> $DIR/negative_literals.rs:12:13
|
LL | let _ = -1f64.asinh();
| ^^^^^^^^^^^^^
@@ -64,7 +68,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:12:13
+ --> $DIR/negative_literals.rs:14:13
|
LL | let _ = -1f64.tan();
| ^^^^^^^^^^^
@@ -80,7 +84,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:14:13
+ --> $DIR/negative_literals.rs:16:13
|
LL | let _ = -1f64.tanh();
| ^^^^^^^^^^^^
@@ -96,7 +100,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:16:13
+ --> $DIR/negative_literals.rs:18:13
|
LL | let _ = -1.0_f64.cos().cos();
| ^^^^^^^^^^^^^^^^^^^^
@@ -112,7 +116,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:18:13
+ --> $DIR/negative_literals.rs:20:13
|
LL | let _ = -1.0_f64.cos().sin();
| ^^^^^^^^^^^^^^^^^^^^
@@ -128,7 +132,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:20:13
+ --> $DIR/negative_literals.rs:22:13
|
LL | let _ = -1.0_f64.sin().cos();
| ^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +148,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:22:13
+ --> $DIR/negative_literals.rs:24:13
|
LL | let _ = -1f64.sin().sin();
| ^^^^^^^^^^^^^^^^^
@@ -160,7 +164,7 @@
| + +
error: `-` has lower precedence than method calls, which might be unexpected
- --> $DIR/negative_literals.rs:25:11
+ --> $DIR/negative_literals.rs:27:11
|
LL | dbg!( -1.0_f32.cos() );
| ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.current.stderr
similarity index 93%
rename from tests/ui/lint/unaligned_references.stderr
rename to tests/ui/lint/unaligned_references.current.stderr
index 328cafb..0f980c5 100644
--- a/tests/ui/lint/unaligned_references.stderr
+++ b/tests/ui/lint/unaligned_references.current.stderr
@@ -1,5 +1,5 @@
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:28:13
+ --> $DIR/unaligned_references.rs:32:13
|
LL | &self.x;
| ^^^^^^^
@@ -9,7 +9,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:40:24
+ --> $DIR/unaligned_references.rs:44:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
@@ -19,7 +19,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:42:24
+ --> $DIR/unaligned_references.rs:46:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
@@ -29,7 +29,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:47:24
+ --> $DIR/unaligned_references.rs:51:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
@@ -39,7 +39,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:57:17
+ --> $DIR/unaligned_references.rs:81:17
|
LL | let _ = &good.ptr;
| ^^^^^^^^^
@@ -49,7 +49,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:58:17
+ --> $DIR/unaligned_references.rs:82:17
|
LL | let _ = &good.data;
| ^^^^^^^^^^
@@ -59,7 +59,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:60:17
+ --> $DIR/unaligned_references.rs:84:17
|
LL | let _ = &good.data as *const _;
| ^^^^^^^^^^
@@ -69,7 +69,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:61:27
+ --> $DIR/unaligned_references.rs:85:27
|
LL | let _: *const _ = &good.data;
| ^^^^^^^^^^
@@ -79,7 +79,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:63:17
+ --> $DIR/unaligned_references.rs:87:17
|
LL | let _ = good.data.clone();
| ^^^^^^^^^
@@ -89,7 +89,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:65:17
+ --> $DIR/unaligned_references.rs:89:17
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
@@ -99,7 +99,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:74:17
+ --> $DIR/unaligned_references.rs:98:17
|
LL | let _ = &packed2.x;
| ^^^^^^^^^^
@@ -109,7 +109,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:113:20
+ --> $DIR/unaligned_references.rs:137:20
|
LL | let _ref = &m1.1.a;
| ^^^^^^^
@@ -119,7 +119,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:116:20
+ --> $DIR/unaligned_references.rs:140:20
|
LL | let _ref = &m2.1.a;
| ^^^^^^^
diff --git a/tests/ui/lint/unaligned_references.stderr b/tests/ui/lint/unaligned_references.next.stderr
similarity index 93%
copy from tests/ui/lint/unaligned_references.stderr
copy to tests/ui/lint/unaligned_references.next.stderr
index 328cafb..0f980c5 100644
--- a/tests/ui/lint/unaligned_references.stderr
+++ b/tests/ui/lint/unaligned_references.next.stderr
@@ -1,5 +1,5 @@
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:28:13
+ --> $DIR/unaligned_references.rs:32:13
|
LL | &self.x;
| ^^^^^^^
@@ -9,7 +9,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:40:24
+ --> $DIR/unaligned_references.rs:44:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
@@ -19,7 +19,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:42:24
+ --> $DIR/unaligned_references.rs:46:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
@@ -29,7 +29,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:47:24
+ --> $DIR/unaligned_references.rs:51:24
|
LL | println!("{:?}", &*foo.0);
| ^^^^^
@@ -39,7 +39,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:57:17
+ --> $DIR/unaligned_references.rs:81:17
|
LL | let _ = &good.ptr;
| ^^^^^^^^^
@@ -49,7 +49,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:58:17
+ --> $DIR/unaligned_references.rs:82:17
|
LL | let _ = &good.data;
| ^^^^^^^^^^
@@ -59,7 +59,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:60:17
+ --> $DIR/unaligned_references.rs:84:17
|
LL | let _ = &good.data as *const _;
| ^^^^^^^^^^
@@ -69,7 +69,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:61:27
+ --> $DIR/unaligned_references.rs:85:27
|
LL | let _: *const _ = &good.data;
| ^^^^^^^^^^
@@ -79,7 +79,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:63:17
+ --> $DIR/unaligned_references.rs:87:17
|
LL | let _ = good.data.clone();
| ^^^^^^^^^
@@ -89,7 +89,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:65:17
+ --> $DIR/unaligned_references.rs:89:17
|
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
@@ -99,7 +99,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:74:17
+ --> $DIR/unaligned_references.rs:98:17
|
LL | let _ = &packed2.x;
| ^^^^^^^^^^
@@ -109,7 +109,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:113:20
+ --> $DIR/unaligned_references.rs:137:20
|
LL | let _ref = &m1.1.a;
| ^^^^^^^
@@ -119,7 +119,7 @@
= help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
error[E0793]: reference to packed field is unaligned
- --> $DIR/unaligned_references.rs:116:20
+ --> $DIR/unaligned_references.rs:140:20
|
LL | let _ref = &m2.1.a;
| ^^^^^^^
diff --git a/tests/ui/lint/unaligned_references.rs b/tests/ui/lint/unaligned_references.rs
index 3f6dab3..321e3ed 100644
--- a/tests/ui/lint/unaligned_references.rs
+++ b/tests/ui/lint/unaligned_references.rs
@@ -1,5 +1,9 @@
-use std::mem::ManuallyDrop;
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
use std::fmt::Debug;
+use std::mem::ManuallyDrop;
#[repr(packed)]
pub struct Good {
@@ -50,6 +54,26 @@ fn packed_dyn() {
println!("{:?}", &*foo.0); // no error!
}
+// Test for #115396
+fn packed_slice_behind_alias() {
+ trait Mirror {
+ type Assoc: ?Sized;
+ }
+ impl<T: ?Sized> Mirror for T {
+ type Assoc = T;
+ }
+
+ struct W<T: ?Sized>(<T as Mirror>::Assoc);
+
+ #[repr(packed)]
+ struct Unaligned<T: ?Sized>(ManuallyDrop<W<T>>);
+
+ // Even if the actual alignment is 1, we cannot know that when looking at `dyn Debug.`
+ let ref local: Unaligned<[_; 3]> = Unaligned(ManuallyDrop::new(W([3, 5, 8u8])));
+ let foo: &Unaligned<[u8]> = local;
+ let x = &foo.0; // Fine, since the tail of `foo` is `[_]`
+}
+
fn main() {
unsafe {
let good = Good { data: 0, ptr: &0, data2: [0, 0], aligned: [0; 32] };
diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
index 6f2ead7..c264fa1 100644
--- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
+++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
@@ -1,4 +1,3 @@
-#![feature(unsafe_extern_blocks)]
#![deny(unsafe_code)]
#[allow(unsafe_code)]
diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
index 5439a31..6d3b064 100644
--- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
+++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
@@ -1,5 +1,5 @@
error: usage of an `unsafe extern` block
- --> $DIR/unsafe-extern-blocks.rs:9:1
+ --> $DIR/unsafe-extern-blocks.rs:8:1
|
LL | / unsafe extern "C" {
LL | |
@@ -8,7 +8,7 @@
| |_^
|
note: the lint level is defined here
- --> $DIR/unsafe-extern-blocks.rs:2:9
+ --> $DIR/unsafe-extern-blocks.rs:1:9
|
LL | #![deny(unsafe_code)]
| ^^^^^^^^^^^
diff --git a/tests/ui/lint/unused/issue-59896.rs b/tests/ui/lint/unused/issue-59896.rs
index a980175..5624e7f 100644
--- a/tests/ui/lint/unused/issue-59896.rs
+++ b/tests/ui/lint/unused/issue-59896.rs
@@ -1,10 +1,9 @@
-//@ check-pass
-#![deny(unused_imports)]
+#![deny(redundant_imports)]
struct S;
fn main() {
- use S; //FIXME(unused_imports): ~ ERROR the item `S` is imported redundantly
+ use S; //~ ERROR the item `S` is imported redundantly
let _s = S;
}
diff --git a/tests/ui/lint/unused/issue-59896.stderr b/tests/ui/lint/unused/issue-59896.stderr
new file mode 100644
index 0000000..363a6419
--- /dev/null
+++ b/tests/ui/lint/unused/issue-59896.stderr
@@ -0,0 +1,17 @@
+error: the item `S` is imported redundantly
+ --> $DIR/issue-59896.rs:6:9
+ |
+LL | struct S;
+ | --------- the item `S` is already defined here
+...
+LL | use S;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-59896.rs:1:9
+ |
+LL | #![deny(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs
index 797e57f..c8c413d 100644
--- a/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs
+++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs
@@ -1,5 +1,5 @@
//@ check-pass
-#![warn(unused_imports)]
+#![warn(redundant_imports)]
pub mod bar {
pub struct Foo(pub Bar);
@@ -9,7 +9,7 @@ pub mod bar {
use bar::*;
pub fn warning() -> Foo {
- use bar::Foo; //FIXME(unused_imports): ~ WARNING imported redundantly
+ use bar::Foo; //~ WARNING imported redundantly
Foo(Bar('a'))
}
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr
new file mode 100644
index 0000000..3b06b2d
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr
@@ -0,0 +1,17 @@
+warning: the item `Foo` is imported redundantly
+ --> $DIR/use-redundant-glob-parent.rs:12:9
+ |
+LL | use bar::*;
+ | ------ the item `Foo` is already imported here
+...
+LL | use bar::Foo;
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/use-redundant-glob-parent.rs:2:9
+ |
+LL | #![warn(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.rs b/tests/ui/lint/use-redundant/use-redundant-glob.rs
index e5835be..52383d4 100644
--- a/tests/ui/lint/use-redundant/use-redundant-glob.rs
+++ b/tests/ui/lint/use-redundant/use-redundant-glob.rs
@@ -1,5 +1,5 @@
//@ check-pass
-#![warn(unused_imports)]
+#![warn(redundant_imports)]
pub mod bar {
pub struct Foo(pub Bar);
@@ -8,7 +8,7 @@ pub mod bar {
pub fn warning() -> bar::Foo {
use bar::*;
- use bar::Foo; //FIXME(unused_imports): ~ WARNING imported redundantly
+ use bar::Foo; //~ WARNING imported redundantly
Foo(Bar('a'))
}
diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.stderr b/tests/ui/lint/use-redundant/use-redundant-glob.stderr
new file mode 100644
index 0000000..47b2ce5
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-glob.stderr
@@ -0,0 +1,16 @@
+warning: the item `Foo` is imported redundantly
+ --> $DIR/use-redundant-glob.rs:11:9
+ |
+LL | use bar::*;
+ | ------ the item `Foo` is already imported here
+LL | use bar::Foo;
+ | ^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/use-redundant-glob.rs:2:9
+ |
+LL | #![warn(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs
index 2db3435..6a3ffa4 100644
--- a/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs
@@ -1,6 +1,6 @@
//@ check-pass
-#![warn(unused_imports)]
+#![warn(redundant_imports)]
mod foo {
use std::fmt;
@@ -23,8 +23,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn main() {
{
- use std::string::String;
- //FIXME(unused_imports): ~^ WARNING the item `String` is imported redundantly
+ use std::string::String; //~ WARNING the item `String` is imported redundantly
// 'String' from 'std::string::String'.
let s = String::new();
println!("{}", s);
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
new file mode 100644
index 0000000..c14ab9e
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
@@ -0,0 +1,17 @@
+warning: the item `String` is imported redundantly
+ --> $DIR/use-redundant-issue-71450.rs:26:13
+ |
+LL | use std::string::String;
+ | ^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `String` is already defined here
+ |
+note: the lint level is defined here
+ --> $DIR/use-redundant-issue-71450.rs:3:9
+ |
+LL | #![warn(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs
index 62f50c8..6abe360 100644
--- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs
@@ -1,16 +1,12 @@
//@ check-pass
-#![warn(unused_imports)]
+#![warn(redundant_imports)]
-use std::option::Option::Some;
-//FIXME(unused_imports): ~^ WARNING the item `Some` is imported redundantly
-use std::option::Option::None;
-//FIXME(unused_imports): ~ WARNING the item `None` is imported redundantly
+use std::option::Option::Some;//~ WARNING the item `Some` is imported redundantly
+use std::option::Option::None; //~ WARNING the item `None` is imported redundantly
-use std::result::Result::Ok;
-//FIXME(unused_imports): ~^ WARNING the item `Ok` is imported redundantly
-use std::result::Result::Err;
-//FIXME(unused_imports): ~^ WARNING the item `Err` is imported redundantly
+use std::result::Result::Ok;//~ WARNING the item `Ok` is imported redundantly
+use std::result::Result::Err;//~ WARNING the item `Err` is imported redundantly
use std::convert::{TryFrom, TryInto};
fn main() {
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
new file mode 100644
index 0000000..2b0e16a
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
@@ -0,0 +1,44 @@
+warning: the item `Some` is imported redundantly
+ --> $DIR/use-redundant-prelude-rust-2015.rs:5:5
+ |
+LL | use std::option::Option::Some;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `Some` is already defined here
+ |
+note: the lint level is defined here
+ --> $DIR/use-redundant-prelude-rust-2015.rs:2:9
+ |
+LL | #![warn(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: the item `None` is imported redundantly
+ --> $DIR/use-redundant-prelude-rust-2015.rs:6:5
+ |
+LL | use std::option::Option::None;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `None` is already defined here
+
+warning: the item `Ok` is imported redundantly
+ --> $DIR/use-redundant-prelude-rust-2015.rs:8:5
+ |
+LL | use std::result::Result::Ok;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `Ok` is already defined here
+
+warning: the item `Err` is imported redundantly
+ --> $DIR/use-redundant-prelude-rust-2015.rs:9:5
+ |
+LL | use std::result::Result::Err;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `Err` is already defined here
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs
index 1baa1ac..236ee03 100644
--- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs
@@ -1,11 +1,9 @@
//@ check-pass
//@ edition:2021
-#![warn(unused_imports)]
+#![warn(redundant_imports)]
-use std::convert::TryFrom;
-//FIXME(unused_imports): ~^ WARNING the item `TryFrom` is imported redundantly
-use std::convert::TryInto;
-//FIXME(unused_imports): ~^ WARNING the item `TryInto` is imported redundantly
+use std::convert::TryFrom;//~ WARNING the item `TryFrom` is imported redundantly
+use std::convert::TryInto;//~ WARNING the item `TryInto` is imported redundantly
fn main() {
let _e: Result<i32, _> = 8u8.try_into();
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
new file mode 100644
index 0000000..526771c
--- /dev/null
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
@@ -0,0 +1,26 @@
+warning: the item `TryFrom` is imported redundantly
+ --> $DIR/use-redundant-prelude-rust-2021.rs:5:5
+ |
+LL | use std::convert::TryFrom;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `TryFrom` is already defined here
+ |
+note: the lint level is defined here
+ --> $DIR/use-redundant-prelude-rust-2021.rs:3:9
+ |
+LL | #![warn(redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: the item `TryInto` is imported redundantly
+ --> $DIR/use-redundant-prelude-rust-2021.rs:6:5
+ |
+LL | use std::convert::TryInto;
+ | ^^^^^^^^^^^^^^^^^^^^^
+ --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
+ |
+ = note: the item `TryInto` is already defined here
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/lint/use-redundant/use-redundant.rs b/tests/ui/lint/use-redundant/use-redundant.rs
index 9e4902a..0efed37 100644
--- a/tests/ui/lint/use-redundant/use-redundant.rs
+++ b/tests/ui/lint/use-redundant/use-redundant.rs
@@ -1,5 +1,5 @@
//@ check-pass
-#![warn(unused_imports)]
+#![warn(unused_imports, redundant_imports)]
use crate::foo::Bar;
@@ -18,7 +18,7 @@ mod m2 { pub struct S {} }
use m2::*; //~ WARNING unused import
fn main() {
- use crate::foo::Bar; //FIXME(unused_imports): ~ WARNING imported redundantly
+ use crate::foo::Bar; //~ WARNING imported redundantly
let _a: Bar = 3;
baz();
diff --git a/tests/ui/lint/use-redundant/use-redundant.stderr b/tests/ui/lint/use-redundant/use-redundant.stderr
index 224e841..76846a1 100644
--- a/tests/ui/lint/use-redundant/use-redundant.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant.stderr
@@ -7,7 +7,7 @@
note: the lint level is defined here
--> $DIR/use-redundant.rs:2:9
|
-LL | #![warn(unused_imports)]
+LL | #![warn(unused_imports, redundant_imports)]
| ^^^^^^^^^^^^^^
warning: unused import: `m2::*`
@@ -16,5 +16,20 @@
LL | use m2::*;
| ^^^^^
-warning: 2 warnings emitted
+warning: the item `Bar` is imported redundantly
+ --> $DIR/use-redundant.rs:21:9
+ |
+LL | use crate::foo::Bar;
+ | --------------- the item `Bar` is already imported here
+...
+LL | use crate::foo::Bar;
+ | ^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/use-redundant.rs:2:25
+ |
+LL | #![warn(unused_imports, redundant_imports)]
+ | ^^^^^^^^^^^^^^^^^
+
+warning: 3 warnings emitted
diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr
index 81a221c..7fe3823 100644
--- a/tests/ui/lint/wide_pointer_comparisons.stderr
+++ b/tests/ui/lint/wide_pointer_comparisons.stderr
@@ -74,7 +74,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(a, b);
- | ~~~~~~~~~~~~~~~~~~ ~ ~
+ | ~~~~~~~~~~~~~~~~~~ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:35:13
@@ -85,7 +85,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(a, b);
- | ~~~~~~~~~~~~~~~~~~~ ~ ~
+ | ~~~~~~~~~~~~~~~~~~~ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:37:13
@@ -96,7 +96,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(a, b);
- | ++++++++++++++++++ ~ ~
+ | ++++++++++++++++++ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:39:13
@@ -107,7 +107,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(a, b);
- | +++++++++++++++++++ ~ ~
+ | +++++++++++++++++++ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:41:13
@@ -283,7 +283,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(*a, *b);
- | ~~~~~~~~~~~~~~~~~~~ ~~~ ~
+ | ~~~~~~~~~~~~~~~~~~~ ~~~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:85:17
@@ -294,7 +294,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(*a, *b);
- | ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
+ | ~~~~~~~~~~~~~~~~~~~~ ~~~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:87:17
@@ -305,7 +305,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(*a, *b);
- | ~~~~~~~~~~~~~~~~~~~ ~~~ ~
+ | ~~~~~~~~~~~~~~~~~~~ ~~~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:89:17
@@ -316,7 +316,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(*a, *b);
- | ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
+ | ~~~~~~~~~~~~~~~~~~~~ ~~~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:91:17
@@ -327,7 +327,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(*a, *b);
- | +++++++++++++++++++ ~~~ ~
+ | +++++++++++++++++++ ~~~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:93:17
@@ -338,7 +338,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(*a, *b);
- | ++++++++++++++++++++ ~~~ ~
+ | ++++++++++++++++++++ ~~~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:95:17
@@ -519,11 +519,11 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(a, b);
- | ~~~~~~~~~~~~~~~~~~ ~ ~
+ | ~~~~~~~~~~~~~~~~~~ ~
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
LL | let _ = std::ptr::eq(a, b);
- | ~~~~~~~~~~~~~ ~ ~
+ | ~~~~~~~~~~~~~ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:133:17
@@ -534,11 +534,11 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(a, b);
- | ~~~~~~~~~~~~~~~~~~~ ~ ~
+ | ~~~~~~~~~~~~~~~~~~~ ~
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
LL | let _ = !std::ptr::eq(a, b);
- | ~~~~~~~~~~~~~~ ~ ~
+ | ~~~~~~~~~~~~~~ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:135:17
@@ -549,11 +549,11 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = std::ptr::addr_eq(a, b);
- | ++++++++++++++++++ ~ ~
+ | ++++++++++++++++++ ~
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
LL | let _ = std::ptr::eq(a, b);
- | +++++++++++++ ~ ~
+ | +++++++++++++ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:137:17
@@ -564,11 +564,11 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | let _ = !std::ptr::addr_eq(a, b);
- | +++++++++++++++++++ ~ ~
+ | +++++++++++++++++++ ~
help: use explicit `std::ptr::eq` method to compare metadata and addresses
|
LL | let _ = !std::ptr::eq(a, b);
- | ++++++++++++++ ~ ~
+ | ++++++++++++++ ~
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:142:9
@@ -594,7 +594,7 @@
help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
|
LL | cmp!(std::ptr::addr_eq(a, b));
- | ++++++++++++++++++ ~ +
+ | ++++++++++++++++++ +
warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
--> $DIR/wide_pointer_comparisons.rs:159:39
diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr
new file mode 100644
index 0000000..335b3f6
--- /dev/null
+++ b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr
@@ -0,0 +1,32 @@
+error: no rules expected the token `_`
+ --> $DIR/expr_2024_underscore_expr.rs:22:12
+ |
+LL | macro_rules! m2021 {
+ | ------------------ when calling this macro
+...
+LL | m2021!(_);
+ | ^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr_2021`
+ --> $DIR/expr_2024_underscore_expr.rs:10:6
+ |
+LL | ($e:expr_2021) => {
+ | ^^^^^^^^^^^^
+
+error: no rules expected the token `_`
+ --> $DIR/expr_2024_underscore_expr.rs:23:12
+ |
+LL | macro_rules! m2024 {
+ | ------------------ when calling this macro
+...
+LL | m2024!(_);
+ | ^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr`
+ --> $DIR/expr_2024_underscore_expr.rs:16:6
+ |
+LL | ($e:expr) => {
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr
new file mode 100644
index 0000000..9e49f66
--- /dev/null
+++ b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr
@@ -0,0 +1,17 @@
+error: no rules expected the token `_`
+ --> $DIR/expr_2024_underscore_expr.rs:22:12
+ |
+LL | macro_rules! m2021 {
+ | ------------------ when calling this macro
+...
+LL | m2021!(_);
+ | ^ no rules expected this token in macro call
+ |
+note: while trying to match meta-variable `$e:expr_2021`
+ --> $DIR/expr_2024_underscore_expr.rs:10:6
+ |
+LL | ($e:expr_2021) => {
+ | ^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/expr_2024_underscore_expr.rs b/tests/ui/macros/expr_2024_underscore_expr.rs
new file mode 100644
index 0000000..b2129bf
--- /dev/null
+++ b/tests/ui/macros/expr_2024_underscore_expr.rs
@@ -0,0 +1,24 @@
+//@ revisions: edi2021 edi2024
+//@[edi2024]compile-flags: --edition=2024 -Z unstable-options
+//@[edi2021]compile-flags: --edition=2021
+// This test ensures that the `_` tok is considered an
+// expression on edition 2024.
+#![feature(expr_fragment_specifier_2024)]
+#![allow(incomplete_features)]
+
+macro_rules! m2021 {
+ ($e:expr_2021) => {
+ $e = 1;
+ };
+}
+
+macro_rules! m2024 {
+ ($e:expr) => {
+ $e = 1;
+ };
+}
+
+fn main() {
+ m2021!(_); //~ ERROR: no rules expected the token `_`
+ m2024!(_); //[edi2021]~ ERROR: no rules expected the token `_`
+}
diff --git a/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs
new file mode 100644
index 0000000..0a6d196
--- /dev/null
+++ b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs
@@ -0,0 +1,11 @@
+// Fix for issue: #122914
+
+use std::future::Future;
+use std::pin::Pin;
+
+fn project(x: Pin<&'missing mut dyn Future<Output = ()>>) {
+ //~^ ERROR use of undeclared lifetime name `'missing`
+ let _ = x.poll(todo!());
+}
+
+fn main() {}
diff --git a/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr
new file mode 100644
index 0000000..2c33941
--- /dev/null
+++ b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr
@@ -0,0 +1,11 @@
+error[E0261]: use of undeclared lifetime name `'missing`
+ --> $DIR/dont-ice-on-object-lookup-w-error-region.rs:6:20
+ |
+LL | fn project(x: Pin<&'missing mut dyn Future<Output = ()>>) {
+ | - ^^^^^^^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'missing` here: `<'missing>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr
index f2c6008..de19a99 100644
--- a/tests/ui/moves/move-fn-self-receiver.stderr
+++ b/tests/ui/moves/move-fn-self-receiver.stderr
@@ -101,15 +101,6 @@
| ^^^^^^^ move out of `mut_foo` occurs here
LL | ret;
| --- borrow later used here
- |
-note: if `Foo` implemented `Clone`, you could clone the value
- --> $DIR/move-fn-self-receiver.rs:5:1
- |
-LL | struct Foo;
- | ^^^^^^^^^^ consider implementing `Clone` for this type
-...
-LL | let ret = mut_foo.use_mut_self();
- | ------- you could clone this value
error[E0382]: use of moved value: `rc_foo`
--> $DIR/move-fn-self-receiver.rs:55:5
diff --git a/tests/ui/never_type/never-result.rs b/tests/ui/never_type/never-result.rs
index bdd06ec..98ad140 100644
--- a/tests/ui/never_type/never-result.rs
+++ b/tests/ui/never_type/never-result.rs
@@ -2,9 +2,8 @@
#![allow(unused_variables)]
#![allow(unreachable_code)]
-
+#![allow(unreachable_patterns)]
// Test that we can extract a ! through pattern matching then use it as several different types.
-
#![feature(never_type)]
fn main() {
@@ -16,6 +15,6 @@ fn main() {
let w: i32 = y;
let e: String = y;
y
- },
+ }
}
}
diff --git a/tests/ui/nll/closure-access-spans.stderr b/tests/ui/nll/closure-access-spans.stderr
index f789e5e..a8024a8 100644
--- a/tests/ui/nll/closure-access-spans.stderr
+++ b/tests/ui/nll/closure-access-spans.stderr
@@ -60,9 +60,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let r = &x;
-LL + let r = x.clone();
- |
+LL | let r = &x.clone();
+ | ++++++++
error[E0382]: borrow of moved value: `x`
--> $DIR/closure-access-spans.rs:35:5
@@ -109,11 +108,6 @@
| ^^ -- borrow occurs due to use in closure
| |
| value borrowed here after move
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | let r = x.clone();
- | ++++++++
error[E0382]: use of moved value: `x`
--> $DIR/closure-access-spans.rs:50:5
@@ -126,11 +120,6 @@
| ^^ - use occurs due to use in closure
| |
| value used here after move
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | let r = x.clone();
- | ++++++++
error: aborting due to 9 previous errors
diff --git a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr
index 39ec45b..ae79780 100644
--- a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr
+++ b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr
@@ -10,11 +10,6 @@
| -- - variable moved due to use in closure
| |
| value moved into closure here
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | _ if { (|| { let bar = b.clone(); *bar = false; })();
- | ++++++++
error[E0382]: use of moved value: `b`
--> $DIR/issue-27282-move-match-input-into-guard.rs:24:5
@@ -28,11 +23,6 @@
| -- - variable moved due to use in closure
| |
| value moved into closure here
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | (|| { let bar = b.clone(); *bar = false; })();
- | ++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
deleted file mode 100644
index 7692be7..0000000
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
+++ /dev/null
@@ -1,23 +0,0 @@
-// Issue 27282: Example 1: This sidesteps the AST checks disallowing
-// mutable borrows in match guards by hiding the mutable borrow in a
-// guard behind a move (of the ref mut pattern id) within a closure.
-//@ run-rustfix
-#![feature(if_let_guard)]
-
-fn main() {
- match Some(&4) {
- None => {},
- ref mut foo
- if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
- //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
- Some(s) => std::process::exit(*s),
- }
-
- match Some(&4) {
- None => {},
- ref mut foo
- if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
- //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
- Some(s) => std::process::exit(*s),
- }
-}
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
index f3d0a18..c3b1988 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
@@ -1,7 +1,7 @@
// Issue 27282: Example 1: This sidesteps the AST checks disallowing
// mutable borrows in match guards by hiding the mutable borrow in a
// guard behind a move (of the ref mut pattern id) within a closure.
-//@ run-rustfix
+
#![feature(if_let_guard)]
fn main() {
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
index 7781e77..e790fda 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
@@ -7,10 +7,6 @@
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
- | ++++++++
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
@@ -21,10 +17,6 @@
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
- | ++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
index f73e4aa..0b5d723 100644
--- a/tests/ui/nll/issue-27282-mutation-in-guard.stderr
+++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
@@ -7,10 +7,6 @@
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | (|| { let bar = foo.clone(); bar.take() })();
- | ++++++++
error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-mutation-in-guard.rs:20:18
@@ -21,10 +17,6 @@
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | (|| { let bar = foo.clone(); bar.take() })();
- | ++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
index f4e7869..7f9cbc3 100644
--- a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
+++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
@@ -41,10 +41,6 @@
|
LL | let p = &s.url; p
| +
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | let p = s.url.clone(); p
- | ++++++++
error: aborting due to 4 previous errors
diff --git a/tests/ui/nll/match-guards-always-borrow.fixed b/tests/ui/nll/match-guards-always-borrow.fixed
deleted file mode 100644
index 56e743b..0000000
--- a/tests/ui/nll/match-guards-always-borrow.fixed
+++ /dev/null
@@ -1,66 +0,0 @@
-#![feature(if_let_guard)]
-#![allow(unused_mut)]
-//@ run-rustfix
-
-// Here is arielb1's basic example from rust-lang/rust#27282
-// that AST borrowck is flummoxed by:
-
-fn should_reject_destructive_mutate_in_guard() {
- match Some(&4) {
- None => {},
- ref mut foo if {
- (|| { let mut bar = foo.clone(); bar.take() })();
- //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
- false } => { },
- Some(s) => std::process::exit(*s),
- }
-
- match Some(&4) {
- None => {},
- ref mut foo if let Some(()) = {
- (|| { let mut bar = foo.clone(); bar.take() })();
- //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
- None } => { },
- Some(s) => std::process::exit(*s),
- }
-}
-
-// Here below is a case that needs to keep working: we only use the
-// binding via immutable-borrow in the guard, and we mutate in the arm
-// body.
-fn allow_mutate_in_arm_body() {
- match Some(&4) {
- None => {},
- ref mut foo if foo.is_some() => { foo.take(); () }
- Some(s) => std::process::exit(*s),
- }
-
- match Some(&4) {
- None => {},
- ref mut foo if let Some(_) = foo => { foo.take(); () }
- Some(s) => std::process::exit(*s),
- }
-}
-
-// Here below is a case that needs to keep working: we only use the
-// binding via immutable-borrow in the guard, and we move into the arm
-// body.
-fn allow_move_into_arm_body() {
- match Some(&4) {
- None => {},
- mut foo if foo.is_some() => { foo.unwrap(); () }
- Some(s) => std::process::exit(*s),
- }
-
- match Some(&4) {
- None => {},
- mut foo if let Some(_) = foo => { foo.unwrap(); () }
- Some(s) => std::process::exit(*s),
- }
-}
-
-fn main() {
- should_reject_destructive_mutate_in_guard();
- allow_mutate_in_arm_body();
- allow_move_into_arm_body();
-}
diff --git a/tests/ui/nll/match-guards-always-borrow.rs b/tests/ui/nll/match-guards-always-borrow.rs
index 927d55c..5271e3c 100644
--- a/tests/ui/nll/match-guards-always-borrow.rs
+++ b/tests/ui/nll/match-guards-always-borrow.rs
@@ -1,6 +1,5 @@
#![feature(if_let_guard)]
#![allow(unused_mut)]
-//@ run-rustfix
// Here is arielb1's basic example from rust-lang/rust#27282
// that AST borrowck is flummoxed by:
diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr
index bb0c5bd..71977bd 100644
--- a/tests/ui/nll/match-guards-always-borrow.stderr
+++ b/tests/ui/nll/match-guards-always-borrow.stderr
@@ -1,5 +1,5 @@
error[E0507]: cannot move out of `foo` in pattern guard
- --> $DIR/match-guards-always-borrow.rs:12:14
+ --> $DIR/match-guards-always-borrow.rs:11:14
|
LL | (|| { let mut bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -7,13 +7,9 @@
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | (|| { let mut bar = foo.clone(); bar.take() })();
- | ++++++++
error[E0507]: cannot move out of `foo` in pattern guard
- --> $DIR/match-guards-always-borrow.rs:21:14
+ --> $DIR/match-guards-always-borrow.rs:20:14
|
LL | (|| { let mut bar = foo; bar.take() })();
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -21,10 +17,6 @@
| `foo` is moved here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | (|| { let mut bar = foo.clone(); bar.take() })();
- | ++++++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/nll/polonius/polonius-smoke-test.stderr b/tests/ui/nll/polonius/polonius-smoke-test.stderr
index 534813b..a8a8267 100644
--- a/tests/ui/nll/polonius/polonius-smoke-test.stderr
+++ b/tests/ui/nll/polonius/polonius-smoke-test.stderr
@@ -27,6 +27,12 @@
| ^ move out of `x` occurs here
LL | y
| - returning this value requires that `*x` is borrowed for `'1`
+ |
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL - let y = &mut *x;
+LL + let y = &mut x.clone();
+ |
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/polonius-smoke-test.rs:42:5
@@ -40,6 +46,12 @@
| ^ move out of `s` occurs here
LL | tmp;
| --- borrow later used here
+ |
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL - let r = &mut *s;
+LL + let r = &mut s.clone();
+ |
error: aborting due to 4 previous errors
diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs
index cb2f047..64850e4 100644
--- a/tests/ui/offset-of/offset-of-enum.rs
+++ b/tests/ui/offset-of/offset-of-enum.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of_enum, offset_of_nested)]
+#![feature(offset_of_enum)]
use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index 1c326b5..8b8ffb5 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of_enum, offset_of_nested)]
+#![feature(offset_of_enum)]
use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs
index 1558e13..e5730b8 100644
--- a/tests/ui/offset-of/offset-of-self.rs
+++ b/tests/ui/offset-of/offset-of-self.rs
@@ -1,5 +1,3 @@
-#![feature(offset_of_nested)]
-
use std::mem::offset_of;
struct C<T> {
diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr
index 7c7576e..5bbb4ec 100644
--- a/tests/ui/offset-of/offset-of-self.stderr
+++ b/tests/ui/offset-of/offset-of-self.stderr
@@ -1,11 +1,11 @@
error: offset_of expects dot-separated field and variant names
- --> $DIR/offset-of-self.rs:20:26
+ --> $DIR/offset-of-self.rs:18:26
|
LL | offset_of!(Self, Self::v);
| ^^^^^^^
error[E0412]: cannot find type `S` in module `self`
- --> $DIR/offset-of-self.rs:34:26
+ --> $DIR/offset-of-self.rs:32:26
|
LL | offset_of!(self::S, v);
| ^ not found in `self`
@@ -21,7 +21,7 @@
|
error[E0411]: cannot find type `Self` in this scope
- --> $DIR/offset-of-self.rs:51:16
+ --> $DIR/offset-of-self.rs:49:16
|
LL | fn main() {
| ---- `Self` not allowed in a function
@@ -30,7 +30,7 @@
| ^^^^ `Self` is only available in impls, traits, and type definitions
error[E0609]: no field `Self` on type `S`
- --> $DIR/offset-of-self.rs:21:23
+ --> $DIR/offset-of-self.rs:19:23
|
LL | offset_of!(S, Self);
| ^^^^
@@ -38,13 +38,13 @@
= note: available fields are: `v`, `w`
error[E0616]: field `v` of struct `T` is private
- --> $DIR/offset-of-self.rs:40:30
+ --> $DIR/offset-of-self.rs:38:30
|
LL | offset_of!(Self, v)
| ^ private field
error[E0609]: no field `self` on type `S`
- --> $DIR/offset-of-self.rs:53:19
+ --> $DIR/offset-of-self.rs:51:19
|
LL | offset_of!(S, self);
| ^^^^
@@ -52,7 +52,7 @@
= note: available fields are: `v`, `w`
error[E0609]: no field `self` on type `u8`
- --> $DIR/offset-of-self.rs:54:21
+ --> $DIR/offset-of-self.rs:52:21
|
LL | offset_of!(S, v.self);
| ^^^^
diff --git a/tests/ui/offset-of/offset-of-slice-normalized.rs b/tests/ui/offset-of/offset-of-slice-normalized.rs
new file mode 100644
index 0000000..9d1fd9d
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-slice-normalized.rs
@@ -0,0 +1,37 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ run-pass
+
+#![feature(offset_of_slice)]
+
+use std::mem::offset_of;
+
+trait Mirror {
+ type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+ type Assoc = T;
+}
+
+#[repr(C)]
+struct S {
+ a: u8,
+ b: (u8, u8),
+ c: <[i32] as Mirror>::Assoc,
+}
+
+#[repr(C)]
+struct T {
+ x: i8,
+ y: S,
+}
+
+type Tup = (i16, <[i32] as Mirror>::Assoc);
+
+fn main() {
+ assert_eq!(offset_of!(S, c), 4);
+ assert_eq!(offset_of!(T, y), 4);
+ assert_eq!(offset_of!(T, y.c), 8);
+ assert_eq!(offset_of!(Tup, 1), 4);
+}
diff --git a/tests/ui/offset-of/offset-of-slice.rs b/tests/ui/offset-of/offset-of-slice.rs
index a0fe319..e6eb12a 100644
--- a/tests/ui/offset-of/offset-of-slice.rs
+++ b/tests/ui/offset-of/offset-of-slice.rs
@@ -1,5 +1,5 @@
//@run-pass
-#![feature(offset_of_slice, offset_of_nested)]
+#![feature(offset_of_slice)]
use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs
index 4a58b71..210a8b6 100644
--- a/tests/ui/offset-of/offset-of-tuple-nested.rs
+++ b/tests/ui/offset-of/offset-of-tuple-nested.rs
@@ -2,8 +2,6 @@
// Test for issue #112204 -- make sure this goes through the entire compilation pipeline,
// similar to why `offset-of-unsized.rs` is also build-pass
-#![feature(offset_of_nested)]
-
use std::mem::offset_of;
type ComplexTup = ((u8, (u8, (u8, u16), u8)), (u8, u32, u16));
diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs
index 75ba8d7..b082235 100644
--- a/tests/ui/offset-of/offset-of-tuple.rs
+++ b/tests/ui/offset-of/offset-of-tuple.rs
@@ -1,4 +1,3 @@
-#![feature(offset_of_nested)]
#![feature(builtin_syntax)]
use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr
index 1e2d924..e6b45c0 100644
--- a/tests/ui/offset-of/offset-of-tuple.stderr
+++ b/tests/ui/offset-of/offset-of-tuple.stderr
@@ -1,11 +1,11 @@
error: suffixes on a tuple index are invalid
- --> $DIR/offset-of-tuple.rs:19:35
+ --> $DIR/offset-of-tuple.rs:18:35
|
LL | builtin # offset_of((u8, u8), 1_u8);
| ^^^^ invalid suffix `u8`
error: leading `+` is not supported
- --> $DIR/offset-of-tuple.rs:23:37
+ --> $DIR/offset-of-tuple.rs:22:37
|
LL | { builtin # offset_of((u8, u8), +1) };
| ^ unexpected `+`
@@ -17,67 +17,67 @@
|
error: offset_of expects dot-separated field and variant names
- --> $DIR/offset-of-tuple.rs:24:38
+ --> $DIR/offset-of-tuple.rs:23:38
|
LL | { builtin # offset_of((u8, u8), 1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:25:40
+ --> $DIR/offset-of-tuple.rs:24:40
|
LL | { builtin # offset_of((u8, u8), 1 .) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:47:45
+ --> $DIR/offset-of-tuple.rs:46:45
|
LL | { builtin # offset_of(ComplexTup, 0.0.1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:48:46
+ --> $DIR/offset-of-tuple.rs:47:46
|
LL | { builtin # offset_of(ComplexTup, 0 .0.1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:49:47
+ --> $DIR/offset-of-tuple.rs:48:47
|
LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:50:46
+ --> $DIR/offset-of-tuple.rs:49:46
|
LL | { builtin # offset_of(ComplexTup, 0. 0.1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:51:46
+ --> $DIR/offset-of-tuple.rs:50:46
|
LL | { builtin # offset_of(ComplexTup, 0.0 .1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:52:47
+ --> $DIR/offset-of-tuple.rs:51:47
|
LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) };
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:53:46
+ --> $DIR/offset-of-tuple.rs:52:46
|
LL | { builtin # offset_of(ComplexTup, 0.0. 1.) };
| ^
error: suffixes on a tuple index are invalid
- --> $DIR/offset-of-tuple.rs:10:26
+ --> $DIR/offset-of-tuple.rs:9:26
|
LL | offset_of!((u8, u8), 1_u8);
| ^^^^ invalid suffix `u8`
error: no rules expected the token `+`
- --> $DIR/offset-of-tuple.rs:12:26
+ --> $DIR/offset-of-tuple.rs:11:26
|
LL | offset_of!((u8, u8), +1);
| ^ no rules expected this token in macro call
@@ -86,115 +86,115 @@
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
error: offset_of expects dot-separated field and variant names
- --> $DIR/offset-of-tuple.rs:13:26
+ --> $DIR/offset-of-tuple.rs:12:26
|
LL | offset_of!((u8, u8), -1);
| ^^
error: offset_of expects dot-separated field and variant names
- --> $DIR/offset-of-tuple.rs:14:27
+ --> $DIR/offset-of-tuple.rs:13:27
|
LL | offset_of!((u8, u8), 1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:15:29
+ --> $DIR/offset-of-tuple.rs:14:29
|
LL | offset_of!((u8, u8), 1 .);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:36:34
+ --> $DIR/offset-of-tuple.rs:35:34
|
LL | offset_of!(ComplexTup, 0.0.1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:37:35
+ --> $DIR/offset-of-tuple.rs:36:35
|
LL | offset_of!(ComplexTup, 0 .0.1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:38:36
+ --> $DIR/offset-of-tuple.rs:37:36
|
LL | offset_of!(ComplexTup, 0 . 0.1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:39:35
+ --> $DIR/offset-of-tuple.rs:38:35
|
LL | offset_of!(ComplexTup, 0. 0.1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:40:35
+ --> $DIR/offset-of-tuple.rs:39:35
|
LL | offset_of!(ComplexTup, 0.0 .1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:41:36
+ --> $DIR/offset-of-tuple.rs:40:36
|
LL | offset_of!(ComplexTup, 0.0 . 1.);
| ^
error: unexpected token: `)`
- --> $DIR/offset-of-tuple.rs:42:35
+ --> $DIR/offset-of-tuple.rs:41:35
|
LL | offset_of!(ComplexTup, 0.0. 1.);
| ^
error[E0609]: no field `_0` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:7:26
+ --> $DIR/offset-of-tuple.rs:6:26
|
LL | offset_of!((u8, u8), _0);
| ^^
error[E0609]: no field `01` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:8:26
+ --> $DIR/offset-of-tuple.rs:7:26
|
LL | offset_of!((u8, u8), 01);
| ^^
error[E0609]: no field `1e2` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:9:26
+ --> $DIR/offset-of-tuple.rs:8:26
|
LL | offset_of!((u8, u8), 1e2);
| ^^^
error[E0609]: no field `1_` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:10:26
+ --> $DIR/offset-of-tuple.rs:9:26
|
LL | offset_of!((u8, u8), 1_u8);
| ^^^^
error[E0609]: no field `1e2` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:16:35
+ --> $DIR/offset-of-tuple.rs:15:35
|
LL | builtin # offset_of((u8, u8), 1e2);
| ^^^
error[E0609]: no field `_0` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:17:35
+ --> $DIR/offset-of-tuple.rs:16:35
|
LL | builtin # offset_of((u8, u8), _0);
| ^^
error[E0609]: no field `01` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:18:35
+ --> $DIR/offset-of-tuple.rs:17:35
|
LL | builtin # offset_of((u8, u8), 01);
| ^^
error[E0609]: no field `1_` on type `(u8, u8)`
- --> $DIR/offset-of-tuple.rs:19:35
+ --> $DIR/offset-of-tuple.rs:18:35
|
LL | builtin # offset_of((u8, u8), 1_u8);
| ^^^^
error[E0609]: no field `2` on type `(u8, u16)`
- --> $DIR/offset-of-tuple.rs:31:47
+ --> $DIR/offset-of-tuple.rs:30:47
|
LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2);
| _____------------------------------------------^-
@@ -207,7 +207,7 @@
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0609]: no field `0` on type `u8`
- --> $DIR/offset-of-tuple.rs:33:49
+ --> $DIR/offset-of-tuple.rs:32:49
|
LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0);
| ^
diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs
index c9d4f30..c2614ba 100644
--- a/tests/ui/offset-of/offset-of-unstable-with-feature.rs
+++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs
@@ -1,7 +1,7 @@
//@ check-pass
//@ aux-build:offset-of-staged-api.rs
-#![feature(offset_of_nested, unstable_test_feature)]
+#![feature(unstable_test_feature)]
use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs
index ab6f89c..d249e88 100644
--- a/tests/ui/offset-of/offset-of-unstable.rs
+++ b/tests/ui/offset-of/offset-of-unstable.rs
@@ -1,7 +1,5 @@
//@ aux-build:offset-of-staged-api.rs
-#![feature(offset_of_nested)]
-
use std::mem::offset_of;
extern crate offset_of_staged_api;
diff --git a/tests/ui/offset-of/offset-of-unstable.stderr b/tests/ui/offset-of/offset-of-unstable.stderr
index 4882dee..44ccad3 100644
--- a/tests/ui/offset-of/offset-of-unstable.stderr
+++ b/tests/ui/offset-of/offset-of-unstable.stderr
@@ -1,5 +1,5 @@
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:14:9
+ --> $DIR/offset-of-unstable.rs:12:9
|
LL | Unstable,
| ^^^^^^^^
@@ -8,7 +8,7 @@
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:23:9
+ --> $DIR/offset-of-unstable.rs:21:9
|
LL | UnstableWithStableFieldType,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:28:9
+ --> $DIR/offset-of-unstable.rs:26:9
|
LL | UnstableWithStableFieldType,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:12:5
+ --> $DIR/offset-of-unstable.rs:10:5
|
LL | / offset_of!(
LL | |
@@ -40,7 +40,7 @@
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:18:5
+ --> $DIR/offset-of-unstable.rs:16:5
|
LL | offset_of!(StableWithUnstableField, unstable);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +50,7 @@
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:20:5
+ --> $DIR/offset-of-unstable.rs:18:5
|
LL | offset_of!(StableWithUnstableFieldType, stable.unstable);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:21:5
+ --> $DIR/offset-of-unstable.rs:19:5
|
LL | / offset_of!(
LL | |
@@ -74,7 +74,7 @@
= note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/offset-of-unstable.rs:26:5
+ --> $DIR/offset-of-unstable.rs:24:5
|
LL | / offset_of!(
LL | |
diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr
index e7def11b0..3417d4b 100644
--- a/tests/ui/panics/panic-in-cleanup.run.stderr
+++ b/tests/ui/panics/panic-in-cleanup.run.stderr
@@ -4,6 +4,6 @@
thread 'main' panicked at $DIR/panic-in-cleanup.rs:16:9:
BOOM
stack backtrace:
-thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL:
+thread 'main' panicked at core/src/panicking.rs:$LINE:$COL:
panic in a destructor during cleanup
thread caused non-unwinding panic. aborting.
diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr
index 5963553..fc70847 100644
--- a/tests/ui/panics/panic-in-ffi.run.stderr
+++ b/tests/ui/panics/panic-in-ffi.run.stderr
@@ -1,7 +1,7 @@
thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5:
Test
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL:
+thread 'main' panicked at core/src/panicking.rs:$LINE:$COL:
panic in a function that cannot unwind
stack backtrace:
thread caused non-unwinding panic. aborting.
diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr
index d76cb25..913a347 100644
--- a/tests/ui/parser/brace-in-let-chain.stderr
+++ b/tests/ui/parser/brace-in-let-chain.stderr
@@ -17,14 +17,8 @@
| - unclosed delimiter
...
LL | fn foo() {
- | - unclosed delimiter
+ | - another 3 unclosed delimiters begin from here
...
-LL | fn bar() {
- | - unclosed delimiter
-...
-LL | fn baz() {
- | - unclosed delimiter
-LL | if false {
LL | {
| - this delimiter might not be properly closed...
LL | && let () = ()
diff --git a/tests/ui/parser/issues/issue-105366.fixed b/tests/ui/parser/issues/issue-105366.fixed
index 95419dc..7157b64 100644
--- a/tests/ui/parser/issues/issue-105366.fixed
+++ b/tests/ui/parser/issues/issue-105366.fixed
@@ -1,6 +1,5 @@
//@ run-rustfix
-#[allow(dead_code)]
struct Foo;
impl From<i32> for Foo {
diff --git a/tests/ui/parser/issues/issue-105366.rs b/tests/ui/parser/issues/issue-105366.rs
index 3278b73..dc3cb8b 100644
--- a/tests/ui/parser/issues/issue-105366.rs
+++ b/tests/ui/parser/issues/issue-105366.rs
@@ -1,6 +1,5 @@
//@ run-rustfix
-#[allow(dead_code)]
struct Foo;
fn From<i32> for Foo {
diff --git a/tests/ui/parser/issues/issue-105366.stderr b/tests/ui/parser/issues/issue-105366.stderr
index 195305a..18c04df 100644
--- a/tests/ui/parser/issues/issue-105366.stderr
+++ b/tests/ui/parser/issues/issue-105366.stderr
@@ -1,5 +1,5 @@
error: you might have meant to write `impl` instead of `fn`
- --> $DIR/issue-105366.rs:6:1
+ --> $DIR/issue-105366.rs:5:1
|
LL | fn From<i32> for Foo {
| ^^
diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
new file mode 100644
index 0000000..5dcaa26
--- /dev/null
+++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
@@ -0,0 +1,6 @@
+// issue: rust-lang/rust#127868
+
+fn main() {
+ let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
+} //~ ERROR mismatched closing delimiter: `}`
+//~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
new file mode 100644
index 0000000..94e25c1
--- /dev/null
+++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
@@ -0,0 +1,30 @@
+error: mismatched closing delimiter: `}`
+ --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:4:42
+ |
+LL | fn main() {
+ | - closing delimiter possibly meant for this
+LL | let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
+ | ^ unclosed delimiter
+LL | }
+ | ^ mismatched closing delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:6:52
+ |
+LL | fn main() {
+ | - unclosed delimiter
+LL | let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
+ | ----- - this delimiter might not be properly closed...
+ | |||||
+ | ||||another 16 unclosed delimiters begin from here
+ | |||unclosed delimiter
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+LL | }
+ | - ...as it matches this but it has different indentation
+LL |
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed
index e9c8980..a851300 100644
--- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed
+++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed
@@ -1,8 +1,7 @@
// Regression test for issues #100790 and #106439.
//@ run-rustfix
-#[allow(dead_code)]
-pub struct Example(usize)
+pub struct Example(#[allow(dead_code)] usize)
where
(): Sized;
//~^^^ ERROR where clauses are not allowed before tuple struct bodies
diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs
index 3bd0f51..10f4358 100644
--- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs
+++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs
@@ -1,11 +1,10 @@
// Regression test for issues #100790 and #106439.
//@ run-rustfix
-#[allow(dead_code)]
pub struct Example
where
(): Sized,
-(usize);
+(#[allow(dead_code)] usize);
//~^^^ ERROR where clauses are not allowed before tuple struct bodies
struct _Demo
diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr
index 77eafa6..ddbf237 100644
--- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr
+++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr
@@ -1,23 +1,23 @@
error: where clauses are not allowed before tuple struct bodies
- --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:6:1
+ --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:5:1
|
LL | pub struct Example
| ------- while parsing this tuple struct
LL | / where
LL | | (): Sized,
| |______________^ unexpected where clause
-LL | (usize);
- | ------- the struct body
+LL | (#[allow(dead_code)] usize);
+ | --------------------------- the struct body
|
help: move the body before the where clause
|
-LL ~ pub struct Example(usize)
+LL ~ pub struct Example(#[allow(dead_code)] usize)
LL | where
LL ~ (): Sized;
|
error: where clauses are not allowed before tuple struct bodies
- --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:12:1
+ --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:11:1
|
LL | struct _Demo
| ----- while parsing this tuple struct
diff --git a/tests/ui/parser/removed-syntax/removed-syntax-box.stderr b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr
index 46b8915..60c39fd 100644
--- a/tests/ui/parser/removed-syntax/removed-syntax-box.stderr
+++ b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr
@@ -7,7 +7,7 @@
help: use `Box::new()` instead
|
LL | let _ = Box::new(());
- | ~~~~~~~~~~~~
+ | ~~~~~~~~~ +
error: `box_syntax` has been removed
--> $DIR/removed-syntax-box.rs:10:13
@@ -18,7 +18,7 @@
help: use `Box::new()` instead
|
LL | let _ = Box::new(1);
- | ~~~~~~~~~~~
+ | ~~~~~~~~~ +
error: `box_syntax` has been removed
--> $DIR/removed-syntax-box.rs:11:13
@@ -29,7 +29,7 @@
help: use `Box::new()` instead
|
LL | let _ = Box::new(T { a: 12, b: 18 });
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~ +
error: `box_syntax` has been removed
--> $DIR/removed-syntax-box.rs:12:13
@@ -40,7 +40,7 @@
help: use `Box::new()` instead
|
LL | let _ = Box::new([5; 30]);
- | ~~~~~~~~~~~~~~~~~
+ | ~~~~~~~~~ +
error: `box_syntax` has been removed
--> $DIR/removed-syntax-box.rs:13:22
@@ -51,7 +51,7 @@
help: use `Box::new()` instead
|
LL | let _: Box<()> = Box::new(());
- | ~~~~~~~~~~~~
+ | ~~~~~~~~~ +
error: aborting due to 5 previous errors
diff --git a/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs b/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs
new file mode 100644
index 0000000..1affee5
--- /dev/null
+++ b/tests/ui/parser/suggest-remove-compount-assign-let-ice.rs
@@ -0,0 +1,16 @@
+//! Previously we would try to issue a suggestion for `let x <op>= 1`, i.e. a compound assignment
+//! within a `let` binding, to remove the `<op>`. The suggestion code unfortunately incorrectly
+//! assumed that the `<op>` is an exactly-1-byte ASCII character, but this assumption is incorrect
+//! because we also recover Unicode-confusables like `➖=` as `-=`. In this example, the suggestion
+//! code used a `+ BytePos(1)` to calculate the span of the `<op>` codepoint that looks like `-` but
+//! the mult-byte Unicode look-alike would cause the suggested removal span to be inside a
+//! multi-byte codepoint boundary, triggering a codepoint boundary assertion.
+//!
+//! issue: rust-lang/rust#128845
+
+fn main() {
+ // Adapted from #128845 but with irrelevant components removed and simplified.
+ let x ➖= 1;
+ //~^ ERROR unknown start of token: \u{2796}
+ //~| ERROR: can't reassign to an uninitialized variable
+}
diff --git a/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr b/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr
new file mode 100644
index 0000000..59716d6
--- /dev/null
+++ b/tests/ui/parser/suggest-remove-compount-assign-let-ice.stderr
@@ -0,0 +1,26 @@
+error: unknown start of token: \u{2796}
+ --> $DIR/suggest-remove-compount-assign-let-ice.rs:13:11
+ |
+LL | let x ➖= 1;
+ | ^^
+ |
+help: Unicode character '➖' (Heavy Minus Sign) looks like '-' (Minus/Hyphen), but it is not
+ |
+LL | let x -= 1;
+ | ~
+
+error: can't reassign to an uninitialized variable
+ --> $DIR/suggest-remove-compount-assign-let-ice.rs:13:11
+ |
+LL | let x ➖= 1;
+ | ^^^
+ |
+ = help: if you meant to overwrite, remove the `let` binding
+help: initialize the variable
+ |
+LL - let x ➖= 1;
+LL + let x = 1;
+ |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs
index 0b63a99..6d339cd 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.rs
+++ b/tests/ui/parser/unsafe-foreign-mod-2.rs
@@ -1,8 +1,6 @@
extern "C" unsafe {
//~^ ERROR expected `{`, found keyword `unsafe`
- //~| ERROR extern block cannot be declared unsafe
unsafe fn foo();
- //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
}
fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr
index 8bd592b5..0625e33 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.stderr
+++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr
@@ -4,21 +4,5 @@
LL | extern "C" unsafe {
| ^^^^^^ expected `{`
-error: extern block cannot be declared unsafe
- --> $DIR/unsafe-foreign-mod-2.rs:1:12
- |
-LL | extern "C" unsafe {
- | ^^^^^^
- |
- = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
- = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: items in unadorned `extern` blocks cannot have safety qualifiers
- --> $DIR/unsafe-foreign-mod-2.rs:4:5
- |
-LL | unsafe fn foo();
- | ^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs
index eab134a..623c3bb 100644
--- a/tests/ui/parser/unsafe-foreign-mod.rs
+++ b/tests/ui/parser/unsafe-foreign-mod.rs
@@ -1,5 +1,5 @@
-unsafe extern "C" {
- //~^ ERROR extern block cannot be declared unsafe
-}
+//@ check-pass
+
+unsafe extern "C" {}
fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr
deleted file mode 100644
index 60b918a..0000000
--- a/tests/ui/parser/unsafe-foreign-mod.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error: extern block cannot be declared unsafe
- --> $DIR/unsafe-foreign-mod.rs:1:1
- |
-LL | unsafe extern "C" {
- | ^^^^^^
- |
- = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
- = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
- = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index e925fe7..9359244 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -333,14 +333,6 @@
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-note: if `U` implemented `Clone`, you could clone the value
- --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
- |
-LL | struct U;
- | ^^^^^^^^ consider implementing `Clone` for this type
-...
-LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
- | - you could clone this value
error[E0507]: cannot move out of `b` in pattern guard
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
@@ -349,14 +341,6 @@
| ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-note: if `U` implemented `Clone`, you could clone the value
- --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
- |
-LL | struct U;
- | ^^^^^^^^ consider implementing `Clone` for this type
-...
-LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
- | - you could clone this value
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0507]: cannot move out of `a` in pattern guard
diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs
index d5c5b68..fd1d5fb 100644
--- a/tests/ui/pattern/issue-22546.rs
+++ b/tests/ui/pattern/issue-22546.rs
@@ -15,7 +15,7 @@ fn foo(&self) {
}
}
-trait Tr {
+trait Tr { //~ WARN trait `Tr` is never used
type U;
}
diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr
new file mode 100644
index 0000000..e067a95
--- /dev/null
+++ b/tests/ui/pattern/issue-22546.stderr
@@ -0,0 +1,10 @@
+warning: trait `Tr` is never used
+ --> $DIR/issue-22546.rs:18:7
+ |
+LL | trait Tr {
+ | ^^
+ |
+ = note: `#[warn(dead_code)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr
index d6304a0..bc74069 100644
--- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
- --> $DIR/always-inhabited-union-ref.rs:25:11
+ --> $DIR/always-inhabited-union-ref.rs:24:11
|
LL | match uninhab_ref() {
| ^^^^^^^^^^^^^
@@ -14,13 +14,13 @@
|
error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
- --> $DIR/always-inhabited-union-ref.rs:29:11
+ --> $DIR/always-inhabited-union-ref.rs:28:11
|
LL | match uninhab_union() {
| ^^^^^^^^^^^^^^^
|
note: `Foo` defined here
- --> $DIR/always-inhabited-union-ref.rs:12:11
+ --> $DIR/always-inhabited-union-ref.rs:11:11
|
LL | pub union Foo {
| ^^^
diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.normal.stderr
similarity index 87%
rename from tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr
rename to tests/ui/pattern/usefulness/always-inhabited-union-ref.normal.stderr
index d6304a0..bc74069 100644
--- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.normal.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
- --> $DIR/always-inhabited-union-ref.rs:25:11
+ --> $DIR/always-inhabited-union-ref.rs:24:11
|
LL | match uninhab_ref() {
| ^^^^^^^^^^^^^
@@ -14,13 +14,13 @@
|
error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
- --> $DIR/always-inhabited-union-ref.rs:29:11
+ --> $DIR/always-inhabited-union-ref.rs:28:11
|
LL | match uninhab_union() {
| ^^^^^^^^^^^^^^^
|
note: `Foo` defined here
- --> $DIR/always-inhabited-union-ref.rs:12:11
+ --> $DIR/always-inhabited-union-ref.rs:11:11
|
LL | pub union Foo {
| ^^^
diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs
index 5088098..335eff4 100644
--- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs
+++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs
@@ -1,10 +1,9 @@
-//@ revisions: min_exhaustive_patterns exhaustive_patterns
+//@ revisions: normal exhaustive_patterns
// The precise semantics of inhabitedness with respect to unions and references is currently
// undecided. This test file currently checks a conservative choice.
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
-#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
#![feature(never_type)]
#![allow(dead_code)]
#![allow(unreachable_code)]
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
index 9e700ee..1b65ff7 100644
--- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
@@ -38,7 +38,7 @@
error[E0005]: refutable pattern in local binding
--> $DIR/empty-match-check-notes.rs:39:9
|
-LL | let None = x;
+LL | let None = *x;
| ^^^^ pattern `Some(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
@@ -47,8 +47,8 @@
= note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
-LL | if let None = x { todo!() };
- | ++ +++++++++++
+LL | if let None = *x { todo!() };
+ | ++ +++++++++++
error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered
--> $DIR/empty-match-check-notes.rs:49:11
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
index 480ae70..1b65ff7 100644
--- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
@@ -38,16 +38,17 @@
error[E0005]: refutable pattern in local binding
--> $DIR/empty-match-check-notes.rs:39:9
|
-LL | let None = x;
+LL | let None = *x;
| ^^^^ pattern `Some(_)` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+ = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
= note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
-LL | if let None = x { todo!() };
- | ++ +++++++++++
+LL | if let None = *x { todo!() };
+ | ++ +++++++++++
error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered
--> $DIR/empty-match-check-notes.rs:49:11
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs
index 2eef283..61a75e6 100644
--- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs
@@ -35,14 +35,14 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
}
}
-fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
- let None = x;
+fn empty_foreign_enum_private(x: &Option<empty::SecretlyUninhabitedForeignStruct>) {
+ let None = *x;
//~^ ERROR refutable pattern in local binding
//~| NOTE `let` bindings require an "irrefutable pattern"
//~| NOTE for more information, visit
//~| NOTE the matched value is of type
//~| NOTE pattern `Some(_)` not covered
- //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
+ //~| NOTE currently uninhabited, but this variant contains private fields
}
fn main() {
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 5f895fa..f2067f0 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `u8` is non-empty
- --> $DIR/empty-match.rs:46:20
+ --> $DIR/empty-match.rs:47:20
|
LL | match_no_arms!(0u8);
| ^^^
@@ -8,7 +8,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `i8` is non-empty
- --> $DIR/empty-match.rs:47:20
+ --> $DIR/empty-match.rs:48:20
|
LL | match_no_arms!(0i8);
| ^^^
@@ -17,7 +17,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
- --> $DIR/empty-match.rs:48:20
+ --> $DIR/empty-match.rs:49:20
|
LL | match_no_arms!(0usize);
| ^^^^^^
@@ -26,7 +26,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `isize` is non-empty
- --> $DIR/empty-match.rs:49:20
+ --> $DIR/empty-match.rs:50:20
|
LL | match_no_arms!(0isize);
| ^^^^^^
@@ -35,7 +35,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
- --> $DIR/empty-match.rs:50:20
+ --> $DIR/empty-match.rs:51:20
|
LL | match_no_arms!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
- --> $DIR/empty-match.rs:51:20
+ --> $DIR/empty-match.rs:52:20
|
LL | match_no_arms!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
- --> $DIR/empty-match.rs:52:20
+ --> $DIR/empty-match.rs:53:20
|
LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
- --> $DIR/empty-match.rs:53:20
+ --> $DIR/empty-match.rs:54:20
|
LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -91,7 +91,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:54:20
+ --> $DIR/empty-match.rs:55:20
|
LL | match_no_arms!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
@@ -107,7 +107,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:55:20
+ --> $DIR/empty-match.rs:56:20
|
LL | match_no_arms!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
@@ -125,7 +125,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:56:20
+ --> $DIR/empty-match.rs:57:20
|
LL | match_no_arms!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -148,8 +148,26 @@
= note: the matched value is of type `NonEmptyEnum5`
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
+error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
+ --> $DIR/empty-match.rs:58:20
+ |
+LL | match_no_arms!(array0_of_empty);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: the matched value is of type `[!; 0]`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `[!; N]` is non-empty
+ --> $DIR/empty-match.rs:59:20
+ |
+LL | match_no_arms!(arrayN_of_empty);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: the matched value is of type `[!; N]`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered
- --> $DIR/empty-match.rs:58:24
+ --> $DIR/empty-match.rs:61:24
|
LL | match_guarded_arm!(0u8);
| ^^^ pattern `0_u8..=u8::MAX` not covered
@@ -163,7 +181,7 @@
|
error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered
- --> $DIR/empty-match.rs:59:24
+ --> $DIR/empty-match.rs:62:24
|
LL | match_guarded_arm!(0i8);
| ^^^ pattern `i8::MIN..=i8::MAX` not covered
@@ -177,7 +195,7 @@
|
error[E0004]: non-exhaustive patterns: `0_usize..` not covered
- --> $DIR/empty-match.rs:60:24
+ --> $DIR/empty-match.rs:63:24
|
LL | match_guarded_arm!(0usize);
| ^^^^^^ pattern `0_usize..` not covered
@@ -191,7 +209,7 @@
|
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/empty-match.rs:61:24
+ --> $DIR/empty-match.rs:64:24
|
LL | match_guarded_arm!(0isize);
| ^^^^^^ pattern `_` not covered
@@ -205,7 +223,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
- --> $DIR/empty-match.rs:62:24
+ --> $DIR/empty-match.rs:65:24
|
LL | match_guarded_arm!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
@@ -224,7 +242,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
- --> $DIR/empty-match.rs:63:24
+ --> $DIR/empty-match.rs:66:24
|
LL | match_guarded_arm!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
@@ -243,7 +261,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
- --> $DIR/empty-match.rs:64:24
+ --> $DIR/empty-match.rs:67:24
|
LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
@@ -262,7 +280,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
- --> $DIR/empty-match.rs:65:24
+ --> $DIR/empty-match.rs:68:24
|
LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
@@ -273,6 +291,7 @@
LL | union NonEmptyUnion2 {
| ^^^^^^^^^^^^^^
= note: the matched value is of type `NonEmptyUnion2`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
= note: match arms with guards don't count towards exhaustivity
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
@@ -281,7 +300,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:66:24
+ --> $DIR/empty-match.rs:69:24
|
LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
@@ -302,7 +321,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:67:24
+ --> $DIR/empty-match.rs:70:24
|
LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
@@ -325,7 +344,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:68:24
+ --> $DIR/empty-match.rs:71:24
|
LL | match_guarded_arm!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -353,6 +372,34 @@
LL + _ => todo!()
|
-error: aborting due to 22 previous errors
+error[E0004]: non-exhaustive patterns: `[]` not covered
+ --> $DIR/empty-match.rs:72:24
+ |
+LL | match_guarded_arm!(array0_of_empty);
+ | ^^^^^^^^^^^^^^^ pattern `[]` not covered
+ |
+ = note: the matched value is of type `[!; 0]`
+ = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ _ if false => {},
+LL + [] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+ --> $DIR/empty-match.rs:73:24
+ |
+LL | match_guarded_arm!(arrayN_of_empty);
+ | ^^^^^^^^^^^^^^^ pattern `[]` not covered
+ |
+ = note: the matched value is of type `[!; N]`
+ = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ _ if false => {},
+LL + [] => todo!()
+ |
+
+error: aborting due to 26 previous errors
For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 5f895fa..f2067f0 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `u8` is non-empty
- --> $DIR/empty-match.rs:46:20
+ --> $DIR/empty-match.rs:47:20
|
LL | match_no_arms!(0u8);
| ^^^
@@ -8,7 +8,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `i8` is non-empty
- --> $DIR/empty-match.rs:47:20
+ --> $DIR/empty-match.rs:48:20
|
LL | match_no_arms!(0i8);
| ^^^
@@ -17,7 +17,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `usize` is non-empty
- --> $DIR/empty-match.rs:48:20
+ --> $DIR/empty-match.rs:49:20
|
LL | match_no_arms!(0usize);
| ^^^^^^
@@ -26,7 +26,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `isize` is non-empty
- --> $DIR/empty-match.rs:49:20
+ --> $DIR/empty-match.rs:50:20
|
LL | match_no_arms!(0isize);
| ^^^^^^
@@ -35,7 +35,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
- --> $DIR/empty-match.rs:50:20
+ --> $DIR/empty-match.rs:51:20
|
LL | match_no_arms!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^
@@ -49,7 +49,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
- --> $DIR/empty-match.rs:51:20
+ --> $DIR/empty-match.rs:52:20
|
LL | match_no_arms!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
- --> $DIR/empty-match.rs:52:20
+ --> $DIR/empty-match.rs:53:20
|
LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
- --> $DIR/empty-match.rs:53:20
+ --> $DIR/empty-match.rs:54:20
|
LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -91,7 +91,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:54:20
+ --> $DIR/empty-match.rs:55:20
|
LL | match_no_arms!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
@@ -107,7 +107,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:55:20
+ --> $DIR/empty-match.rs:56:20
|
LL | match_no_arms!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
@@ -125,7 +125,7 @@
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:56:20
+ --> $DIR/empty-match.rs:57:20
|
LL | match_no_arms!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -148,8 +148,26 @@
= note: the matched value is of type `NonEmptyEnum5`
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
+error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
+ --> $DIR/empty-match.rs:58:20
+ |
+LL | match_no_arms!(array0_of_empty);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: the matched value is of type `[!; 0]`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
+error[E0004]: non-exhaustive patterns: type `[!; N]` is non-empty
+ --> $DIR/empty-match.rs:59:20
+ |
+LL | match_no_arms!(arrayN_of_empty);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: the matched value is of type `[!; N]`
+ = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
+
error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered
- --> $DIR/empty-match.rs:58:24
+ --> $DIR/empty-match.rs:61:24
|
LL | match_guarded_arm!(0u8);
| ^^^ pattern `0_u8..=u8::MAX` not covered
@@ -163,7 +181,7 @@
|
error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered
- --> $DIR/empty-match.rs:59:24
+ --> $DIR/empty-match.rs:62:24
|
LL | match_guarded_arm!(0i8);
| ^^^ pattern `i8::MIN..=i8::MAX` not covered
@@ -177,7 +195,7 @@
|
error[E0004]: non-exhaustive patterns: `0_usize..` not covered
- --> $DIR/empty-match.rs:60:24
+ --> $DIR/empty-match.rs:63:24
|
LL | match_guarded_arm!(0usize);
| ^^^^^^ pattern `0_usize..` not covered
@@ -191,7 +209,7 @@
|
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/empty-match.rs:61:24
+ --> $DIR/empty-match.rs:64:24
|
LL | match_guarded_arm!(0isize);
| ^^^^^^ pattern `_` not covered
@@ -205,7 +223,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
- --> $DIR/empty-match.rs:62:24
+ --> $DIR/empty-match.rs:65:24
|
LL | match_guarded_arm!(NonEmptyStruct1);
| ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
@@ -224,7 +242,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
- --> $DIR/empty-match.rs:63:24
+ --> $DIR/empty-match.rs:66:24
|
LL | match_guarded_arm!(NonEmptyStruct2(true));
| ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
@@ -243,7 +261,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
- --> $DIR/empty-match.rs:64:24
+ --> $DIR/empty-match.rs:67:24
|
LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
@@ -262,7 +280,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
- --> $DIR/empty-match.rs:65:24
+ --> $DIR/empty-match.rs:68:24
|
LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
@@ -273,6 +291,7 @@
LL | union NonEmptyUnion2 {
| ^^^^^^^^^^^^^^
= note: the matched value is of type `NonEmptyUnion2`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
= note: match arms with guards don't count towards exhaustivity
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
@@ -281,7 +300,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
- --> $DIR/empty-match.rs:66:24
+ --> $DIR/empty-match.rs:69:24
|
LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
@@ -302,7 +321,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
- --> $DIR/empty-match.rs:67:24
+ --> $DIR/empty-match.rs:70:24
|
LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
@@ -325,7 +344,7 @@
|
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
- --> $DIR/empty-match.rs:68:24
+ --> $DIR/empty-match.rs:71:24
|
LL | match_guarded_arm!(NonEmptyEnum5::V1);
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
@@ -353,6 +372,34 @@
LL + _ => todo!()
|
-error: aborting due to 22 previous errors
+error[E0004]: non-exhaustive patterns: `[]` not covered
+ --> $DIR/empty-match.rs:72:24
+ |
+LL | match_guarded_arm!(array0_of_empty);
+ | ^^^^^^^^^^^^^^^ pattern `[]` not covered
+ |
+ = note: the matched value is of type `[!; 0]`
+ = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ _ if false => {},
+LL + [] => todo!()
+ |
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+ --> $DIR/empty-match.rs:73:24
+ |
+LL | match_guarded_arm!(arrayN_of_empty);
+ | ^^^^^^^^^^^^^^^ pattern `[]` not covered
+ |
+ = note: the matched value is of type `[!; N]`
+ = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ _ if false => {},
+LL + [] => todo!()
+ |
+
+error: aborting due to 26 previous errors
For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
index 9b22b47..b34427a 100644
--- a/tests/ui/pattern/usefulness/empty-match.rs
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -5,7 +5,7 @@
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
#![deny(unreachable_patterns)]
-fn nonempty() {
+fn nonempty<const N: usize>(arrayN_of_empty: [!; N]) {
macro_rules! match_no_arms {
($e:expr) => {
match $e {}
@@ -42,6 +42,7 @@ enum NonEmptyEnum5 {
V4,
V5,
}
+ let array0_of_empty: [!; 0] = [];
match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
match_no_arms!(0i8); //~ ERROR type `i8` is non-empty
@@ -54,6 +55,8 @@ enum NonEmptyEnum5 {
match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ match_no_arms!(array0_of_empty); //~ ERROR type `[!; 0]` is non-empty
+ match_no_arms!(arrayN_of_empty); //~ ERROR type `[!; N]` is non-empty
match_guarded_arm!(0u8); //~ ERROR `0_u8..=u8::MAX` not covered
match_guarded_arm!(0i8); //~ ERROR `i8::MIN..=i8::MAX` not covered
@@ -66,6 +69,8 @@ enum NonEmptyEnum5 {
match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
+ match_guarded_arm!(array0_of_empty); //~ ERROR `[]` not covered
+ match_guarded_arm!(arrayN_of_empty); //~ ERROR `[]` not covered
}
fn main() {}
diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
index 416a50b..17cb6fb 100644
--- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
@@ -1,18 +1,18 @@
error: unreachable pattern
- --> $DIR/empty-types.rs:51:9
+ --> $DIR/empty-types.rs:49:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
note: the lint level is defined here
- --> $DIR/empty-types.rs:17:9
+ --> $DIR/empty-types.rs:15:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/empty-types.rs:54:9
+ --> $DIR/empty-types.rs:52:9
|
LL | _x => {}
| ^^
@@ -20,7 +20,7 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
- --> $DIR/empty-types.rs:58:11
+ --> $DIR/empty-types.rs:56:11
|
LL | match ref_never {}
| ^^^^^^^^^
@@ -35,7 +35,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:73:9
+ --> $DIR/empty-types.rs:70:9
|
LL | (_, _) => {}
| ^^^^^^
@@ -43,7 +43,7 @@
= note: this pattern matches no values because `(u32, !)` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:80:9
+ --> $DIR/empty-types.rs:76:9
|
LL | _ => {}
| ^
@@ -51,7 +51,7 @@
= note: this pattern matches no values because `(!, !)` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:83:9
+ --> $DIR/empty-types.rs:79:9
|
LL | (_, _) => {}
| ^^^^^^
@@ -59,7 +59,7 @@
= note: this pattern matches no values because `(!, !)` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:87:9
+ --> $DIR/empty-types.rs:83:9
|
LL | _ => {}
| ^
@@ -67,7 +67,7 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
- --> $DIR/empty-types.rs:91:11
+ --> $DIR/empty-types.rs:87:11
|
LL | match res_u32_never {}
| ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -86,7 +86,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:99:9
+ --> $DIR/empty-types.rs:94:9
|
LL | Err(_) => {}
| ^^^^^^
@@ -94,7 +94,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:104:9
+ --> $DIR/empty-types.rs:99:9
|
LL | Err(_) => {}
| ^^^^^^
@@ -102,7 +102,7 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
- --> $DIR/empty-types.rs:101:11
+ --> $DIR/empty-types.rs:96:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -120,7 +120,7 @@
|
error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:108:9
+ --> $DIR/empty-types.rs:102:9
|
LL | let Ok(_x) = res_u32_never.as_ref();
| ^^^^^^ pattern `Err(_)` not covered
@@ -134,6 +134,30 @@
| ++++++++++++++++
error: unreachable pattern
+ --> $DIR/empty-types.rs:112:9
+ |
+LL | _ => {}
+ | ^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:115:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:118:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
--> $DIR/empty-types.rs:119:9
|
LL | _ => {}
@@ -142,47 +166,23 @@
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
+ --> $DIR/empty-types.rs:122:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
--> $DIR/empty-types.rs:123:9
|
-LL | Ok(_) => {}
- | ^^^^^
- |
- = note: this pattern matches no values because `Result<!, !>` is uninhabited
-
-error: unreachable pattern
- --> $DIR/empty-types.rs:126:9
- |
-LL | Ok(_) => {}
- | ^^^^^
- |
- = note: this pattern matches no values because `Result<!, !>` is uninhabited
-
-error: unreachable pattern
- --> $DIR/empty-types.rs:127:9
- |
-LL | _ => {}
- | ^
- |
- = note: this pattern matches no values because `Result<!, !>` is uninhabited
-
-error: unreachable pattern
- --> $DIR/empty-types.rs:130:9
- |
-LL | Ok(_) => {}
- | ^^^^^
- |
- = note: this pattern matches no values because `Result<!, !>` is uninhabited
-
-error: unreachable pattern
- --> $DIR/empty-types.rs:131:9
- |
LL | Err(_) => {}
| ^^^^^^
|
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:140:13
+ --> $DIR/empty-types.rs:132:13
|
LL | _ => {}
| ^
@@ -190,7 +190,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:143:13
+ --> $DIR/empty-types.rs:135:13
|
LL | _ if false => {}
| ^
@@ -198,7 +198,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:152:13
+ --> $DIR/empty-types.rs:143:13
|
LL | Some(_) => {}
| ^^^^^^^
@@ -206,7 +206,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:156:13
+ --> $DIR/empty-types.rs:147:13
|
LL | None => {}
| ---- matches all the values already
@@ -214,7 +214,7 @@
| ^ unreachable pattern
error: unreachable pattern
- --> $DIR/empty-types.rs:208:13
+ --> $DIR/empty-types.rs:199:13
|
LL | _ => {}
| ^
@@ -222,7 +222,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:213:13
+ --> $DIR/empty-types.rs:204:13
|
LL | _ => {}
| ^
@@ -230,7 +230,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:218:13
+ --> $DIR/empty-types.rs:209:13
|
LL | _ => {}
| ^
@@ -238,7 +238,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:223:13
+ --> $DIR/empty-types.rs:214:13
|
LL | _ => {}
| ^
@@ -246,7 +246,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:229:13
+ --> $DIR/empty-types.rs:220:13
|
LL | _ => {}
| ^
@@ -254,7 +254,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:288:9
+ --> $DIR/empty-types.rs:279:9
|
LL | _ => {}
| ^
@@ -262,7 +262,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:291:9
+ --> $DIR/empty-types.rs:282:9
|
LL | (_, _) => {}
| ^^^^^^
@@ -270,7 +270,7 @@
= note: this pattern matches no values because `(!, !)` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:294:9
+ --> $DIR/empty-types.rs:285:9
|
LL | Ok(_) => {}
| ^^^^^
@@ -278,7 +278,7 @@
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:295:9
+ --> $DIR/empty-types.rs:286:9
|
LL | Err(_) => {}
| ^^^^^^
@@ -286,7 +286,7 @@
= note: this pattern matches no values because `Result<!, !>` is uninhabited
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
- --> $DIR/empty-types.rs:327:11
+ --> $DIR/empty-types.rs:318:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@@ -300,7 +300,7 @@
|
error[E0004]: non-exhaustive patterns: `&[]` not covered
- --> $DIR/empty-types.rs:338:11
+ --> $DIR/empty-types.rs:329:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[]` not covered
@@ -313,7 +313,7 @@
|
error[E0004]: non-exhaustive patterns: `&[]` not covered
- --> $DIR/empty-types.rs:352:11
+ --> $DIR/empty-types.rs:343:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[]` not covered
@@ -327,7 +327,7 @@
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
- --> $DIR/empty-types.rs:359:11
+ --> $DIR/empty-types.rs:350:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@@ -341,7 +341,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:369:9
+ --> $DIR/empty-types.rs:359:9
|
LL | _ => {}
| ^
@@ -349,7 +349,7 @@
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:372:9
+ --> $DIR/empty-types.rs:362:9
|
LL | [_, _, _] => {}
| ^^^^^^^^^
@@ -357,7 +357,7 @@
= note: this pattern matches no values because `[!; 3]` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:375:9
+ --> $DIR/empty-types.rs:365:9
|
LL | [_, ..] => {}
| ^^^^^^^
@@ -365,7 +365,7 @@
= note: this pattern matches no values because `[!; 3]` is uninhabited
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
- --> $DIR/empty-types.rs:389:11
+ --> $DIR/empty-types.rs:379:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@@ -379,7 +379,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:396:9
+ --> $DIR/empty-types.rs:386:9
|
LL | [] => {}
| -- matches all the values already
@@ -387,7 +387,7 @@
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `[]` not covered
- --> $DIR/empty-types.rs:398:11
+ --> $DIR/empty-types.rs:388:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -401,7 +401,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:417:9
+ --> $DIR/empty-types.rs:407:9
|
LL | Some(_) => {}
| ^^^^^^^
@@ -409,7 +409,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:422:9
+ --> $DIR/empty-types.rs:412:9
|
LL | Some(_a) => {}
| ^^^^^^^^
@@ -417,7 +417,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:427:9
+ --> $DIR/empty-types.rs:417:9
|
LL | None => {}
| ---- matches all the values already
@@ -426,7 +426,7 @@
| ^ unreachable pattern
error: unreachable pattern
- --> $DIR/empty-types.rs:432:9
+ --> $DIR/empty-types.rs:422:9
|
LL | None => {}
| ---- matches all the values already
@@ -435,7 +435,7 @@
| ^^ unreachable pattern
error: unreachable pattern
- --> $DIR/empty-types.rs:604:9
+ --> $DIR/empty-types.rs:594:9
|
LL | _ => {}
| ^
@@ -443,7 +443,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:607:9
+ --> $DIR/empty-types.rs:597:9
|
LL | _x => {}
| ^^
@@ -451,7 +451,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:610:9
+ --> $DIR/empty-types.rs:600:9
|
LL | _ if false => {}
| ^
@@ -459,7 +459,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:613:9
+ --> $DIR/empty-types.rs:603:9
|
LL | _x if false => {}
| ^^
diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
index 4856a2f..1ecb15f 100644
--- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr
@@ -1,5 +1,5 @@
warning: the feature `never_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/empty-types.rs:14:33
+ --> $DIR/empty-types.rs:12:33
|
LL | #![cfg_attr(never_pats, feature(never_patterns))]
| ^^^^^^^^^^^^^^
@@ -8,20 +8,20 @@
= note: `#[warn(incomplete_features)]` on by default
error: unreachable pattern
- --> $DIR/empty-types.rs:51:9
+ --> $DIR/empty-types.rs:49:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
note: the lint level is defined here
- --> $DIR/empty-types.rs:17:9
+ --> $DIR/empty-types.rs:15:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/empty-types.rs:54:9
+ --> $DIR/empty-types.rs:52:9
|
LL | _x => {}
| ^^
@@ -29,7 +29,7 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
- --> $DIR/empty-types.rs:58:11
+ --> $DIR/empty-types.rs:56:11
|
LL | match ref_never {}
| ^^^^^^^^^
@@ -43,69 +43,43 @@
LL + }
|
-error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
- --> $DIR/empty-types.rs:70:11
+error: unreachable pattern
+ --> $DIR/empty-types.rs:70:9
|
-LL | match tuple_half_never {}
- | ^^^^^^^^^^^^^^^^
+LL | (_, _) => {}
+ | ^^^^^^
|
- = note: the matched value is of type `(u32, !)`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match tuple_half_never {
-LL + _ => todo!(),
-LL + }
- |
-
-error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
- --> $DIR/empty-types.rs:77:11
- |
-LL | match tuple_never {}
- | ^^^^^^^^^^^
- |
- = note: the matched value is of type `(!, !)`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match tuple_never {
-LL + _ => todo!(),
-LL + }
- |
+ = note: this pattern matches no values because `(u32, !)` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:87:9
+ --> $DIR/empty-types.rs:76:9
+ |
+LL | _ => {}
+ | ^
+ |
+ = note: this pattern matches no values because `(!, !)` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:79:9
+ |
+LL | (_, _) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `(!, !)` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:83:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
-error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(!)` not covered
- --> $DIR/empty-types.rs:91:11
+error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
+ --> $DIR/empty-types.rs:87:11
|
LL | match res_u32_never {}
- | ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(!)` not covered
- |
-note: `Result<u32, !>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<u32, !>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match res_u32_never {
-LL + Ok(_) | Err(!) => todo!(),
-LL + }
- |
-
-error[E0004]: non-exhaustive patterns: `Err(!)` not covered
- --> $DIR/empty-types.rs:93:11
- |
-LL | match res_u32_never {
- | ^^^^^^^^^^^^^ pattern `Err(!)` not covered
+ | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
|
note: `Result<u32, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
@@ -115,12 +89,29 @@
= note: the matched value is of type `Result<u32, !>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
-LL ~ Ok(_) => {},
-LL + Err(!)
+LL ~ match res_u32_never {
+LL + Ok(_) => todo!(),
+LL + }
|
+error: unreachable pattern
+ --> $DIR/empty-types.rs:94:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:99:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
- --> $DIR/empty-types.rs:101:11
+ --> $DIR/empty-types.rs:96:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -138,21 +129,7 @@
|
error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:106:9
- |
-LL | let Ok(_x) = res_u32_never;
- | ^^^^^^ pattern `Err(!)` not covered
- |
- = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
- = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
- = note: the matched value is of type `Result<u32, !>`
-help: you might want to use `let else` to handle the variant that isn't matched
- |
-LL | let Ok(_x) = res_u32_never else { todo!() };
- | ++++++++++++++++
-
-error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:108:9
+ --> $DIR/empty-types.rs:102:9
|
LL | let Ok(_x) = res_u32_never.as_ref();
| ^^^^^^ pattern `Err(_)` not covered
@@ -166,7 +143,7 @@
| ++++++++++++++++
error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:112:9
+ --> $DIR/empty-types.rs:106:9
|
LL | let Ok(_x) = &res_u32_never;
| ^^^^^^ pattern `&Err(!)` not covered
@@ -179,47 +156,56 @@
LL | let Ok(_x) = &res_u32_never else { todo!() };
| ++++++++++++++++
-error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered
- --> $DIR/empty-types.rs:116:11
+error: unreachable pattern
+ --> $DIR/empty-types.rs:112:9
|
-LL | match result_never {}
- | ^^^^^^^^^^^^ patterns `Ok(!)` and `Err(!)` not covered
+LL | _ => {}
+ | ^
|
-note: `Result<!, !>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<!, !>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match result_never {
-LL + Ok(!) | Err(!),
-LL + }
- |
-
-error[E0004]: non-exhaustive patterns: `Err(!)` not covered
- --> $DIR/empty-types.rs:121:11
- |
-LL | match result_never {
- | ^^^^^^^^^^^^ pattern `Err(!)` not covered
- |
-note: `Result<!, !>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<!, !>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
- |
-LL | Ok(_) => {}, Err(!)
- | ++++++++
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:140:13
+ --> $DIR/empty-types.rs:115:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:118:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:119:9
+ |
+LL | _ => {}
+ | ^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:122:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:123:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:132:13
|
LL | _ => {}
| ^
@@ -227,33 +213,31 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:143:13
+ --> $DIR/empty-types.rs:135:13
|
LL | _ if false => {}
| ^
|
= note: this pattern matches no values because `Void` is uninhabited
-error[E0004]: non-exhaustive patterns: `Some(!)` not covered
- --> $DIR/empty-types.rs:146:15
+error: unreachable pattern
+ --> $DIR/empty-types.rs:143:13
|
-LL | match opt_void {
- | ^^^^^^^^ pattern `Some(!)` not covered
+LL | Some(_) => {}
+ | ^^^^^^^
|
-note: `Option<Void>` defined here
- --> $SRC_DIR/core/src/option.rs:LL:COL
- ::: $SRC_DIR/core/src/option.rs:LL:COL
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:147:13
|
- = note: not covered
- = note: the matched value is of type `Option<Void>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
- |
-LL ~ None => {},
-LL + Some(!)
- |
+LL | None => {}
+ | ---- matches all the values already
+LL | _ => {}
+ | ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `Some(!)` not covered
- --> $DIR/empty-types.rs:165:15
+ --> $DIR/empty-types.rs:156:15
|
LL | match *ref_opt_void {
| ^^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -264,6 +248,7 @@
|
= note: not covered
= note: the matched value is of type `Option<Void>`
+ = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
@@ -271,7 +256,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:208:13
+ --> $DIR/empty-types.rs:199:13
|
LL | _ => {}
| ^
@@ -279,7 +264,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:213:13
+ --> $DIR/empty-types.rs:204:13
|
LL | _ => {}
| ^
@@ -287,7 +272,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:218:13
+ --> $DIR/empty-types.rs:209:13
|
LL | _ => {}
| ^
@@ -295,7 +280,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:223:13
+ --> $DIR/empty-types.rs:214:13
|
LL | _ => {}
| ^
@@ -303,7 +288,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:229:13
+ --> $DIR/empty-types.rs:220:13
|
LL | _ => {}
| ^
@@ -311,15 +296,39 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:288:9
+ --> $DIR/empty-types.rs:279:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
+error: unreachable pattern
+ --> $DIR/empty-types.rs:282:9
+ |
+LL | (_, _) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `(!, !)` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:285:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:286:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
- --> $DIR/empty-types.rs:316:11
+ --> $DIR/empty-types.rs:307:11
|
LL | match *x {}
| ^^
@@ -333,7 +342,7 @@
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
- --> $DIR/empty-types.rs:318:11
+ --> $DIR/empty-types.rs:309:11
|
LL | match *x {}
| ^^
@@ -347,7 +356,7 @@
|
error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered
- --> $DIR/empty-types.rs:320:11
+ --> $DIR/empty-types.rs:311:11
|
LL | match *x {}
| ^^ patterns `Ok(!)` and `Err(!)` not covered
@@ -369,7 +378,7 @@
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
- --> $DIR/empty-types.rs:322:11
+ --> $DIR/empty-types.rs:313:11
|
LL | match *x {}
| ^^
@@ -383,7 +392,7 @@
|
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
- --> $DIR/empty-types.rs:327:11
+ --> $DIR/empty-types.rs:318:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@@ -397,12 +406,13 @@
|
error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered
- --> $DIR/empty-types.rs:329:11
+ --> $DIR/empty-types.rs:320:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[!, ..]` not covered
|
= note: the matched value is of type `&[!]`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ [] => {},
@@ -410,7 +420,7 @@
|
error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered
- --> $DIR/empty-types.rs:338:11
+ --> $DIR/empty-types.rs:329:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered
@@ -423,7 +433,7 @@
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered
- --> $DIR/empty-types.rs:352:11
+ --> $DIR/empty-types.rs:343:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered
@@ -437,7 +447,7 @@
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
- --> $DIR/empty-types.rs:359:11
+ --> $DIR/empty-types.rs:350:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@@ -450,22 +460,32 @@
LL + }
|
-error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
- --> $DIR/empty-types.rs:366:11
+error: unreachable pattern
+ --> $DIR/empty-types.rs:359:9
|
-LL | match array_3_never {}
- | ^^^^^^^^^^^^^
+LL | _ => {}
+ | ^
|
- = note: the matched value is of type `[!; 3]`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ = note: this pattern matches no values because `[!; 3]` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:362:9
|
-LL ~ match array_3_never {
-LL + _ => todo!(),
-LL + }
+LL | [_, _, _] => {}
+ | ^^^^^^^^^
|
+ = note: this pattern matches no values because `[!; 3]` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:365:9
+ |
+LL | [_, ..] => {}
+ | ^^^^^^^
+ |
+ = note: this pattern matches no values because `[!; 3]` is uninhabited
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
- --> $DIR/empty-types.rs:389:11
+ --> $DIR/empty-types.rs:379:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@@ -479,7 +499,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:396:9
+ --> $DIR/empty-types.rs:386:9
|
LL | [] => {}
| -- matches all the values already
@@ -487,7 +507,7 @@
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `[]` not covered
- --> $DIR/empty-types.rs:398:11
+ --> $DIR/empty-types.rs:388:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -500,8 +520,42 @@
LL + [] => todo!()
|
+error: unreachable pattern
+ --> $DIR/empty-types.rs:407:9
+ |
+LL | Some(_) => {}
+ | ^^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:412:9
+ |
+LL | Some(_a) => {}
+ | ^^^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:417:9
+ |
+LL | None => {}
+ | ---- matches all the values already
+LL | // !useful, !reachable
+LL | _ => {}
+ | ^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:422:9
+ |
+LL | None => {}
+ | ---- matches all the values already
+LL | // !useful, !reachable
+LL | _a => {}
+ | ^^ unreachable pattern
+
error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
- --> $DIR/empty-types.rs:452:11
+ --> $DIR/empty-types.rs:442:11
|
LL | match ref_opt_never {
| ^^^^^^^^^^^^^ pattern `&Some(!)` not covered
@@ -512,6 +566,7 @@
|
= note: not covered
= note: the matched value is of type `&Option<!>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ &None => {},
@@ -519,7 +574,7 @@
|
error[E0004]: non-exhaustive patterns: `Some(!)` not covered
- --> $DIR/empty-types.rs:493:11
+ --> $DIR/empty-types.rs:483:11
|
LL | match *ref_opt_never {
| ^^^^^^^^^^^^^^ pattern `Some(!)` not covered
@@ -530,6 +585,7 @@
|
= note: not covered
= note: the matched value is of type `Option<!>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
@@ -537,7 +593,7 @@
|
error[E0004]: non-exhaustive patterns: `Err(!)` not covered
- --> $DIR/empty-types.rs:541:11
+ --> $DIR/empty-types.rs:531:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@@ -548,6 +604,7 @@
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Ok(_) => {},
@@ -555,7 +612,7 @@
|
error[E0004]: non-exhaustive patterns: `Err(!)` not covered
- --> $DIR/empty-types.rs:552:11
+ --> $DIR/empty-types.rs:542:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(!)` not covered
@@ -566,6 +623,7 @@
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Ok(_a) => {},
@@ -573,7 +631,7 @@
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
- --> $DIR/empty-types.rs:571:11
+ --> $DIR/empty-types.rs:561:11
|
LL | match *ref_tuple_half_never {}
| ^^^^^^^^^^^^^^^^^^^^^
@@ -587,7 +645,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:604:9
+ --> $DIR/empty-types.rs:594:9
|
LL | _ => {}
| ^
@@ -595,7 +653,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:607:9
+ --> $DIR/empty-types.rs:597:9
|
LL | _x => {}
| ^^
@@ -603,7 +661,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:610:9
+ --> $DIR/empty-types.rs:600:9
|
LL | _ if false => {}
| ^
@@ -611,7 +669,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:613:9
+ --> $DIR/empty-types.rs:603:9
|
LL | _x if false => {}
| ^^
@@ -619,12 +677,13 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: `&!` not covered
- --> $DIR/empty-types.rs:638:11
+ --> $DIR/empty-types.rs:628:11
|
LL | match ref_never {
| ^^^^^^^^^ pattern `&!` not covered
|
= note: the matched value is of type `&!`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
= note: references are always considered inhabited
= note: match arms with guards don't count towards exhaustivity
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
@@ -634,7 +693,7 @@
|
error[E0004]: non-exhaustive patterns: `Ok(!)` not covered
- --> $DIR/empty-types.rs:654:11
+ --> $DIR/empty-types.rs:644:11
|
LL | match *ref_result_never {
| ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered
@@ -645,6 +704,7 @@
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Err(_) => {},
@@ -652,7 +712,7 @@
|
error[E0004]: non-exhaustive patterns: `Some(!)` not covered
- --> $DIR/empty-types.rs:674:11
+ --> $DIR/empty-types.rs:664:11
|
LL | match *x {
| ^^ pattern `Some(!)` not covered
@@ -663,13 +723,14 @@
|
= note: not covered
= note: the matched value is of type `Option<Result<!, !>>`
+ = note: `Result<!, !>` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
LL + Some(!)
|
-error: aborting due to 49 previous errors; 1 warning emitted
+error: aborting due to 64 previous errors; 1 warning emitted
Some errors have detailed explanations: E0004, E0005.
For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr
index 78db9ee3..c3421cd 100644
--- a/tests/ui/pattern/usefulness/empty-types.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr
@@ -1,18 +1,18 @@
error: unreachable pattern
- --> $DIR/empty-types.rs:51:9
+ --> $DIR/empty-types.rs:49:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
note: the lint level is defined here
- --> $DIR/empty-types.rs:17:9
+ --> $DIR/empty-types.rs:15:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/empty-types.rs:54:9
+ --> $DIR/empty-types.rs:52:9
|
LL | _x => {}
| ^^
@@ -20,7 +20,7 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: type `&!` is non-empty
- --> $DIR/empty-types.rs:58:11
+ --> $DIR/empty-types.rs:56:11
|
LL | match ref_never {}
| ^^^^^^^^^
@@ -34,69 +34,43 @@
LL + }
|
-error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
- --> $DIR/empty-types.rs:70:11
+error: unreachable pattern
+ --> $DIR/empty-types.rs:70:9
|
-LL | match tuple_half_never {}
- | ^^^^^^^^^^^^^^^^
+LL | (_, _) => {}
+ | ^^^^^^
|
- = note: the matched value is of type `(u32, !)`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match tuple_half_never {
-LL + _ => todo!(),
-LL + }
- |
-
-error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
- --> $DIR/empty-types.rs:77:11
- |
-LL | match tuple_never {}
- | ^^^^^^^^^^^
- |
- = note: the matched value is of type `(!, !)`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match tuple_never {
-LL + _ => todo!(),
-LL + }
- |
+ = note: this pattern matches no values because `(u32, !)` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:87:9
+ --> $DIR/empty-types.rs:76:9
+ |
+LL | _ => {}
+ | ^
+ |
+ = note: this pattern matches no values because `(!, !)` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:79:9
+ |
+LL | (_, _) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `(!, !)` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:83:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
-error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
- --> $DIR/empty-types.rs:91:11
+error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
+ --> $DIR/empty-types.rs:87:11
|
LL | match res_u32_never {}
- | ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
- |
-note: `Result<u32, !>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<u32, !>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match res_u32_never {
-LL + Ok(_) | Err(_) => todo!(),
-LL + }
- |
-
-error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/empty-types.rs:93:11
- |
-LL | match res_u32_never {
- | ^^^^^^^^^^^^^ pattern `Err(_)` not covered
+ | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
|
note: `Result<u32, !>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
@@ -106,12 +80,29 @@
= note: the matched value is of type `Result<u32, !>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
-LL ~ Ok(_) => {},
-LL + Err(_) => todo!()
+LL ~ match res_u32_never {
+LL + Ok(_) => todo!(),
+LL + }
|
+error: unreachable pattern
+ --> $DIR/empty-types.rs:94:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:99:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
- --> $DIR/empty-types.rs:101:11
+ --> $DIR/empty-types.rs:96:11
|
LL | match res_u32_never {
| ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -129,21 +120,7 @@
|
error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:106:9
- |
-LL | let Ok(_x) = res_u32_never;
- | ^^^^^^ pattern `Err(_)` not covered
- |
- = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
- = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
- = note: the matched value is of type `Result<u32, !>`
-help: you might want to use `let else` to handle the variant that isn't matched
- |
-LL | let Ok(_x) = res_u32_never else { todo!() };
- | ++++++++++++++++
-
-error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:108:9
+ --> $DIR/empty-types.rs:102:9
|
LL | let Ok(_x) = res_u32_never.as_ref();
| ^^^^^^ pattern `Err(_)` not covered
@@ -157,7 +134,7 @@
| ++++++++++++++++
error[E0005]: refutable pattern in local binding
- --> $DIR/empty-types.rs:112:9
+ --> $DIR/empty-types.rs:106:9
|
LL | let Ok(_x) = &res_u32_never;
| ^^^^^^ pattern `&Err(_)` not covered
@@ -170,47 +147,56 @@
LL | let Ok(_x) = &res_u32_never else { todo!() };
| ++++++++++++++++
-error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
- --> $DIR/empty-types.rs:116:11
+error: unreachable pattern
+ --> $DIR/empty-types.rs:112:9
|
-LL | match result_never {}
- | ^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
+LL | _ => {}
+ | ^
|
-note: `Result<!, !>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<!, !>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match result_never {
-LL + Ok(_) | Err(_) => todo!(),
-LL + }
- |
-
-error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/empty-types.rs:121:11
- |
-LL | match result_never {
- | ^^^^^^^^^^^^ pattern `Err(_)` not covered
- |
-note: `Result<!, !>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<!, !>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
- |
-LL | Ok(_) => {}, Err(_) => todo!()
- | +++++++++++++++++++
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:140:13
+ --> $DIR/empty-types.rs:115:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:118:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:119:9
+ |
+LL | _ => {}
+ | ^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:122:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:123:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:132:13
|
LL | _ => {}
| ^
@@ -218,33 +204,31 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:143:13
+ --> $DIR/empty-types.rs:135:13
|
LL | _ if false => {}
| ^
|
= note: this pattern matches no values because `Void` is uninhabited
-error[E0004]: non-exhaustive patterns: `Some(_)` not covered
- --> $DIR/empty-types.rs:146:15
+error: unreachable pattern
+ --> $DIR/empty-types.rs:143:13
|
-LL | match opt_void {
- | ^^^^^^^^ pattern `Some(_)` not covered
+LL | Some(_) => {}
+ | ^^^^^^^
|
-note: `Option<Void>` defined here
- --> $SRC_DIR/core/src/option.rs:LL:COL
- ::: $SRC_DIR/core/src/option.rs:LL:COL
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:147:13
|
- = note: not covered
- = note: the matched value is of type `Option<Void>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
- |
-LL ~ None => {},
-LL + Some(_) => todo!()
- |
+LL | None => {}
+ | ---- matches all the values already
+LL | _ => {}
+ | ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
- --> $DIR/empty-types.rs:165:15
+ --> $DIR/empty-types.rs:156:15
|
LL | match *ref_opt_void {
| ^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -255,6 +239,7 @@
|
= note: not covered
= note: the matched value is of type `Option<Void>`
+ = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
@@ -262,7 +247,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:208:13
+ --> $DIR/empty-types.rs:199:13
|
LL | _ => {}
| ^
@@ -270,7 +255,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:213:13
+ --> $DIR/empty-types.rs:204:13
|
LL | _ => {}
| ^
@@ -278,7 +263,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:218:13
+ --> $DIR/empty-types.rs:209:13
|
LL | _ => {}
| ^
@@ -286,7 +271,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:223:13
+ --> $DIR/empty-types.rs:214:13
|
LL | _ => {}
| ^
@@ -294,7 +279,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:229:13
+ --> $DIR/empty-types.rs:220:13
|
LL | _ => {}
| ^
@@ -302,15 +287,39 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:288:9
+ --> $DIR/empty-types.rs:279:9
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `!` is uninhabited
+error: unreachable pattern
+ --> $DIR/empty-types.rs:282:9
+ |
+LL | (_, _) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `(!, !)` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:285:9
+ |
+LL | Ok(_) => {}
+ | ^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:286:9
+ |
+LL | Err(_) => {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Result<!, !>` is uninhabited
+
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
- --> $DIR/empty-types.rs:316:11
+ --> $DIR/empty-types.rs:307:11
|
LL | match *x {}
| ^^
@@ -324,7 +333,7 @@
|
error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
- --> $DIR/empty-types.rs:318:11
+ --> $DIR/empty-types.rs:309:11
|
LL | match *x {}
| ^^
@@ -338,7 +347,7 @@
|
error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
- --> $DIR/empty-types.rs:320:11
+ --> $DIR/empty-types.rs:311:11
|
LL | match *x {}
| ^^ patterns `Ok(_)` and `Err(_)` not covered
@@ -360,7 +369,7 @@
|
error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
- --> $DIR/empty-types.rs:322:11
+ --> $DIR/empty-types.rs:313:11
|
LL | match *x {}
| ^^
@@ -374,7 +383,7 @@
|
error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
- --> $DIR/empty-types.rs:327:11
+ --> $DIR/empty-types.rs:318:11
|
LL | match slice_never {}
| ^^^^^^^^^^^
@@ -388,12 +397,13 @@
|
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
- --> $DIR/empty-types.rs:329:11
+ --> $DIR/empty-types.rs:320:11
|
LL | match slice_never {
| ^^^^^^^^^^^ pattern `&[_, ..]` not covered
|
= note: the matched value is of type `&[!]`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ [] => {},
@@ -401,7 +411,7 @@
|
error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
- --> $DIR/empty-types.rs:338:11
+ --> $DIR/empty-types.rs:329:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
@@ -414,7 +424,7 @@
|
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
- --> $DIR/empty-types.rs:352:11
+ --> $DIR/empty-types.rs:343:11
|
LL | match slice_never {
| ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
@@ -428,7 +438,7 @@
|
error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
- --> $DIR/empty-types.rs:359:11
+ --> $DIR/empty-types.rs:350:11
|
LL | match *slice_never {}
| ^^^^^^^^^^^^
@@ -441,22 +451,32 @@
LL + }
|
-error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
- --> $DIR/empty-types.rs:366:11
+error: unreachable pattern
+ --> $DIR/empty-types.rs:359:9
|
-LL | match array_3_never {}
- | ^^^^^^^^^^^^^
+LL | _ => {}
+ | ^
|
- = note: the matched value is of type `[!; 3]`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+ = note: this pattern matches no values because `[!; 3]` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:362:9
|
-LL ~ match array_3_never {
-LL + _ => todo!(),
-LL + }
+LL | [_, _, _] => {}
+ | ^^^^^^^^^
|
+ = note: this pattern matches no values because `[!; 3]` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:365:9
+ |
+LL | [_, ..] => {}
+ | ^^^^^^^
+ |
+ = note: this pattern matches no values because `[!; 3]` is uninhabited
error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
- --> $DIR/empty-types.rs:389:11
+ --> $DIR/empty-types.rs:379:11
|
LL | match array_0_never {}
| ^^^^^^^^^^^^^
@@ -470,7 +490,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:396:9
+ --> $DIR/empty-types.rs:386:9
|
LL | [] => {}
| -- matches all the values already
@@ -478,7 +498,7 @@
| ^ unreachable pattern
error[E0004]: non-exhaustive patterns: `[]` not covered
- --> $DIR/empty-types.rs:398:11
+ --> $DIR/empty-types.rs:388:11
|
LL | match array_0_never {
| ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -491,8 +511,42 @@
LL + [] => todo!()
|
+error: unreachable pattern
+ --> $DIR/empty-types.rs:407:9
+ |
+LL | Some(_) => {}
+ | ^^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:412:9
+ |
+LL | Some(_a) => {}
+ | ^^^^^^^^
+ |
+ = note: this pattern matches no values because `!` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:417:9
+ |
+LL | None => {}
+ | ---- matches all the values already
+LL | // !useful, !reachable
+LL | _ => {}
+ | ^ unreachable pattern
+
+error: unreachable pattern
+ --> $DIR/empty-types.rs:422:9
+ |
+LL | None => {}
+ | ---- matches all the values already
+LL | // !useful, !reachable
+LL | _a => {}
+ | ^^ unreachable pattern
+
error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
- --> $DIR/empty-types.rs:452:11
+ --> $DIR/empty-types.rs:442:11
|
LL | match ref_opt_never {
| ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
@@ -503,6 +557,7 @@
|
= note: not covered
= note: the matched value is of type `&Option<!>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ &None => {},
@@ -510,7 +565,7 @@
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
- --> $DIR/empty-types.rs:493:11
+ --> $DIR/empty-types.rs:483:11
|
LL | match *ref_opt_never {
| ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -521,6 +576,7 @@
|
= note: not covered
= note: the matched value is of type `Option<!>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
@@ -528,7 +584,7 @@
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/empty-types.rs:541:11
+ --> $DIR/empty-types.rs:531:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -539,6 +595,7 @@
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Ok(_) => {},
@@ -546,7 +603,7 @@
|
error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/empty-types.rs:552:11
+ --> $DIR/empty-types.rs:542:11
|
LL | match *ref_res_never {
| ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -557,6 +614,7 @@
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Ok(_a) => {},
@@ -564,7 +622,7 @@
|
error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
- --> $DIR/empty-types.rs:571:11
+ --> $DIR/empty-types.rs:561:11
|
LL | match *ref_tuple_half_never {}
| ^^^^^^^^^^^^^^^^^^^^^
@@ -578,7 +636,7 @@
|
error: unreachable pattern
- --> $DIR/empty-types.rs:604:9
+ --> $DIR/empty-types.rs:594:9
|
LL | _ => {}
| ^
@@ -586,7 +644,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:607:9
+ --> $DIR/empty-types.rs:597:9
|
LL | _x => {}
| ^^
@@ -594,7 +652,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:610:9
+ --> $DIR/empty-types.rs:600:9
|
LL | _ if false => {}
| ^
@@ -602,7 +660,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/empty-types.rs:613:9
+ --> $DIR/empty-types.rs:603:9
|
LL | _x if false => {}
| ^^
@@ -610,12 +668,13 @@
= note: this pattern matches no values because `!` is uninhabited
error[E0004]: non-exhaustive patterns: `&_` not covered
- --> $DIR/empty-types.rs:638:11
+ --> $DIR/empty-types.rs:628:11
|
LL | match ref_never {
| ^^^^^^^^^ pattern `&_` not covered
|
= note: the matched value is of type `&!`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
= note: references are always considered inhabited
= note: match arms with guards don't count towards exhaustivity
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
@@ -625,7 +684,7 @@
|
error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
- --> $DIR/empty-types.rs:654:11
+ --> $DIR/empty-types.rs:644:11
|
LL | match *ref_result_never {
| ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -636,6 +695,7 @@
|
= note: not covered
= note: the matched value is of type `Result<!, !>`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ Err(_) => {},
@@ -643,7 +703,7 @@
|
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
- --> $DIR/empty-types.rs:674:11
+ --> $DIR/empty-types.rs:664:11
|
LL | match *x {
| ^^ pattern `Some(_)` not covered
@@ -654,13 +714,14 @@
|
= note: not covered
= note: the matched value is of type `Option<Result<!, !>>`
+ = note: `Result<!, !>` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
LL + Some(_) => todo!()
|
-error: aborting due to 49 previous errors
+error: aborting due to 64 previous errors
Some errors have detailed explanations: E0004, E0005.
For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs
index cc71f67..639c48c 100644
--- a/tests/ui/pattern/usefulness/empty-types.rs
+++ b/tests/ui/pattern/usefulness/empty-types.rs
@@ -1,5 +1,4 @@
-//@ revisions: normal min_exh_pats exhaustive_patterns never_pats
-// gate-test-min_exhaustive_patterns
+//@ revisions: normal exhaustive_patterns never_pats
//
// This tests correct handling of empty types in exhaustiveness checking.
//
@@ -10,7 +9,6 @@
// This feature is useful to avoid `!` falling back to `()` all the time.
#![feature(never_type_fallback)]
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
-#![cfg_attr(min_exh_pats, feature(min_exhaustive_patterns))]
#![cfg_attr(never_pats, feature(never_patterns))]
//[never_pats]~^ WARN the feature `never_patterns` is incomplete
#![allow(dead_code, unreachable_code)]
@@ -68,19 +66,17 @@ fn basic(x: NeverBundle) {
let tuple_half_never: (u32, !) = x.tuple_half_never;
match tuple_half_never {}
- //[normal,never_pats]~^ ERROR non-empty
match tuple_half_never {
- (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ (_, _) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
let tuple_never: (!, !) = x.tuple_never;
match tuple_never {}
- //[normal,never_pats]~^ ERROR non-empty
match tuple_never {
- _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match tuple_never {
- (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ (_, _) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match tuple_never.0 {}
match tuple_never.0 {
@@ -91,44 +87,40 @@ fn basic(x: NeverBundle) {
match res_u32_never {}
//~^ ERROR non-exhaustive
match res_u32_never {
- //[normal,never_pats]~^ ERROR non-exhaustive
Ok(_) => {}
}
match res_u32_never {
Ok(_) => {}
- Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match res_u32_never {
//~^ ERROR non-exhaustive
Ok(0) => {}
- Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
let Ok(_x) = res_u32_never;
- //[normal,never_pats]~^ ERROR refutable
let Ok(_x) = res_u32_never.as_ref();
//~^ ERROR refutable
// Non-obvious difference: here there's an implicit dereference in the patterns, which makes the
// inner place !known_valid. `exhaustive_patterns` ignores this.
let Ok(_x) = &res_u32_never;
- //[normal,min_exh_pats,never_pats]~^ ERROR refutable
+ //[normal,never_pats]~^ ERROR refutable
let result_never: Result<!, !> = x.result_never;
match result_never {}
- //[normal,never_pats]~^ ERROR non-exhaustive
match result_never {
- _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match result_never {
- //[normal,never_pats]~^ ERROR non-exhaustive
- Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match result_never {
- Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
- _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
+ _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match result_never {
- Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
- Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
+ Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
}
@@ -144,16 +136,15 @@ fn void_same_as_never(x: NeverBundle) {
}
let opt_void: Option<Void> = None;
match opt_void {
- //[normal,never_pats]~^ ERROR non-exhaustive
None => {}
}
match opt_void {
None => {}
- Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Some(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match opt_void {
None => {}
- _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
let ref_void: &Void = &x.void;
@@ -163,7 +154,7 @@ fn void_same_as_never(x: NeverBundle) {
}
let ref_opt_void: &Option<Void> = &None;
match *ref_opt_void {
- //[normal,min_exh_pats,never_pats]~^ ERROR non-exhaustive
+ //[normal,never_pats]~^ ERROR non-exhaustive
None => {}
}
match *ref_opt_void {
@@ -288,11 +279,11 @@ fn nested_validity_tracking(bundle: NeverBundle) {
_ => {} //~ ERROR unreachable pattern
}
match tuple_never {
- (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ (_, _) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match result_never {
- Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
- Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Ok(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
+ Err(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
// These should be considered !known_valid and not warn unreachable.
@@ -313,13 +304,13 @@ fn invalid_empty_match(bundle: NeverBundle) {
match *x {}
let x: &(u32, !) = &bundle.tuple_half_never;
- match *x {} //[normal,min_exh_pats,never_pats]~ ERROR non-exhaustive
+ match *x {} //[normal,never_pats]~ ERROR non-exhaustive
let x: &(!, !) = &bundle.tuple_never;
- match *x {} //[normal,min_exh_pats,never_pats]~ ERROR non-exhaustive
+ match *x {} //[normal,never_pats]~ ERROR non-exhaustive
let x: &Result<!, !> = &bundle.result_never;
- match *x {} //[normal,min_exh_pats,never_pats]~ ERROR non-exhaustive
+ match *x {} //[normal,never_pats]~ ERROR non-exhaustive
let x: &[!; 3] = &bundle.array_3_never;
- match *x {} //[normal,min_exh_pats,never_pats]~ ERROR non-exhaustive
+ match *x {} //[normal,never_pats]~ ERROR non-exhaustive
}
fn arrays_and_slices(x: NeverBundle) {
@@ -327,7 +318,7 @@ fn arrays_and_slices(x: NeverBundle) {
match slice_never {}
//~^ ERROR non-empty
match slice_never {
- //[normal,min_exh_pats,never_pats]~^ ERROR not covered
+ //[normal,never_pats]~^ ERROR not covered
[] => {}
}
match slice_never {
@@ -336,7 +327,7 @@ fn arrays_and_slices(x: NeverBundle) {
[_, _, ..] => {}
}
match slice_never {
- //[normal,min_exh_pats]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
+ //[normal]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
//[exhaustive_patterns]~^^ ERROR `&[]` not covered
//[never_pats]~^^^ ERROR `&[]`, `&[!]` and `&[!, !]` not covered
[_, _, _, ..] => {}
@@ -350,7 +341,7 @@ fn arrays_and_slices(x: NeverBundle) {
_x => {}
}
match slice_never {
- //[normal,min_exh_pats]~^ ERROR `&[]` and `&[_, ..]` not covered
+ //[normal]~^ ERROR `&[]` and `&[_, ..]` not covered
//[exhaustive_patterns]~^^ ERROR `&[]` not covered
//[never_pats]~^^^ ERROR `&[]` and `&[!, ..]` not covered
&[..] if false => {}
@@ -364,15 +355,14 @@ fn arrays_and_slices(x: NeverBundle) {
let array_3_never: [!; 3] = x.array_3_never;
match array_3_never {}
- //[normal,never_pats]~^ ERROR non-empty
match array_3_never {
- _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match array_3_never {
- [_, _, _] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ [_, _, _] => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match array_3_never {
- [_, ..] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ [_, ..] => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
let ref_array_3_never: &[!; 3] = &array_3_never;
@@ -414,22 +404,22 @@ fn bindings(x: NeverBundle) {
match opt_never {
None => {}
// !useful, !reachable
- Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Some(_) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match opt_never {
None => {}
// !useful, !reachable
- Some(_a) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ Some(_a) => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match opt_never {
None => {}
// !useful, !reachable
- _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ _ => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
match opt_never {
None => {}
// !useful, !reachable
- _a => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+ _a => {} //[exhaustive_patterns,normal,never_pats]~ ERROR unreachable pattern
}
// The scrutinee is known_valid, but under the `&` isn't anymore.
@@ -450,7 +440,7 @@ fn bindings(x: NeverBundle) {
&_a => {}
}
match ref_opt_never {
- //[normal,min_exh_pats,never_pats]~^ ERROR non-exhaustive
+ //[normal,never_pats]~^ ERROR non-exhaustive
&None => {}
}
match ref_opt_never {
@@ -491,7 +481,7 @@ fn bindings(x: NeverBundle) {
ref _a => {}
}
match *ref_opt_never {
- //[normal,min_exh_pats,never_pats]~^ ERROR non-exhaustive
+ //[normal,never_pats]~^ ERROR non-exhaustive
None => {}
}
match *ref_opt_never {
@@ -539,7 +529,7 @@ fn bindings(x: NeverBundle) {
let ref_res_never: &Result<!, !> = &x.result_never;
match *ref_res_never {
- //[normal,min_exh_pats,never_pats]~^ ERROR non-exhaustive
+ //[normal,never_pats]~^ ERROR non-exhaustive
// useful, reachable
Ok(_) => {}
}
@@ -550,7 +540,7 @@ fn bindings(x: NeverBundle) {
_ => {}
}
match *ref_res_never {
- //[normal,min_exh_pats,never_pats]~^ ERROR non-exhaustive
+ //[normal,never_pats]~^ ERROR non-exhaustive
// useful, !reachable
Ok(_a) => {}
}
@@ -569,7 +559,7 @@ fn bindings(x: NeverBundle) {
let ref_tuple_half_never: &(u32, !) = &x.tuple_half_never;
match *ref_tuple_half_never {}
- //[normal,min_exh_pats,never_pats]~^ ERROR non-empty
+ //[normal,never_pats]~^ ERROR non-empty
match *ref_tuple_half_never {
// useful, reachable
(_, _) => {}
@@ -636,7 +626,7 @@ fn guards_and_validity(x: NeverBundle) {
_a if false => {}
}
match ref_never {
- //[normal,min_exh_pats,never_pats]~^ ERROR non-exhaustive
+ //[normal,never_pats]~^ ERROR non-exhaustive
// useful, !reachable
&_a if false => {}
}
@@ -652,7 +642,7 @@ fn guards_and_validity(x: NeverBundle) {
Err(_) => {}
}
match *ref_result_never {
- //[normal,min_exh_pats]~^ ERROR `Ok(_)` not covered
+ //[normal]~^ ERROR `Ok(_)` not covered
//[never_pats]~^^ ERROR `Ok(!)` not covered
// useful, reachable
Ok(_) if false => {}
@@ -672,7 +662,7 @@ fn diagnostics_subtlety(x: NeverBundle) {
// Regression test for diagnostics: don't report `Some(Ok(_))` and `Some(Err(_))`.
let x: &Option<Result<!, !>> = &None;
match *x {
- //[normal,min_exh_pats]~^ ERROR `Some(_)` not covered
+ //[normal]~^ ERROR `Some(_)` not covered
//[never_pats]~^^ ERROR `Some(!)` not covered
None => {}
}
diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs
index 98f781b..44d1940 100644
--- a/tests/ui/pattern/usefulness/explain-unreachable-pats.rs
+++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.rs
@@ -1,5 +1,4 @@
#![feature(never_type)]
-#![feature(min_exhaustive_patterns)]
#![deny(unreachable_patterns)]
//~^ NOTE lint level is defined here
diff --git a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr
index e2eecf4..105d4f7 100644
--- a/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr
+++ b/tests/ui/pattern/usefulness/explain-unreachable-pats.stderr
@@ -1,5 +1,5 @@
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:11:9
+ --> $DIR/explain-unreachable-pats.rs:10:9
|
LL | (1 | 2,) => {}
| -------- matches all the values already
@@ -8,19 +8,19 @@
| ^^^^ unreachable pattern
|
note: the lint level is defined here
- --> $DIR/explain-unreachable-pats.rs:3:9
+ --> $DIR/explain-unreachable-pats.rs:2:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:22:9
+ --> $DIR/explain-unreachable-pats.rs:21:9
|
LL | (1 | 2,) => {}
| ^^^^^^^^ unreachable pattern
|
note: these patterns collectively make the last one unreachable
- --> $DIR/explain-unreachable-pats.rs:22:9
+ --> $DIR/explain-unreachable-pats.rs:21:9
|
LL | (1,) => {}
| ---- matches some of the same values
@@ -32,7 +32,7 @@
| ^^^^^^^^ collectively making this unreachable
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:33:9
+ --> $DIR/explain-unreachable-pats.rs:32:9
|
LL | Err(_) => {}
| ^^^^^^
@@ -40,7 +40,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:46:9
+ --> $DIR/explain-unreachable-pats.rs:45:9
|
LL | (Err(_), Err(_)) => {}
| ^^^^^^^^^^^^^^^^
@@ -48,7 +48,7 @@
= note: this pattern matches no values because `Void2` is uninhabited
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:52:9
+ --> $DIR/explain-unreachable-pats.rs:51:9
|
LL | (Err(_), Err(_)) => {}
| ^^^^^^^^^^^^^^^^
@@ -56,7 +56,7 @@
= note: this pattern matches no values because `Void1` is uninhabited
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:61:11
+ --> $DIR/explain-unreachable-pats.rs:60:11
|
LL | if let (0
| - matches all the values already
@@ -65,13 +65,13 @@
| ^ unreachable pattern
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:71:9
+ --> $DIR/explain-unreachable-pats.rs:70:9
|
LL | (_, true) => {}
| ^^^^^^^^^ unreachable pattern
|
note: these patterns collectively make the last one unreachable
- --> $DIR/explain-unreachable-pats.rs:71:9
+ --> $DIR/explain-unreachable-pats.rs:70:9
|
LL | (true, _) => {}
| --------- matches some of the same values
@@ -83,7 +83,7 @@
| ^^^^^^^^^ collectively making this unreachable
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:84:9
+ --> $DIR/explain-unreachable-pats.rs:83:9
|
LL | (true, _) => {}
| --------- matches all the values already
@@ -92,7 +92,7 @@
| ^^^^^^^^^^^^ unreachable pattern
error: unreachable pattern
- --> $DIR/explain-unreachable-pats.rs:96:9
+ --> $DIR/explain-unreachable-pats.rs:95:9
|
LL | (_, true, 0..10) => {}
| ---------------- matches all the values already
diff --git a/tests/ui/pattern/usefulness/impl-trait.rs b/tests/ui/pattern/usefulness/impl-trait.rs
index 1fec9a2..c1cc279 100644
--- a/tests/ui/pattern/usefulness/impl-trait.rs
+++ b/tests/ui/pattern/usefulness/impl-trait.rs
@@ -1,5 +1,4 @@
#![feature(never_type)]
-#![feature(min_exhaustive_patterns)]
#![feature(type_alias_impl_trait)]
#![feature(non_exhaustive_omitted_patterns_lint)]
#![deny(unreachable_patterns)]
diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr
index c079f5a..92932e4 100644
--- a/tests/ui/pattern/usefulness/impl-trait.stderr
+++ b/tests/ui/pattern/usefulness/impl-trait.stderr
@@ -1,18 +1,18 @@
error: unreachable pattern
- --> $DIR/impl-trait.rs:17:13
+ --> $DIR/impl-trait.rs:16:13
|
LL | _ => {}
| ^
|
= note: this pattern matches no values because `Void` is uninhabited
note: the lint level is defined here
- --> $DIR/impl-trait.rs:5:9
+ --> $DIR/impl-trait.rs:4:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/impl-trait.rs:31:13
+ --> $DIR/impl-trait.rs:30:13
|
LL | _ => {}
| ^
@@ -20,7 +20,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/impl-trait.rs:45:13
+ --> $DIR/impl-trait.rs:44:13
|
LL | Some(_) => {}
| ^^^^^^^
@@ -28,7 +28,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/impl-trait.rs:49:13
+ --> $DIR/impl-trait.rs:48:13
|
LL | None => {}
| ---- matches all the values already
@@ -36,7 +36,7 @@
| ^ unreachable pattern
error: unreachable pattern
- --> $DIR/impl-trait.rs:59:13
+ --> $DIR/impl-trait.rs:58:13
|
LL | Some(_) => {}
| ^^^^^^^
@@ -44,7 +44,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/impl-trait.rs:63:13
+ --> $DIR/impl-trait.rs:62:13
|
LL | None => {}
| ---- matches all the values already
@@ -52,7 +52,7 @@
| ^ unreachable pattern
error: unreachable pattern
- --> $DIR/impl-trait.rs:76:9
+ --> $DIR/impl-trait.rs:75:9
|
LL | _ => {}
| ^
@@ -60,7 +60,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/impl-trait.rs:86:9
+ --> $DIR/impl-trait.rs:85:9
|
LL | _ => {}
| - matches any value
@@ -68,7 +68,7 @@
| ^^^^^^^^^^^^ unreachable pattern
error: unreachable pattern
- --> $DIR/impl-trait.rs:94:13
+ --> $DIR/impl-trait.rs:93:13
|
LL | _ => {}
| ^
@@ -76,7 +76,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/impl-trait.rs:105:9
+ --> $DIR/impl-trait.rs:104:9
|
LL | Some((a, b)) => {}
| ------------ matches all the values already
@@ -84,7 +84,7 @@
| ^^^^^^^^^^^^^^^^^^^^ unreachable pattern
error: unreachable pattern
- --> $DIR/impl-trait.rs:124:13
+ --> $DIR/impl-trait.rs:123:13
|
LL | _ => {}
| - matches any value
@@ -92,7 +92,7 @@
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable pattern
error: unreachable pattern
- --> $DIR/impl-trait.rs:138:13
+ --> $DIR/impl-trait.rs:137:13
|
LL | _ => {}
| ^
@@ -100,7 +100,7 @@
= note: this pattern matches no values because `SecretelyVoid` is uninhabited
error: unreachable pattern
- --> $DIR/impl-trait.rs:151:13
+ --> $DIR/impl-trait.rs:150:13
|
LL | _ => {}
| ^
@@ -108,7 +108,7 @@
= note: this pattern matches no values because `SecretelyDoubleVoid` is uninhabited
error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
- --> $DIR/impl-trait.rs:23:11
+ --> $DIR/impl-trait.rs:22:11
|
LL | match return_never_rpit(x) {}
| ^^^^^^^^^^^^^^^^^^^^
@@ -122,7 +122,7 @@
|
error[E0004]: non-exhaustive patterns: type `T` is non-empty
- --> $DIR/impl-trait.rs:37:11
+ --> $DIR/impl-trait.rs:36:11
|
LL | match return_never_tait(x) {}
| ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr
index 261a4b3..463e104 100644
--- a/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
- --> $DIR/match-privately-empty.rs:15:11
+ --> $DIR/match-privately-empty.rs:14:11
|
LL | match private::DATA {
| ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
diff --git a/tests/ui/pattern/usefulness/match-privately-empty.normal.stderr b/tests/ui/pattern/usefulness/match-privately-empty.normal.stderr
new file mode 100644
index 0000000..463e104
--- /dev/null
+++ b/tests/ui/pattern/usefulness/match-privately-empty.normal.stderr
@@ -0,0 +1,21 @@
+error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered
+ --> $DIR/match-privately-empty.rs:14:11
+ |
+LL | match private::DATA {
+ | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered
+ |
+note: `Option<Private>` defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ ::: $SRC_DIR/core/src/option.rs:LL:COL
+ |
+ = note: not covered
+ = note: the matched value is of type `Option<Private>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ Some(private::Private { misc: false, .. }) => {},
+LL + Some(Private { misc: true, .. }) => todo!()
+ |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs
index 7e1d0dc..bfea15a 100644
--- a/tests/ui/pattern/usefulness/match-privately-empty.rs
+++ b/tests/ui/pattern/usefulness/match-privately-empty.rs
@@ -1,6 +1,5 @@
-//@ revisions: min_exhaustive_patterns exhaustive_patterns
+//@ revisions: normal exhaustive_patterns
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
-#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
#![feature(never_type)]
mod private {
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr
index e5e5814..c4fcd67 100644
--- a/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `&[]` not covered
- --> $DIR/slice_of_empty.rs:21:11
+ --> $DIR/slice_of_empty.rs:20:11
|
LL | match nevers {
| ^^^^^^ pattern `&[]` not covered
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.normal.stderr b/tests/ui/pattern/usefulness/slice_of_empty.normal.stderr
new file mode 100644
index 0000000..c9afd1b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/slice_of_empty.normal.stderr
@@ -0,0 +1,30 @@
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+ --> $DIR/slice_of_empty.rs:9:11
+ |
+LL | match nevers {
+ | ^^^^^^ pattern `&[_, ..]` not covered
+ |
+ = note: the matched value is of type `&[!]`
+ = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+ |
+LL ~ &[] => (),
+LL ~ &[_, ..] => todo!(),
+ |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+ --> $DIR/slice_of_empty.rs:20:11
+ |
+LL | match nevers {
+ | ^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered
+ |
+ = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+ |
+LL ~ &[_] => (),
+LL ~ &[] | &[_, _, ..] => todo!(),
+ |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs
index 785fcca..e186ba5 100644
--- a/tests/ui/pattern/usefulness/slice_of_empty.rs
+++ b/tests/ui/pattern/usefulness/slice_of_empty.rs
@@ -1,6 +1,5 @@
-//@ revisions: min_exhaustive_patterns exhaustive_patterns
+//@ revisions: normal exhaustive_patterns
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
-#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
#![feature(never_type)]
#![deny(unreachable_patterns)]
@@ -8,7 +7,7 @@ fn main() {}
fn foo(nevers: &[!]) {
match nevers {
- //[min_exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[_, ..]` not covered
+ //[normal]~^ ERROR non-exhaustive patterns: `&[_, ..]` not covered
&[] => (),
};
@@ -20,7 +19,7 @@ fn foo(nevers: &[!]) {
match nevers {
//[exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[]` not covered
- //[min_exhaustive_patterns]~^^ ERROR non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+ //[normal]~^^ ERROR non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
&[_] => (),
};
}
diff --git a/tests/ui/pattern/usefulness/uninhabited.rs b/tests/ui/pattern/usefulness/uninhabited.rs
index 72e602e..5c774b7 100644
--- a/tests/ui/pattern/usefulness/uninhabited.rs
+++ b/tests/ui/pattern/usefulness/uninhabited.rs
@@ -5,7 +5,6 @@
// `Ty::is_inhabited_from` function.
#![feature(never_type)]
#![feature(never_type_fallback)]
-#![feature(min_exhaustive_patterns)]
#![deny(unreachable_patterns)]
macro_rules! assert_empty {
diff --git a/tests/ui/polymorphization/inline-tainted-body.rs b/tests/ui/polymorphization/inline-tainted-body.rs
new file mode 100644
index 0000000..13aec97
--- /dev/null
+++ b/tests/ui/polymorphization/inline-tainted-body.rs
@@ -0,0 +1,21 @@
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
+
+#![feature(unboxed_closures)]
+
+use std::sync::Arc;
+
+pub struct WeakOnce<T>();
+//~^ ERROR type parameter `T` is never used
+
+impl<T> WeakOnce<T> {
+ extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
+ //~^ ERROR functions with the "rust-call" ABI must take a single non-self tuple argument
+ //~| ERROR mismatched types
+
+ pub fn get(&self) -> Arc<T> {
+ self.try_get()
+ .unwrap_or_else(|| panic!("Singleton {} not available", std::any::type_name::<T>()))
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/polymorphization/inline-tainted-body.stderr b/tests/ui/polymorphization/inline-tainted-body.stderr
new file mode 100644
index 0000000..5c3bd70
--- /dev/null
+++ b/tests/ui/polymorphization/inline-tainted-body.stderr
@@ -0,0 +1,30 @@
+error[E0392]: type parameter `T` is never used
+ --> $DIR/inline-tainted-body.rs:7:21
+ |
+LL | pub struct WeakOnce<T>();
+ | ^ unused type parameter
+ |
+ = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+ = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
+
+error: functions with the "rust-call" ABI must take a single non-self tuple argument
+ --> $DIR/inline-tainted-body.rs:11:35
+ |
+LL | extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
+ | ^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/inline-tainted-body.rs:11:45
+ |
+LL | extern "rust-call" fn try_get(&self) -> Option<Arc<T>> {}
+ | ------- ^^^^^^^^^^^^^^ expected `Option<Arc<T>>`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected enum `Option<Arc<T>>`
+ found unit type `()`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0392.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/print-calling-conventions.rs b/tests/ui/print-calling-conventions.rs
new file mode 100644
index 0000000..302ed08
--- /dev/null
+++ b/tests/ui/print-calling-conventions.rs
@@ -0,0 +1,2 @@
+//@ compile-flags: --print calling-conventions
+//@ build-pass
diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout
new file mode 100644
index 0000000..da67a57
--- /dev/null
+++ b/tests/ui/print-calling-conventions.stdout
@@ -0,0 +1,34 @@
+C
+C-cmse-nonsecure-call
+C-unwind
+Rust
+aapcs
+aapcs-unwind
+avr-interrupt
+avr-non-blocking-interrupt
+cdecl
+cdecl-unwind
+efiapi
+fastcall
+fastcall-unwind
+msp430-interrupt
+ptx-kernel
+riscv-interrupt-m
+riscv-interrupt-s
+rust-call
+rust-cold
+rust-intrinsic
+stdcall
+stdcall-unwind
+system
+system-unwind
+sysv64
+sysv64-unwind
+thiscall
+thiscall-unwind
+unadjusted
+vectorcall
+vectorcall-unwind
+win64
+win64-unwind
+x86-interrupt
diff --git a/tests/ui/privacy/issue-75907.stderr b/tests/ui/privacy/issue-75907.stderr
index f7cb874..3121cc0 100644
--- a/tests/ui/privacy/issue-75907.stderr
+++ b/tests/ui/privacy/issue-75907.stderr
@@ -14,7 +14,7 @@
help: consider making the fields publicly accessible
|
LL | pub(crate) struct Bar(pub u8, pub u8, pub Foo);
- | ~~~ ~~~ +++
+ | ~~~ +++
error[E0532]: cannot match against a tuple struct which contains private fields
--> $DIR/issue-75907.rs:15:19
diff --git a/tests/ui/privacy/privacy5.stderr b/tests/ui/privacy/privacy5.stderr
index 615b0af..ec3abe9 100644
--- a/tests/ui/privacy/privacy5.stderr
+++ b/tests/ui/privacy/privacy5.stderr
@@ -53,7 +53,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `A` is private
--> $DIR/privacy5.rs:56:12
@@ -262,7 +262,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:69:12
@@ -281,7 +281,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:70:12
@@ -300,7 +300,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:71:12
@@ -319,7 +319,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:72:18
@@ -338,7 +338,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:73:18
@@ -357,7 +357,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:74:18
@@ -376,7 +376,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `C` is private
--> $DIR/privacy5.rs:75:18
@@ -395,7 +395,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `A` is private
--> $DIR/privacy5.rs:83:17
@@ -452,7 +452,7 @@
help: consider making the fields publicly accessible
|
LL | pub struct C(pub isize, pub isize);
- | ~~~ +++
+ | +++
error[E0603]: tuple struct constructor `A` is private
--> $DIR/privacy5.rs:90:20
diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr
index a48bb67..5deaffb 100644
--- a/tests/ui/privacy/restricted/test.stderr
+++ b/tests/ui/privacy/restricted/test.stderr
@@ -4,7 +4,10 @@
LL | pub(in bad::path) mod m1 {}
| ^^^ you might be missing crate `bad`
|
- = help: consider adding `extern crate bad` to use the `bad` crate
+help: consider importing the `bad` crate
+ |
+LL + extern crate bad;
+ |
error[E0742]: visibilities can only be restricted to ancestor modules
--> $DIR/test.rs:51:12
diff --git a/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs
new file mode 100644
index 0000000..07e135e
--- /dev/null
+++ b/tests/ui/proc-macro/auxiliary/parse-invis-delim-issue-128895.rs
@@ -0,0 +1,44 @@
+//@ force-host
+//@ no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+// This proc macro ignores its input and returns this token stream
+//
+// impl <«A1»: Comparable> Comparable for («A1»,) {}
+//
+// where `«`/`»` are invisible delimiters. This was being misparsed in bug
+// #128895.
+#[proc_macro]
+pub fn main(_input: TokenStream) -> TokenStream {
+ let a1 = TokenTree::Group(
+ Group::new(
+ Delimiter::None,
+ std::iter::once(TokenTree::Ident(Ident::new("A1", Span::call_site()))).collect(),
+ )
+ );
+ vec![
+ TokenTree::Ident(Ident::new("impl", Span::call_site())),
+ TokenTree::Punct(Punct::new('<', Spacing::Alone)),
+ a1.clone(),
+ TokenTree::Punct(Punct::new(':', Spacing::Alone)),
+ TokenTree::Ident(Ident::new("Comparable", Span::call_site())),
+ TokenTree::Punct(Punct::new('>', Spacing::Alone)),
+ TokenTree::Ident(Ident::new("Comparable", Span::call_site())),
+ TokenTree::Ident(Ident::new("for", Span::call_site())),
+ TokenTree::Group(
+ Group::new(
+ Delimiter::Parenthesis,
+ vec![
+ a1.clone(),
+ TokenTree::Punct(Punct::new(',', Spacing::Alone)),
+ ].into_iter().collect::<TokenStream>(),
+ )
+ ),
+ TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
+ ].into_iter().collect::<TokenStream>()
+}
diff --git a/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs
new file mode 100644
index 0000000..3d5af5f
--- /dev/null
+++ b/tests/ui/proc-macro/parse-invis-delim-issue-128895.rs
@@ -0,0 +1,14 @@
+//@ aux-build:parse-invis-delim-issue-128895.rs
+//@ check-pass
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate parse_invis_delim_issue_128895;
+
+trait Comparable {}
+
+parse_invis_delim_issue_128895::main!();
+
+fn main() {}
diff --git a/tests/ui/process/println-with-broken-pipe.run.stderr b/tests/ui/process/println-with-broken-pipe.run.stderr
index a334c0a..f9d138a 100644
--- a/tests/ui/process/println-with-broken-pipe.run.stderr
+++ b/tests/ui/process/println-with-broken-pipe.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at library/std/src/io/stdio.rs:LL:CC:
+thread 'main' panicked at std/src/io/stdio.rs:LL:CC:
failed printing to stdout: Broken pipe (os error 32)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/pub/pub-ident-struct-4.fixed b/tests/ui/pub/pub-ident-struct-4.fixed
index a62ece4..5fedbb7 100644
--- a/tests/ui/pub/pub-ident-struct-4.fixed
+++ b/tests/ui/pub/pub-ident-struct-4.fixed
@@ -1,7 +1,6 @@
//@ run-rustfix
-#[allow(dead_code)]
-pub struct T(String);
+pub struct T(#[allow(dead_code)] String);
//~^ ERROR missing `struct` for struct definition
fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-4.rs b/tests/ui/pub/pub-ident-struct-4.rs
index 0d56a31..5c721c2 100644
--- a/tests/ui/pub/pub-ident-struct-4.rs
+++ b/tests/ui/pub/pub-ident-struct-4.rs
@@ -1,7 +1,6 @@
//@ run-rustfix
-#[allow(dead_code)]
-pub T(String);
+pub T(#[allow(dead_code)] String);
//~^ ERROR missing `struct` for struct definition
fn main() {}
diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr
index d307246..04965a1 100644
--- a/tests/ui/pub/pub-ident-struct-4.stderr
+++ b/tests/ui/pub/pub-ident-struct-4.stderr
@@ -1,12 +1,12 @@
error: missing `struct` for struct definition
- --> $DIR/pub-ident-struct-4.rs:4:1
+ --> $DIR/pub-ident-struct-4.rs:3:1
|
-LL | pub T(String);
+LL | pub T(#[allow(dead_code)] String);
| ^^^^^
|
help: add `struct` here to parse `T` as a struct
|
-LL | pub struct T(String);
+LL | pub struct T(#[allow(dead_code)] String);
| ++++++
error: aborting due to 1 previous error
diff --git a/tests/ui/reachable/unreachable-loop-patterns.rs b/tests/ui/reachable/unreachable-loop-patterns.rs
index 4294a18..d074e3a 100644
--- a/tests/ui/reachable/unreachable-loop-patterns.rs
+++ b/tests/ui/reachable/unreachable-loop-patterns.rs
@@ -1,6 +1,4 @@
#![feature(never_type, never_type_fallback)]
-#![feature(min_exhaustive_patterns)]
-
#![allow(unreachable_code)]
#![deny(unreachable_patterns)]
diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr
index bdd9b5e..9b7c2ba 100644
--- a/tests/ui/reachable/unreachable-loop-patterns.stderr
+++ b/tests/ui/reachable/unreachable-loop-patterns.stderr
@@ -1,12 +1,12 @@
error: unreachable pattern
- --> $DIR/unreachable-loop-patterns.rs:18:9
+ --> $DIR/unreachable-loop-patterns.rs:16:9
|
LL | for _ in unimplemented!() as Void {}
| ^
|
= note: this pattern matches no values because `Void` is uninhabited
note: the lint level is defined here
- --> $DIR/unreachable-loop-patterns.rs:5:9
+ --> $DIR/unreachable-loop-patterns.rs:3:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/regions/regions-issue-21422.rs b/tests/ui/regions/regions-issue-21422.rs
index 67852a6..54beed9 100644
--- a/tests/ui/regions/regions-issue-21422.rs
+++ b/tests/ui/regions/regions-issue-21422.rs
@@ -5,7 +5,6 @@
//@ pretty-expanded FIXME #23616
-#[allow(dead_code)]
pub struct P<'a> {
_ptr: *const &'a u8,
}
diff --git a/tests/ui/resolve/editions-crate-root-2015.stderr b/tests/ui/resolve/editions-crate-root-2015.stderr
index 74fb7e6..7a842ac 100644
--- a/tests/ui/resolve/editions-crate-root-2015.stderr
+++ b/tests/ui/resolve/editions-crate-root-2015.stderr
@@ -4,7 +4,10 @@
LL | fn global_inner(_: ::nonexistant::Foo) {
| ^^^^^^^^^^^ you might be missing crate `nonexistant`
|
- = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate
+help: consider importing the `nonexistant` crate
+ |
+LL + extern crate nonexistant;
+ |
error[E0433]: failed to resolve: you might be missing crate `nonexistant`
--> $DIR/editions-crate-root-2015.rs:7:30
@@ -12,7 +15,10 @@
LL | fn crate_inner(_: crate::nonexistant::Foo) {
| ^^^^^^^^^^^ you might be missing crate `nonexistant`
|
- = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate
+help: consider importing the `nonexistant` crate
+ |
+LL + extern crate nonexistant;
+ |
error[E0412]: cannot find type `nonexistant` in the crate root
--> $DIR/editions-crate-root-2015.rs:11:25
diff --git a/tests/ui/resolve/extern-prelude-fail.stderr b/tests/ui/resolve/extern-prelude-fail.stderr
index 4c2d5ab..77c10f5 100644
--- a/tests/ui/resolve/extern-prelude-fail.stderr
+++ b/tests/ui/resolve/extern-prelude-fail.stderr
@@ -4,7 +4,10 @@
LL | use extern_prelude::S;
| ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude`
|
- = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate
+help: consider importing the `extern_prelude` crate
+ |
+LL + extern crate extern_prelude;
+ |
error[E0433]: failed to resolve: you might be missing crate `extern_prelude`
--> $DIR/extern-prelude-fail.rs:8:15
@@ -12,7 +15,10 @@
LL | let s = ::extern_prelude::S;
| ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude`
|
- = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate
+help: consider importing the `extern_prelude` crate
+ |
+LL + extern crate extern_prelude;
+ |
error: aborting due to 2 previous errors
diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr
index ce0061a..bc7e0f0 100644
--- a/tests/ui/resolve/issue-82865.stderr
+++ b/tests/ui/resolve/issue-82865.stderr
@@ -4,7 +4,10 @@
LL | use x::y::z;
| ^ you might be missing crate `x`
|
- = help: consider adding `extern crate x` to use the `x` crate
+help: consider importing the `x` crate
+ |
+LL + extern crate x;
+ |
error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope
--> $DIR/issue-82865.rs:8:10
diff --git a/tests/ui/resolve/resolve-bad-visibility.stderr b/tests/ui/resolve/resolve-bad-visibility.stderr
index 8e47573..281e5af 100644
--- a/tests/ui/resolve/resolve-bad-visibility.stderr
+++ b/tests/ui/resolve/resolve-bad-visibility.stderr
@@ -22,7 +22,10 @@
LL | pub(in nonexistent) struct G;
| ^^^^^^^^^^^ you might be missing crate `nonexistent`
|
- = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate
+help: consider importing the `nonexistent` crate
+ |
+LL + extern crate nonexistent;
+ |
error[E0433]: failed to resolve: you might be missing crate `too_soon`
--> $DIR/resolve-bad-visibility.rs:8:8
@@ -30,7 +33,10 @@
LL | pub(in too_soon) struct H;
| ^^^^^^^^ you might be missing crate `too_soon`
|
- = help: consider adding `extern crate too_soon` to use the `too_soon` crate
+help: consider importing the `too_soon` crate
+ |
+LL + extern crate too_soon;
+ |
error: aborting due to 5 previous errors
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
index dc13dd0..77f7900 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
@@ -11,22 +11,22 @@ macro_rules! never {
}
fn no_arms_or_guards(x: Void) {
- match None::<Void> {
+ match &None::<Void> {
Some(!) => {}
//~^ ERROR a never pattern is always unreachable
None => {}
}
- match None::<Void> { //~ ERROR: `Some(!)` not covered
+ match &None::<Void> { //~ ERROR: `&Some(!)` not covered
Some(!) if true,
//~^ ERROR guard on a never pattern
None => {}
}
- match None::<Void> { //~ ERROR: `Some(!)` not covered
+ match &None::<Void> { //~ ERROR: `&Some(!)` not covered
Some(!) if true => {}
//~^ ERROR a never pattern is always unreachable
None => {}
}
- match None::<Void> {
+ match &None::<Void> {
Some(never!()) => {}
//~^ ERROR a never pattern is always unreachable
None => {}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
index fbf7aa0..4622ea5 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
@@ -31,40 +31,42 @@
| this will never be executed
| help: remove this expression
-error[E0004]: non-exhaustive patterns: `Some(!)` not covered
+error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
--> $DIR/check.rs:19:11
|
-LL | match None::<Void> {
- | ^^^^^^^^^^^^ pattern `Some(!)` not covered
+LL | match &None::<Void> {
+ | ^^^^^^^^^^^^^ pattern `&Some(!)` not covered
|
note: `Option<Void>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
- = note: the matched value is of type `Option<Void>`
+ = note: the matched value is of type `&Option<Void>`
+ = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
-LL + Some(!)
+LL + &Some(!)
|
-error[E0004]: non-exhaustive patterns: `Some(!)` not covered
+error[E0004]: non-exhaustive patterns: `&Some(!)` not covered
--> $DIR/check.rs:24:11
|
-LL | match None::<Void> {
- | ^^^^^^^^^^^^ pattern `Some(!)` not covered
+LL | match &None::<Void> {
+ | ^^^^^^^^^^^^^ pattern `&Some(!)` not covered
|
note: `Option<Void>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
- = note: the matched value is of type `Option<Void>`
+ = note: the matched value is of type `&Option<Void>`
+ = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
-LL + Some(!)
+LL + &Some(!)
|
error: aborting due to 6 previous errors
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr
index 013a8b5..9e2ae28 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr
@@ -1,5 +1,5 @@
error: mismatched types
- --> $DIR/typeck.rs:25:9
+ --> $DIR/typeck.rs:24:9
|
LL | !,
| ^ a never pattern must be used on an uninhabited type
@@ -7,7 +7,7 @@
= note: the matched value is of type `()`
error: mismatched types
- --> $DIR/typeck.rs:29:9
+ --> $DIR/typeck.rs:28:9
|
LL | !,
| ^ a never pattern must be used on an uninhabited type
@@ -15,7 +15,7 @@
= note: the matched value is of type `(i32, bool)`
error: mismatched types
- --> $DIR/typeck.rs:33:13
+ --> $DIR/typeck.rs:32:13
|
LL | (_, !),
| ^ a never pattern must be used on an uninhabited type
@@ -23,7 +23,7 @@
= note: the matched value is of type `bool`
error: mismatched types
- --> $DIR/typeck.rs:38:14
+ --> $DIR/typeck.rs:37:14
|
LL | Some(!),
| ^ a never pattern must be used on an uninhabited type
@@ -31,7 +31,7 @@
= note: the matched value is of type `i32`
error: mismatched types
- --> $DIR/typeck.rs:45:9
+ --> $DIR/typeck.rs:44:9
|
LL | !,
| ^ a never pattern must be used on an uninhabited type
@@ -39,7 +39,7 @@
= note: the matched value is of type `()`
error: mismatched types
- --> $DIR/typeck.rs:52:9
+ --> $DIR/typeck.rs:51:9
|
LL | !,
| ^ a never pattern must be used on an uninhabited type
@@ -47,7 +47,7 @@
= note: the matched value is of type `Option<Void>`
error: mismatched types
- --> $DIR/typeck.rs:57:9
+ --> $DIR/typeck.rs:56:9
|
LL | !,
| ^ a never pattern must be used on an uninhabited type
@@ -55,7 +55,7 @@
= note: the matched value is of type `[Void]`
error: mismatched types
- --> $DIR/typeck.rs:63:9
+ --> $DIR/typeck.rs:62:9
|
LL | !,
| ^ a never pattern must be used on an uninhabited type
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
index 8300f95..bf74b282 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs
@@ -2,7 +2,6 @@
//@[pass] check-pass
//@[fail] check-fail
#![feature(never_patterns)]
-#![feature(min_exhaustive_patterns)]
#![allow(incomplete_features)]
#[derive(Copy, Clone)]
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr
index a875041..d78f4a5 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr
@@ -1,18 +1,18 @@
error: unreachable pattern
- --> $DIR/unreachable.rs:17:9
+ --> $DIR/unreachable.rs:16:9
|
LL | Err(!),
| ^^^^^^
|
= note: this pattern matches no values because `Void` is uninhabited
note: the lint level is defined here
- --> $DIR/unreachable.rs:7:9
+ --> $DIR/unreachable.rs:6:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/unreachable.rs:20:19
+ --> $DIR/unreachable.rs:19:19
|
LL | let (Ok(_x) | Err(!)) = res_void;
| ^^^^^^
@@ -20,7 +20,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/unreachable.rs:22:12
+ --> $DIR/unreachable.rs:21:12
|
LL | if let Err(!) = res_void {}
| ^^^^^^
@@ -28,7 +28,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/unreachable.rs:24:24
+ --> $DIR/unreachable.rs:23:24
|
LL | if let (Ok(true) | Err(!)) = res_void {}
| ^^^^^^
@@ -36,7 +36,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/unreachable.rs:26:23
+ --> $DIR/unreachable.rs:25:23
|
LL | for (Ok(mut _x) | Err(!)) in [res_void] {}
| ^^^^^^
@@ -44,7 +44,7 @@
= note: this pattern matches no values because `Void` is uninhabited
error: unreachable pattern
- --> $DIR/unreachable.rs:30:18
+ --> $DIR/unreachable.rs:29:18
|
LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
| ^^^^^^
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr
new file mode 100644
index 0000000..a3bf8e8
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr
@@ -0,0 +1,44 @@
+error: unreachable pattern
+ --> $DIR/unreachable.rs:16:9
+ |
+LL | Err(!),
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unreachable.rs:6:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:19:19
+ |
+LL | let (Ok(_x) | Err(!)) = res_void;
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:21:12
+ |
+LL | if let Err(!) = res_void {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:23:24
+ |
+LL | if let (Ok(true) | Err(!)) = res_void {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:25:23
+ |
+LL | for (Ok(mut _x) | Err(!)) in [res_void] {}
+ | ^^^^^^
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:29:18
+ |
+LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
+ | ^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs
index 4d20c67..f68da4a 100644
--- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs
@@ -1,8 +1,5 @@
-//@ revisions: normal exh_pats
-//@[normal] check-pass
#![feature(never_patterns)]
#![allow(incomplete_features)]
-#![cfg_attr(exh_pats, feature(min_exhaustive_patterns))]
#![allow(dead_code, unreachable_code)]
#![deny(unreachable_patterns)]
@@ -15,17 +12,17 @@ fn main() {
match res_void {
Ok(_x) => {}
Err(!),
- //[exh_pats]~^ ERROR unreachable
+ //~^ ERROR unreachable
}
let (Ok(_x) | Err(!)) = res_void;
- //[exh_pats]~^ ERROR unreachable
+ //~^ ERROR unreachable
if let Err(!) = res_void {}
- //[exh_pats]~^ ERROR unreachable
+ //~^ ERROR unreachable
if let (Ok(true) | Err(!)) = res_void {}
- //[exh_pats]~^ ERROR unreachable
+ //~^ ERROR unreachable
for (Ok(mut _x) | Err(!)) in [res_void] {}
- //[exh_pats]~^ ERROR unreachable
+ //~^ ERROR unreachable
}
fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
-//[exh_pats]~^ ERROR unreachable
+//~^ ERROR unreachable
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr
new file mode 100644
index 0000000..79b640d
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.stderr
@@ -0,0 +1,55 @@
+error: unreachable pattern
+ --> $DIR/unreachable.rs:14:9
+ |
+LL | Err(!),
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Void` is uninhabited
+note: the lint level is defined here
+ --> $DIR/unreachable.rs:4:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:17:19
+ |
+LL | let (Ok(_x) | Err(!)) = res_void;
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:19:12
+ |
+LL | if let Err(!) = res_void {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:21:24
+ |
+LL | if let (Ok(true) | Err(!)) = res_void {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:23:23
+ |
+LL | for (Ok(mut _x) | Err(!)) in [res_void] {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: unreachable pattern
+ --> $DIR/unreachable.rs:27:18
+ |
+LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {}
+ | ^^^^^^
+ |
+ = note: this pattern matches no values because `Void` is uninhabited
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
index 8f090fe..d81896e 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.rs
@@ -1,3 +1,4 @@
+//@ check-pass
#![feature(never_type)]
#[non_exhaustive]
@@ -28,24 +29,24 @@ pub enum UninhabitedVariants {
struct A;
// This test checks that an empty match on a non-exhaustive uninhabited type through a level of
-// indirection from the defining crate will not compile without `#![feature(exhaustive_patterns)]`.
+// indirection from the defining crate compiles.
fn cannot_empty_match_on_empty_enum_to_anything(x: IndirectUninhabitedEnum) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn cannot_empty_match_on_empty_struct_to_anything(x: IndirectUninhabitedStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: IndirectUninhabitedTupleStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(
x: IndirectUninhabitedVariants,
) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
deleted file mode 100644
index c121905..0000000
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr
+++ /dev/null
@@ -1,79 +0,0 @@
-error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
- --> $DIR/indirect_match_same_crate.rs:34:11
- |
-LL | match x {}
- | ^
- |
-note: `IndirectUninhabitedEnum` defined here
- --> $DIR/indirect_match_same_crate.rs:20:12
- |
-LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
- | ^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `IndirectUninhabitedEnum`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
- --> $DIR/indirect_match_same_crate.rs:38:11
- |
-LL | match x {}
- | ^
- |
-note: `IndirectUninhabitedStruct` defined here
- --> $DIR/indirect_match_same_crate.rs:22:12
- |
-LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `IndirectUninhabitedStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
- --> $DIR/indirect_match_same_crate.rs:42:11
- |
-LL | match x {}
- | ^
- |
-note: `IndirectUninhabitedTupleStruct` defined here
- --> $DIR/indirect_match_same_crate.rs:24:12
- |
-LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `IndirectUninhabitedTupleStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
- --> $DIR/indirect_match_same_crate.rs:48:11
- |
-LL | match x {}
- | ^
- |
-note: `IndirectUninhabitedVariants` defined here
- --> $DIR/indirect_match_same_crate.rs:26:12
- |
-LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `IndirectUninhabitedVariants`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
index c40a267..dd9a570 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.rs
@@ -1,6 +1,5 @@
//@ aux-build:uninhabited.rs
#![deny(unreachable_patterns)]
-#![feature(min_exhaustive_patterns)]
#![feature(never_type)]
extern crate uninhabited;
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
index ef97c1f..745b196 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty
- --> $DIR/indirect_match_with_exhaustive_patterns.rs:23:11
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:22:11
|
LL | match x {}
| ^
@@ -18,7 +18,7 @@
|
error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty
- --> $DIR/indirect_match_with_exhaustive_patterns.rs:27:11
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:26:11
|
LL | match x {}
| ^
@@ -37,7 +37,7 @@
|
error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty
- --> $DIR/indirect_match_with_exhaustive_patterns.rs:31:11
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:30:11
|
LL | match x {}
| ^
@@ -56,7 +56,7 @@
|
error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty
- --> $DIR/indirect_match_with_exhaustive_patterns.rs:37:11
+ --> $DIR/indirect_match_with_exhaustive_patterns.rs:36:11
|
LL | match x {}
| ^
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
index efaec0e..32f5f50 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns_same_crate.rs
@@ -1,7 +1,6 @@
//@ check-pass
#![deny(unreachable_patterns)]
-#![feature(min_exhaustive_patterns)]
#![feature(never_type)]
#[non_exhaustive]
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
index ebbdfba..04f7fe2 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.rs
@@ -1,3 +1,4 @@
+//@ check-pass
#![feature(never_type)]
#[non_exhaustive]
@@ -27,15 +28,15 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
}
fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+ match x {}
}
fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
deleted file mode 100644
index 7a12aca..0000000
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr
+++ /dev/null
@@ -1,64 +0,0 @@
-error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
- --> $DIR/match_same_crate.rs:30:11
- |
-LL | match x {}
- | ^
- |
-note: `UninhabitedStruct` defined here
- --> $DIR/match_same_crate.rs:8:12
- |
-LL | pub struct UninhabitedStruct {
- | ^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
- --> $DIR/match_same_crate.rs:34:11
- |
-LL | match x {}
- | ^
- |
-note: `UninhabitedTupleStruct` defined here
- --> $DIR/match_same_crate.rs:13:12
- |
-LL | pub struct UninhabitedTupleStruct(!);
- | ^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedTupleStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- --> $DIR/match_same_crate.rs:38:11
- |
-LL | match x {}
- | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- |
-note: `UninhabitedVariants` defined here
- --> $DIR/match_same_crate.rs:15:10
- |
-LL | pub enum UninhabitedVariants {
- | ^^^^^^^^^^^^^^^^^^^
-LL | #[non_exhaustive] Tuple(!),
- | ----- not covered
-LL | #[non_exhaustive] Struct { x: ! }
- | ------ not covered
- = note: the matched value is of type `UninhabitedVariants`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match x {
-LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
-LL ~ }
- |
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
index 69b15fc..108cac7 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
@@ -1,6 +1,5 @@
//@ aux-build:uninhabited.rs
#![deny(unreachable_patterns)]
-#![feature(min_exhaustive_patterns)]
#![feature(never_type)]
extern crate uninhabited;
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
index 19e2546..0c8b14a 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
- --> $DIR/match_with_exhaustive_patterns.rs:22:11
+ --> $DIR/match_with_exhaustive_patterns.rs:21:11
|
LL | match x {}
| ^
@@ -18,7 +18,7 @@
|
error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
- --> $DIR/match_with_exhaustive_patterns.rs:26:11
+ --> $DIR/match_with_exhaustive_patterns.rs:25:11
|
LL | match x {}
| ^
@@ -37,7 +37,7 @@
|
error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
- --> $DIR/match_with_exhaustive_patterns.rs:30:11
+ --> $DIR/match_with_exhaustive_patterns.rs:29:11
|
LL | match x {}
| ^
@@ -56,7 +56,7 @@
|
error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- --> $DIR/match_with_exhaustive_patterns.rs:34:11
+ --> $DIR/match_with_exhaustive_patterns.rs:33:11
|
LL | match x {}
| ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
index bbc5d03..468703c 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
@@ -1,7 +1,6 @@
//@ check-pass
#![deny(unreachable_patterns)]
-#![feature(min_exhaustive_patterns)]
#![feature(never_type)]
#[non_exhaustive]
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
index 0007614..be55ad51 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
@@ -1,7 +1,6 @@
//@ aux-build:uninhabited.rs
//@ build-pass (FIXME(62277): could be check-pass?)
#![deny(unreachable_patterns)]
-#![feature(min_exhaustive_patterns)]
extern crate uninhabited;
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
index 898be87..1194d7b 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
@@ -1,5 +1,4 @@
#![deny(unreachable_patterns)]
-#![feature(min_exhaustive_patterns)]
#![feature(never_type)]
#[non_exhaustive]
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
index d5192a7..c399bb9 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
@@ -1,5 +1,5 @@
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:52:9
+ --> $DIR/patterns_same_crate.rs:51:9
|
LL | Some(_x) => (),
| ^^^^^^^^
@@ -12,7 +12,7 @@
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:57:9
+ --> $DIR/patterns_same_crate.rs:56:9
|
LL | Some(_x) => (),
| ^^^^^^^^
@@ -20,7 +20,7 @@
= note: this pattern matches no values because `UninhabitedVariants` is uninhabited
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:61:15
+ --> $DIR/patterns_same_crate.rs:60:15
|
LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,7 +28,7 @@
= note: this pattern matches no values because `!` is uninhabited
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:65:15
+ --> $DIR/patterns_same_crate.rs:64:15
|
LL | while let Some(_x) = uninhabited_struct() {
| ^^^^^^^^
@@ -36,7 +36,7 @@
= note: this pattern matches no values because `UninhabitedStruct` is uninhabited
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:68:15
+ --> $DIR/patterns_same_crate.rs:67:15
|
LL | while let Some(_x) = uninhabited_tuple_struct() {
| ^^^^^^^^
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
index de002ef..fec4e75 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs
@@ -34,6 +34,7 @@ fn foo() {
#[target_feature(enable = "sse2")]
fn bar() {
+ sse2();
avx_bmi2();
//~^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
Quux.avx_bmi2();
@@ -43,7 +44,6 @@ fn bar() {
#[target_feature(enable = "avx")]
fn baz() {
sse2();
- //~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
avx_bmi2();
//~^ ERROR call to function `avx_bmi2` with `#[target_feature]` is unsafe
Quux.avx_bmi2();
@@ -54,7 +54,8 @@ fn baz() {
#[target_feature(enable = "bmi2")]
fn qux() {
sse2();
- //~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
+ avx_bmi2();
+ Quux.avx_bmi2();
}
const _: () = sse2();
@@ -64,8 +65,6 @@ fn qux() {
//~^ ERROR call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe
#[deny(unsafe_op_in_unsafe_fn)]
-#[target_feature(enable = "avx")]
-#[target_feature(enable = "bmi2")]
unsafe fn needs_unsafe_block() {
sse2();
//~^ ERROR call to function `sse2` with `#[target_feature]` is unsafe
diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
index 537819a..1ddf05b 100644
--- a/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
+++ b/tests/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr
@@ -24,7 +24,7 @@
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:37:5
+ --> $DIR/safe-calls.rs:38:5
|
LL | avx_bmi2();
| ^^^^^^^^^^ call to function with `#[target_feature]`
@@ -32,22 +32,13 @@
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
error[E0133]: call to function `Quux::avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:39:5
+ --> $DIR/safe-calls.rs:40:5
|
LL | Quux.avx_bmi2();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
|
= help: in order for the call to be safe, the context requires the following additional target features: avx and bmi2
-error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:45:5
- |
-LL | sse2();
- | ^^^^^^ call to function with `#[target_feature]`
- |
- = help: in order for the call to be safe, the context requires the following additional target feature: sse2
- = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
-
error[E0133]: call to function `avx_bmi2` with `#[target_feature]` is unsafe and requires unsafe function or block
--> $DIR/safe-calls.rs:47:5
|
@@ -65,16 +56,7 @@
= help: in order for the call to be safe, the context requires the following additional target feature: bmi2
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:56:5
- |
-LL | sse2();
- | ^^^^^^ call to function with `#[target_feature]`
- |
- = help: in order for the call to be safe, the context requires the following additional target feature: sse2
- = note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
-
-error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:60:15
+ --> $DIR/safe-calls.rs:61:15
|
LL | const _: () = sse2();
| ^^^^^^ call to function with `#[target_feature]`
@@ -83,7 +65,7 @@
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
error[E0133]: call to function `sse2_and_fxsr` with `#[target_feature]` is unsafe and requires unsafe function or block
- --> $DIR/safe-calls.rs:63:15
+ --> $DIR/safe-calls.rs:64:15
|
LL | const _: () = sse2_and_fxsr();
| ^^^^^^^^^^^^^^^ call to function with `#[target_feature]`
@@ -92,7 +74,7 @@
= note: the fxsr and sse2 target features being enabled in the build configuration does not remove the requirement to list them in `#[target_feature]`
error[E0133]: call to function `sse2` with `#[target_feature]` is unsafe and requires unsafe block
- --> $DIR/safe-calls.rs:70:5
+ --> $DIR/safe-calls.rs:69:5
|
LL | sse2();
| ^^^^^^ call to function with `#[target_feature]`
@@ -101,16 +83,16 @@
= help: in order for the call to be safe, the context requires the following additional target feature: sse2
= note: the sse2 target feature being enabled in the build configuration does not remove the requirement to list it in `#[target_feature]`
note: an unsafe function restricts its caller, but its body is safe by default
- --> $DIR/safe-calls.rs:69:1
+ --> $DIR/safe-calls.rs:68:1
|
LL | unsafe fn needs_unsafe_block() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: the lint level is defined here
- --> $DIR/safe-calls.rs:66:8
+ --> $DIR/safe-calls.rs:67:8
|
LL | #[deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 12 previous errors
+error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr
index 9d1ca5d..b451555 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.precise.stderr
@@ -40,7 +40,7 @@
LL | const fn a<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:54:5
|
LL | #[const_trait]
@@ -49,7 +49,7 @@
LL | fn foo();
| - expected 0 const parameters
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:54:5
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr
index 2f93f9a..296614f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.stock.stderr
@@ -40,7 +40,7 @@
LL | const fn a<T: ~const Destruct>(_: T) {}
| ^^^^^^^^
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:54:5
|
LL | #[const_trait]
@@ -49,7 +49,7 @@
LL | fn foo();
| - expected 0 const parameters
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-drop.rs:54:5
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
index b4c4cf0..7643697 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-bound-non-const-specialized-bound.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-default-bound-non-const-specialized-bound.rs:16:1
|
LL | #[const_trait]
@@ -16,7 +16,7 @@
LL | | T: Specialize,
| |__________________^
-error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1
|
LL | #[const_trait]
@@ -25,7 +25,7 @@
LL | fn baz();
| - expected 0 const parameters
-error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-default-bound-non-const-specialized-bound.rs:36:1
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr
index cabf201..9b2ae8d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/const-default-const-specialized.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-default-const-specialized.rs:10:1
|
LL | #[const_trait]
@@ -7,7 +7,7 @@
LL | fn value() -> u32;
| - expected 0 const parameters
-error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const-default-const-specialized.rs:10:1
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr
index 52c8708..18a2504 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/default-keyword.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/default-keyword.rs:7:1
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr
index 1aa3463..ecdc7b9 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95186-specialize-on-tilde-const.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1
|
LL | #[const_trait]
@@ -7,7 +7,7 @@
LL | fn foo();
| - expected 0 const parameters
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95186-specialize-on-tilde-const.rs:14:1
|
LL | #[const_trait]
@@ -18,7 +18,7 @@
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1
|
LL | #[const_trait]
@@ -27,7 +27,7 @@
LL | fn bar() {}
| - expected 0 const parameters
-error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95186-specialize-on-tilde-const.rs:30:1
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr
index 0e0f391..6679bb4 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/issue-95187-same-trait-bound-different-constness.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1
|
LL | #[const_trait]
@@ -7,7 +7,7 @@
LL | fn bar();
| - expected 0 const parameters
-error[E0049]: method `bar` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `bar` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95187-same-trait-bound-different-constness.rs:18:1
|
LL | #[const_trait]
@@ -18,7 +18,7 @@
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1
|
LL | #[const_trait]
@@ -27,7 +27,7 @@
LL | fn baz();
| - expected 0 const parameters
-error[E0049]: method `baz` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `baz` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/issue-95187-same-trait-bound-different-constness.rs:38:1
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr
index d49beb9..7f36392 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specialization/non-const-default-const-specialized.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/non-const-default-const-specialized.rs:9:1
|
LL | #[const_trait]
@@ -7,7 +7,7 @@
LL | fn value() -> u32;
| - expected 0 const parameters
-error[E0049]: method `value` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `value` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/non-const-default-const-specialized.rs:9:1
|
LL | #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr
index d082cd6..bf273f3 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/specializing-constness-2.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/specializing-constness-2.rs:9:1
|
LL | #[const_trait]
@@ -7,7 +7,7 @@
LL | fn a() -> u32;
| - expected 0 const parameters
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/specializing-constness-2.rs:9:1
|
LL | #[const_trait]
diff --git a/tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/auxiliary/edition-lint-infer-outlives-macro.rs
similarity index 100%
rename from tests/ui/rust-2018/auxiliary/edition-lint-infer-outlives-macro.rs
rename to tests/ui/rust-2018/edition-lint-inter-outlives/auxiliary/edition-lint-infer-outlives-macro.rs
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.fixed
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.fixed
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.fixed
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.rs
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.rs
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.rs
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives-macro.stderr
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.rs
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives-multispan.rs
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.rs
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives-multispan.stderr
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.fixed
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives.fixed
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.fixed
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.rs
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives.rs
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.rs
diff --git a/tests/ui/rust-2018/edition-lint-infer-outlives.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.stderr
similarity index 100%
rename from tests/ui/rust-2018/edition-lint-infer-outlives.stderr
rename to tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives.stderr
diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed
new file mode 100644
index 0000000..7b9fac8
--- /dev/null
+++ b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.fixed
@@ -0,0 +1,41 @@
+//@ run-rustfix
+//@ check-pass
+#![deny(explicit_outlives_requirements)]
+
+pub trait TypeCx {
+ type Ty;
+}
+
+pub struct Pat<Cx: TypeCx> {
+ pub ty: Cx::Ty,
+}
+
+// Simple recursive case: no warning
+pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> {
+ pub pat: Pat<MyTypeContextSimpleRecursive<'thir, 'tcx>>,
+}
+impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextSimpleRecursive<'thir, 'tcx> {
+ type Ty = ();
+}
+
+// Non-recursive case: we want a warning
+pub struct MyTypeContextNotRecursive<'thir, 'tcx: 'thir> {
+ pub tcx: &'tcx (),
+ pub thir: &'thir (),
+}
+impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextNotRecursive<'thir, 'tcx> {
+ type Ty = ();
+}
+
+
+// Mixed-recursive case: we want a warning
+pub struct MyTypeContextMixedRecursive<'thir, 'tcx: 'thir> {
+ pub pat: Pat<MyTypeContextMixedRecursive<'thir, 'tcx>>,
+ pub tcx: &'tcx (),
+ pub thir: &'thir (),
+}
+impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> {
+ type Ty = ();
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs
new file mode 100644
index 0000000..7b9fac8
--- /dev/null
+++ b/tests/ui/rust-2018/edition-lint-inter-outlives/explicit-outlives-recursive-119228.rs
@@ -0,0 +1,41 @@
+//@ run-rustfix
+//@ check-pass
+#![deny(explicit_outlives_requirements)]
+
+pub trait TypeCx {
+ type Ty;
+}
+
+pub struct Pat<Cx: TypeCx> {
+ pub ty: Cx::Ty,
+}
+
+// Simple recursive case: no warning
+pub struct MyTypeContextSimpleRecursive<'thir, 'tcx: 'thir> {
+ pub pat: Pat<MyTypeContextSimpleRecursive<'thir, 'tcx>>,
+}
+impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextSimpleRecursive<'thir, 'tcx> {
+ type Ty = ();
+}
+
+// Non-recursive case: we want a warning
+pub struct MyTypeContextNotRecursive<'thir, 'tcx: 'thir> {
+ pub tcx: &'tcx (),
+ pub thir: &'thir (),
+}
+impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextNotRecursive<'thir, 'tcx> {
+ type Ty = ();
+}
+
+
+// Mixed-recursive case: we want a warning
+pub struct MyTypeContextMixedRecursive<'thir, 'tcx: 'thir> {
+ pub pat: Pat<MyTypeContextMixedRecursive<'thir, 'tcx>>,
+ pub tcx: &'tcx (),
+ pub thir: &'thir (),
+}
+impl<'thir, 'tcx: 'thir> TypeCx for MyTypeContextMixedRecursive<'thir, 'tcx> {
+ type Ty = ();
+}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs
new file mode 100644
index 0000000..7bf5118
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs
@@ -0,0 +1,17 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@ check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+
+use std::future::Future;
+
+fn main() {
+ core::pin::pin!(async {}).poll(&mut context());
+}
+
+fn context() -> core::task::Context<'static> {
+ loop {}
+}
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed
new file mode 100644
index 0000000..44850c8
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed
@@ -0,0 +1,21 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn poll(&self, _ctx: &mut core::task::Context<'_>) {}
+}
+impl<T> Meow for T {}
+fn main() {
+ Meow::poll(&core::pin::pin!(async {}), &mut context());
+ //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
+
+fn context() -> core::task::Context<'static> {
+ loop {}
+}
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr
new file mode 100644
index 0000000..496b319
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr
@@ -0,0 +1,16 @@
+error: trait method `poll` will become ambiguous in Rust 2024
+ --> $DIR/future-poll-async-block.rs:14:5
+ |
+LL | core::pin::pin!(async {}).poll(&mut context());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())`
+ |
+ = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
+note: the lint level is defined here
+ --> $DIR/future-poll-async-block.rs:8:9
+ |
+LL | #![deny(rust_2024_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs
new file mode 100644
index 0000000..614e4c7
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs
@@ -0,0 +1,21 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn poll(&self, _ctx: &mut core::task::Context<'_>) {}
+}
+impl<T> Meow for T {}
+fn main() {
+ core::pin::pin!(async {}).poll(&mut context());
+ //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
+
+fn context() -> core::task::Context<'static> {
+ loop {}
+}
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed
new file mode 100644
index 0000000..c96d1dc
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed
@@ -0,0 +1,21 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn poll(&self) {}
+}
+impl<T> Meow for T {}
+fn main() {
+ // This is a deliberate false positive.
+ // While `()` does not implement `Future` and can therefore not be ambiguous, we
+ // do not check that in the lint, as that introduces additional complexities.
+ // Just checking whether the self type is `Pin<&mut _>` is enough.
+ Meow::poll(&core::pin::pin!(()));
+ //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr
new file mode 100644
index 0000000..020a00c
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr
@@ -0,0 +1,16 @@
+error: trait method `poll` will become ambiguous in Rust 2024
+ --> $DIR/future-poll-not-future-pinned.rs:18:5
+ |
+LL | core::pin::pin!(()).poll();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(()))`
+ |
+ = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
+note: the lint level is defined here
+ --> $DIR/future-poll-not-future-pinned.rs:8:9
+ |
+LL | #![deny(rust_2024_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs
new file mode 100644
index 0000000..21b170a
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs
@@ -0,0 +1,21 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn poll(&self) {}
+}
+impl<T> Meow for T {}
+fn main() {
+ // This is a deliberate false positive.
+ // While `()` does not implement `Future` and can therefore not be ambiguous, we
+ // do not check that in the lint, as that introduces additional complexities.
+ // Just checking whether the self type is `Pin<&mut _>` is enough.
+ core::pin::pin!(()).poll();
+ //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs
new file mode 100644
index 0000000..899b69e
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs
@@ -0,0 +1,15 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@ check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn poll(&self) {}
+}
+impl<T> Meow for T {}
+fn main() {
+ // As the self type here is not `Pin<&mut _>`, the lint does not fire.
+ ().poll();
+}
diff --git a/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs
new file mode 100644
index 0000000..b6a5d27
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs
@@ -0,0 +1,17 @@
+//@ edition: 2021
+
+#![deny(rust_2024_compatibility)]
+
+trait Meow {
+ fn poll(&self, _ctx: &mut core::task::Context<'_>) {}
+}
+impl<T> Meow for T {}
+fn main() {
+ core::pin::pin!(async {}).poll(&mut context());
+ //~^ ERROR trait method `poll` will become ambiguous in Rust 2024
+ //~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
+
+fn context() -> core::task::Context<'static> {
+ loop {}
+}
diff --git a/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr
new file mode 100644
index 0000000..5865029
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr
@@ -0,0 +1,17 @@
+error: trait method `poll` will become ambiguous in Rust 2024
+ --> $DIR/in_2024_compatibility.rs:10:5
+ |
+LL | core::pin::pin!(async {}).poll(&mut context());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())`
+ |
+ = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
+note: the lint level is defined here
+ --> $DIR/in_2024_compatibility.rs:3:9
+ |
+LL | #![deny(rust_2024_compatibility)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `#[deny(rust_2024_prelude_collisions)]` implied by `#[deny(rust_2024_compatibility)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed
new file mode 100644
index 0000000..0b0873e
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed
@@ -0,0 +1,29 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn into_future(&self) {}
+}
+impl Meow for Cat {}
+
+struct Cat;
+
+impl core::future::IntoFuture for Cat {
+ type Output = ();
+ type IntoFuture = core::future::Ready<()>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ core::future::ready(())
+ }
+}
+
+fn main() {
+ Meow::into_future(&Cat);
+ //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr
new file mode 100644
index 0000000..b74e80e
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr
@@ -0,0 +1,16 @@
+error: trait method `into_future` will become ambiguous in Rust 2024
+ --> $DIR/into-future-adt.rs:26:5
+ |
+LL | Cat.into_future();
+ | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)`
+ |
+ = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
+note: the lint level is defined here
+ --> $DIR/into-future-adt.rs:8:9
+ |
+LL | #![deny(rust_2024_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.rs b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs
new file mode 100644
index 0000000..0db7093
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs
@@ -0,0 +1,29 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn into_future(&self) {}
+}
+impl Meow for Cat {}
+
+struct Cat;
+
+impl core::future::IntoFuture for Cat {
+ type Output = ();
+ type IntoFuture = core::future::Ready<()>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ core::future::ready(())
+ }
+}
+
+fn main() {
+ Cat.into_future();
+ //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs
new file mode 100644
index 0000000..6bc2ea3
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs
@@ -0,0 +1,24 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@ check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+
+use core::future::IntoFuture;
+
+struct Cat;
+
+impl IntoFuture for Cat {
+ type Output = ();
+ type IntoFuture = core::future::Ready<()>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ core::future::ready(())
+ }
+}
+
+fn main() {
+ let _ = Cat.into_future();
+}
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed
new file mode 100644
index 0000000..a798014
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed
@@ -0,0 +1,23 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn into_future(&self) {}
+}
+impl Meow for Cat {}
+
+struct Cat;
+
+fn main() {
+ // This is a false positive, but it should be rare enough to not matter, and checking whether
+ // it implements the trait can have other nontrivial consequences, so it was decided to accept
+ // this.
+ Meow::into_future(&Cat);
+ //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr
new file mode 100644
index 0000000..6ea4580
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr
@@ -0,0 +1,16 @@
+error: trait method `into_future` will become ambiguous in Rust 2024
+ --> $DIR/into-future-not-into-future.rs:20:5
+ |
+LL | Cat.into_future();
+ | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)`
+ |
+ = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/prelude.html>
+note: the lint level is defined here
+ --> $DIR/into-future-not-into-future.rs:8:9
+ |
+LL | #![deny(rust_2024_prelude_collisions)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs
new file mode 100644
index 0000000..23e81cf
--- /dev/null
+++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs
@@ -0,0 +1,23 @@
+//@ revisions: e2021 e2024
+//@[e2021] edition: 2021
+//@[e2021] run-rustfix
+//@[e2024] edition: 2024
+//@[e2024] compile-flags: -Zunstable-options
+//@[e2024] check-pass
+
+#![deny(rust_2024_prelude_collisions)]
+trait Meow {
+ fn into_future(&self) {}
+}
+impl Meow for Cat {}
+
+struct Cat;
+
+fn main() {
+ // This is a false positive, but it should be rare enough to not matter, and checking whether
+ // it implements the trait can have other nontrivial consequences, so it was decided to accept
+ // this.
+ Cat.into_future();
+ //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024
+ //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024!
+}
diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs
index 6773df5..674b78d 100644
--- a/tests/ui/rust-2024/safe-outside-extern.rs
+++ b/tests/ui/rust-2024/safe-outside-extern.rs
@@ -1,29 +1,21 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
safe fn foo() {}
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
safe static FOO: i32 = 1;
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
trait Foo {
safe fn foo();
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
- //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
}
impl Foo for () {
safe fn foo() {}
//~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
- //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
}
type FnPtr = safe fn(i32, i32) -> i32;
//~^ ERROR: function pointers cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
unsafe static LOL: u8 = 0;
//~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
diff --git a/tests/ui/rust-2024/safe-outside-extern.stderr b/tests/ui/rust-2024/safe-outside-extern.stderr
new file mode 100644
index 0000000..19d7c5f
--- /dev/null
+++ b/tests/ui/rust-2024/safe-outside-extern.stderr
@@ -0,0 +1,38 @@
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+ --> $DIR/safe-outside-extern.rs:1:1
+ |
+LL | safe fn foo() {}
+ | ^^^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+ --> $DIR/safe-outside-extern.rs:4:1
+ |
+LL | safe static FOO: i32 = 1;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+ --> $DIR/safe-outside-extern.rs:8:5
+ |
+LL | safe fn foo();
+ | ^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+ --> $DIR/safe-outside-extern.rs:13:5
+ |
+LL | safe fn foo() {}
+ | ^^^^^^^^^^^^^^^^
+
+error: function pointers cannot be declared with `safe` safety qualifier
+ --> $DIR/safe-outside-extern.rs:17:14
+ |
+LL | type FnPtr = safe fn(i32, i32) -> i32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+ --> $DIR/safe-outside-extern.rs:20:1
+ |
+LL | unsafe static LOL: u8 = 0;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
index 3a99caa..77554da 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
@@ -1,5 +1,5 @@
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
- --> $DIR/extern-items-unsafe.rs:14:5
+ --> $DIR/extern-items-unsafe.rs:12:5
|
LL | test1(TEST1);
| ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@
= note: consult the function's documentation for information on how to avoid undefined behavior
error[E0133]: use of extern static is unsafe and requires unsafe function or block
- --> $DIR/extern-items-unsafe.rs:14:11
+ --> $DIR/extern-items-unsafe.rs:12:11
|
LL | test1(TEST1);
| ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
index fcf937b..33b7527 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
@@ -1,5 +1,5 @@
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
- --> $DIR/extern-items-unsafe.rs:14:5
+ --> $DIR/extern-items-unsafe.rs:12:5
|
LL | test1(TEST1);
| ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@
= note: consult the function's documentation for information on how to avoid undefined behavior
error[E0133]: use of extern static is unsafe and requires unsafe block
- --> $DIR/extern-items-unsafe.rs:14:11
+ --> $DIR/extern-items-unsafe.rs:12:11
|
LL | test1(TEST1);
| ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
index ad569a2..721e07a 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
@@ -3,8 +3,6 @@
//@[edition2024] edition:2024
//@[edition2024] compile-flags: -Zunstable-options
-#![feature(unsafe_extern_blocks)]
-
unsafe extern "C" {
static TEST1: i32;
fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
index d456cfc..8ef7c2c 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
@@ -1,5 +1,5 @@
error: extern blocks must be unsafe
- --> $DIR/extern-items.rs:9:1
+ --> $DIR/extern-items.rs:7:1
|
LL | / extern "C" {
LL | |
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
index 16fa1bb..08805c3 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
@@ -4,8 +4,6 @@
//@[edition2024] edition:2024
//@[edition2024] compile-flags: -Zunstable-options
-#![feature(unsafe_extern_blocks)]
-
extern "C" {
//[edition2024]~^ ERROR extern blocks must be unsafe
static TEST1: i32;
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
index 57c03e4..67df8c1 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
@@ -1,6 +1,3 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
trait Bar {}
safe impl Bar for () { }
//~^ ERROR expected one of `!` or `::`, found keyword `impl`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
similarity index 83%
rename from tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr
rename to tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
index 80e7a45..f102172 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
@@ -1,5 +1,5 @@
error: expected one of `!` or `::`, found keyword `impl`
- --> $DIR/safe-impl-trait.rs:5:6
+ --> $DIR/safe-impl-trait.rs:2:6
|
LL | safe impl Bar for () { }
| ^^^^ expected one of `!` or `::`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
index 74cd562..b0b8a8b 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
@@ -4,8 +4,6 @@
//@[edition2024] compile-flags: -Zunstable-options
//@ check-pass
-#![feature(unsafe_extern_blocks)]
-
unsafe extern "C" {
safe static TEST1: i32;
safe fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
index e73cb45..52773b4 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
@@ -1,6 +1,3 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
safe trait Foo {}
//~^ ERROR expected one of `!` or `::`, found keyword `trait`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr
new file mode 100644
index 0000000..1733336
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found keyword `trait`
+ --> $DIR/safe-trait.rs:1:6
+ |
+LL | safe trait Foo {}
+ | ^^^^^ expected one of `!` or `::`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
index e906133..9379798 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
@@ -1,5 +1,5 @@
error: items in unadorned `extern` blocks cannot have safety qualifiers
- --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+ --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5
|
LL | safe static TEST1: i32;
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@
| ++++++
error: items in unadorned `extern` blocks cannot have safety qualifiers
- --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+ --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
|
LL | safe fn test1(i: i32);
| ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
index 1207ee1..e9db600 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
@@ -1,5 +1,5 @@
error: extern blocks must be unsafe
- --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1
+ --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1
|
LL | / extern "C" {
LL | |
@@ -11,7 +11,7 @@
| |_^
error: items in unadorned `extern` blocks cannot have safety qualifiers
- --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+ --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5
|
LL | safe static TEST1: i32;
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@
| ++++++
error: items in unadorned `extern` blocks cannot have safety qualifiers
- --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+ --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
|
LL | safe fn test1(i: i32);
| ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
index 11f55cb..4badb50 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
@@ -3,8 +3,6 @@
//@[edition2024] edition:2024
//@[edition2024] compile-flags: -Zunstable-options
-#![feature(unsafe_extern_blocks)]
-
extern "C" {
//[edition2024]~^ ERROR extern blocks must be unsafe
safe static TEST1: i32;
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
index 10c1975..f686809 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
@@ -1,6 +1,5 @@
//@ run-rustfix
-#![feature(unsafe_extern_blocks)]
#![deny(missing_unsafe_on_extern)]
#![allow(unused)]
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
index b81e52d..00f1cbd 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
@@ -1,6 +1,5 @@
//@ run-rustfix
-#![feature(unsafe_extern_blocks)]
#![deny(missing_unsafe_on_extern)]
#![allow(unused)]
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
index 0a3c2cd..bb1d068 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
@@ -1,5 +1,5 @@
error: extern blocks should be unsafe
- --> $DIR/unsafe-extern-suggestion.rs:7:1
+ --> $DIR/unsafe-extern-suggestion.rs:6:1
|
LL | extern "C" {
| ^
@@ -16,7 +16,7 @@
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
= note: for more information, see issue #123743 <https://github.com/rust-lang/rust/issues/123743>
note: the lint level is defined here
- --> $DIR/unsafe-extern-suggestion.rs:4:9
+ --> $DIR/unsafe-extern-suggestion.rs:3:9
|
LL | #![deny(missing_unsafe_on_extern)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
index 8bb7ffe..e3626bb 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
@@ -1,5 +1,5 @@
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
- --> $DIR/unsafe-items.rs:20:5
+ --> $DIR/unsafe-items.rs:18:5
|
LL | test1(TEST1);
| ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@
= note: consult the function's documentation for information on how to avoid undefined behavior
error[E0133]: use of extern static is unsafe and requires unsafe function or block
- --> $DIR/unsafe-items.rs:20:11
+ --> $DIR/unsafe-items.rs:18:11
|
LL | test1(TEST1);
| ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
index 9a30142..89bc501 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
@@ -1,5 +1,5 @@
error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
- --> $DIR/unsafe-items.rs:20:5
+ --> $DIR/unsafe-items.rs:18:5
|
LL | test1(TEST1);
| ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@
= note: consult the function's documentation for information on how to avoid undefined behavior
error[E0133]: use of extern static is unsafe and requires unsafe block
- --> $DIR/unsafe-items.rs:20:11
+ --> $DIR/unsafe-items.rs:18:11
|
LL | test1(TEST1);
| ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
index 9066953..dc2bae8 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
@@ -3,8 +3,6 @@
//@[edition2024] edition:2024
//@[edition2024] compile-flags: -Zunstable-options
-#![feature(unsafe_extern_blocks)]
-
unsafe extern "C" {
unsafe static TEST1: i32;
unsafe fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
index 2ff595c..857d34e 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
@@ -1,6 +1,5 @@
//@ run-rustfix
-#![feature(unsafe_extern_blocks)]
#![allow(dead_code)]
unsafe extern "C" {
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
index 6fe43f7..edab985 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
@@ -1,6 +1,5 @@
//@ run-rustfix
-#![feature(unsafe_extern_blocks)]
#![allow(dead_code)]
extern "C" {
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
index 05d23d0..073245e 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
@@ -1,5 +1,5 @@
error: items in unadorned `extern` blocks cannot have safety qualifiers
- --> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5
+ --> $DIR/unsafe-on-extern-block-issue-126756.rs:6:5
|
LL | unsafe fn foo();
| ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-assoc-ty-lifetime-issue-123053.rs
rename to tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs
diff --git a/tests/ui/sanitizer/cfi-async-closures.rs b/tests/ui/sanitizer/cfi/async-closures.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-async-closures.rs
rename to tests/ui/sanitizer/cfi/async-closures.rs
diff --git a/tests/ui/sanitizer/cfi/can-reveal-opaques.rs b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs
new file mode 100644
index 0000000..55988a6
--- /dev/null
+++ b/tests/ui/sanitizer/cfi/can-reveal-opaques.rs
@@ -0,0 +1,44 @@
+//@ needs-sanitizer-cfi
+//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi
+//@ no-prefer-dynamic
+//@ only-x86_64-unknown-linux-gnu
+//@ build-pass
+
+// See comment below for why this test exists.
+
+trait Tr<U> {
+ type Projection;
+}
+
+impl<F, U> Tr<U> for F
+where
+ F: Fn() -> U
+{
+ type Projection = U;
+}
+
+fn test<B: Tr<U>, U>(b: B) -> B::Projection
+{
+ todo!()
+}
+
+fn main() {
+ fn rpit_fn() -> impl Sized {}
+
+ // When CFI runs, it tries to compute the signature of the call. This
+ // ends up giving us a signature of:
+ // `fn test::<rpit_fn, ()>() -> <rpit_fn as Tr<()>>::Projection`,
+ // where `rpit_fn` is the ZST FnDef for the function. However, we were
+ // previously using a Reveal::UserFacing param-env. This means that the
+ // `<rpit_fn as Tr<()>>::Projection` return type is impossible to normalize,
+ // since it would require proving `rpit_fn: Fn() -> ()`, but we cannot
+ // prove that the `impl Sized` opaque is `()` with a user-facing param-env.
+ // This leads to a normalization error, and then an ICE.
+ //
+ // Side-note:
+ // So why is the second generic of `test` "`()`", and not the
+ // `impl Sized` since we inferred it from the return type of `rpit_fn`
+ // during typeck? Well, that's because we're using the generics from the
+ // terminator of the MIR, which has had the RevealAll pass performed on it.
+ let _ = test(rpit_fn);
+}
diff --git a/tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.rs b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.rs
rename to tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.rs
diff --git a/tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.stderr b/tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-canonical-jump-tables-requires-cfi.stderr
rename to tests/ui/sanitizer/cfi/canonical-jump-tables-requires-cfi.stderr
diff --git a/tests/ui/sanitizer/cfi-closures.rs b/tests/ui/sanitizer/cfi/closures.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-closures.rs
rename to tests/ui/sanitizer/cfi/closures.rs
diff --git a/tests/ui/sanitizer/cfi-complex-receiver.rs b/tests/ui/sanitizer/cfi/complex-receiver.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-complex-receiver.rs
rename to tests/ui/sanitizer/cfi/complex-receiver.rs
diff --git a/tests/ui/sanitizer/cfi-coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-coroutine.rs
rename to tests/ui/sanitizer/cfi/coroutine.rs
diff --git a/tests/ui/sanitizer/cfi-drop-in-place.rs b/tests/ui/sanitizer/cfi/drop-in-place.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-drop-in-place.rs
rename to tests/ui/sanitizer/cfi/drop-in-place.rs
diff --git a/tests/ui/sanitizer/cfi-drop-no-principal.rs b/tests/ui/sanitizer/cfi/drop-no-principal.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-drop-no-principal.rs
rename to tests/ui/sanitizer/cfi/drop-no-principal.rs
diff --git a/tests/ui/sanitizer/cfi-fn-ptr.rs b/tests/ui/sanitizer/cfi/fn-ptr.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-fn-ptr.rs
rename to tests/ui/sanitizer/cfi/fn-ptr.rs
diff --git a/tests/ui/sanitizer/cfi-generalize-pointers-attr-cfg.rs b/tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-generalize-pointers-attr-cfg.rs
rename to tests/ui/sanitizer/cfi/generalize-pointers-attr-cfg.rs
diff --git a/tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.rs b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.rs
rename to tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.rs
diff --git a/tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.stderr b/tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-generalize-pointers-requires-cfi.stderr
rename to tests/ui/sanitizer/cfi/generalize-pointers-requires-cfi.stderr
diff --git a/tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.rs b/tests/ui/sanitizer/cfi/invalid-attr-encoding.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.rs
rename to tests/ui/sanitizer/cfi/invalid-attr-encoding.rs
diff --git a/tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.stderr b/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr
similarity index 79%
rename from tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.stderr
rename to tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr
index 93ec134..1aa6bef 100644
--- a/tests/ui/sanitizer/cfi-invalid-attr-cfi-encoding.stderr
+++ b/tests/ui/sanitizer/cfi/invalid-attr-encoding.stderr
@@ -1,5 +1,5 @@
error: malformed `cfi_encoding` attribute input
- --> $DIR/cfi-invalid-attr-cfi-encoding.rs:10:1
+ --> $DIR/invalid-attr-encoding.rs:10:1
|
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
diff --git a/tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.aarch64.stderr b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.aarch64.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.aarch64.stderr
rename to tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.aarch64.stderr
diff --git a/tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.rs b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.rs
rename to tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.rs
diff --git a/tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.x86_64.stderr b/tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.x86_64.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-is-incompatible-with-kcfi.x86_64.stderr
rename to tests/ui/sanitizer/cfi/is-incompatible-with-kcfi.x86_64.stderr
diff --git a/tests/ui/sanitizer/cfi-normalize-integers-attr-cfg.rs b/tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-normalize-integers-attr-cfg.rs
rename to tests/ui/sanitizer/cfi/normalize-integers-attr-cfg.rs
diff --git a/tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.rs b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.rs
rename to tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.rs
diff --git a/tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.stderr b/tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-normalize-integers-requires-cfi.stderr
rename to tests/ui/sanitizer/cfi/normalize-integers-requires-cfi.stderr
diff --git a/tests/ui/sanitizer/cfi-requires-lto.rs b/tests/ui/sanitizer/cfi/requires-lto.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-requires-lto.rs
rename to tests/ui/sanitizer/cfi/requires-lto.rs
diff --git a/tests/ui/sanitizer/cfi-requires-lto.stderr b/tests/ui/sanitizer/cfi/requires-lto.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-requires-lto.stderr
rename to tests/ui/sanitizer/cfi/requires-lto.stderr
diff --git a/tests/ui/sanitizer/cfi-self-ref.rs b/tests/ui/sanitizer/cfi/self-ref.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-self-ref.rs
rename to tests/ui/sanitizer/cfi/self-ref.rs
diff --git a/tests/ui/sanitizer/cfi/sized-associated-ty.rs b/tests/ui/sanitizer/cfi/sized-associated-ty.rs
new file mode 100644
index 0000000..f5b4e22
--- /dev/null
+++ b/tests/ui/sanitizer/cfi/sized-associated-ty.rs
@@ -0,0 +1,38 @@
+// Check that we only elaborate non-`Self: Sized` associated types when
+// erasing the receiver from trait ref.
+
+//@ revisions: cfi kcfi
+// FIXME(#122848) Remove only-linux once OSX CFI binaries work
+//@ only-linux
+//@ [cfi] needs-sanitizer-cfi
+//@ [kcfi] needs-sanitizer-kcfi
+//@ compile-flags: -C target-feature=-crt-static
+//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
+//@ [cfi] compile-flags: -Z sanitizer=cfi
+//@ [kcfi] compile-flags: -Z sanitizer=kcfi
+//@ [kcfi] compile-flags: -C panic=abort -C prefer-dynamic=off
+//@ run-pass
+
+trait Foo {
+ type Bar<'a>
+ where
+ Self: Sized;
+
+ fn test(&self);
+}
+
+impl Foo for () {
+ type Bar<'a> = ()
+ where
+ Self: Sized;
+
+ fn test(&self) {}
+}
+
+fn test(x: &dyn Foo) {
+ x.test();
+}
+
+fn main() {
+ test(&());
+}
diff --git a/tests/ui/sanitizer/cfi-supertraits.rs b/tests/ui/sanitizer/cfi/supertraits.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-supertraits.rs
rename to tests/ui/sanitizer/cfi/supertraits.rs
diff --git a/tests/ui/sanitizer/cfi-virtual-auto.rs b/tests/ui/sanitizer/cfi/virtual-auto.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-virtual-auto.rs
rename to tests/ui/sanitizer/cfi/virtual-auto.rs
diff --git a/tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.rs b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs
similarity index 100%
rename from tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.rs
rename to tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.rs
diff --git a/tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.stderr b/tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.stderr
similarity index 100%
rename from tests/ui/sanitizer/cfi-with-rustc-lto-requires-single-codegen-unit.stderr
rename to tests/ui/sanitizer/cfi/with-rustc-lto-requires-single-codegen-unit.stderr
diff --git a/tests/ui/short-error-format.stderr b/tests/ui/short-error-format.stderr
index 8a22d67..1a4a6d4 100644
--- a/tests/ui/short-error-format.stderr
+++ b/tests/ui/short-error-format.stderr
@@ -1,3 +1,3 @@
-$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types
-$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope
+$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types: expected `u32`, found `String`
+$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32`
error: aborting due to 2 previous errors
diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
index e01e1ed..6559845 100644
--- a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
+++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr
@@ -17,10 +17,6 @@
LL | .sum::<_>()
| ^^^ cannot infer type of the type parameter `S` declared on the method `sum`
|
-help: consider specifying the generic argument
- |
-LL | .sum::<_>()
- | ~~~~~
error: aborting due to 2 previous errors
diff --git a/tests/ui/span/send-is-not-static-std-sync.stderr b/tests/ui/span/send-is-not-static-std-sync.stderr
index 50b8ffe..6bc3ed8 100644
--- a/tests/ui/span/send-is-not-static-std-sync.stderr
+++ b/tests/ui/span/send-is-not-static-std-sync.stderr
@@ -15,7 +15,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - *lock.lock().unwrap() = &*y;
-LL + *lock.lock().unwrap() = y.clone();
+LL + *lock.lock().unwrap() = &y.clone();
|
error[E0597]: `z` does not live long enough
@@ -48,7 +48,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - *lock.write().unwrap() = &*y;
-LL + *lock.write().unwrap() = y.clone();
+LL + *lock.write().unwrap() = &y.clone();
|
error[E0597]: `z` does not live long enough
@@ -81,7 +81,7 @@
help: consider cloning the value if the performance cost is acceptable
|
LL - tx.send(&*y);
-LL + tx.send(y.clone());
+LL + tx.send(&y.clone());
|
error[E0597]: `z` does not live long enough
diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr
index e391389..643f1de 100644
--- a/tests/ui/specialization/const_trait_impl.stderr
+++ b/tests/ui/specialization/const_trait_impl.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:6:1
|
LL | #[const_trait]
@@ -7,7 +7,7 @@
LL | fn foo() -> u32;
| - expected 0 const parameters
-error[E0049]: method `foo` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `foo` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:6:1
|
LL | #[const_trait]
@@ -36,7 +36,7 @@
LL | impl<T: ~const Default + ~const Sub> const A for T {
| ^^^^^^^
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:29:1
|
LL | #[const_trait]
@@ -45,7 +45,7 @@
LL | fn a() -> u32;
| - expected 0 const parameters
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:29:1
|
LL | #[const_trait]
@@ -56,7 +56,7 @@
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
+error[E0049]: associated function `a` has 1 const parameter but its trait declaration has 0 const parameters
--> $DIR/const_trait_impl.rs:29:1
|
LL | #[const_trait]
diff --git a/tests/ui/stable-mir-print/basic_function.stdout b/tests/ui/stable-mir-print/basic_function.stdout
index 3926c10..76288c2 100644
--- a/tests/ui/stable-mir-print/basic_function.stdout
+++ b/tests/ui/stable-mir-print/basic_function.stdout
@@ -44,14 +44,14 @@
let mut _0: u8;
debug input => _1;
bb0: {
- switchInt(_1) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
+ switchInt(_1) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
}
bb1: {
_0 = 0_u8;
goto -> bb5;
}
bb2: {
- _0 = 10_u8;
+ _0 = 8_u8;
goto -> bb5;
}
bb3: {
@@ -59,7 +59,7 @@
goto -> bb5;
}
bb4: {
- _0 = 8_u8;
+ _0 = 10_u8;
goto -> bb5;
}
bb5: {
diff --git a/tests/ui/static/static-lifetime.rs b/tests/ui/static/static-lifetime.rs
index ce1eeb6..a861a2f 100644
--- a/tests/ui/static/static-lifetime.rs
+++ b/tests/ui/static/static-lifetime.rs
@@ -1,6 +1,7 @@
pub trait Arbitrary: Sized + 'static {}
impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
+//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'a`
fn main() {
}
diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr
index 8c9434c..7a956db 100644
--- a/tests/ui/static/static-lifetime.stderr
+++ b/tests/ui/static/static-lifetime.stderr
@@ -11,6 +11,32 @@
| ^^
= note: but lifetime parameter must outlive the static lifetime
-error: aborting due to 1 previous error
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+ --> $DIR/static-lifetime.rs:3:34
+ |
+LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
+ --> $DIR/static-lifetime.rs:3:6
+ |
+LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/static-lifetime.rs:3:34
+ |
+LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected `<Cow<'a, A> as Arbitrary>`
+ found `<Cow<'_, A> as Arbitrary>`
+ = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that the declared lifetime parameter bounds are satisfied
+ --> $DIR/static-lifetime.rs:3:34
+ |
+LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-For more information about this error, try `rustc --explain E0478`.
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0478, E0495.
+For more information about an error, try `rustc --explain E0478`.
diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs
new file mode 100644
index 0000000..cd15be5
--- /dev/null
+++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs
@@ -0,0 +1,17 @@
+// This ensures we don't ICE in situations like rust-lang/rust#127299.
+
+trait Qux {
+ fn bar() -> i32;
+}
+
+pub struct Lint {
+ pub desc: &'static dyn Qux,
+ //~^ ERROR cannot be made into an object
+}
+
+static FOO: &Lint = &Lint { desc: "desc" };
+//~^ ERROR cannot be shared between threads safely
+//~| ERROR cannot be made into an object
+//~| ERROR cannot be made into an object
+
+fn main() {}
diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
new file mode 100644
index 0000000..49e8d87
--- /dev/null
+++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr
@@ -0,0 +1,87 @@
+error[E0038]: the trait `Qux` cannot be made into an object
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:8:24
+ |
+LL | pub desc: &'static dyn Qux,
+ | ^^^^^^^ `Qux` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
+ |
+LL | trait Qux {
+ | --- this trait cannot be made into an object...
+LL | fn bar() -> i32;
+ | ^^^ ...because associated function `bar` has no `self` parameter
+help: consider turning `bar` into a method by giving it a `&self` argument
+ |
+LL | fn bar(&self) -> i32;
+ | +++++
+help: alternatively, consider constraining `bar` so it does not apply to trait objects
+ |
+LL | fn bar() -> i32 where Self: Sized;
+ | +++++++++++++++++
+
+error[E0277]: `(dyn Qux + 'static)` cannot be shared between threads safely
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:12:13
+ |
+LL | static FOO: &Lint = &Lint { desc: "desc" };
+ | ^^^^^ `(dyn Qux + 'static)` cannot be shared between threads safely
+ |
+ = help: within `&'static Lint`, the trait `Sync` is not implemented for `(dyn Qux + 'static)`, which is required by `&'static Lint: Sync`
+ = note: required because it appears within the type `&'static (dyn Qux + 'static)`
+note: required because it appears within the type `Lint`
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:7:12
+ |
+LL | pub struct Lint {
+ | ^^^^
+ = note: required because it appears within the type `&'static Lint`
+ = note: shared static variables must have a type that implements `Sync`
+
+error[E0038]: the trait `Qux` cannot be made into an object
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:12:35
+ |
+LL | static FOO: &Lint = &Lint { desc: "desc" };
+ | ^^^^^^ `Qux` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
+ |
+LL | trait Qux {
+ | --- this trait cannot be made into an object...
+LL | fn bar() -> i32;
+ | ^^^ ...because associated function `bar` has no `self` parameter
+ = note: required for the cast from `&'static str` to `&'static (dyn Qux + 'static)`
+help: consider turning `bar` into a method by giving it a `&self` argument
+ |
+LL | fn bar(&self) -> i32;
+ | +++++
+help: alternatively, consider constraining `bar` so it does not apply to trait objects
+ |
+LL | fn bar() -> i32 where Self: Sized;
+ | +++++++++++++++++
+
+error[E0038]: the trait `Qux` cannot be made into an object
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:12:35
+ |
+LL | static FOO: &Lint = &Lint { desc: "desc" };
+ | ^^^^^^ `Qux` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8
+ |
+LL | trait Qux {
+ | --- this trait cannot be made into an object...
+LL | fn bar() -> i32;
+ | ^^^ ...because associated function `bar` has no `self` parameter
+help: consider turning `bar` into a method by giving it a `&self` argument
+ |
+LL | fn bar(&self) -> i32;
+ | +++++
+help: alternatively, consider constraining `bar` so it does not apply to trait objects
+ |
+LL | fn bar() -> i32 where Self: Sized;
+ | +++++++++++++++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0038, E0277.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs
index 16439a7..19672e4 100644
--- a/tests/ui/structs-enums/newtype-struct-with-dtor.rs
+++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs
@@ -3,10 +3,8 @@
#![allow(unused_variables)]
//@ pretty-expanded FIXME #23616
-#[allow(dead_code)]
pub struct Fd(u32);
-#[allow(dead_code)]
fn foo(a: u32) {}
impl Drop for Fd {
diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs
index 1074dbc..97bc7d84 100644
--- a/tests/ui/structs-enums/uninstantiable-struct.rs
+++ b/tests/ui/structs-enums/uninstantiable-struct.rs
@@ -1,5 +1,4 @@
//@ run-pass
-#[allow(dead_code)]
-pub struct Z(&'static Z);
+pub struct Z(#[allow(dead_code)] &'static Z);
pub fn main() {}
diff --git a/tests/ui/structs/field-implied-unsizing-wfcheck.rs b/tests/ui/structs/field-implied-unsizing-wfcheck.rs
new file mode 100644
index 0000000..a46c9b5
--- /dev/null
+++ b/tests/ui/structs/field-implied-unsizing-wfcheck.rs
@@ -0,0 +1,32 @@
+struct FooStruct {
+ nested: &'static Bar<dyn std::fmt::Debug>,
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+}
+
+struct FooTuple(&'static Bar<dyn std::fmt::Debug>);
+//~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+
+enum FooEnum1 {
+ Struct { nested: &'static Bar<dyn std::fmt::Debug> },
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+}
+
+enum FooEnum2 {
+ Tuple(&'static Bar<dyn std::fmt::Debug>),
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+}
+
+struct Bar<T>(T);
+
+fn main() {
+ // Ensure there's an error at the construction site, for error tainting purposes.
+
+ FooStruct { nested: &Bar(4) };
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ FooTuple(&Bar(4));
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ FooEnum1::Struct { nested: &Bar(4) };
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ FooEnum2::Tuple(&Bar(4));
+ //~^ ERROR the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+}
diff --git a/tests/ui/structs/field-implied-unsizing-wfcheck.stderr b/tests/ui/structs/field-implied-unsizing-wfcheck.stderr
new file mode 100644
index 0000000..47d486f
--- /dev/null
+++ b/tests/ui/structs/field-implied-unsizing-wfcheck.stderr
@@ -0,0 +1,163 @@
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:2:13
+ |
+LL | nested: &'static Bar<dyn std::fmt::Debug>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:6:17
+ |
+LL | struct FooTuple(&'static Bar<dyn std::fmt::Debug>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:10:22
+ |
+LL | Struct { nested: &'static Bar<dyn std::fmt::Debug> },
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:15:11
+ |
+LL | Tuple(&'static Bar<dyn std::fmt::Debug>),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:24:25
+ |
+LL | FooStruct { nested: &Bar(4) };
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:26:14
+ |
+LL | FooTuple(&Bar(4));
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:28:32
+ |
+LL | FooEnum1::Struct { nested: &Bar(4) };
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
+ --> $DIR/field-implied-unsizing-wfcheck.rs:30:21
+ |
+LL | FooEnum2::Tuple(&Bar(4));
+ | ^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
+note: required by an implicit `Sized` bound in `Bar`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ required by the implicit `Sized` requirement on this type parameter in `Bar`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+ --> $DIR/field-implied-unsizing-wfcheck.rs:19:12
+ |
+LL | struct Bar<T>(T);
+ | ^ - ...if indirection were used here: `Box<T>`
+ | |
+ | this could be changed to `T: ?Sized`...
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/borrow-for-loop-head.stderr b/tests/ui/suggestions/borrow-for-loop-head.stderr
index a8de998..55fcb44 100644
--- a/tests/ui/suggestions/borrow-for-loop-head.stderr
+++ b/tests/ui/suggestions/borrow-for-loop-head.stderr
@@ -10,9 +10,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - for i in &a {
-LL + for i in a.clone() {
- |
+LL | for i in &a.clone() {
+ | ++++++++
error[E0382]: use of moved value: `a`
--> $DIR/borrow-for-loop-head.rs:4:18
diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed
index cf800c6..4dc362f 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.fixed
+++ b/tests/ui/suggestions/derive-clone-for-eq.fixed
@@ -1,7 +1,6 @@
//@ run-rustfix
// https://github.com/rust-lang/rust/issues/79076
-#[allow(dead_code)]
#[derive(Clone, Eq)] //~ ERROR [E0277]
pub struct Struct<T: std::clone::Clone>(T);
diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs
index 8473642..b363500 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.rs
+++ b/tests/ui/suggestions/derive-clone-for-eq.rs
@@ -1,7 +1,6 @@
//@ run-rustfix
// https://github.com/rust-lang/rust/issues/79076
-#[allow(dead_code)]
#[derive(Clone, Eq)] //~ ERROR [E0277]
pub struct Struct<T>(T);
diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr
index 54670fb..6fae6e1 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.stderr
+++ b/tests/ui/suggestions/derive-clone-for-eq.stderr
@@ -1,11 +1,11 @@
error[E0277]: the trait bound `T: Clone` is not satisfied
- --> $DIR/derive-clone-for-eq.rs:5:17
+ --> $DIR/derive-clone-for-eq.rs:4:17
|
LL | #[derive(Clone, Eq)]
| ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct<T>: PartialEq`
|
note: required for `Struct<T>` to implement `PartialEq`
- --> $DIR/derive-clone-for-eq.rs:8:19
+ --> $DIR/derive-clone-for-eq.rs:7:19
|
LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
| ----- ^^^^^^^^^^^^ ^^^^^^^^^
diff --git a/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr b/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr
index aeeec3a..3a1f685 100644
--- a/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr
+++ b/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr
@@ -2,18 +2,13 @@
--> $DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:7:5
|
LL | fn bar(src: &crate::Foo) -> impl Iterator<Item = i32> {
- | ---------- ------------------------- opaque type defined here
- | |
- | hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures the anonymous lifetime defined here
+ | ------------------------- opaque type defined here
LL | / [0].into_iter()
LL | |
LL | | .filter_map(|_| foo(src))
| |_________________________________^
|
-help: to declare that `impl Iterator<Item = i32>` captures `'_`, you can introduce a named lifetime parameter `'a`
- |
-LL | fn bar<'a>(src: &'a crate::Foo<'a>) -> impl Iterator<Item = i32> + 'a {
- | ++++ ++ ++++ ++++
+ = note: hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures lifetime `'_`
error: aborting due to 1 previous error
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
index a2a78dd..db16fff 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr
@@ -44,15 +44,13 @@
| ----- in this derive macro expansion
LL | pub struct AABB<K: Debug> {
LL | pub loc: Vector2<K>,
- | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`, which is required by `Vector2<K>: Clone`
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`
|
-note: required for `Vector2<K>` to implement `Clone`
- --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23
+note: required by a bound in `Vector2`
+ --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:31
|
-LL | #[derive(Debug, Copy, Clone)]
- | ^^^^^
LL | pub struct Vector2<T: Debug + Copy + Clone> {
- | ---- unsatisfied trait bound introduced in this `derive` macro
+ | ^^^^ required by this bound in `Vector2`
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider further restricting this bound
|
diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
index 2ae0871..cf383b5 100644
--- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
+++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr
@@ -95,15 +95,13 @@
| ----- in this derive macro expansion
LL | pub struct AABB<K> {
LL | pub loc: Vector2<K>,
- | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`, which is required by `Vector2<K>: Clone`
+ | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K`
|
-note: required for `Vector2<K>` to implement `Clone`
- --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23
+note: required by a bound in `Vector2`
+ --> $DIR/missing-bound-in-derive-copy-impl.rs:4:31
|
-LL | #[derive(Debug, Copy, Clone)]
- | ^^^^^
LL | pub struct Vector2<T: Debug + Copy + Clone> {
- | ---- unsatisfied trait bound introduced in this `derive` macro
+ | ^^^^ required by this bound in `Vector2`
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `K`
|
diff --git a/tests/ui/suggestions/option-content-move.fixed b/tests/ui/suggestions/option-content-move.fixed
index ef07d55..4a5a948 100644
--- a/tests/ui/suggestions/option-content-move.fixed
+++ b/tests/ui/suggestions/option-content-move.fixed
@@ -1,5 +1,4 @@
//@ run-rustfix
-#[allow(dead_code)]
pub struct LipogramCorpora {
selections: Vec<(char, Option<String>)>,
}
@@ -18,7 +17,6 @@
}
}
-#[allow(dead_code)]
pub struct LipogramCorpora2 {
selections: Vec<(char, Result<String, String>)>,
}
diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs
index 5be6358..90d05c7 100644
--- a/tests/ui/suggestions/option-content-move.rs
+++ b/tests/ui/suggestions/option-content-move.rs
@@ -1,5 +1,4 @@
//@ run-rustfix
-#[allow(dead_code)]
pub struct LipogramCorpora {
selections: Vec<(char, Option<String>)>,
}
@@ -18,7 +17,6 @@ pub fn validate_all(&mut self) -> Result<(), char> {
}
}
-#[allow(dead_code)]
pub struct LipogramCorpora2 {
selections: Vec<(char, Result<String, String>)>,
}
diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr
index b4ec5b1..a382a04 100644
--- a/tests/ui/suggestions/option-content-move.stderr
+++ b/tests/ui/suggestions/option-content-move.stderr
@@ -1,5 +1,5 @@
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
- --> $DIR/option-content-move.rs:11:20
+ --> $DIR/option-content-move.rs:10:20
|
LL | if selection.1.unwrap().contains(selection.0) {
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
@@ -19,7 +19,7 @@
| ++++++++
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
- --> $DIR/option-content-move.rs:30:20
+ --> $DIR/option-content-move.rs:28:20
|
LL | if selection.1.unwrap().contains(selection.0) {
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
index 618ccba..dde6060 100644
--- a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
+++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
@@ -40,7 +40,7 @@
help: surround the type parameters with angle brackets
|
LL | let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
- | + ~
+ | +
error: aborting due to 4 previous errors
diff --git a/tests/ui/target-feature/asm-implied-features-issue-128125.rs b/tests/ui/target-feature/asm-implied-features-issue-128125.rs
new file mode 100644
index 0000000..2b4f1d7
--- /dev/null
+++ b/tests/ui/target-feature/asm-implied-features-issue-128125.rs
@@ -0,0 +1,10 @@
+//@ only-x86_64
+//@ build-pass
+#![allow(dead_code)]
+
+#[target_feature(enable = "avx2")]
+unsafe fn demo(v: std::arch::x86_64::__m256i) {
+ std::arch::asm!("/* {v} */", v = in(ymm_reg) v);
+}
+
+fn main() {}
diff --git a/tests/ui/target-feature/implicit-features-cli.rs b/tests/ui/target-feature/implicit-features-cli.rs
new file mode 100644
index 0000000..34e7c3d
--- /dev/null
+++ b/tests/ui/target-feature/implicit-features-cli.rs
@@ -0,0 +1,9 @@
+//@ only-wasm32-wasip1
+//@ compile-flags: -Ctarget-feature=+relaxed-simd --crate-type=lib
+//@ build-pass
+
+use std::arch::wasm32::*;
+
+pub fn test(a: v128, b: v128, m: v128) -> v128 {
+ i64x2_relaxed_laneselect(a, b, m)
+}
diff --git a/tests/ui/target-feature/implicit-features.rs b/tests/ui/target-feature/implicit-features.rs
new file mode 100644
index 0000000..b9c48b0
--- /dev/null
+++ b/tests/ui/target-feature/implicit-features.rs
@@ -0,0 +1,10 @@
+//@ only-wasm32-wasip1
+//@ compile-flags: --crate-type=lib
+//@ build-pass
+
+use std::arch::wasm32::*;
+
+#[target_feature(enable = "relaxed-simd")]
+pub fn test(a: v128, b: v128, m: v128) -> v128 {
+ i64x2_relaxed_laneselect(a, b, m)
+}
diff --git a/tests/ui/target-feature/implied-features.rs b/tests/ui/target-feature/implied-features.rs
new file mode 100644
index 0000000..4fdd843
--- /dev/null
+++ b/tests/ui/target-feature/implied-features.rs
@@ -0,0 +1,24 @@
+//@ only-x86_64
+//@ build-pass
+#![feature(target_feature_11)]
+#![allow(dead_code)]
+
+#[target_feature(enable = "ssse3")]
+fn call_ssse3() {}
+
+#[target_feature(enable = "avx")]
+fn call_avx() {}
+
+#[target_feature(enable = "avx2")]
+fn test_avx2() {
+ call_ssse3();
+ call_avx();
+}
+
+#[target_feature(enable = "fma")]
+fn test_fma() {
+ call_ssse3();
+ call_avx();
+}
+
+fn main() {}
diff --git a/tests/ui/target-feature/wasm-relaxed-simd.rs b/tests/ui/target-feature/wasm-relaxed-simd.rs
new file mode 100644
index 0000000..34e7c3d
--- /dev/null
+++ b/tests/ui/target-feature/wasm-relaxed-simd.rs
@@ -0,0 +1,9 @@
+//@ only-wasm32-wasip1
+//@ compile-flags: -Ctarget-feature=+relaxed-simd --crate-type=lib
+//@ build-pass
+
+use std::arch::wasm32::*;
+
+pub fn test(a: v128, b: v128, m: v128) -> v128 {
+ i64x2_relaxed_laneselect(a, b, m)
+}
diff --git a/tests/ui/traits/alias/not-a-marker.rs b/tests/ui/traits/alias/not-a-marker.rs
new file mode 100644
index 0000000..b004b9f
--- /dev/null
+++ b/tests/ui/traits/alias/not-a-marker.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias, marker_trait_attr)]
+
+#[marker]
+//~^ ERROR attribute should be applied to a trait
+trait Foo = Send;
+
+fn main() {}
diff --git a/tests/ui/traits/alias/not-a-marker.stderr b/tests/ui/traits/alias/not-a-marker.stderr
new file mode 100644
index 0000000..2f3f6fe
--- /dev/null
+++ b/tests/ui/traits/alias/not-a-marker.stderr
@@ -0,0 +1,11 @@
+error: attribute should be applied to a trait
+ --> $DIR/not-a-marker.rs:3:1
+ |
+LL | #[marker]
+ | ^^^^^^^^^
+LL |
+LL | trait Foo = Send;
+ | ----------------- not a trait
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/non_lifetime_binders/shadowed.rs b/tests/ui/traits/non_lifetime_binders/shadowed.rs
new file mode 100644
index 0000000..1c480e3
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/shadowed.rs
@@ -0,0 +1,18 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+fn function<T>() where for<T> (): Sized {}
+//~^ ERROR the name `T` is already used for a generic parameter
+
+struct Struct<T>(T) where for<T> (): Sized;
+//~^ ERROR the name `T` is already used for a generic parameter
+
+impl<T> Struct<T> {
+ fn method() where for<T> (): Sized {}
+ //~^ ERROR the name `T` is already used for a generic parameter
+}
+
+fn repeated() where for<T, T> (): Sized {}
+//~^ ERROR the name `T` is already used for a generic parameter
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/shadowed.stderr b/tests/ui/traits/non_lifetime_binders/shadowed.stderr
new file mode 100644
index 0000000..59a073a
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/shadowed.stderr
@@ -0,0 +1,44 @@
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/shadowed.rs:4:28
+ |
+LL | fn function<T>() where for<T> (): Sized {}
+ | - ^ already used
+ | |
+ | first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/shadowed.rs:7:31
+ |
+LL | struct Struct<T>(T) where for<T> (): Sized;
+ | - ^ already used
+ | |
+ | first use of `T`
+
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/shadowed.rs:11:27
+ |
+LL | impl<T> Struct<T> {
+ | - first use of `T`
+LL | fn method() where for<T> (): Sized {}
+ | ^ already used
+
+error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
+ --> $DIR/shadowed.rs:15:28
+ |
+LL | fn repeated() where for<T, T> (): Sized {}
+ | - ^ already used
+ | |
+ | first use of `T`
+
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/shadowed.rs:1:12
+ |
+LL | #![feature(non_lifetime_binders)]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0403`.
diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs
index 0ae562c..462b0bc 100644
--- a/tests/ui/traits/object/generics.rs
+++ b/tests/ui/traits/object/generics.rs
@@ -7,7 +7,6 @@ pub trait Trait2<A> {
fn doit(&self) -> A;
}
-#[allow(dead_code)]
pub struct Impl<A1, A2, A3> {
m1: marker::PhantomData<(A1,A2,A3)>,
/*
diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr
index 6f69329..28941cb 100644
--- a/tests/ui/try-block/try-block-bad-lifetime.stderr
+++ b/tests/ui/try-block/try-block-bad-lifetime.stderr
@@ -34,11 +34,6 @@
...
LL | ::std::mem::drop(k);
| ^ value used here after move
- |
-help: consider cloning the value if the performance cost is acceptable
- |
-LL | Err(k.clone()) ?;
- | ++++++++
error[E0506]: cannot assign to `i` because it is borrowed
--> $DIR/try-block-bad-lifetime.rs:32:9
diff --git a/tests/ui/try-trait/try-operator-custom.rs b/tests/ui/try-trait/try-operator-custom.rs
index ab0772d..936c0b0 100644
--- a/tests/ui/try-trait/try-operator-custom.rs
+++ b/tests/ui/try-trait/try-operator-custom.rs
@@ -31,7 +31,6 @@ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
impl<U, V, W> FromResidual<MyResult<Never, V>> for MyResult<U, W> where V: Into<W> {
fn from_residual(x: MyResult<Never, V>) -> Self {
match x {
- MyResult::Awesome(u) => match u {},
MyResult::Terrible(e) => MyResult::Terrible(e.into()),
}
}
@@ -42,7 +41,6 @@ fn from_residual(x: MyResult<Never, V>) -> Self {
impl<U, V, W> FromResidual<ResultResidual<V>> for MyResult<U, W> where V: Into<W> {
fn from_residual(x: ResultResidual<V>) -> Self {
match x {
- Ok(v) => match v {}
Err(e) => MyResult::Terrible(e.into()),
}
}
@@ -51,7 +49,6 @@ fn from_residual(x: ResultResidual<V>) -> Self {
impl<U, V, W> FromResidual<MyResult<Never, V>> for Result<U, W> where V: Into<W> {
fn from_residual(x: MyResult<Never, V>) -> Self {
match x {
- MyResult::Awesome(u) => match u {},
MyResult::Terrible(e) => Err(e.into()),
}
}
diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr
index dc0bea5..bf8829c 100644
--- a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr
+++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr
@@ -12,3 +12,13 @@
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.
+Future incompatibility report: Future breakage diagnostic:
+warning: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11
+ |
+LL | fn foo<T, U = u64>() -> (T, U) {
+ | ^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs b/tests/ui/type/default_type_parameter_in_fn_or_impl.rs
similarity index 100%
rename from tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs
rename to tests/ui/type/default_type_parameter_in_fn_or_impl.rs
diff --git a/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr
new file mode 100644
index 0000000..a3205cd
--- /dev/null
+++ b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr
@@ -0,0 +1,43 @@
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8
+ |
+LL | fn avg<T=i32>(_: T) {}
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6
+ |
+LL | impl<T=i32> S<T> {}
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+
+error: aborting due to 2 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8
+ |
+LL | fn avg<T=i32>(_: T) {}
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
+Future breakage diagnostic:
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6
+ |
+LL | impl<T=i32> S<T> {}
+ | ^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
index 6f74b89..03e91b5 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
@@ -4,6 +4,7 @@
LL | type NonNullU32 = pattern_type!(u32 is 1..);
| ^^^^^^^^^^^^
|
+ = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
@@ -13,6 +14,7 @@
LL | type Percent = pattern_type!(u32 is 0..=100);
| ^^^^^^^^^^^^
|
+ = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
@@ -22,6 +24,7 @@
LL | type Negative = pattern_type!(i32 is ..=0);
| ^^^^^^^^^^^^
|
+ = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
@@ -31,6 +34,7 @@
LL | type Positive = pattern_type!(i32 is 0..);
| ^^^^^^^^^^^^
|
+ = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
@@ -40,6 +44,7 @@
LL | type Always = pattern_type!(Option<u32> is Some(_));
| ^^^^^^^^^^^^
|
+ = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/type/pattern_types/missing-is.rs b/tests/ui/type/pattern_types/missing-is.rs
new file mode 100644
index 0000000..2fbcc19
--- /dev/null
+++ b/tests/ui/type/pattern_types/missing-is.rs
@@ -0,0 +1,8 @@
+#![feature(core_pattern_type, core_pattern_types)]
+
+use std::pat::pattern_type;
+
+fn main() {
+ let x: pattern_type!(i32 0..1);
+ //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `is`, found `0`
+}
diff --git a/tests/ui/type/pattern_types/missing-is.stderr b/tests/ui/type/pattern_types/missing-is.stderr
new file mode 100644
index 0000000..8ed654f
--- /dev/null
+++ b/tests/ui/type/pattern_types/missing-is.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `+`, `::`, `<`, or `is`, found `0`
+ --> $DIR/missing-is.rs:6:30
+ |
+LL | let x: pattern_type!(i32 0..1);
+ | ^ expected one of `!`, `(`, `+`, `::`, `<`, or `is`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/typeck/issue-36708.stderr b/tests/ui/typeck/issue-36708.stderr
index 3589796..0aca575 100644
--- a/tests/ui/typeck/issue-36708.stderr
+++ b/tests/ui/typeck/issue-36708.stderr
@@ -1,4 +1,4 @@
-error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+error[E0049]: associated function `foo` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/issue-36708.rs:8:12
|
LL | fn foo<T>() {}
diff --git a/tests/ui/typeck/suggest-arg-comma-delete-ice.rs b/tests/ui/typeck/suggest-arg-comma-delete-ice.rs
new file mode 100644
index 0000000..48d02e1
--- /dev/null
+++ b/tests/ui/typeck/suggest-arg-comma-delete-ice.rs
@@ -0,0 +1,19 @@
+//! Previously, we tried to remove extra arg commas when providing extra arg removal suggestions.
+//! One of the edge cases is having to account for an arg that has a closing delimiter `)`
+//! following it. However, the previous suggestion code assumed that the delimiter is in fact
+//! exactly the 1-byte `)` character. This assumption was proven incorrect, because we recover
+//! from Unicode-confusable delimiters in the parser, which means that the ending delimiter could be
+//! a multi-byte codepoint that looks *like* a `)`. Subtracing 1 byte could land us in the middle of
+//! a codepoint, triggering a codepoint boundary assertion.
+//!
+//! issue: rust-lang/rust#128717
+
+fn main() {
+ // The following example has been modified from #128717 to remove irrelevant Unicode as they do
+ // not otherwise partake in the right delimiter calculation causing the codepoint boundary
+ // assertion.
+ main(rahh);
+ //~^ ERROR unknown start of token
+ //~| ERROR this function takes 0 arguments but 1 argument was supplied
+ //~| ERROR cannot find value `rahh` in this scope
+}
diff --git a/tests/ui/typeck/suggest-arg-comma-delete-ice.stderr b/tests/ui/typeck/suggest-arg-comma-delete-ice.stderr
new file mode 100644
index 0000000..5360839
--- /dev/null
+++ b/tests/ui/typeck/suggest-arg-comma-delete-ice.stderr
@@ -0,0 +1,38 @@
+error: unknown start of token: \u{ff09}
+ --> $DIR/suggest-arg-comma-delete-ice.rs:15:14
+ |
+LL | main(rahh);
+ | ^^
+ |
+help: Unicode character ')' (Fullwidth Right Parenthesis) looks like ')' (Right Parenthesis), but it is not
+ |
+LL | main(rahh);
+ | ~
+
+error[E0425]: cannot find value `rahh` in this scope
+ --> $DIR/suggest-arg-comma-delete-ice.rs:15:10
+ |
+LL | main(rahh);
+ | ^^^^ not found in this scope
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+ --> $DIR/suggest-arg-comma-delete-ice.rs:15:5
+ |
+LL | main(rahh);
+ | ^^^^ ---- unexpected argument
+ |
+note: function defined here
+ --> $DIR/suggest-arg-comma-delete-ice.rs:11:4
+ |
+LL | fn main() {
+ | ^^^^
+help: remove the extra argument
+ |
+LL - main(rahh);
+LL + main();
+ |
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0061, E0425.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.stderr
index 2407429..d8a4b6b 100644
--- a/tests/ui/underscore-imports/issue-110164.stderr
+++ b/tests/ui/underscore-imports/issue-110164.stderr
@@ -38,33 +38,25 @@
--> $DIR/issue-110164.rs:8:5
|
LL | use _::*;
- | ^ you might be missing crate `_`
- |
- = help: consider adding `extern crate _` to use the `_` crate
+ | ^ `_` is not a valid crate or module name
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:5:5
|
LL | use _::a;
- | ^ you might be missing crate `_`
- |
- = help: consider adding `extern crate _` to use the `_` crate
+ | ^ `_` is not a valid crate or module name
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:13:9
|
LL | use _::a;
- | ^ you might be missing crate `_`
- |
- = help: consider adding `extern crate _` to use the `_` crate
+ | ^ `_` is not a valid crate or module name
error[E0432]: unresolved import `_`
--> $DIR/issue-110164.rs:16:9
|
LL | use _::*;
- | ^ you might be missing crate `_`
- |
- = help: consider adding `extern crate _` to use the `_` crate
+ | ^ `_` is not a valid crate or module name
error: aborting due to 10 previous errors
diff --git a/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs b/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs
index 3130fb3..722d9b4 100644
--- a/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs
+++ b/tests/ui/uninhabited/exhaustive-wo-nevertype-issue-51221.rs
@@ -1,7 +1,5 @@
//@ check-pass
-#![feature(min_exhaustive_patterns)]
-
enum Void {}
fn main() {
let a: Option<Void> = None;
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr
index bc1a9fa..50f3360 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0005]: refutable pattern in local binding
- --> $DIR/uninhabited-irrefutable.rs:31:9
+ --> $DIR/uninhabited-irrefutable.rs:30:9
|
LL | let Foo::D(_y, _z) = x;
| ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
@@ -7,7 +7,7 @@
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
note: `Foo` defined here
- --> $DIR/uninhabited-irrefutable.rs:20:6
+ --> $DIR/uninhabited-irrefutable.rs:19:6
|
LL | enum Foo {
| ^^^
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr
new file mode 100644
index 0000000..50f3360
--- /dev/null
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.normal.stderr
@@ -0,0 +1,26 @@
+error[E0005]: refutable pattern in local binding
+ --> $DIR/uninhabited-irrefutable.rs:30:9
+ |
+LL | let Foo::D(_y, _z) = x;
+ | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered
+ |
+ = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+ = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+note: `Foo` defined here
+ --> $DIR/uninhabited-irrefutable.rs:19:6
+ |
+LL | enum Foo {
+ | ^^^
+LL |
+LL | A(foo::SecretlyEmpty),
+ | - not covered
+ = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
+ = note: the matched value is of type `Foo`
+help: you might want to use `let else` to handle the variant that isn't matched
+ |
+LL | let Foo::D(_y, _z) = x else { todo!() };
+ | ++++++++++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0005`.
diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs
index c1f4e5f..cbaa989 100644
--- a/tests/ui/uninhabited/uninhabited-irrefutable.rs
+++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs
@@ -1,6 +1,5 @@
-//@ revisions: min_exhaustive_patterns exhaustive_patterns
+//@ revisions: normal exhaustive_patterns
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
-#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))]
#![feature(never_type)]
mod foo {
diff --git a/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs b/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs
index e804afc..1b158dd 100644
--- a/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs
+++ b/tests/ui/uninhabited/uninhabited-matches-feature-gated.rs
@@ -15,10 +15,10 @@ fn main() {
let _ = match x {}; //~ ERROR non-exhaustive
let x: (Void,) = unsafe { zeroed() };
- let _ = match x {}; //~ ERROR non-exhaustive
+ let _ = match x {};
let x: [Void; 1] = unsafe { zeroed() };
- let _ = match x {}; //~ ERROR non-exhaustive
+ let _ = match x {};
let x: &[Void] = unsafe { zeroed() };
let _ = match x { //~ ERROR non-exhaustive
@@ -29,11 +29,10 @@ fn main() {
let _ = match x {}; // okay
let x: Result<u32, Void> = Ok(23);
- let _ = match x { //~ ERROR non-exhaustive
+ let _ = match x {
Ok(x) => x,
};
let x: Result<u32, Void> = Ok(23);
let Ok(x) = x;
- //~^ ERROR refutable
}
diff --git a/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 466d7f2..2cd3c93 100644
--- a/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/tests/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -36,34 +36,6 @@
LL ~ };
|
-error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
- --> $DIR/uninhabited-matches-feature-gated.rs:18:19
- |
-LL | let _ = match x {};
- | ^
- |
- = note: the matched value is of type `(Void,)`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ let _ = match x {
-LL + _ => todo!(),
-LL ~ };
- |
-
-error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
- --> $DIR/uninhabited-matches-feature-gated.rs:21:19
- |
-LL | let _ = match x {};
- | ^
- |
- = note: the matched value is of type `[Void; 1]`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ let _ = match x {
-LL + _ => todo!(),
-LL ~ };
- |
-
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/uninhabited-matches-feature-gated.rs:24:19
|
@@ -71,45 +43,13 @@
| ^ pattern `&[_, ..]` not covered
|
= note: the matched value is of type `&[Void]`
+ = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ &[] => (),
LL ~ &[_, ..] => todo!(),
|
-error[E0004]: non-exhaustive patterns: `Err(_)` not covered
- --> $DIR/uninhabited-matches-feature-gated.rs:32:19
- |
-LL | let _ = match x {
- | ^ pattern `Err(_)` not covered
- |
-note: `Result<u32, Void>` defined here
- --> $SRC_DIR/core/src/result.rs:LL:COL
- ::: $SRC_DIR/core/src/result.rs:LL:COL
- |
- = note: not covered
- = note: the matched value is of type `Result<u32, Void>`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
- |
-LL ~ Ok(x) => x,
-LL ~ Err(_) => todo!(),
- |
+error: aborting due to 3 previous errors
-error[E0005]: refutable pattern in local binding
- --> $DIR/uninhabited-matches-feature-gated.rs:37:9
- |
-LL | let Ok(x) = x;
- | ^^^^^ pattern `Err(_)` not covered
- |
- = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
- = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
- = note: the matched value is of type `Result<u32, Void>`
-help: you might want to use `let else` to handle the variant that isn't matched
- |
-LL | let Ok(x) = x else { todo!() };
- | ++++++++++++++++
-
-error: aborting due to 7 previous errors
-
-Some errors have detailed explanations: E0004, E0005.
-For more information about an error, try `rustc --explain E0004`.
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/uninhabited/uninhabited-patterns.rs b/tests/ui/uninhabited/uninhabited-patterns.rs
index ae12c0f..988383e 100644
--- a/tests/ui/uninhabited/uninhabited-patterns.rs
+++ b/tests/ui/uninhabited/uninhabited-patterns.rs
@@ -1,6 +1,5 @@
#![feature(box_patterns)]
#![feature(never_type)]
-#![feature(min_exhaustive_patterns)]
#![deny(unreachable_patterns)]
mod foo {
diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr
index ca62386..4e4aaa9 100644
--- a/tests/ui/uninhabited/uninhabited-patterns.stderr
+++ b/tests/ui/uninhabited/uninhabited-patterns.stderr
@@ -1,18 +1,18 @@
error: unreachable pattern
- --> $DIR/uninhabited-patterns.rs:30:9
+ --> $DIR/uninhabited-patterns.rs:29:9
|
LL | Ok(box _) => (),
| ^^^^^^^^^
|
= note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited
note: the lint level is defined here
- --> $DIR/uninhabited-patterns.rs:4:9
+ --> $DIR/uninhabited-patterns.rs:3:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/uninhabited-patterns.rs:39:9
+ --> $DIR/uninhabited-patterns.rs:38:9
|
LL | Err(Ok(_y)) => (),
| ^^^^^^^^^^^
@@ -20,7 +20,7 @@
= note: this pattern matches no values because `NotSoSecretlyEmpty` is uninhabited
error: unreachable pattern
- --> $DIR/uninhabited-patterns.rs:42:15
+ --> $DIR/uninhabited-patterns.rs:41:15
|
LL | while let Some(_y) = foo() {
| ^^^^^^^^
diff --git a/tests/ui/unop/unop-move-semantics.stderr b/tests/ui/unop/unop-move-semantics.stderr
index bc9b3ea..0ae918d 100644
--- a/tests/ui/unop/unop-move-semantics.stderr
+++ b/tests/ui/unop/unop-move-semantics.stderr
@@ -40,7 +40,7 @@
LL | fn move_borrowed<T: Not<Output=T>>(x: T, mut y: T) {
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
- | -- you could clone this value
+ | - you could clone this value
error[E0505]: cannot move out of `y` because it is borrowed
--> $DIR/unop-move-semantics.rs:17:6
@@ -63,7 +63,7 @@
| ^ consider constraining this type parameter with `Clone`
LL | let m = &x;
LL | let n = &mut y;
- | ------ you could clone this value
+ | - you could clone this value
error[E0507]: cannot move out of `*m` which is behind a mutable reference
--> $DIR/unop-move-semantics.rs:24:6
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 92c2e7b..29472df 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -25,7 +25,6 @@
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(unnamed_fields)]
-#![feature(unsafe_extern_blocks)]
#![feature(yeet_expr)]
#![allow(incomplete_features)]
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 137a8aa..cf2f6f8 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -26,7 +26,6 @@
#![feature(trait_alias)]
#![feature(try_blocks)]
#![feature(unnamed_fields)]
-#![feature(unsafe_extern_blocks)]
#![feature(yeet_expr)]
#![allow(incomplete_features)]
#[prelude_import]
diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.stderr b/tests/ui/unresolved/unresolved-asterisk-imports.stderr
index 299ec69..ed01f3f 100644
--- a/tests/ui/unresolved/unresolved-asterisk-imports.stderr
+++ b/tests/ui/unresolved/unresolved-asterisk-imports.stderr
@@ -4,7 +4,10 @@
LL | use not_existing_crate::*;
| ^^^^^^^^^^^^^^^^^^ you might be missing crate `not_existing_crate`
|
- = help: consider adding `extern crate not_existing_crate` to use the `not_existing_crate` crate
+help: consider importing the `not_existing_crate` crate
+ |
+LL + extern crate not_existing_crate;
+ |
error: aborting due to 1 previous error
diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs
index e8f3b32..ee520d6 100644
--- a/tests/ui/unresolved/unresolved-import.rs
+++ b/tests/ui/unresolved/unresolved-import.rs
@@ -1,7 +1,8 @@
use foo::bar;
//~^ ERROR unresolved import `foo` [E0432]
//~| NOTE you might be missing crate `foo`
-//~| HELP consider adding `extern crate foo` to use the `foo` crate
+//~| HELP consider importing the `foo` crate
+//~| SUGGESTION extern crate foo;
use bar::Baz as x;
//~^ ERROR unresolved import `bar::Baz` [E0432]
diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr
index 7b03717..a1ff2f1 100644
--- a/tests/ui/unresolved/unresolved-import.stderr
+++ b/tests/ui/unresolved/unresolved-import.stderr
@@ -4,10 +4,13 @@
LL | use foo::bar;
| ^^^ you might be missing crate `foo`
|
- = help: consider adding `extern crate foo` to use the `foo` crate
+help: consider importing the `foo` crate
+ |
+LL + extern crate foo;
+ |
error[E0432]: unresolved import `bar::Baz`
- --> $DIR/unresolved-import.rs:6:5
+ --> $DIR/unresolved-import.rs:7:5
|
LL | use bar::Baz as x;
| ^^^^^---^^^^^
@@ -16,7 +19,7 @@
| no `Baz` in `bar`
error[E0432]: unresolved import `food::baz`
- --> $DIR/unresolved-import.rs:12:5
+ --> $DIR/unresolved-import.rs:13:5
|
LL | use food::baz;
| ^^^^^^---
@@ -25,7 +28,7 @@
| no `baz` in `food`
error[E0432]: unresolved import `food::beens`
- --> $DIR/unresolved-import.rs:18:12
+ --> $DIR/unresolved-import.rs:19:12
|
LL | use food::{beens as Foo};
| -----^^^^^^^
@@ -34,13 +37,13 @@
| help: a similar name exists in the module: `beans`
error[E0432]: unresolved import `MyEnum`
- --> $DIR/unresolved-import.rs:43:9
+ --> $DIR/unresolved-import.rs:44:9
|
LL | use MyEnum::*;
| ^^^^^^ help: a similar path exists: `self::MyEnum`
error[E0432]: unresolved import `Enum`
- --> $DIR/unresolved-import.rs:54:9
+ --> $DIR/unresolved-import.rs:55:9
|
LL | use Enum::*;
| ^^^^ help: a similar path exists: `self::Enum`
diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr
index 0a810b7..21d8de6 100644
--- a/tests/ui/variance/variance-issue-20533.stderr
+++ b/tests/ui/variance/variance-issue-20533.stderr
@@ -17,7 +17,7 @@
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = foo(&a);
- | -- you could clone this value
+ | - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:41:14
@@ -38,7 +38,7 @@
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = bar(&a);
- | -- you could clone this value
+ | - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:47:14
@@ -59,7 +59,7 @@
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = baz(&a);
- | -- you could clone this value
+ | - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:53:14
@@ -80,7 +80,7 @@
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let x = bat(&a);
- | -- you could clone this value
+ | - you could clone this value
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:59:14
@@ -96,9 +96,8 @@
|
help: consider cloning the value if the performance cost is acceptable
|
-LL - let x = foo(&a);
-LL + let x = foo(a.clone());
- |
+LL | let x = foo(&a.clone());
+ | ++++++++
error: aborting due to 5 previous errors
diff --git a/tests/ui/wf/wf-in-where-clause-static.current.stderr b/tests/ui/wf/wf-in-where-clause-static.current.stderr
new file mode 100644
index 0000000..d0bb898
--- /dev/null
+++ b/tests/ui/wf/wf-in-where-clause-static.current.stderr
@@ -0,0 +1,12 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/wf-in-where-clause-static.rs:18:18
+ |
+LL | let s = foo(&String::from("blah blah blah"));
+ | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
+ | | |
+ | | creates a temporary value which is freed while still in use
+ | argument requires that borrow lasts for `'static`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/wf/wf-in-where-clause-static.next.stderr b/tests/ui/wf/wf-in-where-clause-static.next.stderr
new file mode 100644
index 0000000..d0bb898
--- /dev/null
+++ b/tests/ui/wf/wf-in-where-clause-static.next.stderr
@@ -0,0 +1,12 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/wf-in-where-clause-static.rs:18:18
+ |
+LL | let s = foo(&String::from("blah blah blah"));
+ | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
+ | | |
+ | | creates a temporary value which is freed while still in use
+ | argument requires that borrow lasts for `'static`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/tests/ui/wf/wf-in-where-clause-static.rs b/tests/ui/wf/wf-in-where-clause-static.rs
index a3d360e..8ee654e 100644
--- a/tests/ui/wf/wf-in-where-clause-static.rs
+++ b/tests/ui/wf/wf-in-where-clause-static.rs
@@ -1,9 +1,6 @@
-//@ check-pass
-//@ known-bug: #98117
-
-// Should fail. Functions are responsible for checking the well-formedness of
-// their own where clauses, so this should fail and require an explicit bound
-// `T: 'static`.
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
use std::fmt::Display;
@@ -19,5 +16,6 @@ fn foo<S: Display>(x: S) -> Box<dyn Display>
fn main() {
let s = foo(&String::from("blah blah blah"));
+ //~^ ERROR temporary value dropped while borrowed
println!("{}", s);
}
diff --git a/triagebot.toml b/triagebot.toml
index 5c5aa47..33108f7 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -778,6 +778,14 @@
Otherwise, you can ignore this comment.
"""
+[mentions."library/Cargo.lock"]
+message = """
+These commits modify the `library/Cargo.lock` file. Unintentional changes to `library/Cargo.lock` can be introduced when switching branches and rebasing PRs.
+
+If this was unintentional then you should revert the changes before this PR is merged.
+Otherwise, you can ignore this comment.
+"""
+
[mentions."src/tools/x"]
message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version."
@@ -852,7 +860,7 @@
cc = ["@Urgau"]
[mentions."src/doc/rustc/src/platform-support"]
-cc = ["@Nilstrieb"]
+cc = ["@Noratrieb"]
[mentions."tests/codegen/sanitizer"]
cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"]
@@ -938,7 +946,7 @@
"@cuviper",
"@Mark-Simulacrum",
"@Amanieu",
- "@Nilstrieb",
+ "@Noratrieb",
"@workingjubilee",
"@joboet",
"@jhpratt",