Rollup merge of #132984 - sunshowers:pipe2, r=tgross35
[illumos] use pipe2 to create anonymous pipes
pipe2 allows the newly-created pipe to atomically be CLOEXEC.
pipe2 was added to illumos a long time ago:
https://github.com/illumos/illumos-gate/commit/5dbfd19ad5fcc2b779f40f80fa05c1bd28fd0b4e. I've verified that this change passes all of std's tests on illumos.
diff --git a/Cargo.lock b/Cargo.lock
index 97d07cd..b98c4fd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -41,7 +41,6 @@
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
- "getrandom",
"once_cell",
"version_check",
"zerocopy",
@@ -112,9 +111,9 @@
[[package]]
name = "anstream"
-version = "0.6.15"
+version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -127,65 +126,65 @@
[[package]]
name = "anstyle"
-version = "1.0.8"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-lossy"
-version = "1.1.2"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f45c79b3b9413932fc255f2c19ca0d48eaab72c4ea1913bafaebf289cbc099f2"
+checksum = "934ff8719effd2023a48cf63e69536c1c3ced9d3895068f6f5cc9a4ff845e59b"
dependencies = [
"anstyle",
]
[[package]]
name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anstyle-svg"
-version = "0.1.5"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "962f6d5681926dbe5503b71057202d6723a33abe464c983b1d160bca3095a3bb"
+checksum = "d3607949e9f6de49ea4bafe12f5e4fd73613ebf24795e48587302a8cc0e4bb35"
dependencies = [
"anstream",
"anstyle",
"anstyle-lossy",
"html-escape",
- "unicode-width 0.1.14",
+ "unicode-width 0.2.0",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
-version = "1.0.89"
+version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
+checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
dependencies = [
"backtrace",
]
@@ -196,14 +195,14 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4"
dependencies = [
- "object 0.36.4",
+ "object 0.36.5",
]
[[package]]
name = "arrayref"
-version = "0.3.7"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
@@ -270,9 +269,9 @@
[[package]]
name = "blake3"
-version = "1.5.2"
+version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d08263faac5cde2a4d52b513dadb80846023aade56fcd8fc99ba73ba8050e92"
+checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7"
dependencies = [
"arrayref",
"arrayvec",
@@ -297,7 +296,7 @@
checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
dependencies = [
"memchr",
- "regex-automata 0.4.7",
+ "regex-automata 0.4.8",
"serde",
]
@@ -357,9 +356,9 @@
[[package]]
name = "bytes"
-version = "1.7.2"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
+checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
[[package]]
name = "camino"
@@ -412,9 +411,9 @@
[[package]]
name = "cc"
-version = "1.1.23"
+version = "1.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17"
+checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9"
dependencies = [
"shlex",
]
@@ -477,9 +476,9 @@
[[package]]
name = "clap"
-version = "4.5.18"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -497,9 +496,9 @@
[[package]]
name = "clap_builder"
-version = "4.5.18"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
@@ -510,9 +509,9 @@
[[package]]
name = "clap_complete"
-version = "4.5.29"
+version = "4.5.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8937760c3f4c60871870b8c3ee5f9b30771f792a7045c48bcbba999d7d6b3b8e"
+checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2"
dependencies = [
"clap",
]
@@ -526,7 +525,7 @@
"heck 0.5.0",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -557,7 +556,7 @@
"rustc_tools_util",
"serde",
"serde_json",
- "syn 2.0.79",
+ "syn 2.0.87",
"tempfile",
"termize",
"tokio",
@@ -600,7 +599,7 @@
"itertools",
"quine-mc_cluskey",
"regex",
- "regex-syntax 0.8.4",
+ "regex-syntax 0.8.5",
"semver",
"serde",
"serde_json",
@@ -665,7 +664,7 @@
"nom",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -682,9 +681,9 @@
[[package]]
name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "colored"
@@ -745,9 +744,9 @@
[[package]]
name = "constant_time_eq"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2"
+checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
[[package]]
name = "core-foundation-sys"
@@ -841,9 +840,9 @@
[[package]]
name = "curl"
-version = "0.4.46"
+version = "0.4.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6"
+checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265"
dependencies = [
"curl-sys",
"libc",
@@ -856,9 +855,9 @@
[[package]]
name = "curl-sys"
-version = "0.4.76+curl-8.10.1"
+version = "0.4.77+curl-8.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00462dbe9cbb9344e1b2be34d9094d74e3b8aac59a883495b335eafd02e25120"
+checksum = "f469e8a5991f277a208224f6c7ad72ecb5f986e36d09ae1f2c1bb9259478a480"
dependencies = [
"cc",
"libc",
@@ -890,7 +889,7 @@
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -901,7 +900,7 @@
dependencies = [
"darling_core",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -938,38 +937,38 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
name = "derive_builder"
-version = "0.20.1"
+version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b"
+checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
-version = "0.20.1"
+version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38"
+checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
name = "derive_builder_macro"
-version = "0.20.1"
+version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc"
+checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -981,7 +980,7 @@
"darling",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -1059,7 +1058,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -1261,6 +1260,12 @@
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
+name = "foldhash"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
+
+[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1296,9 +1301,9 @@
[[package]]
name = "futures"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
dependencies = [
"futures-channel",
"futures-core",
@@ -1311,9 +1316,9 @@
[[package]]
name = "futures-channel"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
@@ -1321,15 +1326,15 @@
[[package]]
name = "futures-core"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
@@ -1338,38 +1343,38 @@
[[package]]
name = "futures-io"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-macro"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
name = "futures-sink"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
-version = "0.3.30"
+version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-channel",
"futures-core",
@@ -1451,9 +1456,9 @@
[[package]]
name = "gimli"
-version = "0.31.0"
+version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
dependencies = [
"fallible-iterator",
"indexmap",
@@ -1475,8 +1480,8 @@
"aho-corasick",
"bstr",
"log",
- "regex-automata 0.4.7",
- "regex-syntax 0.8.4",
+ "regex-automata 0.4.8",
+ "regex-syntax 0.8.5",
]
[[package]]
@@ -1514,6 +1519,15 @@
]
[[package]]
+name = "hashbrown"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1574,7 +1588,7 @@
"markup5ever",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -1706,7 +1720,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -1747,7 +1761,7 @@
"globset",
"log",
"memchr",
- "regex-automata 0.4.7",
+ "regex-automata 0.4.8",
"same-file",
"walkdir",
"winapi-util",
@@ -1761,12 +1775,12 @@
[[package]]
name = "indexmap"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
- "hashbrown",
+ "hashbrown 0.15.0",
"rustc-rayon",
"serde",
]
@@ -1882,9 +1896,9 @@
[[package]]
name = "js-sys"
-version = "0.3.70"
+version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
@@ -1951,9 +1965,9 @@
[[package]]
name = "libc"
-version = "0.2.159"
+version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "libdbus-sys"
@@ -1996,9 +2010,9 @@
[[package]]
name = "libm"
-version = "0.2.8"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "libredox"
@@ -2451,17 +2465,17 @@
[[package]]
name = "object"
-version = "0.36.4"
+version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a"
+checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
dependencies = [
"crc32fast",
"flate2",
- "hashbrown",
+ "hashbrown 0.15.0",
"indexmap",
"memchr",
"ruzstd",
- "wasmparser 0.216.0",
+ "wasmparser 0.218.0",
]
[[package]]
@@ -2475,21 +2489,9 @@
[[package]]
name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
-
-[[package]]
-name = "once_map"
-version = "0.4.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30c7f82d6d446dd295845094f3a76bcdc5e6183b66667334e169f019cd05e5a0"
-dependencies = [
- "ahash",
- "hashbrown",
- "parking_lot",
- "stable_deref_trait",
-]
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "opener"
@@ -2511,9 +2513,9 @@
[[package]]
name = "openssl-sys"
-version = "0.9.103"
+version = "0.9.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
+checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
dependencies = [
"cc",
"libc",
@@ -2617,9 +2619,9 @@
[[package]]
name = "pathdiff"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361"
[[package]]
name = "percent-encoding"
@@ -2638,9 +2640,9 @@
[[package]]
name = "pest"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9"
+checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
dependencies = [
"memchr",
"thiserror",
@@ -2649,9 +2651,9 @@
[[package]]
name = "pest_derive"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0"
+checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
dependencies = [
"pest",
"pest_generator",
@@ -2659,22 +2661,22 @@
[[package]]
name = "pest_generator"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e"
+checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
name = "pest_meta"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f"
+checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
dependencies = [
"once_cell",
"pest",
@@ -2740,9 +2742,9 @@
[[package]]
name = "pin-project-lite"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]]
name = "pin-utils"
@@ -2812,9 +2814,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@@ -2957,9 +2959,9 @@
[[package]]
name = "redox_syscall"
-version = "0.5.6"
+version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags 2.6.0",
]
@@ -2977,14 +2979,14 @@
[[package]]
name = "regex"
-version = "1.10.6"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
- "regex-automata 0.4.7",
- "regex-syntax 0.8.4",
+ "regex-automata 0.4.8",
+ "regex-syntax 0.8.5",
]
[[package]]
@@ -3007,13 +3009,13 @@
[[package]]
name = "regex-automata"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
- "regex-syntax 0.8.4",
+ "regex-syntax 0.8.5",
]
[[package]]
@@ -3030,9 +3032,9 @@
[[package]]
name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "remote-test-client"
@@ -3052,41 +3054,39 @@
[[package]]
name = "rinja"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f28580fecce391f3c0e65a692e5f2b5db258ba2346ee04f355ae56473ab973dc"
+checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5"
dependencies = [
"humansize",
"itoa",
- "num-traits",
"percent-encoding",
"rinja_derive",
]
[[package]]
name = "rinja_derive"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f1ae91455a4c82892d9513fcfa1ac8faff6c523602d0041536341882714aede"
+checksum = "08d9ed0146aef6e2825f1b1515f074510549efba38d71f4554eec32eb36ba18b"
dependencies = [
"basic-toml",
"memchr",
"mime",
"mime_guess",
- "once_map",
"proc-macro2",
"quote",
"rinja_parser",
"rustc-hash 2.0.0",
"serde",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
name = "rinja_parser"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ea17639e1f35032e1c67539856e498c04cd65fe2a45f55ec437ec55e4be941"
+checksum = "93f9a866e2e00a7a1fb27e46e9e324a6f7c0e7edc4543cae1d38f4e4a100c610"
dependencies = [
"memchr",
"nom",
@@ -3106,9 +3106,9 @@
dependencies = [
"bstr",
"build_helper",
- "gimli 0.31.0",
+ "gimli 0.31.1",
"libc",
- "object 0.36.4",
+ "object 0.36.5",
"regex",
"serde_json",
"similar",
@@ -3407,7 +3407,7 @@
"itertools",
"libc",
"measureme",
- "object 0.36.4",
+ "object 0.36.5",
"rustc-demangle",
"rustc_abi",
"rustc_ast",
@@ -3447,7 +3447,7 @@
"itertools",
"jobserver",
"libc",
- "object 0.36.4",
+ "object 0.36.5",
"pathdiff",
"regex",
"rustc_abi",
@@ -3695,7 +3695,7 @@
"fluent-syntax",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"unic-langid",
]
@@ -3830,7 +3830,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -3978,7 +3978,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"synstructure",
]
@@ -4443,7 +4443,7 @@
version = "0.0.0"
dependencies = [
"bitflags 2.6.0",
- "object 0.36.4",
+ "object 0.36.5",
"rustc_abi",
"rustc_data_structures",
"rustc_fs_util",
@@ -4565,7 +4565,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"synstructure",
]
@@ -4654,7 +4654,7 @@
"proc-macro2",
"quote",
"serde",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -4688,9 +4688,9 @@
[[package]]
name = "rustix"
-version = "0.38.37"
+version = "0.38.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
+checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
dependencies = [
"bitflags 2.6.0",
"errno",
@@ -4701,9 +4701,9 @@
[[package]]
name = "rustversion"
-version = "1.0.17"
+version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "ruzstd"
@@ -4731,9 +4731,9 @@
[[package]]
name = "schannel"
-version = "0.1.24"
+version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b"
+checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1"
dependencies = [
"windows-sys 0.59.0",
]
@@ -4776,29 +4776,29 @@
[[package]]
name = "serde"
-version = "1.0.210"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
+checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.210"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
+checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
name = "serde_json"
-version = "1.0.128"
+version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"indexmap",
"itoa",
@@ -5049,9 +5049,9 @@
[[package]]
name = "syn"
-version = "2.0.79"
+version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [
"proc-macro2",
"quote",
@@ -5066,7 +5066,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -5092,9 +5092,9 @@
[[package]]
name = "tar"
-version = "0.4.42"
+version = "0.4.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020"
+checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6"
dependencies = [
"filetime",
"libc",
@@ -5147,12 +5147,12 @@
[[package]]
name = "terminal_size"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
+checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
dependencies = [
"rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -5184,22 +5184,22 @@
[[package]]
name = "thiserror"
-version = "1.0.64"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
+checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.64"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
+checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -5209,8 +5209,8 @@
checksum = "813ba76597db32dc4f6992fd8bf8f394715b88d352fd97401da67dab6283b4c6"
dependencies = [
"gimli 0.30.0",
- "hashbrown",
- "object 0.36.4",
+ "hashbrown 0.14.5",
+ "object 0.36.5",
"tracing",
]
@@ -5312,9 +5312,9 @@
[[package]]
name = "tokio"
-version = "1.40.0"
+version = "1.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
+checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb"
dependencies = [
"backtrace",
"bytes",
@@ -5390,7 +5390,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -5492,9 +5492,9 @@
[[package]]
name = "ucd-trie"
-version = "0.1.6"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "ui_test"
@@ -5561,24 +5561,21 @@
dependencies = [
"proc-macro-hack",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"unic-langid-impl",
]
[[package]]
name = "unicase"
-version = "2.7.0"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
-dependencies = [
- "version_check",
-]
+checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
[[package]]
name = "unicode-bidi"
-version = "0.3.15"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
[[package]]
name = "unicode-ident"
@@ -5597,9 +5594,9 @@
[[package]]
name = "unicode-properties"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
+checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
[[package]]
name = "unicode-script"
@@ -5696,9 +5693,9 @@
[[package]]
name = "uuid"
-version = "1.10.0"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
+checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a"
dependencies = [
"getrandom",
]
@@ -5739,15 +5736,15 @@
[[package]]
name = "wasi-preview1-component-adapter-provider"
-version = "24.0.0"
+version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36e6cadfa74538edd5409b6f8c79628436529138e9618b7373bec7aae7805835"
+checksum = "0f76d9fa52234153eeb40b088de91a8c13dc28a912cf6f31cd89ca4bac9024e0"
[[package]]
name = "wasm-bindgen"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
"once_cell",
@@ -5756,24 +5753,24 @@
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5781,22 +5778,22 @@
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
+checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "wasm-component-ld"
@@ -5809,7 +5806,7 @@
"lexopt",
"tempfile",
"wasi-preview1-component-adapter-provider",
- "wasmparser 0.219.0",
+ "wasmparser 0.219.1",
"wat",
"wit-component",
"wit-parser",
@@ -5833,19 +5830,19 @@
[[package]]
name = "wasm-encoder"
-version = "0.219.0"
+version = "0.219.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2b1b95711b3ad655656a341e301cc64e33cbee94de9a99a1c5a2ab88efab79d"
+checksum = "29cbbd772edcb8e7d524a82ee8cef8dd046fc14033796a754c3ad246d019fa54"
dependencies = [
"leb128",
- "wasmparser 0.219.0",
+ "wasmparser 0.219.1",
]
[[package]]
name = "wasm-metadata"
-version = "0.219.0"
+version = "0.219.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96132fe00dd17d092d2be289eeed5a0a68ad3cf30b68e8875bc953b96f55f0be"
+checksum = "2af5a8e37a5e996861e1813f8de30911c47609c9ff51a7284f7dbd754dc3a9f3"
dependencies = [
"anyhow",
"indexmap",
@@ -5853,8 +5850,8 @@
"serde_derive",
"serde_json",
"spdx",
- "wasm-encoder 0.219.0",
- "wasmparser 0.219.0",
+ "wasm-encoder 0.219.1",
+ "wasmparser 0.219.1",
]
[[package]]
@@ -5869,13 +5866,22 @@
[[package]]
name = "wasmparser"
-version = "0.219.0"
+version = "0.218.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "324b4e56d24439495b88cd81439dad5e97f3c7b1eedc3c7e10455ed1e045e9a2"
+checksum = "b09e46c7fceceaa72b2dd1a8a137ea7fd8f93dfaa69806010a709918e496c5dc"
+dependencies = [
+ "bitflags 2.6.0",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.219.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5"
dependencies = [
"ahash",
"bitflags 2.6.0",
- "hashbrown",
+ "hashbrown 0.14.5",
"indexmap",
"semver",
"serde",
@@ -5883,22 +5889,22 @@
[[package]]
name = "wast"
-version = "219.0.0"
+version = "219.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06880ecb25662bc21db6a83f4fcc27c41f71fbcba4f1980b650c88ada92728e1"
+checksum = "4f79a9d9df79986a68689a6b40bcc8d5d40d807487b235bebc2ac69a242b54a1"
dependencies = [
"bumpalo",
"leb128",
"memchr",
"unicode-width 0.1.14",
- "wasm-encoder 0.219.0",
+ "wasm-encoder 0.219.1",
]
[[package]]
name = "wat"
-version = "1.219.0"
+version = "1.219.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11e56dbf9fc89111b0d97c91e683d7895b1a6e5633a729f2ccad2303724005b6"
+checksum = "8bc3cf014fb336883a411cd662f987abf6a1d2a27f2f0008616a0070bbf6bd0d"
dependencies = [
"wast",
]
@@ -5954,7 +5960,7 @@
"rayon",
"serde",
"serde_json",
- "syn 2.0.79",
+ "syn 2.0.87",
"windows-metadata",
]
@@ -5987,7 +5993,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -5998,7 +6004,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -6175,9 +6181,9 @@
[[package]]
name = "wit-component"
-version = "0.219.0"
+version = "0.219.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99a76111c20444a814019de20499d30940ecd219b9512ee296f034a5edb18a2d"
+checksum = "ad1673163c0cb14a6a19ddbf44dd4efe6f015ec1ebb8156710ac32501f19fba2"
dependencies = [
"anyhow",
"bitflags 2.6.0",
@@ -6186,17 +6192,17 @@
"serde",
"serde_derive",
"serde_json",
- "wasm-encoder 0.219.0",
+ "wasm-encoder 0.219.1",
"wasm-metadata",
- "wasmparser 0.219.0",
+ "wasmparser 0.219.1",
"wit-parser",
]
[[package]]
name = "wit-parser"
-version = "0.219.0"
+version = "0.219.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23102e180c0c464f36e293d31a27b524e3ece930d7b5527d2f33f9d2c963de64"
+checksum = "4a86f669283257e8e424b9a4fc3518e3ade0b95deb9fbc0f93a1876be3eda598"
dependencies = [
"anyhow",
"id-arena",
@@ -6207,7 +6213,7 @@
"serde_derive",
"serde_json",
"unicode-xid",
- "wasmparser 0.219.0",
+ "wasmparser 0.219.1",
]
[[package]]
@@ -6265,7 +6271,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"synstructure",
]
@@ -6287,7 +6293,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
[[package]]
@@ -6307,7 +6313,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
"synstructure",
]
@@ -6330,5 +6336,5 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.79",
+ "syn 2.0.87",
]
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index e5b2828..454fd14 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -27,7 +27,7 @@
};
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
- self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
+ self, ClauseKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
suggest_constraining_type_params,
};
use rustc_middle::util::CallKind;
@@ -39,6 +39,7 @@
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
use tracing::{debug, instrument};
@@ -201,16 +202,15 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
let mut has_suggest_reborrow = false;
if !seen_spans.contains(&move_span) {
- if !closure {
- self.suggest_ref_or_clone(
- mpi,
- &mut err,
- &mut in_pattern,
- move_spans,
- moved_place.as_ref(),
- &mut has_suggest_reborrow,
- );
- }
+ self.suggest_ref_or_clone(
+ mpi,
+ &mut err,
+ &mut in_pattern,
+ move_spans,
+ moved_place.as_ref(),
+ &mut has_suggest_reborrow,
+ closure,
+ );
let msg_opt = CapturedMessageOpt {
is_partial_move,
@@ -266,27 +266,11 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
}
}
- let opt_name = self.describe_place_with_options(place.as_ref(), DescribePlaceOpt {
- including_downcast: true,
- including_tuple_field: true,
- });
- let note_msg = match opt_name {
- Some(name) => format!("`{name}`"),
- None => "value".to_owned(),
- };
- if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, ¬e_msg)
- || if let UseSpans::FnSelfUse { kind, .. } = use_spans
- && let CallKind::FnCall { fn_trait_id, self_ty } = kind
- && let ty::Param(_) = self_ty.kind()
- && ty == self_ty
- && self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce)
- {
- // this is a type parameter `T: FnOnce()`, don't suggest `T: FnOnce() + Clone`.
- true
- } else {
- false
- }
- {
+ if self.param_env.caller_bounds().iter().any(|c| {
+ c.as_trait_clause().is_some_and(|pred| {
+ pred.skip_binder().self_ty() == ty && self.infcx.tcx.is_fn_trait(pred.def_id())
+ })
+ }) {
// Suppress the next suggestion since we don't want to put more bounds onto
// something that already has `Fn`-like bounds (or is a closure), so we can't
// restrict anyways.
@@ -295,6 +279,14 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
self.suggest_adding_bounds(&mut err, ty, copy_did, span);
}
+ let opt_name = self.describe_place_with_options(place.as_ref(), DescribePlaceOpt {
+ including_downcast: true,
+ including_tuple_field: true,
+ });
+ let note_msg = match opt_name {
+ Some(name) => format!("`{name}`"),
+ None => "value".to_owned(),
+ };
if needs_note {
if let Some(local) = place.as_local() {
let span = self.body.local_decls[local].source_info.span;
@@ -341,6 +333,7 @@ fn suggest_ref_or_clone(
move_spans: UseSpans<'tcx>,
moved_place: PlaceRef<'tcx>,
has_suggest_reborrow: &mut bool,
+ moved_or_invoked_closure: bool,
) {
let move_span = match move_spans {
UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
@@ -428,104 +421,76 @@ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
}
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
- let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
+ let (def_id, call_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
{
- (typeck.type_dependent_def_id(parent_expr.hir_id), args, 1)
+ let def_id = typeck.type_dependent_def_id(parent_expr.hir_id);
+ (def_id, Some(parent_expr.hir_id), args, 1)
} else if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
{
- (Some(*def_id), args, 0)
+ (Some(*def_id), Some(call.hir_id), args, 0)
} else {
- (None, &[][..], 0)
+ (None, None, &[][..], 0)
};
+ let ty = place.ty(self.body, self.infcx.tcx).ty;
- // If the moved value is a mut reference, it is used in a
- // generic function and it's type is a generic param, it can be
- // reborrowed to avoid moving.
- // for example:
- // struct Y(u32);
- // x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`.
+ let mut can_suggest_clone = true;
if let Some(def_id) = def_id
- && self.infcx.tcx.def_kind(def_id).is_fn_like()
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
- && let Some(arg) = self
- .infcx
- .tcx
- .fn_sig(def_id)
- .skip_binder()
- .skip_binder()
- .inputs()
- .get(pos + offset)
- && let ty::Param(_) = arg.kind()
{
- let place = &self.move_data.move_paths[mpi].place;
- let ty = place.ty(self.body, self.infcx.tcx).ty;
- if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
+ // The move occurred as one of the arguments to a function call. Is that
+ // argument generic? `def_id` can't be a closure here, so using `fn_sig` is fine
+ let arg_param = if self.infcx.tcx.def_kind(def_id).is_fn_like()
+ && let sig =
+ self.infcx.tcx.fn_sig(def_id).instantiate_identity().skip_binder()
+ && let Some(arg_ty) = sig.inputs().get(pos + offset)
+ && let ty::Param(arg_param) = arg_ty.kind()
+ {
+ Some(arg_param)
+ } else {
+ None
+ };
+
+ // If the moved value is a mut reference, it is used in a
+ // generic function and it's type is a generic param, it can be
+ // reborrowed to avoid moving.
+ // for example:
+ // struct Y(u32);
+ // x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`.
+ if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind()
+ && arg_param.is_some()
+ {
*has_suggest_reborrow = true;
self.suggest_reborrow(err, expr.span, moved_place);
return;
}
- }
- let mut can_suggest_clone = true;
- if let Some(def_id) = def_id
- && let Some(local_def_id) = def_id.as_local()
- && let node = self.infcx.tcx.hir_node_by_def_id(local_def_id)
- && let Some(fn_sig) = node.fn_sig()
- && let Some(ident) = node.ident()
- && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
- && let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
- {
- let mut is_mut = false;
- if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = arg.kind
- && let Res::Def(DefKind::TyParam, param_def_id) = path.res
- && self
- .infcx
- .tcx
- .predicates_of(def_id)
- .instantiate_identity(self.infcx.tcx)
- .predicates
- .into_iter()
- .any(|pred| {
- if let ty::ClauseKind::Trait(predicate) = pred.kind().skip_binder()
- && [
- self.infcx.tcx.get_diagnostic_item(sym::AsRef),
- self.infcx.tcx.get_diagnostic_item(sym::AsMut),
- self.infcx.tcx.get_diagnostic_item(sym::Borrow),
- self.infcx.tcx.get_diagnostic_item(sym::BorrowMut),
- ]
- .contains(&Some(predicate.def_id()))
- && let ty::Param(param) = predicate.self_ty().kind()
- && let generics = self.infcx.tcx.generics_of(def_id)
- && let param = generics.type_param(*param, self.infcx.tcx)
- && param.def_id == param_def_id
- {
- if [
- self.infcx.tcx.get_diagnostic_item(sym::AsMut),
- self.infcx.tcx.get_diagnostic_item(sym::BorrowMut),
- ]
- .contains(&Some(predicate.def_id()))
- {
- is_mut = true;
- }
- true
- } else {
- false
- }
- })
+ // If the moved place is used generically by the callee and a reference to it
+ // would still satisfy any bounds on its type, suggest borrowing.
+ if let Some(¶m) = arg_param
+ && let Some(generic_args) = call_id.and_then(|id| typeck.node_args_opt(id))
+ && let Some(ref_mutability) = self.suggest_borrow_generic_arg(
+ err,
+ def_id,
+ generic_args,
+ param,
+ moved_place,
+ pos + offset,
+ ty,
+ expr.span,
+ )
{
- // The type of the argument corresponding to the expression that got moved
- // is a type parameter `T`, which is has a `T: AsRef` obligation.
- err.span_suggestion_verbose(
- expr.span.shrink_to_lo(),
- "borrow the value to avoid moving it",
- format!("&{}", if is_mut { "mut " } else { "" }),
- Applicability::MachineApplicable,
- );
- can_suggest_clone = is_mut;
- } else {
+ can_suggest_clone = ref_mutability.is_mut();
+ } else if let Some(local_def_id) = def_id.as_local()
+ && let node = self.infcx.tcx.hir_node_by_def_id(local_def_id)
+ && let Some(fn_decl) = node.fn_decl()
+ && let Some(ident) = node.ident()
+ && let Some(arg) = fn_decl.inputs.get(pos + offset)
+ {
+ // If we can't suggest borrowing in the call, but the function definition
+ // is local, instead offer changing the function to borrow that argument.
let mut span: MultiSpan = arg.span.into();
span.push_span_label(
arg.span,
@@ -546,8 +511,6 @@ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
);
}
}
- let place = &self.move_data.move_paths[mpi].place;
- let ty = place.ty(self.body, self.infcx.tcx).ty;
if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
&& let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
@@ -557,6 +520,8 @@ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
} else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans
{
// We already suggest cloning for these cases in `explain_captures`.
+ } else if moved_or_invoked_closure {
+ // Do not suggest `closure.clone()()`.
} else if let UseSpans::ClosureUse {
closure_kind:
ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)),
@@ -665,6 +630,113 @@ pub(crate) fn suggest_reborrow(
);
}
+ /// If a place is used after being moved as an argument to a function, the function is generic
+ /// in that argument, and a reference to the argument's type would still satisfy the function's
+ /// bounds, suggest borrowing. This covers, e.g., borrowing an `impl Fn()` argument being passed
+ /// in an `impl FnOnce()` position.
+ /// Returns `Some(mutability)` when suggesting to borrow with mutability `mutability`, or `None`
+ /// if no suggestion is made.
+ fn suggest_borrow_generic_arg(
+ &self,
+ err: &mut Diag<'_>,
+ callee_did: DefId,
+ generic_args: ty::GenericArgsRef<'tcx>,
+ param: ty::ParamTy,
+ moved_place: PlaceRef<'tcx>,
+ moved_arg_pos: usize,
+ moved_arg_ty: Ty<'tcx>,
+ place_span: Span,
+ ) -> Option<ty::Mutability> {
+ let tcx = self.infcx.tcx;
+ let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
+ let clauses = tcx.predicates_of(callee_did).instantiate_identity(self.infcx.tcx).predicates;
+
+ // First, is there at least one method on one of `param`'s trait bounds?
+ // This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
+ if !clauses.iter().any(|clause| {
+ clause.as_trait_clause().is_some_and(|tc| {
+ tc.self_ty().skip_binder().is_param(param.index)
+ && tc.polarity() == ty::PredicatePolarity::Positive
+ && tcx
+ .supertrait_def_ids(tc.def_id())
+ .flat_map(|trait_did| tcx.associated_items(trait_did).in_definition_order())
+ .any(|item| item.fn_has_self_parameter)
+ })
+ }) {
+ return None;
+ }
+
+ // Try borrowing a shared reference first, then mutably.
+ if let Some(mutbl) = [ty::Mutability::Not, ty::Mutability::Mut].into_iter().find(|&mutbl| {
+ let re = self.infcx.tcx.lifetimes.re_erased;
+ let ref_ty = Ty::new_ref(self.infcx.tcx, re, moved_arg_ty, mutbl);
+
+ // Ensure that substituting `ref_ty` in the callee's signature doesn't break
+ // other inputs or the return type.
+ let new_args = tcx.mk_args_from_iter(generic_args.iter().enumerate().map(
+ |(i, arg)| {
+ if i == param.index as usize { ref_ty.into() } else { arg }
+ },
+ ));
+ let can_subst = |ty: Ty<'tcx>| {
+ // Normalize before comparing to see through type aliases and projections.
+ let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args);
+ let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args);
+ if let Ok(old_ty) = tcx.try_normalize_erasing_regions(self.param_env, old_ty)
+ && let Ok(new_ty) = tcx.try_normalize_erasing_regions(self.param_env, new_ty)
+ {
+ old_ty == new_ty
+ } else {
+ false
+ }
+ };
+ if !can_subst(sig.output())
+ || sig
+ .inputs()
+ .iter()
+ .enumerate()
+ .any(|(i, &input_ty)| i != moved_arg_pos && !can_subst(input_ty))
+ {
+ return false;
+ }
+
+ // Test the callee's predicates, substituting a reference in for the self ty
+ // in bounds on `param`.
+ clauses.iter().all(|&clause| {
+ let clause_for_ref = clause.kind().map_bound(|kind| match kind {
+ ClauseKind::Trait(c) if c.self_ty().is_param(param.index) => {
+ ClauseKind::Trait(c.with_self_ty(tcx, ref_ty))
+ }
+ ClauseKind::Projection(c) if c.self_ty().is_param(param.index) => {
+ ClauseKind::Projection(c.with_self_ty(tcx, ref_ty))
+ }
+ _ => kind,
+ });
+ self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
+ tcx,
+ ObligationCause::dummy(),
+ self.param_env,
+ ty::EarlyBinder::bind(clause_for_ref).instantiate(tcx, generic_args),
+ ))
+ })
+ }) {
+ let place_desc = if let Some(desc) = self.describe_place(moved_place) {
+ format!("`{desc}`")
+ } else {
+ "here".to_owned()
+ };
+ err.span_suggestion_verbose(
+ place_span.shrink_to_lo(),
+ format!("consider {}borrowing {place_desc}", mutbl.mutably_str()),
+ mutbl.ref_prefix_str(),
+ Applicability::MaybeIncorrect,
+ );
+ Some(mutbl)
+ } else {
+ None
+ }
+ }
+
fn report_use_of_uninitialized(
&self,
mpi: MovePathIndex,
@@ -845,74 +917,6 @@ fn suggest_assign_value(
);
}
- fn suggest_borrow_fn_like(
- &self,
- err: &mut Diag<'_>,
- ty: Ty<'tcx>,
- move_sites: &[MoveSite],
- value_name: &str,
- ) -> bool {
- let tcx = self.infcx.tcx;
-
- // Find out if the predicates show that the type is a Fn or FnMut
- let find_fn_kind_from_did = |(pred, _): (ty::Clause<'tcx>, _)| {
- if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
- && pred.self_ty() == ty
- {
- if tcx.is_lang_item(pred.def_id(), LangItem::Fn) {
- return Some(hir::Mutability::Not);
- } else if tcx.is_lang_item(pred.def_id(), LangItem::FnMut) {
- return Some(hir::Mutability::Mut);
- }
- }
- None
- };
-
- // If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
- // borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
- // These types seem reasonably opaque enough that they could be instantiated with their
- // borrowed variants in a function body when we see a move error.
- let borrow_level = match *ty.kind() {
- ty::Param(_) => tcx
- .explicit_predicates_of(self.mir_def_id().to_def_id())
- .predicates
- .iter()
- .copied()
- .find_map(find_fn_kind_from_did),
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx
- .explicit_item_super_predicates(def_id)
- .iter_instantiated_copied(tcx, args)
- .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))),
- ty::Closure(_, args) => match args.as_closure().kind() {
- ty::ClosureKind::Fn => Some(hir::Mutability::Not),
- ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
- _ => None,
- },
- _ => None,
- };
-
- let Some(borrow_level) = borrow_level else {
- return false;
- };
- let sugg = move_sites
- .iter()
- .map(|move_site| {
- let move_out = self.move_data.moves[(*move_site).moi];
- let moved_place = &self.move_data.move_paths[move_out.path].place;
- let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
- let move_span = move_spans.args_or_use();
- let suggestion = borrow_level.ref_prefix_str().to_owned();
- (move_span.shrink_to_lo(), suggestion)
- })
- .collect();
- err.multipart_suggestion_verbose(
- format!("consider {}borrowing {value_name}", borrow_level.mutably_str()),
- sugg,
- Applicability::MaybeIncorrect,
- );
- true
- }
-
/// In a move error that occurs on a call within a loop, we try to identify cases where cloning
/// the value would lead to a logic error. We infer these cases by seeing if the moved value is
/// part of the logic to break the loop, either through an explicit `break` or if the expression
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 1ed702a..489c911 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -882,10 +882,12 @@
SanitizerOptions->SanitizeKernelAddress) {
OptimizerLastEPCallbacks.push_back(
#if LLVM_VERSION_GE(20, 0)
- [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level,
- ThinOrFullLTOPhase phase) {
+ [SanitizerOptions, TM](ModulePassManager &MPM,
+ OptimizationLevel Level,
+ ThinOrFullLTOPhase phase) {
#else
- [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
+ [SanitizerOptions, TM](ModulePassManager &MPM,
+ OptimizationLevel Level) {
#endif
auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
AddressSanitizerOptions opts = AddressSanitizerOptions{
@@ -895,7 +897,12 @@
/*UseAfterScope=*/true,
AsanDetectStackUseAfterReturnMode::Runtime,
};
- MPM.addPass(AddressSanitizerPass(opts));
+ MPM.addPass(AddressSanitizerPass(
+ opts,
+ /*UseGlobalGC*/ true,
+ // UseOdrIndicator should be false on windows machines
+ // https://reviews.llvm.org/D137227
+ !TM->getTargetTriple().isOSWindows()));
});
}
if (SanitizerOptions->SanitizeHWAddress) {
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 757034f..f956353 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -325,6 +325,9 @@ pub fn eval(
match c.kind() {
ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))),
+ ConstKind::Expr(_) => {
+ bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
+ }
_ => Err(tcx.dcx().delayed_bug("Unevaluated `ty::Const` in MIR body").into()),
}
}
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 6da387b..8528a2e 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -1,12 +1,19 @@
monomorphize_abi_error_disabled_vector_type_call =
- ABI error: this function call uses a vector type that requires the `{$required_feature}` target feature, which is not enabled in the caller
+ this function call uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller
.label = function called here
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
monomorphize_abi_error_disabled_vector_type_def =
- ABI error: this function definition uses a vector type that requires the `{$required_feature}` target feature, which is not enabled
+ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled
.label = function defined here
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
+monomorphize_abi_error_unsupported_vector_type_call =
+ this function call uses a SIMD vector type that is not currently supported with the chosen ABI
+ .label = function called here
+monomorphize_abi_error_unsupported_vector_type_def =
+ this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
+ .label = function defined here
+
monomorphize_couldnt_dump_mono_stats =
unexpected error occurred while dumping monomorphization stats: {$error}
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 5048a8d..02865ca 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -110,3 +110,17 @@ pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> {
pub span: Span,
pub required_feature: &'a str,
}
+
+#[derive(LintDiagnostic)]
+#[diag(monomorphize_abi_error_unsupported_vector_type_def)]
+pub(crate) struct AbiErrorUnsupportedVectorTypeDef {
+ #[label]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(monomorphize_abi_error_unsupported_vector_type_call)]
+pub(crate) struct AbiErrorUnsupportedVectorTypeCall {
+ #[label]
+ pub span: Span,
+}
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 221200e..d535959 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -10,7 +10,10 @@
use rustc_target::abi::call::{FnAbi, PassMode};
use rustc_target::abi::{BackendRepr, RegKind};
-use crate::errors::{AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef};
+use crate::errors::{
+ AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef,
+ AbiErrorUnsupportedVectorTypeCall, AbiErrorUnsupportedVectorTypeDef,
+};
fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
match mode {
@@ -23,11 +26,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
}
}
+/// Checks whether a certain function ABI is compatible with the target features currently enabled
+/// for a certain function.
+/// If not, `emit_err` is called, with `Some(feature)` if a certain feature should be enabled and
+/// with `None` if no feature is known that would make the ABI compatible.
fn do_check_abi<'tcx>(
tcx: TyCtxt<'tcx>,
abi: &FnAbi<'tcx, Ty<'tcx>>,
target_feature_def: DefId,
- mut emit_err: impl FnMut(&'static str),
+ mut emit_err: impl FnMut(Option<&'static str>),
) {
let Some(feature_def) = tcx.sess.target.features_for_correct_vector_abi() else {
return;
@@ -40,7 +47,7 @@ fn do_check_abi<'tcx>(
let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
Some((_, feature)) => feature,
None => {
- emit_err("<no available feature for this size>");
+ emit_err(None);
continue;
}
};
@@ -48,7 +55,7 @@ fn do_check_abi<'tcx>(
if !tcx.sess.unstable_target_features.contains(&feature_sym)
&& !codegen_attrs.target_features.iter().any(|x| x.name == feature_sym)
{
- emit_err(feature);
+ emit_err(Some(&feature));
}
}
}
@@ -65,12 +72,21 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
};
do_check_abi(tcx, abi, instance.def_id(), |required_feature| {
let span = tcx.def_span(instance.def_id());
- tcx.emit_node_span_lint(
- ABI_UNSUPPORTED_VECTOR_TYPES,
- CRATE_HIR_ID,
- span,
- AbiErrorDisabledVectorTypeDef { span, required_feature },
- );
+ if let Some(required_feature) = required_feature {
+ tcx.emit_node_span_lint(
+ ABI_UNSUPPORTED_VECTOR_TYPES,
+ CRATE_HIR_ID,
+ span,
+ AbiErrorDisabledVectorTypeDef { span, required_feature },
+ );
+ } else {
+ tcx.emit_node_span_lint(
+ ABI_UNSUPPORTED_VECTOR_TYPES,
+ CRATE_HIR_ID,
+ span,
+ AbiErrorUnsupportedVectorTypeDef { span },
+ );
+ }
})
}
@@ -109,12 +125,21 @@ fn check_call_site_abi<'tcx>(
return;
};
do_check_abi(tcx, callee_abi, caller.def_id(), |required_feature| {
- tcx.emit_node_span_lint(
- ABI_UNSUPPORTED_VECTOR_TYPES,
- CRATE_HIR_ID,
- span,
- AbiErrorDisabledVectorTypeCall { span, required_feature },
- );
+ if let Some(required_feature) = required_feature {
+ tcx.emit_node_span_lint(
+ ABI_UNSUPPORTED_VECTOR_TYPES,
+ CRATE_HIR_ID,
+ span,
+ AbiErrorDisabledVectorTypeCall { span, required_feature },
+ );
+ } else {
+ tcx.emit_node_span_lint(
+ ABI_UNSUPPORTED_VECTOR_TYPES,
+ CRATE_HIR_ID,
+ span,
+ AbiErrorUnsupportedVectorTypeCall { span },
+ );
+ }
});
}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 7f11401..3546e5b 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -683,7 +683,9 @@ fn parse_pat_with_range_pat(
})
{
self.bump();
- self.dcx().emit_err(RemoveLet { span: lo });
+ // Trim extra space after the `let`
+ let span = lo.with_hi(self.token.span.lo());
+ self.dcx().emit_err(RemoveLet { span });
lo = self.token.span;
}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index baa1c2c..8966cfc 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -559,12 +559,6 @@ pub fn is_visible(self, sm: &SourceMap) -> bool {
!self.is_dummy() && sm.is_span_accessible(self)
}
- /// Returns `true` if this span comes from any kind of macro, desugaring or inlining.
- #[inline]
- pub fn from_expansion(self) -> bool {
- !self.ctxt().is_root()
- }
-
/// Returns `true` if `span` originates in a derive-macro's expansion.
pub fn in_derive_expansion(self) -> bool {
matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _))
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index db8170f..9d6c7d2 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -303,6 +303,13 @@ pub fn data_untracked(self) -> SpanData {
}
}
+ /// Returns `true` if this span comes from any kind of macro, desugaring or inlining.
+ #[inline]
+ pub fn from_expansion(self) -> bool {
+ // If the span is fully inferred then ctxt > MAX_CTXT
+ self.inline_ctxt().map_or(true, |ctxt| !ctxt.is_root())
+ }
+
/// Returns `true` if this is a dummy span with any hygienic context.
#[inline]
pub fn is_dummy(self) -> bool {
@@ -370,9 +377,10 @@ pub fn ctxt(self) -> SyntaxContext {
pub fn eq_ctxt(self, other: Span) -> bool {
match (self.inline_ctxt(), other.inline_ctxt()) {
(Ok(ctxt1), Ok(ctxt2)) => ctxt1 == ctxt2,
- (Ok(ctxt), Err(index)) | (Err(index), Ok(ctxt)) => {
- with_span_interner(|interner| ctxt == interner.spans[index].ctxt)
- }
+ // If `inline_ctxt` returns `Ok` the context is <= MAX_CTXT.
+ // If it returns `Err` the span is fully interned and the context is > MAX_CTXT.
+ // As these do not overlap an `Ok` and `Err` result cannot have an equal context.
+ (Ok(_), Err(_)) | (Err(_), Ok(_)) => false,
(Err(index1), Err(index2)) => with_span_interner(|interner| {
interner.spans[index1].ctxt == interner.spans[index2].ctxt
}),
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index b7588b0..8853692 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -586,9 +586,20 @@ pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
// certain size to have their "proper" ABI on each architecture.
// Note that they must be kept sorted by vector size.
const X86_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
- &[(128, "sse"), (256, "avx"), (512, "avx512f")];
+ &[(128, "sse"), (256, "avx"), (512, "avx512f")]; // FIXME: might need changes for AVX10.
const AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")];
+// We might want to add "helium" too.
+const ARM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")];
+
+const POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "altivec")];
+const WASM_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "simd128")];
+const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vector")];
+const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] =
+ &[/*(64, "zvl64b"), */ (128, "v")];
+// Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment.
+const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(128, "vis")*/];
+
impl super::spec::Target {
pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
match &*self.arch {
@@ -613,8 +624,15 @@ pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, Implie
pub fn features_for_correct_vector_abi(&self) -> Option<&'static [(u64, &'static str)]> {
match &*self.arch {
"x86" | "x86_64" => Some(X86_FEATURES_FOR_CORRECT_VECTOR_ABI),
- "aarch64" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI),
- // FIXME: add support for non-tier1 architectures
+ "aarch64" | "arm64ec" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ "arm" => Some(ARM_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ "powerpc" | "powerpc64" => Some(POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ "loongarch64" => Some(&[]), // on-stack ABI, so we complain about all by-val vectors
+ "riscv32" | "riscv64" => Some(RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ "wasm32" | "wasm64" => Some(WASM_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ "s390x" => Some(S390X_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ "sparc" | "sparc64" => Some(SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI),
+ // FIXME: add support for non-tier2 architectures
_ => None,
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 17636d4..fe90066 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -578,16 +578,28 @@ pub fn try_evaluate_const<'tcx>(
(args, param_env)
}
}
- } else {
- // FIXME: We don't check anything on stable as the only way we can wind up with
- // an unevaluated constant containing generic parameters is through array repeat
- // expression counts which have a future compat lint for usage of generic parameters
- // instead of a hard error.
+ } else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
+ // FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
//
- // This codepath is however also reachable by `generic_const_exprs` and some other
- // feature gates which allow constants in the type system to use generic parameters.
- // In theory we should be checking for generic parameters here and returning an error
- // in such cases.
+ // Diagnostics will sometimes replace the identity args of anon consts in
+ // array repeat expr counts with inference variables so we have to handle this
+ // even though it is not something we should ever actually encounter.
+ //
+ // Array repeat expr counts are allowed to syntactically use generic parameters
+ // but must not actually depend on them in order to evalaute succesfully. This means
+ // that it is actually fine to evalaute them in their own environment rather than with
+ // the actually provided generic arguments.
+ tcx.dcx().delayed_bug(
+ "Encountered anon const with inference variable args but no error reported",
+ );
+
+ let args = GenericArgs::identity_for_item(tcx, uv.def);
+ let param_env = tcx.param_env(uv.def);
+ (args, param_env)
+ } else {
+ // FIXME: This codepath is reachable under `associated_const_equality` and in the
+ // future will be reachable by `min_generic_const_args`. We should handle inference
+ // variables and generic parameters properly instead of doing nothing.
(uv.args, param_env)
};
let uv = ty::UnevaluatedConst::new(uv.def, args);
diff --git a/config.example.toml b/config.example.toml
index 2bc79a6..9dc71b1 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -503,8 +503,8 @@
# Set this to "if-unchanged" if you are working on `src/tools`, `tests` or `library` (on CI, `library`
# changes triggers in-tree compiler build) to speed up the build process.
#
-# Set this to `true` to download unconditionally.
-#download-rustc = false
+# Set this to `true` to always download or `false` to always use the in-tree compiler.
+#download-rustc = "if-unchanged"
# Number of codegen units to use for each compiler invocation. A value of 0
# means "the number of cores on this machine", and 1+ is passed through to the
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 772f9b1..70ecac4 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -79,9 +79,9 @@
[[package]]
name = "dlmalloc"
-version = "0.2.6"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3264b043b8e977326c1ee9e723da2c1f8d09a99df52cacf00b4dbce5ac54414d"
+checksum = "d9b5e0d321d61de16390ed273b647ce51605b575916d3c25e6ddf27a1e140035"
dependencies = [
"cfg-if",
"compiler_builtins",
@@ -189,9 +189,9 @@
[[package]]
name = "object"
-version = "0.36.4"
+version = "0.36.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a"
+checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
dependencies = [
"compiler_builtins",
"memchr",
@@ -427,9 +427,9 @@
[[package]]
name = "windows-sys"
-version = "0.52.0"
+version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index c5024a0..bb6dd1d 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1735,7 +1735,7 @@ fn clone(&self) -> Self {
// Pre-allocate memory to allow writing the cloned value directly.
let mut boxed = Self::new_uninit_in(self.1.clone());
unsafe {
- (**self).clone_to_uninit(boxed.as_mut_ptr());
+ (**self).clone_to_uninit(boxed.as_mut_ptr().cast());
boxed.assume_init()
}
}
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 55649d8..66353cc 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -289,40 +289,12 @@ fn clone_subtree<'a, K: Clone, V: Clone, A: Allocator + Clone>(
}
}
-impl<K, Q: ?Sized, A: Allocator + Clone> super::Recover<Q> for BTreeMap<K, SetValZST, A>
-where
- K: Borrow<Q> + Ord,
- Q: Ord,
-{
- type Key = K;
-
- fn get(&self, key: &Q) -> Option<&K> {
- let root_node = self.root.as_ref()?.reborrow();
- match root_node.search_tree(key) {
- Found(handle) => Some(handle.into_kv().0),
- GoDown(_) => None,
- }
- }
-
- fn take(&mut self, key: &Q) -> Option<K> {
- let (map, dormant_map) = DormantMutRef::new(self);
- let root_node = map.root.as_mut()?.borrow_mut();
- match root_node.search_tree(key) {
- Found(handle) => Some(
- OccupiedEntry {
- handle,
- dormant_map,
- alloc: (*map.alloc).clone(),
- _marker: PhantomData,
- }
- .remove_kv()
- .0,
- ),
- GoDown(_) => None,
- }
- }
-
- fn replace(&mut self, key: K) -> Option<K> {
+/// Internal functionality for `BTreeSet`.
+impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
+ pub(super) fn replace(&mut self, key: K) -> Option<K>
+ where
+ K: Ord,
+ {
let (map, dormant_map) = DormantMutRef::new(self);
let root_node =
map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut();
diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs
index c7d0144..b8667d0 100644
--- a/library/alloc/src/collections/btree/mod.rs
+++ b/library/alloc/src/collections/btree/mod.rs
@@ -12,11 +12,3 @@
pub mod set;
mod set_val;
mod split;
-
-trait Recover<Q: ?Sized> {
- type Key;
-
- fn get(&self, key: &Q) -> Option<&Self::Key>;
- fn take(&mut self, key: &Q) -> Option<Self::Key>;
- fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
-}
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index a40209f..8daee60 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -7,7 +7,6 @@
use core::mem::ManuallyDrop;
use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub};
-use super::Recover;
use super::map::{BTreeMap, Keys};
use super::merge_iter::MergeIterInner;
use super::set_val::SetValZST;
@@ -635,7 +634,7 @@ pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
T: Borrow<Q> + Ord,
Q: Ord,
{
- Recover::get(&self.map, value)
+ self.map.get_key_value(value).map(|(k, _)| k)
}
/// Returns `true` if `self` has no elements in common with `other`.
@@ -926,7 +925,7 @@ pub fn replace(&mut self, value: T) -> Option<T>
where
T: Ord,
{
- Recover::replace(&mut self.map, value)
+ self.map.replace(value)
}
/// If the set contains an element equal to the value, removes it from the
@@ -978,7 +977,7 @@ pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
T: Borrow<Q> + Ord,
Q: Ord,
{
- Recover::take(&mut self.map, value)
+ self.map.remove_entry(value).map(|(k, _)| k)
}
/// Retains only the elements specified by the predicate.
diff --git a/library/alloc/src/collections/btree/set_val.rs b/library/alloc/src/collections/btree/set_val.rs
index 80c459b..cf30160 100644
--- a/library/alloc/src/collections/btree/set_val.rs
+++ b/library/alloc/src/collections/btree/set_val.rs
@@ -3,14 +3,14 @@
/// * `BTreeMap<T, ()>` (possible user-defined map)
/// * `BTreeMap<T, SetValZST>` (internal set representation)
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Default)]
-pub struct SetValZST;
+pub(super) struct SetValZST;
/// A trait to differentiate between `BTreeMap` and `BTreeSet` values.
/// Returns `true` only for type `SetValZST`, `false` for all other types (blanket implementation).
/// `TypeId` requires a `'static` lifetime, use of this trait avoids that restriction.
///
/// [`TypeId`]: std::any::TypeId
-pub trait IsSetVal {
+pub(super) trait IsSetVal {
fn is_set_val() -> bool;
}
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 4718264..3a9bd1b 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1876,7 +1876,7 @@ pub fn make_mut(this: &mut Self) -> &mut T {
// Initialize with clone of this.
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
- this_data_ref.clone_to_uninit(in_progress.data_ptr());
+ this_data_ref.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_rc()
};
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 8520c3c..da2d6bb 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -2272,7 +2272,7 @@ pub fn make_mut(this: &mut Self) -> &mut T {
let initialized_clone = unsafe {
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
- this_data_ref.clone_to_uninit(in_progress.data_ptr());
+ this_data_ref.clone_to_uninit(in_progress.data_ptr().cast());
// Cast type of pointer, now that it is initialized.
in_progress.into_arc()
};
diff --git a/library/core/benches/fmt.rs b/library/core/benches/fmt.rs
index 4baefd5..ed478b0 100644
--- a/library/core/benches/fmt.rs
+++ b/library/core/benches/fmt.rs
@@ -149,3 +149,17 @@ fn write_u64_min(bh: &mut Bencher) {
test::black_box(format!("{}", 0u64));
});
}
+
+#[bench]
+fn write_u8_max(bh: &mut Bencher) {
+ bh.iter(|| {
+ test::black_box(format!("{}", u8::MAX));
+ });
+}
+
+#[bench]
+fn write_u8_min(bh: &mut Bencher) {
+ bh.iter(|| {
+ test::black_box(format!("{}", 0u8));
+ });
+}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 6e79e79..974e7ba 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -301,7 +301,7 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
///
/// # Panics
///
- /// Panics if given a radix larger than 36.
+ /// Panics if given a radix smaller than 2 or larger than 36.
///
/// # Examples
///
@@ -319,6 +319,13 @@ pub const fn from_digit(num: u32, radix: u32) -> Option<char> {
/// // this panics
/// '1'.is_digit(37);
/// ```
+ ///
+ /// Passing a small radix, causing a panic:
+ ///
+ /// ```should_panic
+ /// // this panics
+ /// '1'.is_digit(1);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_char_classify", issue = "132241")]
#[inline]
@@ -345,7 +352,7 @@ pub const fn is_digit(self, radix: u32) -> bool {
///
/// # Panics
///
- /// Panics if given a radix larger than 36.
+ /// Panics if given a radix smaller than 2 or larger than 36.
///
/// # Examples
///
@@ -369,24 +376,35 @@ pub const fn is_digit(self, radix: u32) -> bool {
/// // this panics
/// let _ = '1'.to_digit(37);
/// ```
+ /// Passing a small radix, causing a panic:
+ ///
+ /// ```should_panic
+ /// // this panics
+ /// let _ = '1'.to_digit(1);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn to_digit(self, radix: u32) -> Option<u32> {
- // If not a digit, a number greater than radix will be created.
- let mut digit = (self as u32).wrapping_sub('0' as u32);
- if radix > 10 {
- assert!(radix <= 36, "to_digit: radix is too high (maximum 36)");
- if digit < 10 {
- return Some(digit);
- }
- // Force the 6th bit to be set to ensure ascii is lower case.
- digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10);
- }
+ assert!(
+ radix >= 2 && radix <= 36,
+ "to_digit: invalid radix -- radix must be in the range 2 to 36 inclusive"
+ );
+ // check radix to remove letter handling code when radix is a known constant
+ let value = if self > '9' && radix > 10 {
+ // convert ASCII letters to lowercase
+ let lower = self as u32 | 0x20;
+ // convert an ASCII letter to the corresponding value,
+ // non-letters convert to values > 36
+ lower.wrapping_sub('a' as u32) as u64 + 10
+ } else {
+ // convert digit to value, non-digits wrap to values > 36
+ (self as u32).wrapping_sub('0' as u32) as u64
+ };
// FIXME(const-hack): once then_some is const fn, use it here
- if digit < radix { Some(digit) } else { None }
+ if value < radix as u64 { Some(value as u32) } else { None }
}
/// Returns an iterator that yields the hexadecimal Unicode escape of a
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index c5f8bd7..ec1aed5 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -232,20 +232,20 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
pub unsafe trait CloneToUninit {
/// Performs copy-assignment from `self` to `dst`.
///
- /// This is analogous to `std::ptr::write(dst, self.clone())`,
+ /// This is analogous to `std::ptr::write(dst.cast(), self.clone())`,
/// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)).
///
/// Before this function is called, `dst` may point to uninitialized memory.
/// After this function is called, `dst` will point to initialized memory; it will be
- /// sound to create a `&Self` reference from the pointer.
+ /// sound to create a `&Self` reference from the pointer with the [pointer metadata]
+ /// from `self`.
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
- /// * `dst` must be [valid] for writes.
- /// * `dst` must be properly aligned.
- /// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`.
+ /// * `dst` must be [valid] for writes for `std::mem::size_of_val(self)` bytes.
+ /// * `dst` must be properly aligned to `std::mem::align_of_val(self)`.
///
/// [valid]: crate::ptr#safety
/// [pointer metadata]: crate::ptr::metadata()
@@ -266,15 +266,15 @@ pub unsafe trait CloneToUninit {
/// that might have already been created. (For example, if a `[Foo]` of length 3 is being
/// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo`
/// cloned should be dropped.)
- unsafe fn clone_to_uninit(&self, dst: *mut Self);
+ unsafe fn clone_to_uninit(&self, dst: *mut u8);
}
#[unstable(feature = "clone_to_uninit", issue = "126799")]
unsafe impl<T: Clone> CloneToUninit for T {
#[inline]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
// SAFETY: we're calling a specialization with the same contract
- unsafe { <T as self::uninit::CopySpec>::clone_one(self, dst) }
+ unsafe { <T as self::uninit::CopySpec>::clone_one(self, dst.cast::<T>()) }
}
}
@@ -282,7 +282,8 @@ unsafe fn clone_to_uninit(&self, dst: *mut Self) {
unsafe impl<T: Clone> CloneToUninit for [T] {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ let dst: *mut [T] = dst.with_metadata_of(self);
// SAFETY: we're calling a specialization with the same contract
unsafe { <T as self::uninit::CopySpec>::clone_slice(self, dst) }
}
@@ -292,21 +293,21 @@ unsafe fn clone_to_uninit(&self, dst: *mut Self) {
unsafe impl CloneToUninit for str {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
// SAFETY: str is just a [u8] with UTF-8 invariant
- unsafe { self.as_bytes().clone_to_uninit(dst as *mut [u8]) }
+ unsafe { self.as_bytes().clone_to_uninit(dst) }
}
}
#[unstable(feature = "clone_to_uninit", issue = "126799")]
unsafe impl CloneToUninit for crate::ffi::CStr {
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
// SAFETY: For now, CStr is just a #[repr(trasnsparent)] [c_char] with some invariants.
// And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul).
- // The pointer metadata properly preserves the length (NUL included).
+ // The pointer metadata properly preserves the length (so NUL is also copied).
// See: `cstr_metadata_is_length_with_nul` in tests.
- unsafe { self.to_bytes_with_nul().clone_to_uninit(dst as *mut [u8]) }
+ unsafe { self.to_bytes_with_nul().clone_to_uninit(dst) }
}
}
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index c70dbf5..04230b1 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -13,7 +13,7 @@ macro_rules! impl_general_format {
($($t:ident)*) => {
$(impl GeneralFormat for $t {
fn already_rounded_value_should_use_exponential(&self) -> bool {
- let abs = $t::abs_private(*self);
+ let abs = $t::abs(*self);
(abs != 0.0 && abs < 1e-4) || abs >= 1e+16
}
})*
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index d43f25d..f2d7e0f 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -65,11 +65,11 @@ fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::R
if is_nonnegative {
// Accumulate each digit of the number from the least significant
// to the most significant figure.
- for byte in buf.iter_mut().rev() {
+ loop {
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
- byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
curr -= 1;
+ buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
if x == zero {
// No more digits left to accumulate.
break;
@@ -77,11 +77,11 @@ fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::R
}
} else {
// Do the same as above, but accounting for two's complement.
- for byte in buf.iter_mut().rev() {
+ loop {
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
- byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
curr -= 1;
+ buf[curr].write(Self::digit(n.to_u8())); // Store the digit in the buffer.
if x == zero {
// No more digits left to accumulate.
break;
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index b6e22c4..72e34e5 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -85,830 +85,1304 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
unsafe { crate::ptr::drop_in_place(to_drop) }
}
-extern "rust-intrinsic" {
- // N.B., these intrinsics take raw pointers because they mutate aliased
- // memory, which is not valid for either `&` or `&mut`.
+// N.B., these intrinsics take raw pointers because they mutate aliased
+// memory, which is not valid for either `&` or `&mut`.
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Relaxed`] as both the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Acquire`] as both the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange` method by passing
- /// [`Ordering::SeqCst`] as both the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange`].
- #[rustc_nounwind]
- pub fn atomic_cxchg_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Relaxed`] as both the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_relaxed_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_relaxed_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_relaxed_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_acquire_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Acquire`] as both the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_acquire_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_acquire_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_release_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_release_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_release_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_acqrel_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_acqrel_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_acqrel_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_seqcst_relaxed<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_seqcst_acquire<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange` method by passing
+/// [`Ordering::SeqCst`] as both the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchg_seqcst_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Relaxed`] as both the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_relaxed_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_relaxed_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_acquire_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Acquire`] as both the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_acquire_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_acquire_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_release_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_release_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_release_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_acqrel_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_seqcst_acquire<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
- /// Stores a value if the current value is the same as the `old` value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `compare_exchange_weak` method by passing
- /// [`Ordering::SeqCst`] as both the success and failure parameters.
- /// For example, [`AtomicBool::compare_exchange_weak`].
- #[rustc_nounwind]
- pub fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(dst: *mut T, old: T, src: T) -> (T, bool);
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Relaxed`] as both the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_relaxed_relaxed<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Relaxed`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_relaxed_acquire<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Relaxed`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_relaxed_seqcst<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Acquire`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_acquire_relaxed<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Acquire`] as both the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_acquire_acquire<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Acquire`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_acquire_seqcst<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Release`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_release_relaxed<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Release`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_release_acquire<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::Release`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_release_seqcst<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::AcqRel`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_acqrel_relaxed<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::AcqRel`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_acqrel_acquire<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::AcqRel`] and [`Ordering::SeqCst`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_acqrel_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::SeqCst`] and [`Ordering::Relaxed`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_seqcst_relaxed<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::SeqCst`] and [`Ordering::Acquire`] as the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_seqcst_acquire<T: Copy>(
+ _dst: *mut T,
+ _old: T,
+ _src: T,
+) -> (T, bool) {
+ unreachable!()
+}
+/// Stores a value if the current value is the same as the `old` value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `compare_exchange_weak` method by passing
+/// [`Ordering::SeqCst`] as both the success and failure parameters.
+/// For example, [`AtomicBool::compare_exchange_weak`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_cxchgweak_seqcst_seqcst<T: Copy>(_dst: *mut T, _old: T, _src: T) -> (T, bool) {
+ unreachable!()
+}
- /// Loads the current value of the pointer.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `load` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
- #[rustc_nounwind]
- pub fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
- /// Loads the current value of the pointer.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `load` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
- #[rustc_nounwind]
- pub fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
- /// Loads the current value of the pointer.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `load` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
- #[rustc_nounwind]
- pub fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
- /// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model!
- /// In terms of the Rust Abstract Machine, this operation is equivalent to `src.read()`,
- /// i.e., it performs a non-atomic read.
- #[rustc_nounwind]
- pub fn atomic_load_unordered<T: Copy>(src: *const T) -> T;
+/// Loads the current value of the pointer.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `load` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_load_seqcst<T: Copy>(_src: *const T) -> T {
+ unreachable!()
+}
+/// Loads the current value of the pointer.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `load` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_load_acquire<T: Copy>(_src: *const T) -> T {
+ unreachable!()
+}
+/// Loads the current value of the pointer.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `load` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_load_relaxed<T: Copy>(_src: *const T) -> T {
+ unreachable!()
+}
+/// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model!
+/// In terms of the Rust Abstract Machine, this operation is equivalent to `src.read()`,
+/// i.e., it performs a non-atomic read.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_load_unordered<T: Copy>(_src: *const T) -> T {
+ unreachable!()
+}
- /// Stores the value at the specified memory location.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `store` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`].
- #[rustc_nounwind]
- pub fn atomic_store_seqcst<T: Copy>(dst: *mut T, val: T);
- /// Stores the value at the specified memory location.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `store` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`].
- #[rustc_nounwind]
- pub fn atomic_store_release<T: Copy>(dst: *mut T, val: T);
- /// Stores the value at the specified memory location.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `store` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`].
- #[rustc_nounwind]
- pub fn atomic_store_relaxed<T: Copy>(dst: *mut T, val: T);
- /// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model!
- /// In terms of the Rust Abstract Machine, this operation is equivalent to `dst.write(val)`,
- /// i.e., it performs a non-atomic write.
- #[rustc_nounwind]
- pub fn atomic_store_unordered<T: Copy>(dst: *mut T, val: T);
+/// Stores the value at the specified memory location.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `store` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::store`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_store_seqcst<T: Copy>(_dst: *mut T, _val: T) {
+ unreachable!()
+}
+/// Stores the value at the specified memory location.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `store` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::store`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_store_release<T: Copy>(_dst: *mut T, _val: T) {
+ unreachable!()
+}
+/// Stores the value at the specified memory location.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `store` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::store`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_store_relaxed<T: Copy>(_dst: *mut T, _val: T) {
+ unreachable!()
+}
+/// Do NOT use this intrinsic; "unordered" operations do not exist in our memory model!
+/// In terms of the Rust Abstract Machine, this operation is equivalent to `dst.write(val)`,
+/// i.e., it performs a non-atomic write.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_store_unordered<T: Copy>(_dst: *mut T, _val: T) {
+ unreachable!()
+}
- /// Stores the value at the specified memory location, returning the old value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `swap` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`].
- #[rustc_nounwind]
- pub fn atomic_xchg_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Stores the value at the specified memory location, returning the old value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `swap` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`].
- #[rustc_nounwind]
- pub fn atomic_xchg_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Stores the value at the specified memory location, returning the old value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `swap` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`].
- #[rustc_nounwind]
- pub fn atomic_xchg_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Stores the value at the specified memory location, returning the old value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `swap` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`].
- #[rustc_nounwind]
- pub fn atomic_xchg_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Stores the value at the specified memory location, returning the old value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `swap` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`].
- #[rustc_nounwind]
- pub fn atomic_xchg_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Stores the value at the specified memory location, returning the old value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `swap` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::swap`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xchg_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Stores the value at the specified memory location, returning the old value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `swap` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::swap`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xchg_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Stores the value at the specified memory location, returning the old value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `swap` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::swap`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xchg_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Stores the value at the specified memory location, returning the old value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `swap` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::swap`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xchg_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Stores the value at the specified memory location, returning the old value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `swap` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::swap`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xchg_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Adds to the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_add` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- #[rustc_nounwind]
- pub fn atomic_xadd_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Adds to the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_add` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- #[rustc_nounwind]
- pub fn atomic_xadd_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Adds to the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_add` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- #[rustc_nounwind]
- pub fn atomic_xadd_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Adds to the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_add` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- #[rustc_nounwind]
- pub fn atomic_xadd_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Adds to the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_add` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`].
- #[rustc_nounwind]
- pub fn atomic_xadd_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Adds to the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_add` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_add`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xadd_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Adds to the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_add` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_add`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xadd_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Adds to the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_add` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_add`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xadd_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Adds to the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_add` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_add`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xadd_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Adds to the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_add` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_add`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xadd_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Subtract from the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_sub` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- #[rustc_nounwind]
- pub fn atomic_xsub_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Subtract from the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_sub` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- #[rustc_nounwind]
- pub fn atomic_xsub_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Subtract from the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_sub` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- #[rustc_nounwind]
- pub fn atomic_xsub_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Subtract from the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_sub` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- #[rustc_nounwind]
- pub fn atomic_xsub_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Subtract from the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_sub` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
- #[rustc_nounwind]
- pub fn atomic_xsub_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Subtract from the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_sub` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xsub_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Subtract from the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_sub` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xsub_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Subtract from the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_sub` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xsub_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Subtract from the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_sub` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xsub_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Subtract from the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_sub` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicIsize::fetch_sub`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xsub_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Bitwise and with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_and` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`].
- #[rustc_nounwind]
- pub fn atomic_and_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise and with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_and` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`].
- #[rustc_nounwind]
- pub fn atomic_and_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise and with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_and` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`].
- #[rustc_nounwind]
- pub fn atomic_and_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise and with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_and` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`].
- #[rustc_nounwind]
- pub fn atomic_and_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise and with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_and` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`].
- #[rustc_nounwind]
- pub fn atomic_and_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Bitwise and with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_and` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_and`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_and_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise and with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_and` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_and`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_and_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise and with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_and` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_and`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_and_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise and with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_and` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_and`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_and_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise and with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_and` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_and`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_and_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Bitwise nand with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`AtomicBool`] type via the `fetch_nand` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- #[rustc_nounwind]
- pub fn atomic_nand_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise nand with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`AtomicBool`] type via the `fetch_nand` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- #[rustc_nounwind]
- pub fn atomic_nand_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise nand with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`AtomicBool`] type via the `fetch_nand` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- #[rustc_nounwind]
- pub fn atomic_nand_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise nand with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`AtomicBool`] type via the `fetch_nand` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- #[rustc_nounwind]
- pub fn atomic_nand_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise nand with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`AtomicBool`] type via the `fetch_nand` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`].
- #[rustc_nounwind]
- pub fn atomic_nand_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Bitwise nand with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`AtomicBool`] type via the `fetch_nand` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_nand`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_nand_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise nand with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`AtomicBool`] type via the `fetch_nand` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_nand`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_nand_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise nand with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`AtomicBool`] type via the `fetch_nand` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_nand`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_nand_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise nand with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`AtomicBool`] type via the `fetch_nand` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_nand`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_nand_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise nand with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`AtomicBool`] type via the `fetch_nand` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_nand`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_nand_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Bitwise or with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_or` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`].
- #[rustc_nounwind]
- pub fn atomic_or_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise or with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_or` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`].
- #[rustc_nounwind]
- pub fn atomic_or_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise or with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_or` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`].
- #[rustc_nounwind]
- pub fn atomic_or_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise or with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_or` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`].
- #[rustc_nounwind]
- pub fn atomic_or_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise or with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_or` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`].
- #[rustc_nounwind]
- pub fn atomic_or_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Bitwise or with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_or` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_or`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_or_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise or with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_or` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_or`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_or_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise or with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_or` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_or`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_or_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise or with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_or` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_or`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_or_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise or with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_or` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_or`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_or_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Bitwise xor with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_xor` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- #[rustc_nounwind]
- pub fn atomic_xor_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise xor with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_xor` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- #[rustc_nounwind]
- pub fn atomic_xor_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise xor with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_xor` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- #[rustc_nounwind]
- pub fn atomic_xor_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise xor with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_xor` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- #[rustc_nounwind]
- pub fn atomic_xor_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Bitwise xor with the current value, returning the previous value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] types via the `fetch_xor` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`].
- #[rustc_nounwind]
- pub fn atomic_xor_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Bitwise xor with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_xor` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::fetch_xor`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xor_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise xor with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_xor` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::fetch_xor`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xor_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise xor with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_xor` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicBool::fetch_xor`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xor_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise xor with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_xor` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicBool::fetch_xor`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xor_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Bitwise xor with the current value, returning the previous value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] types via the `fetch_xor` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::fetch_xor`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_xor_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Maximum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_max` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_max_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_max` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_max_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_max` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_max_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_max` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_max_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_max` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_max_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Maximum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_max` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_max_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_max` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_max_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_max` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_max_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_max` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_max_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_max` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_max_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Minimum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_min` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_min_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_min` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_min_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_min` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_min_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_min` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_min_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using a signed comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] signed integer types via the `fetch_min` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_min_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Minimum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_min` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicI32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_min_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_min` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicI32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_min_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_min` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicI32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_min_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_min` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicI32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_min_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using a signed comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] signed integer types via the `fetch_min` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicI32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_min_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Minimum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_umin_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_umin_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_umin_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_umin_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Minimum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_min` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`].
- #[rustc_nounwind]
- pub fn atomic_umin_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Minimum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umin_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umin_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umin_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umin_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Minimum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_min` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_min`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umin_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// Maximum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
- /// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_umax_seqcst<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
- /// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_umax_acquire<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
- /// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_umax_release<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
- /// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_umax_acqrel<T: Copy>(dst: *mut T, src: T) -> T;
- /// Maximum with the current value using an unsigned comparison.
- ///
- /// The stabilized version of this intrinsic is available on the
- /// [`atomic`] unsigned integer types via the `fetch_max` method by passing
- /// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`].
- #[rustc_nounwind]
- pub fn atomic_umax_relaxed<T: Copy>(dst: *mut T, src: T) -> T;
+/// Maximum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicU32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umax_seqcst<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicU32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umax_acquire<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+/// [`Ordering::Release`] as the `order`. For example, [`AtomicU32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umax_release<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+/// [`Ordering::AcqRel`] as the `order`. For example, [`AtomicU32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umax_acqrel<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
+/// Maximum with the current value using an unsigned comparison.
+///
+/// The stabilized version of this intrinsic is available on the
+/// [`atomic`] unsigned integer types via the `fetch_max` method by passing
+/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicU32::fetch_max`].
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_umax_relaxed<T: Copy>(_dst: *mut T, _src: T) -> T {
+ unreachable!()
+}
- /// An atomic fence.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::fence`] by passing [`Ordering::SeqCst`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_fence_seqcst();
- /// An atomic fence.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::fence`] by passing [`Ordering::Acquire`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_fence_acquire();
- /// An atomic fence.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::fence`] by passing [`Ordering::Release`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_fence_release();
- /// An atomic fence.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::fence`] by passing [`Ordering::AcqRel`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_fence_acqrel();
+/// An atomic fence.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::fence`] by passing [`Ordering::SeqCst`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_fence_seqcst() {
+ unreachable!()
+}
+/// An atomic fence.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::fence`] by passing [`Ordering::Acquire`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_fence_acquire() {
+ unreachable!()
+}
+/// An atomic fence.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::fence`] by passing [`Ordering::Release`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_fence_release() {
+ unreachable!()
+}
+/// An atomic fence.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::fence`] by passing [`Ordering::AcqRel`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_fence_acqrel() {
+ unreachable!()
+}
- /// A compiler-only memory barrier.
- ///
- /// Memory accesses will never be reordered across this barrier by the
- /// compiler, but no instructions will be emitted for it. This is
- /// appropriate for operations on the same thread that may be preempted,
- /// such as when interacting with signal handlers.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_singlethreadfence_seqcst();
- /// A compiler-only memory barrier.
- ///
- /// Memory accesses will never be reordered across this barrier by the
- /// compiler, but no instructions will be emitted for it. This is
- /// appropriate for operations on the same thread that may be preempted,
- /// such as when interacting with signal handlers.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_singlethreadfence_acquire();
- /// A compiler-only memory barrier.
- ///
- /// Memory accesses will never be reordered across this barrier by the
- /// compiler, but no instructions will be emitted for it. This is
- /// appropriate for operations on the same thread that may be preempted,
- /// such as when interacting with signal handlers.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::compiler_fence`] by passing [`Ordering::Release`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_singlethreadfence_release();
- /// A compiler-only memory barrier.
- ///
- /// Memory accesses will never be reordered across this barrier by the
- /// compiler, but no instructions will be emitted for it. This is
- /// appropriate for operations on the same thread that may be preempted,
- /// such as when interacting with signal handlers.
- ///
- /// The stabilized version of this intrinsic is available in
- /// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`]
- /// as the `order`.
- #[rustc_nounwind]
- pub fn atomic_singlethreadfence_acqrel();
+/// A compiler-only memory barrier.
+///
+/// Memory accesses will never be reordered across this barrier by the
+/// compiler, but no instructions will be emitted for it. This is
+/// appropriate for operations on the same thread that may be preempted,
+/// such as when interacting with signal handlers.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::compiler_fence`] by passing [`Ordering::SeqCst`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_singlethreadfence_seqcst() {
+ unreachable!()
+}
+/// A compiler-only memory barrier.
+///
+/// Memory accesses will never be reordered across this barrier by the
+/// compiler, but no instructions will be emitted for it. This is
+/// appropriate for operations on the same thread that may be preempted,
+/// such as when interacting with signal handlers.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::compiler_fence`] by passing [`Ordering::Acquire`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_singlethreadfence_acquire() {
+ unreachable!()
+}
+/// A compiler-only memory barrier.
+///
+/// Memory accesses will never be reordered across this barrier by the
+/// compiler, but no instructions will be emitted for it. This is
+/// appropriate for operations on the same thread that may be preempted,
+/// such as when interacting with signal handlers.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::compiler_fence`] by passing [`Ordering::Release`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_singlethreadfence_release() {
+ unreachable!()
+}
+/// A compiler-only memory barrier.
+///
+/// Memory accesses will never be reordered across this barrier by the
+/// compiler, but no instructions will be emitted for it. This is
+/// appropriate for operations on the same thread that may be preempted,
+/// such as when interacting with signal handlers.
+///
+/// The stabilized version of this intrinsic is available in
+/// [`atomic::compiler_fence`] by passing [`Ordering::AcqRel`]
+/// as the `order`.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn atomic_singlethreadfence_acqrel() {
+ unreachable!()
+}
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- #[rustc_nounwind]
- pub fn prefetch_read_data<T>(data: *const T, locality: i32);
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- #[rustc_nounwind]
- pub fn prefetch_write_data<T>(data: *const T, locality: i32);
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- #[rustc_nounwind]
- pub fn prefetch_read_instruction<T>(data: *const T, locality: i32);
- /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
- /// if supported; otherwise, it is a no-op.
- /// Prefetches have no effect on the behavior of the program but can change its performance
- /// characteristics.
- ///
- /// The `locality` argument must be a constant integer and is a temporal locality specifier
- /// ranging from (0) - no locality, to (3) - extremely local keep in cache.
- ///
- /// This intrinsic does not have a stable counterpart.
- #[rustc_nounwind]
- pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
+/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+/// if supported; otherwise, it is a no-op.
+/// Prefetches have no effect on the behavior of the program but can change its performance
+/// characteristics.
+///
+/// The `locality` argument must be a constant integer and is a temporal locality specifier
+/// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn prefetch_read_data<T>(_data: *const T, _locality: i32) {
+ unreachable!()
+}
+/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+/// if supported; otherwise, it is a no-op.
+/// Prefetches have no effect on the behavior of the program but can change its performance
+/// characteristics.
+///
+/// The `locality` argument must be a constant integer and is a temporal locality specifier
+/// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn prefetch_write_data<T>(_data: *const T, _locality: i32) {
+ unreachable!()
+}
+/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+/// if supported; otherwise, it is a no-op.
+/// Prefetches have no effect on the behavior of the program but can change its performance
+/// characteristics.
+///
+/// The `locality` argument must be a constant integer and is a temporal locality specifier
+/// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn prefetch_read_instruction<T>(_data: *const T, _locality: i32) {
+ unreachable!()
+}
+/// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+/// if supported; otherwise, it is a no-op.
+/// Prefetches have no effect on the behavior of the program but can change its performance
+/// characteristics.
+///
+/// The `locality` argument must be a constant integer and is a temporal locality specifier
+/// ranging from (0) - no locality, to (3) - extremely local keep in cache.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) {
+ unreachable!()
+}
- /// Executes a breakpoint trap, for inspection by a debugger.
- ///
- /// This intrinsic does not have a stable counterpart.
- #[rustc_nounwind]
- pub fn breakpoint();
+/// Executes a breakpoint trap, for inspection by a debugger.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+pub unsafe fn breakpoint() {
+ unreachable!()
}
/// Magic intrinsic that derives its meaning from attributes
@@ -2989,14 +3463,35 @@ pub const fn const_eval_select<ARG: Tuple, F, G, RET>(
$(#[$compiletime_attr:meta])* $compiletime:block
else
$(#[$runtime_attr:meta])* $runtime:block
+ ) => {
+ // Use the `noinline` arm, after adding explicit `inline` attributes
+ $crate::intrinsics::const_eval_select!(
+ @capture { $($arg : $ty = $val),* } $(-> $ret)? :
+ #[noinline]
+ if const
+ #[inline] // prevent codegen on this function
+ $(#[$compiletime_attr])*
+ $compiletime
+ else
+ #[inline] // avoid the overhead of an extra fn call
+ $(#[$runtime_attr])*
+ $runtime
+ )
+ },
+ // With a leading #[noinline], we don't add inline attributes
+ (
+ @capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
+ #[noinline]
+ if const
+ $(#[$compiletime_attr:meta])* $compiletime:block
+ else
+ $(#[$runtime_attr:meta])* $runtime:block
) => {{
- #[inline] // avoid the overhead of an extra fn call
$(#[$runtime_attr])*
fn runtime($($arg: $ty),*) $( -> $ret )? {
$runtime
}
- #[inline] // prevent codegen on this function
$(#[$compiletime_attr])*
const fn compiletime($($arg: $ty),*) $( -> $ret )? {
// Don't warn if one of the arguments is unused.
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 87bfd0d..6dca740 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -58,7 +58,7 @@
//!
//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
//! a small percentage of possible errors. Far more extensive tests are located in the directory
-//! `src/etc/test-float-parse` as a Python script.
+//! `src/etc/test-float-parse` as a Rust program.
//!
//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 0484611..c3862d9 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -285,17 +285,6 @@ pub const fn is_nan(self) -> bool {
self != self
}
- // FIXME(#50145): `abs` is publicly unavailable in core due to
- // concerns about portability, so this implementation is for
- // private use internally.
- #[inline]
- pub(crate) const fn abs_private(self) -> f128 {
- // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
- unsafe {
- mem::transmute::<u128, f128>(mem::transmute::<f128, u128>(self) & !Self::SIGN_MASK)
- }
- }
-
/// Returns `true` if this value is positive infinity or negative infinity, and
/// `false` otherwise.
///
@@ -345,10 +334,11 @@ pub const fn is_infinite(self) -> bool {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
+ #[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
pub const fn is_finite(self) -> bool {
// There's no need to handle NaN separately: if self is NaN,
// the comparison is not true, exactly as desired.
- self.abs_private() < Self::INFINITY
+ self.abs() < Self::INFINITY
}
/// Returns `true` if the number is [subnormal].
@@ -836,8 +826,8 @@ pub fn midpoint(self, other: f128) -> f128 {
const HI: f128 = f128::MAX / 2.;
let (a, b) = (self, other);
- let abs_a = a.abs_private();
- let abs_b = b.abs_private();
+ let abs_a = a.abs();
+ let abs_b = b.abs();
if abs_a <= HI && abs_b <= HI {
// Overflow is impossible
@@ -1268,8 +1258,9 @@ pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
min <= max,
"min > max, or either was NaN",
"min > max, or either was NaN. min = {min:?}, max = {max:?}",
- min: f128,
- max: f128,
+ // FIXME(f16_f128): Passed by-ref to avoid codegen crashes
+ min: &f128 = &min,
+ max: &f128 = &max,
);
if self < min {
@@ -1280,4 +1271,100 @@ pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
}
self
}
+
+ /// Computes the absolute value of `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
+ ///
+ /// let x = 3.5_f128;
+ /// let y = -3.5_f128;
+ ///
+ /// assert_eq!(x.abs(), x);
+ /// assert_eq!(y.abs(), -y);
+ ///
+ /// assert!(f128::NAN.abs().is_nan());
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub const fn abs(self) -> Self {
+ // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
+ // 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(all(target_arch = "x86_64", target_os = "linux"))] {
+ ///
+ /// 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]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub const 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 same payload as `self` and the sign bit of `sign` is
+ /// returned.
+ ///
+ /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
+ /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f128)]
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
+ ///
+ /// 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]
+ #[unstable(feature = "f128", issue = "116909")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub const fn copysign(self, sign: f128) -> f128 {
+ // SAFETY: this is actually a safe intrinsic
+ unsafe { intrinsics::copysignf128(self, sign) }
+ }
}
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 898caf8..ed35316 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -279,15 +279,6 @@ pub const fn is_nan(self) -> bool {
self != self
}
- // FIXMxE(#50145): `abs` is publicly unavailable in core due to
- // concerns about portability, so this implementation is for
- // private use internally.
- #[inline]
- pub(crate) const fn abs_private(self) -> f16 {
- // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
- unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
- }
-
/// Returns `true` if this value is positive infinity or negative infinity, and
/// `false` otherwise.
///
@@ -335,10 +326,11 @@ pub const fn is_infinite(self) -> bool {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
+ #[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
pub const fn is_finite(self) -> bool {
// There's no need to handle NaN separately: if self is NaN,
// the comparison is not true, exactly as desired.
- self.abs_private() < Self::INFINITY
+ self.abs() < Self::INFINITY
}
/// Returns `true` if the number is [subnormal].
@@ -821,8 +813,8 @@ pub fn midpoint(self, other: f16) -> f16 {
const HI: f16 = f16::MAX / 2.;
let (a, b) = (self, other);
- let abs_a = a.abs_private();
- let abs_b = b.abs_private();
+ let abs_a = a.abs();
+ let abs_b = b.abs();
if abs_a <= HI && abs_b <= HI {
// Overflow is impossible
@@ -1243,8 +1235,9 @@ pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
min <= max,
"min > max, or either was NaN",
"min > max, or either was NaN. min = {min:?}, max = {max:?}",
- min: f16,
- max: f16,
+ // FIXME(f16_f128): Passed by-ref to avoid codegen crashes
+ min: &f16 = &min,
+ max: &f16 = &max,
);
if self < min {
@@ -1255,4 +1248,99 @@ pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
}
self
}
+
+ /// Computes the absolute value of `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
+ ///
+ /// let x = 3.5_f16;
+ /// let y = -3.5_f16;
+ ///
+ /// assert_eq!(x.abs(), x);
+ /// assert_eq!(y.abs(), -y);
+ ///
+ /// assert!(f16::NAN.abs().is_nan());
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub const 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(all(target_arch = "x86_64", target_os = "linux"))] {
+ ///
+ /// 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]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub const 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 same payload as `self` and the sign bit of `sign` is
+ /// returned.
+ ///
+ /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
+ /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(f16)]
+ /// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
+ ///
+ /// 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]
+ #[unstable(feature = "f16", issue = "116909")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ pub const fn copysign(self, sign: f16) -> f16 {
+ // SAFETY: this is actually a safe intrinsic
+ unsafe { intrinsics::copysignf16(self, sign) }
+ }
}
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 20ece88..ae9e69f 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -525,15 +525,6 @@ pub const fn is_nan(self) -> bool {
self != self
}
- // FIXME(#50145): `abs` is publicly unavailable in core due to
- // concerns about portability, so this implementation is for
- // private use internally.
- #[inline]
- pub(crate) const fn abs_private(self) -> f32 {
- // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
- unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & !Self::SIGN_MASK) }
- }
-
/// Returns `true` if this value is positive infinity or negative infinity, and
/// `false` otherwise.
///
@@ -578,10 +569,11 @@ pub const fn is_infinite(self) -> bool {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
#[inline]
+ #[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
pub const fn is_finite(self) -> bool {
// There's no need to handle NaN separately: if self is NaN,
// the comparison is not true, exactly as desired.
- self.abs_private() < Self::INFINITY
+ self.abs() < Self::INFINITY
}
/// Returns `true` if the number is [subnormal].
@@ -1019,8 +1011,8 @@ pub fn midpoint(self, other: f32) -> f32 {
const HI: f32 = f32::MAX / 2.;
let (a, b) = (self, other);
- let abs_a = a.abs_private();
- let abs_b = b.abs_private();
+ let abs_a = a.abs();
+ let abs_b = b.abs();
if abs_a <= HI && abs_b <= HI {
// Overflow is impossible
@@ -1424,4 +1416,87 @@ pub const fn clamp(mut self, min: f32, max: f32) -> f32 {
}
self
}
+
+ /// Computes the absolute value of `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let x = 3.5_f32;
+ /// let y = -3.5_f32;
+ ///
+ /// assert_eq!(x.abs(), x);
+ /// assert_eq!(y.abs(), -y);
+ ///
+ /// assert!(f32::NAN.abs().is_nan());
+ /// ```
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[inline]
+ pub const fn abs(self) -> f32 {
+ // SAFETY: this is actually a safe intrinsic
+ unsafe { intrinsics::fabsf32(self) }
+ }
+
+ /// 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
+ ///
+ /// ```
+ /// let f = 3.5_f32;
+ ///
+ /// assert_eq!(f.signum(), 1.0);
+ /// assert_eq!(f32::NEG_INFINITY.signum(), -1.0);
+ ///
+ /// assert!(f32::NAN.signum().is_nan());
+ /// ```
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[inline]
+ pub const fn signum(self) -> f32 {
+ if self.is_nan() { Self::NAN } else { 1.0_f32.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 same payload as `self` and the sign bit of `sign` is
+ /// returned.
+ ///
+ /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
+ /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let f = 3.5_f32;
+ ///
+ /// assert_eq!(f.copysign(0.42), 3.5_f32);
+ /// assert_eq!(f.copysign(-0.42), -3.5_f32);
+ /// assert_eq!((-f).copysign(0.42), 3.5_f32);
+ /// assert_eq!((-f).copysign(-0.42), -3.5_f32);
+ ///
+ /// assert!(f32::NAN.copysign(1.0).is_nan());
+ /// ```
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[inline]
+ #[stable(feature = "copysign", since = "1.35.0")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ pub const fn copysign(self, sign: f32) -> f32 {
+ // SAFETY: this is actually a safe intrinsic
+ unsafe { intrinsics::copysignf32(self, sign) }
+ }
}
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 5640e71..98dcbff 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -524,15 +524,6 @@ pub const fn is_nan(self) -> bool {
self != self
}
- // FIXME(#50145): `abs` is publicly unavailable in core due to
- // concerns about portability, so this implementation is for
- // private use internally.
- #[inline]
- pub(crate) const fn abs_private(self) -> f64 {
- // SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
- unsafe { mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & !Self::SIGN_MASK) }
- }
-
/// Returns `true` if this value is positive infinity or negative infinity, and
/// `false` otherwise.
///
@@ -577,10 +568,11 @@ pub const fn is_infinite(self) -> bool {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
#[inline]
+ #[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
pub const fn is_finite(self) -> bool {
// There's no need to handle NaN separately: if self is NaN,
// the comparison is not true, exactly as desired.
- self.abs_private() < Self::INFINITY
+ self.abs() < Self::INFINITY
}
/// Returns `true` if the number is [subnormal].
@@ -1022,8 +1014,8 @@ pub fn midpoint(self, other: f64) -> f64 {
const HI: f64 = f64::MAX / 2.;
let (a, b) = (self, other);
- let abs_a = a.abs_private();
- let abs_b = b.abs_private();
+ let abs_a = a.abs();
+ let abs_b = b.abs();
if abs_a <= HI && abs_b <= HI {
// Overflow is impossible
@@ -1424,4 +1416,87 @@ pub const fn clamp(mut self, min: f64, max: f64) -> f64 {
}
self
}
+
+ /// Computes the absolute value of `self`.
+ ///
+ /// This function always returns the precise result.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let x = 3.5_f64;
+ /// let y = -3.5_f64;
+ ///
+ /// assert_eq!(x.abs(), x);
+ /// assert_eq!(y.abs(), -y);
+ ///
+ /// assert!(f64::NAN.abs().is_nan());
+ /// ```
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[inline]
+ pub const fn abs(self) -> f64 {
+ // SAFETY: this is actually a safe intrinsic
+ unsafe { intrinsics::fabsf64(self) }
+ }
+
+ /// 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
+ ///
+ /// ```
+ /// let f = 3.5_f64;
+ ///
+ /// assert_eq!(f.signum(), 1.0);
+ /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
+ ///
+ /// assert!(f64::NAN.signum().is_nan());
+ /// ```
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[inline]
+ pub const fn signum(self) -> f64 {
+ if self.is_nan() { Self::NAN } else { 1.0_f64.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 same payload as `self` and the sign bit of `sign` is
+ /// returned.
+ ///
+ /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
+ /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
+ /// info.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let f = 3.5_f64;
+ ///
+ /// assert_eq!(f.copysign(0.42), 3.5_f64);
+ /// assert_eq!(f.copysign(-0.42), -3.5_f64);
+ /// assert_eq!((-f).copysign(0.42), 3.5_f64);
+ /// assert_eq!((-f).copysign(-0.42), -3.5_f64);
+ ///
+ /// assert!(f64::NAN.copysign(1.0).is_nan());
+ /// ```
+ #[must_use = "method returns a new number and does not mutate the original value"]
+ #[stable(feature = "copysign", since = "1.35.0")]
+ #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+ #[inline]
+ pub const fn copysign(self, sign: f64) -> f64 {
+ // SAFETY: this is actually a safe intrinsic
+ unsafe { intrinsics::copysignf64(self, sign) }
+ }
}
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 550b6a0..568c526 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -763,6 +763,33 @@ pub const fn strict_sub(self, rhs: Self) -> Self {
}
}
+ /// Checked subtraction with a signed integer. Computes `self - rhs`,
+ /// returning `None` if overflow occurred.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(mixed_integer_ops_unsigned_sub)]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(2), None);")]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_signed(-2), Some(3));")]
+ #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_sub_signed(-4), None);")]
+ /// ```
+ #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_sub_signed(self, rhs: $SignedT) -> Option<Self> {
+ let (res, overflow) = self.overflowing_sub_signed(rhs);
+
+ if !overflow {
+ Some(res)
+ } else {
+ None
+ }
+ }
+
#[doc = concat!(
"Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
stringify!($SignedT), "`], returning `None` if overflow occurred."
@@ -1793,6 +1820,35 @@ pub const fn saturating_sub(self, rhs: Self) -> Self {
intrinsics::saturating_sub(self, rhs)
}
+ /// Saturating integer subtraction. Computes `self` - `rhs`, saturating at
+ /// the numeric bounds instead of overflowing.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(mixed_integer_ops_unsigned_sub)]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(2), 0);")]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_sub_signed(-2), 3);")]
+ #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_sub_signed(-4), ", stringify!($SelfT), "::MAX);")]
+ /// ```
+ #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn saturating_sub_signed(self, rhs: $SignedT) -> Self {
+ let (res, overflow) = self.overflowing_sub_signed(rhs);
+
+ if !overflow {
+ res
+ } else if rhs < 0 {
+ Self::MAX
+ } else {
+ 0
+ }
+ }
+
/// Saturating integer multiplication. Computes `self * rhs`,
/// saturating at the numeric bounds instead of overflowing.
///
@@ -1926,6 +1982,27 @@ pub const fn wrapping_sub(self, rhs: Self) -> Self {
intrinsics::wrapping_sub(self, rhs)
}
+ /// Wrapping (modular) subtraction with a signed integer. Computes
+ /// `self - rhs`, wrapping around at the boundary of the type.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(mixed_integer_ops_unsigned_sub)]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(2), ", stringify!($SelfT), "::MAX);")]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_sub_signed(-2), 3);")]
+ #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_sub_signed(-4), 1);")]
+ /// ```
+ #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn wrapping_sub_signed(self, rhs: $SignedT) -> Self {
+ self.wrapping_sub(rhs as Self)
+ }
+
/// Wrapping (modular) multiplication. Computes `self *
/// rhs`, wrapping around at the boundary of the type.
///
@@ -2378,6 +2455,32 @@ pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
(c, b || d)
}
+ /// Calculates `self` - `rhs` with a signed `rhs`
+ ///
+ /// Returns a tuple of the subtraction along with a boolean indicating
+ /// whether an arithmetic overflow would occur. If an overflow would
+ /// have occurred then the wrapped value is returned.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// #![feature(mixed_integer_ops_unsigned_sub)]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(2), (", stringify!($SelfT), "::MAX, true));")]
+ #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_signed(-2), (3, false));")]
+ #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_sub_signed(-4), (1, true));")]
+ /// ```
+ #[unstable(feature = "mixed_integer_ops_unsigned_sub", issue = "126043")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn overflowing_sub_signed(self, rhs: $SignedT) -> (Self, bool) {
+ let (res, overflow) = self.overflowing_sub(rhs as Self);
+
+ (res, overflow ^ (rhs < 0))
+ }
+
/// Computes the absolute difference between `self` and `other`.
///
/// # Examples
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index f8f3962..e702056 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -206,15 +206,16 @@ fn as_str(&mut self) -> Option<&str> {
// add the `rustc_allow_const_fn_unstable`. This is okay to do
// because both variants will panic, just with different messages.
#[rustc_allow_const_fn_unstable(const_eval_select)]
- #[inline(always)]
+ #[inline(always)] // inline the wrapper
#[track_caller]
#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))]
const fn do_panic($($arg: $ty),*) -> ! {
$crate::intrinsics::const_eval_select!(
- @capture { $($arg: $ty),* } -> !:
- if const #[track_caller] {
+ @capture { $($arg: $ty = $arg),* } -> !:
+ #[noinline]
+ if const #[track_caller] #[inline] { // Inline this, to prevent codegen
$crate::panic!($const_msg)
- } else #[track_caller] {
+ } else #[track_caller] { // Do not inline this, it makes perf worse
$crate::panic!($runtime_msg)
}
)
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index ce9d04d..ef52cc4 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -4097,7 +4097,23 @@ pub fn is_sorted(&self) -> bool
where
T: PartialOrd,
{
- self.is_sorted_by(|a, b| a <= b)
+ // This odd number works the best. 32 + 1 extra due to overlapping chunk boundaries.
+ const CHUNK_SIZE: usize = 33;
+ if self.len() < CHUNK_SIZE {
+ return self.windows(2).all(|w| w[0] <= w[1]);
+ }
+ let mut i = 0;
+ // Check in chunks for autovectorization.
+ while i < self.len() - CHUNK_SIZE {
+ let chunk = &self[i..i + CHUNK_SIZE];
+ if !chunk.windows(2).fold(true, |acc, w| acc & (w[0] <= w[1])) {
+ return false;
+ }
+ // We need to ensure that chunk boundaries are also sorted.
+ // Overlap the next chunk with the last element of our last chunk.
+ i += CHUNK_SIZE - 1;
+ }
+ self[i..].windows(2).all(|w| w[0] <= w[1])
}
/// Checks if the elements of this slice are sorted using the given comparator function.
diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs
index 71a3287..054b1d3 100644
--- a/library/core/tests/clone.rs
+++ b/library/core/tests/clone.rs
@@ -28,7 +28,7 @@ fn test_clone_to_uninit_slice_success() {
let mut storage: MaybeUninit<[String; 3]> = MaybeUninit::uninit();
let b: [String; 3] = unsafe {
- a[..].clone_to_uninit(storage.as_mut_ptr() as *mut [String]);
+ a[..].clone_to_uninit(storage.as_mut_ptr().cast());
storage.assume_init()
};
@@ -70,7 +70,7 @@ fn drop(&mut self) {
let mut storage: MaybeUninit<[CountsDropsAndPanics; 3]> = MaybeUninit::uninit();
// This should panic halfway through
unsafe {
- a[..].clone_to_uninit(storage.as_mut_ptr() as *mut [CountsDropsAndPanics]);
+ a[..].clone_to_uninit(storage.as_mut_ptr().cast());
}
})
.unwrap_err();
@@ -89,13 +89,13 @@ fn test_clone_to_uninit_str() {
let a = "hello";
let mut storage: MaybeUninit<[u8; 5]> = MaybeUninit::uninit();
- unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut str) };
+ unsafe { a.clone_to_uninit(storage.as_mut_ptr().cast()) };
assert_eq!(a.as_bytes(), unsafe { storage.assume_init() }.as_slice());
let mut b: Box<str> = "world".into();
assert_eq!(a.len(), b.len());
assert_ne!(a, &*b);
- unsafe { a.clone_to_uninit(ptr::from_mut::<str>(&mut b)) };
+ unsafe { a.clone_to_uninit(ptr::from_mut::<str>(&mut b).cast()) };
assert_eq!(a, &*b);
}
@@ -104,13 +104,13 @@ fn test_clone_to_uninit_cstr() {
let a = c"hello";
let mut storage: MaybeUninit<[u8; 6]> = MaybeUninit::uninit();
- unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut CStr) };
+ unsafe { a.clone_to_uninit(storage.as_mut_ptr().cast()) };
assert_eq!(a.to_bytes_with_nul(), unsafe { storage.assume_init() }.as_slice());
let mut b: Box<CStr> = c"world".into();
assert_eq!(a.count_bytes(), b.count_bytes());
assert_ne!(a, &*b);
- unsafe { a.clone_to_uninit(ptr::from_mut::<CStr>(&mut b)) };
+ unsafe { a.clone_to_uninit(ptr::from_mut::<CStr>(&mut b).cast()) };
assert_eq!(a, &*b);
}
diff --git a/library/profiler_builtins/Cargo.toml b/library/profiler_builtins/Cargo.toml
index 5b10fb5..f94ea9a 100644
--- a/library/profiler_builtins/Cargo.toml
+++ b/library/profiler_builtins/Cargo.toml
@@ -13,4 +13,5 @@
compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] }
[build-dependencies]
-cc = "1.0.97"
+# FIXME: Pinned due to build error when bumped (#132556)
+cc = "=1.1.22"
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 229f979..e93e915 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -188,104 +188,6 @@ pub fn fract(self) -> f128 {
self - self.trunc()
}
- /// Computes the absolute value of `self`.
- ///
- /// This function always returns the precise result.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(f128)]
- /// # #[cfg(reliable_f128)] {
- ///
- /// let x = 3.5_f128;
- /// let y = -3.5_f128;
- ///
- /// assert_eq!(x.abs(), x);
- /// assert_eq!(y.abs(), -y);
- ///
- /// assert!(f128::NAN.abs().is_nan());
- /// # }
- /// ```
- #[inline]
- #[rustc_allow_incoherent_impl]
- #[unstable(feature = "f128", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[must_use = "method returns a new number and does not mutate the original value"]
- pub const fn abs(self) -> Self {
- // FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
- // 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")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[must_use = "method returns a new number and does not mutate the original value"]
- pub const 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 same payload as `self` and the sign bit of `sign` is
- /// returned.
- ///
- /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
- /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) 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")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[must_use = "method returns a new number and does not mutate the original value"]
- pub const 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.
///
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index bed21cd..5b7fcaa 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -188,103 +188,6 @@ pub fn fract(self) -> f16 {
self - self.trunc()
}
- /// Computes the absolute value of `self`.
- ///
- /// This function always returns the precise result.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(f16)]
- /// # #[cfg(reliable_f16)] {
- ///
- /// let x = 3.5_f16;
- /// let y = -3.5_f16;
- ///
- /// assert_eq!(x.abs(), x);
- /// assert_eq!(y.abs(), -y);
- ///
- /// assert!(f16::NAN.abs().is_nan());
- /// # }
- /// ```
- #[inline]
- #[rustc_allow_incoherent_impl]
- #[unstable(feature = "f16", issue = "116909")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[must_use = "method returns a new number and does not mutate the original value"]
- pub const 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")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[must_use = "method returns a new number and does not mutate the original value"]
- pub const 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 same payload as `self` and the sign bit of `sign` is
- /// returned.
- ///
- /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
- /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) 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")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[must_use = "method returns a new number and does not mutate the original value"]
- pub const 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.
///
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 30cf4e1..7cb285b 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -176,90 +176,6 @@ pub fn fract(self) -> f32 {
self - self.trunc()
}
- /// Computes the absolute value of `self`.
- ///
- /// This function always returns the precise result.
- ///
- /// # Examples
- ///
- /// ```
- /// let x = 3.5_f32;
- /// let y = -3.5_f32;
- ///
- /// assert_eq!(x.abs(), x);
- /// assert_eq!(y.abs(), -y);
- ///
- /// assert!(f32::NAN.abs().is_nan());
- /// ```
- #[rustc_allow_incoherent_impl]
- #[must_use = "method returns a new number and does not mutate the original value"]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[inline]
- pub const fn abs(self) -> f32 {
- unsafe { intrinsics::fabsf32(self) }
- }
-
- /// 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
- ///
- /// ```
- /// let f = 3.5_f32;
- ///
- /// assert_eq!(f.signum(), 1.0);
- /// assert_eq!(f32::NEG_INFINITY.signum(), -1.0);
- ///
- /// assert!(f32::NAN.signum().is_nan());
- /// ```
- #[rustc_allow_incoherent_impl]
- #[must_use = "method returns a new number and does not mutate the original value"]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[inline]
- pub const fn signum(self) -> f32 {
- if self.is_nan() { Self::NAN } else { 1.0_f32.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 same payload as `self` and the sign bit of `sign` is
- /// returned.
- ///
- /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
- /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
- /// info.
- ///
- /// # Examples
- ///
- /// ```
- /// let f = 3.5_f32;
- ///
- /// assert_eq!(f.copysign(0.42), 3.5_f32);
- /// assert_eq!(f.copysign(-0.42), -3.5_f32);
- /// assert_eq!((-f).copysign(0.42), 3.5_f32);
- /// assert_eq!((-f).copysign(-0.42), -3.5_f32);
- ///
- /// assert!(f32::NAN.copysign(1.0).is_nan());
- /// ```
- #[rustc_allow_incoherent_impl]
- #[must_use = "method returns a new number and does not mutate the original value"]
- #[inline]
- #[stable(feature = "copysign", since = "1.35.0")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- pub const fn copysign(self, sign: f32) -> f32 {
- unsafe { intrinsics::copysignf32(self, sign) }
- }
-
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error, yielding a more accurate result than an unfused multiply-add.
///
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 51d5476..47163c2 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -176,90 +176,6 @@ pub fn fract(self) -> f64 {
self - self.trunc()
}
- /// Computes the absolute value of `self`.
- ///
- /// This function always returns the precise result.
- ///
- /// # Examples
- ///
- /// ```
- /// let x = 3.5_f64;
- /// let y = -3.5_f64;
- ///
- /// assert_eq!(x.abs(), x);
- /// assert_eq!(y.abs(), -y);
- ///
- /// assert!(f64::NAN.abs().is_nan());
- /// ```
- #[rustc_allow_incoherent_impl]
- #[must_use = "method returns a new number and does not mutate the original value"]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[inline]
- pub const fn abs(self) -> f64 {
- unsafe { intrinsics::fabsf64(self) }
- }
-
- /// 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
- ///
- /// ```
- /// let f = 3.5_f64;
- ///
- /// assert_eq!(f.signum(), 1.0);
- /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
- ///
- /// assert!(f64::NAN.signum().is_nan());
- /// ```
- #[rustc_allow_incoherent_impl]
- #[must_use = "method returns a new number and does not mutate the original value"]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[inline]
- pub const fn signum(self) -> f64 {
- if self.is_nan() { Self::NAN } else { 1.0_f64.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 same payload as `self` and the sign bit of `sign` is
- /// returned.
- ///
- /// If `sign` is a NaN, then this operation will still carry over its sign into the result. 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 `copysign` with `sign` being a NaN might produce an unexpected or non-portable
- /// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
- /// info.
- ///
- /// # Examples
- ///
- /// ```
- /// let f = 3.5_f64;
- ///
- /// assert_eq!(f.copysign(0.42), 3.5_f64);
- /// assert_eq!(f.copysign(-0.42), -3.5_f64);
- /// assert_eq!((-f).copysign(0.42), 3.5_f64);
- /// assert_eq!((-f).copysign(-0.42), -3.5_f64);
- ///
- /// assert!(f64::NAN.copysign(1.0).is_nan());
- /// ```
- #[rustc_allow_incoherent_impl]
- #[must_use = "method returns a new number and does not mutate the original value"]
- #[stable(feature = "copysign", since = "1.35.0")]
- #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
- #[inline]
- pub const fn copysign(self, sign: f64) -> f64 {
- unsafe { intrinsics::copysignf64(self, sign) }
- }
-
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error, yielding a more accurate result than an unfused multiply-add.
///
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index b19d482..79dfb47 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -112,7 +112,7 @@ impl crate::sealed::Sealed for OsString {}
/// [conversions]: super#conversions
#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
#[stable(feature = "rust1", since = "1.0.0")]
-// `OsStr::from_inner` current implementation relies
+// `OsStr::from_inner` and `impl CloneToUninit for OsStr` current implementation relies
// on `OsStr` being layout-compatible with `Slice`.
// However, `OsStr` layout is considered an implementation detail and must not be relied upon.
#[repr(transparent)]
@@ -1278,9 +1278,9 @@ fn clone(&self) -> Self {
unsafe impl CloneToUninit for OsStr {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
- // SAFETY: we're just a wrapper around a platform-specific Slice
- unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around a platform-specific Slice
+ unsafe { self.inner.clone_to_uninit(dst) }
}
}
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index 6714793..cbec44c 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -294,12 +294,12 @@ fn clone_to_uninit() {
let a = OsStr::new("hello.txt");
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
- unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut OsStr) };
+ unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
let mut b: Box<OsStr> = OsStr::new("world.exe").into();
assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
assert_ne!(a, &*b);
- unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b)) };
+ unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b).cast()) };
assert_eq!(a, &*b);
}
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 05efed6..018e195 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -204,6 +204,13 @@ fn file_test_io_seek_and_write() {
}
#[test]
+#[cfg(any(
+ windows,
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+))]
fn file_lock_multiple_shared() {
let tmpdir = tmpdir();
let filename = &tmpdir.join("file_lock_multiple_shared_test.txt");
@@ -220,6 +227,13 @@ fn file_lock_multiple_shared() {
}
#[test]
+#[cfg(any(
+ windows,
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+))]
fn file_lock_blocking() {
let tmpdir = tmpdir();
let filename = &tmpdir.join("file_lock_blocking_test.txt");
@@ -237,6 +251,13 @@ fn file_lock_blocking() {
}
#[test]
+#[cfg(any(
+ windows,
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+))]
fn file_lock_drop() {
let tmpdir = tmpdir();
let filename = &tmpdir.join("file_lock_dup_test.txt");
@@ -251,6 +272,13 @@ fn file_lock_drop() {
}
#[test]
+#[cfg(any(
+ windows,
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+))]
fn file_lock_dup() {
let tmpdir = tmpdir();
let filename = &tmpdir.join("file_lock_dup_test.txt");
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 71dfd06..21e7077 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1340,6 +1340,25 @@ pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
bufs[0].advance(left);
}
}
+
+ /// Get the underlying bytes as a mutable slice with the original lifetime.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(io_slice_as_bytes)]
+ /// use std::io::IoSliceMut;
+ ///
+ /// let mut data = *b"abcdef";
+ /// let io_slice = IoSliceMut::new(&mut data);
+ /// io_slice.into_slice()[0] = b'A';
+ ///
+ /// assert_eq!(&data, b"Abcdef");
+ /// ```
+ #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ self.0.into_slice()
+ }
}
#[stable(feature = "iovec", since = "1.36.0")]
@@ -1482,6 +1501,32 @@ pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
bufs[0].advance(left);
}
}
+
+ /// Get the underlying bytes as a slice with the original lifetime.
+ ///
+ /// This doesn't borrow from `self`, so is less restrictive than calling
+ /// `.deref()`, which does.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(io_slice_as_bytes)]
+ /// use std::io::IoSlice;
+ ///
+ /// let data = b"abcdef";
+ ///
+ /// let mut io_slice = IoSlice::new(data);
+ /// let tail = &io_slice.as_slice()[3..];
+ ///
+ /// // This works because `tail` doesn't borrow `io_slice`
+ /// io_slice = IoSlice::new(tail);
+ ///
+ /// assert_eq!(io_slice.as_slice(), b"def");
+ /// ```
+ #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
+ pub const fn as_slice(self) -> &'a [u8] {
+ self.0.as_slice()
+ }
}
#[stable(feature = "iovec", since = "1.36.0")]
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index 56b71c4..89e806c 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -531,6 +531,20 @@ fn io_slice_advance_slices_beyond_total_length() {
assert!(bufs.is_empty());
}
+#[test]
+fn io_slice_as_slice() {
+ let buf = [1; 8];
+ let slice = IoSlice::new(&buf).as_slice();
+ assert_eq!(slice, buf);
+}
+
+#[test]
+fn io_slice_into_slice() {
+ let mut buf = [1; 8];
+ let slice = IoSliceMut::new(&mut buf).into_slice();
+ assert_eq!(slice, [1; 8]);
+}
+
/// 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 {
diff --git a/library/std/src/os/nuttx/raw.rs b/library/std/src/os/nuttx/raw.rs
index 113079c..431e66d 100644
--- a/library/std/src/os/nuttx/raw.rs
+++ b/library/std/src/os/nuttx/raw.rs
@@ -1,4 +1,4 @@
-//! rtems raw type definitions
+//! NuttX raw type definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
#![deprecated(
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 5662a44..b0291e3 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2128,7 +2128,7 @@ fn as_ref(&self) -> &OsStr {
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
#[stable(feature = "rust1", since = "1.0.0")]
-// `Path::new` current implementation relies
+// `Path::new` and `impl CloneToUninit for Path` current implementation relies
// on `Path` being layout-compatible with `OsStr`.
// However, `Path` layout is considered an implementation detail and must not be relied upon.
#[repr(transparent)]
@@ -3170,9 +3170,9 @@ pub fn into_path_buf(self: Box<Path>) -> PathBuf {
unsafe impl CloneToUninit for Path {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
- // SAFETY: Path is just a wrapper around OsStr
- unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: Path is just a transparent wrapper around OsStr
+ unsafe { self.inner.clone_to_uninit(dst) }
}
}
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index b75793d..ff3f715 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -2068,7 +2068,7 @@ fn clone_to_uninit() {
let a = Path::new("hello.txt");
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
- unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut Path) };
+ unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
MaybeUninit::slice_assume_init_ref(&storage)
});
@@ -2076,6 +2076,6 @@ fn clone_to_uninit() {
let mut b: Box<Path> = Path::new("world.exe").into();
assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
assert_ne!(a, &*b);
- unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b)) };
+ unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b).cast()) };
assert_eq!(a, &*b);
}
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 8e0609f..5b65d86 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -352,8 +352,8 @@ pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
unsafe impl CloneToUninit for Slice {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
- // SAFETY: we're just a wrapper around [u8]
- unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around [u8]
+ unsafe { self.inner.clone_to_uninit(dst) }
}
}
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index b383438..a4ad596 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -275,8 +275,8 @@ pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
unsafe impl CloneToUninit for Slice {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
- // SAFETY: we're just a wrapper around Wtf8
- unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around Wtf8
+ unsafe { self.inner.clone_to_uninit(dst) }
}
}
diff --git a/library/std/src/sys/pal/hermit/io.rs b/library/std/src/sys/pal/hermit/io.rs
index aad1eef..0424a1a 100644
--- a/library/std/src/sys/pal/hermit/io.rs
+++ b/library/std/src/sys/pal/hermit/io.rs
@@ -33,7 +33,7 @@ pub fn advance(&mut self, n: usize) {
}
#[inline]
- pub fn as_slice(&self) -> &[u8] {
+ pub const fn as_slice(&self) -> &'a [u8] {
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}
@@ -71,6 +71,11 @@ pub fn as_slice(&self) -> &[u8] {
}
#[inline]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+ }
+
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
diff --git a/library/std/src/sys/pal/solid/io.rs b/library/std/src/sys/pal/solid/io.rs
index 4b1f788..9ef4b70 100644
--- a/library/std/src/sys/pal/solid/io.rs
+++ b/library/std/src/sys/pal/solid/io.rs
@@ -33,7 +33,7 @@ pub fn advance(&mut self, n: usize) {
}
#[inline]
- pub fn as_slice(&self) -> &[u8] {
+ pub const fn as_slice(&self) -> &'a [u8] {
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}
@@ -71,6 +71,11 @@ pub fn as_slice(&self) -> &[u8] {
}
#[inline]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+ }
+
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index be23638..96f99ef 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -1254,16 +1254,54 @@ unsafe fn os_datasync(fd: c_int) -> c_int {
}
}
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ ))]
pub fn lock(&self) -> io::Result<()> {
cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_EX) })?;
return Ok(());
}
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ )))]
+ pub fn lock(&self) -> io::Result<()> {
+ Err(io::const_io_error!(io::ErrorKind::Unsupported, "lock() not supported"))
+ }
+
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ ))]
pub fn lock_shared(&self) -> io::Result<()> {
cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_SH) })?;
return Ok(());
}
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ )))]
+ pub fn lock_shared(&self) -> io::Result<()> {
+ Err(io::const_io_error!(io::ErrorKind::Unsupported, "lock_shared() not supported"))
+ }
+
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ ))]
pub fn try_lock(&self) -> io::Result<bool> {
let result = cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) });
if let Err(ref err) = result {
@@ -1275,6 +1313,22 @@ pub fn try_lock(&self) -> io::Result<bool> {
return Ok(true);
}
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ )))]
+ pub fn try_lock(&self) -> io::Result<bool> {
+ Err(io::const_io_error!(io::ErrorKind::Unsupported, "try_lock() not supported"))
+ }
+
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ ))]
pub fn try_lock_shared(&self) -> io::Result<bool> {
let result = cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_SH | libc::LOCK_NB) });
if let Err(ref err) = result {
@@ -1286,11 +1340,37 @@ pub fn try_lock_shared(&self) -> io::Result<bool> {
return Ok(true);
}
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ )))]
+ pub fn try_lock_shared(&self) -> io::Result<bool> {
+ Err(io::const_io_error!(io::ErrorKind::Unsupported, "try_lock_shared() not supported"))
+ }
+
+ #[cfg(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ ))]
pub fn unlock(&self) -> io::Result<()> {
cvt(unsafe { libc::flock(self.as_raw_fd(), libc::LOCK_UN) })?;
return Ok(());
}
+ #[cfg(not(any(
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "netbsd",
+ target_vendor = "apple",
+ )))]
+ pub fn unlock(&self) -> io::Result<()> {
+ Err(io::const_io_error!(io::ErrorKind::Unsupported, "unlock() not supported"))
+ }
+
pub fn truncate(&self, size: u64) -> io::Result<()> {
let size: off64_t =
size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
diff --git a/library/std/src/sys/pal/unix/io.rs b/library/std/src/sys/pal/unix/io.rs
index 181c35a..0d5a152 100644
--- a/library/std/src/sys/pal/unix/io.rs
+++ b/library/std/src/sys/pal/unix/io.rs
@@ -33,7 +33,7 @@ pub fn advance(&mut self, n: usize) {
}
#[inline]
- pub fn as_slice(&self) -> &[u8] {
+ pub const fn as_slice(&self) -> &'a [u8] {
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}
@@ -71,6 +71,11 @@ pub fn as_slice(&self) -> &[u8] {
}
#[inline]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
+ }
+
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
diff --git a/library/std/src/sys/pal/unsupported/io.rs b/library/std/src/sys/pal/unsupported/io.rs
index 6372fca..604735d 100644
--- a/library/std/src/sys/pal/unsupported/io.rs
+++ b/library/std/src/sys/pal/unsupported/io.rs
@@ -15,7 +15,7 @@ pub fn advance(&mut self, n: usize) {
}
#[inline]
- pub fn as_slice(&self) -> &[u8] {
+ pub const fn as_slice(&self) -> &'a [u8] {
self.0
}
}
@@ -41,6 +41,11 @@ pub fn as_slice(&self) -> &[u8] {
}
#[inline]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ self.0
+ }
+
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.0
}
diff --git a/library/std/src/sys/pal/wasi/io.rs b/library/std/src/sys/pal/wasi/io.rs
index b7c2f03..57f81bc 100644
--- a/library/std/src/sys/pal/wasi/io.rs
+++ b/library/std/src/sys/pal/wasi/io.rs
@@ -30,7 +30,7 @@ pub fn advance(&mut self, n: usize) {
}
#[inline]
- pub fn as_slice(&self) -> &[u8] {
+ pub const fn as_slice(&self) -> &'a [u8] {
unsafe { slice::from_raw_parts(self.vec.buf as *const u8, self.vec.buf_len) }
}
}
@@ -68,6 +68,11 @@ pub fn as_slice(&self) -> &[u8] {
}
#[inline]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.buf_len) }
+ }
+
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.buf_len) }
}
diff --git a/library/std/src/sys/pal/windows/io.rs b/library/std/src/sys/pal/windows/io.rs
index 1e7d029..f2865d2 100644
--- a/library/std/src/sys/pal/windows/io.rs
+++ b/library/std/src/sys/pal/windows/io.rs
@@ -36,7 +36,7 @@ pub fn advance(&mut self, n: usize) {
}
#[inline]
- pub fn as_slice(&self) -> &[u8] {
+ pub const fn as_slice(&self) -> &'a [u8] {
unsafe { slice::from_raw_parts(self.vec.buf, self.vec.len as usize) }
}
}
@@ -75,6 +75,11 @@ pub fn as_slice(&self) -> &[u8] {
}
#[inline]
+ pub const fn into_slice(self) -> &'a mut [u8] {
+ unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) }
+ }
+
+ #[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.buf, self.vec.len as usize) }
}
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 19d4c94..666942b 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -1052,8 +1052,8 @@ fn hash<H: Hasher>(&self, state: &mut H) {
unsafe impl CloneToUninit for Wtf8 {
#[inline]
#[cfg_attr(debug_assertions, track_caller)]
- unsafe fn clone_to_uninit(&self, dst: *mut Self) {
- // SAFETY: we're just a wrapper around [u8]
- unsafe { self.bytes.clone_to_uninit(&raw mut (*dst).bytes) }
+ unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+ // SAFETY: we're just a transparent wrapper around [u8]
+ unsafe { self.bytes.clone_to_uninit(dst) }
}
}
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index 147939d2..57a0ca5 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -19,6 +19,7 @@
# Forces frame pointers to be used with `-Cforce-frame-pointers`.
# This can be helpful for profiling at a small performance cost.
frame-pointers = true
+download-rustc = false
[llvm]
# Having this set to true disrupts compiler development workflows for people who use `llvm.download-ci-llvm = true`
diff --git a/src/bootstrap/defaults/config.dist.toml b/src/bootstrap/defaults/config.dist.toml
index d4feffe..4346a9c 100644
--- a/src/bootstrap/defaults/config.dist.toml
+++ b/src/bootstrap/defaults/config.dist.toml
@@ -11,6 +11,7 @@
# Most users installing from source want to build all parts of the project from source.
[llvm]
download-ci-llvm = false
+
[rust]
# We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`).
# Make sure they don't get set when installing from source.
diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml
index 3d697be..67ceb22 100644
--- a/src/bootstrap/defaults/config.library.toml
+++ b/src/bootstrap/defaults/config.library.toml
@@ -8,11 +8,9 @@
[rust]
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
incremental = true
-# Download rustc from CI instead of building it from source.
-# For stage > 1 builds, this cuts compile times significantly when there are no changes on "compiler" tree.
-download-rustc = "if-unchanged"
# Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
lto = "off"
+download-rustc = false
[llvm]
# Will download LLVM from CI if available on your platform.
diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml
index 27c1d1c..76b47a8 100644
--- a/src/bootstrap/defaults/config.tools.toml
+++ b/src/bootstrap/defaults/config.tools.toml
@@ -3,11 +3,6 @@
[rust]
# This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower.
incremental = true
-# Download rustc from CI instead of building it from source.
-# For stage > 1 builds, this cuts compile times significantly when there are no changes on "compiler" tree.
-# Using these defaults will download the stage2 compiler (see `download-rustc`
-# setting) and the stage2 toolchain should therefore be used for these defaults.
-download-rustc = "if-unchanged"
[build]
# Document with the in-tree rustdoc by default, since `download-rustc` makes it quick to compile.
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index 0406906..d857de9 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -226,6 +226,8 @@ fn do_op<F>(path: &Path, desc: &str, mut f: F)
Err(ref e) if e.kind() == ErrorKind::PermissionDenied => {
let m = t!(path.symlink_metadata());
let mut p = m.permissions();
+ // this os not unix, so clippy gives FP
+ #[expect(clippy::permissions_set_readonly_false)]
p.set_readonly(false);
t!(fs::set_permissions(path, p));
f(path).unwrap_or_else(|e| {
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index 6fb37e8..0884d86 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -20,14 +20,12 @@
"wrong_self_convention",
];
-fn lint_args(builder: &Builder<'_>, ignored_rules: &[&str]) -> Vec<String> {
+fn lint_args(builder: &Builder<'_>, config: &LintConfig, ignored_rules: &[&str]) -> Vec<String> {
fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
arr.iter().copied().map(String::from)
}
- let Subcommand::Clippy { fix, allow_dirty, allow_staged, allow, deny, warn, forbid } =
- &builder.config.cmd
- else {
+ let Subcommand::Clippy { fix, allow_dirty, allow_staged, .. } = &builder.config.cmd else {
unreachable!("clippy::lint_args can only be called from `clippy` subcommands.");
};
@@ -53,12 +51,12 @@ fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
args.extend(strings(&["--"]));
- if deny.is_empty() && forbid.is_empty() {
+ if config.deny.is_empty() && config.forbid.is_empty() {
args.extend(strings(&["--cap-lints", "warn"]));
}
let all_args = std::env::args().collect::<Vec<_>>();
- args.extend(get_clippy_rules_in_order(&all_args, allow, deny, warn, forbid));
+ args.extend(get_clippy_rules_in_order(&all_args, config));
args.extend(ignored_rules.iter().map(|lint| format!("-Aclippy::{}", lint)));
args.extend(builder.config.free_args.clone());
@@ -68,21 +66,17 @@ fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
/// We need to keep the order of the given clippy lint rules before passing them.
/// Since clap doesn't offer any useful interface for this purpose out of the box,
/// we have to handle it manually.
-pub(crate) fn get_clippy_rules_in_order(
- all_args: &[String],
- allow_rules: &[String],
- deny_rules: &[String],
- warn_rules: &[String],
- forbid_rules: &[String],
-) -> Vec<String> {
+pub fn get_clippy_rules_in_order(all_args: &[String], config: &LintConfig) -> Vec<String> {
let mut result = vec![];
for (prefix, item) in
- [("-A", allow_rules), ("-D", deny_rules), ("-W", warn_rules), ("-F", forbid_rules)]
+ [("-A", &config.allow), ("-D", &config.deny), ("-W", &config.warn), ("-F", &config.forbid)]
{
item.iter().for_each(|v| {
let rule = format!("{prefix}{v}");
- let position = all_args.iter().position(|t| t == &rule || t == v).unwrap();
+ // Arguments added by bootstrap in LintConfig won't show up in the all_args list, so
+ // put them at the end of the command line.
+ let position = all_args.iter().position(|t| t == &rule || t == v).unwrap_or(usize::MAX);
result.push((position, rule));
});
}
@@ -92,8 +86,41 @@ pub(crate) fn get_clippy_rules_in_order(
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LintConfig {
+ pub allow: Vec<String>,
+ pub warn: Vec<String>,
+ pub deny: Vec<String>,
+ pub forbid: Vec<String>,
+}
+
+impl LintConfig {
+ fn new(builder: &Builder<'_>) -> Self {
+ match builder.config.cmd.clone() {
+ Subcommand::Clippy { allow, deny, warn, forbid, .. } => {
+ Self { allow, warn, deny, forbid }
+ }
+ _ => unreachable!("LintConfig can only be called from `clippy` subcommands."),
+ }
+ }
+
+ fn merge(&self, other: &Self) -> Self {
+ let merged = |self_attr: &[String], other_attr: &[String]| -> Vec<String> {
+ self_attr.iter().cloned().chain(other_attr.iter().cloned()).collect()
+ };
+ // This is written this way to ensure we get a compiler error if we add a new field.
+ Self {
+ allow: merged(&self.allow, &other.allow),
+ warn: merged(&self.warn, &other.warn),
+ deny: merged(&self.deny, &other.deny),
+ forbid: merged(&self.forbid, &other.forbid),
+ }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Std {
pub target: TargetSelection,
+ config: LintConfig,
/// Whether to lint only a subset of crates.
crates: Vec<String>,
}
@@ -108,7 +135,8 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
fn make_run(run: RunConfig<'_>) {
let crates = std_crates_for_run_make(&run);
- run.builder.ensure(Std { target: run.target, crates });
+ let config = LintConfig::new(run.builder);
+ run.builder.ensure(Std { target: run.target, config, crates });
}
fn run(self, builder: &Builder<'_>) {
@@ -138,7 +166,7 @@ fn run(self, builder: &Builder<'_>) {
run_cargo(
builder,
cargo,
- lint_args(builder, IGNORED_RULES_FOR_STD_AND_RUSTC),
+ lint_args(builder, &self.config, IGNORED_RULES_FOR_STD_AND_RUSTC),
&libstd_stamp(builder, compiler, target),
vec![],
true,
@@ -150,6 +178,7 @@ fn run(self, builder: &Builder<'_>) {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
pub target: TargetSelection,
+ config: LintConfig,
/// Whether to lint only a subset of crates.
crates: Vec<String>,
}
@@ -165,7 +194,8 @@ 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 });
+ let config = LintConfig::new(run.builder);
+ run.builder.ensure(Rustc { target: run.target, config, crates });
}
/// Lints the compiler.
@@ -212,7 +242,7 @@ fn run(self, builder: &Builder<'_>) {
run_cargo(
builder,
cargo,
- lint_args(builder, IGNORED_RULES_FOR_STD_AND_RUSTC),
+ lint_args(builder, &self.config, IGNORED_RULES_FOR_STD_AND_RUSTC),
&librustc_stamp(builder, compiler, target),
vec![],
true,
@@ -232,6 +262,7 @@ macro_rules! lint_any {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct $name {
pub target: TargetSelection,
+ config: LintConfig,
}
impl Step for $name {
@@ -243,8 +274,10 @@ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
}
fn make_run(run: RunConfig<'_>) {
+ let config = LintConfig::new(run.builder);
run.builder.ensure($name {
target: run.target,
+ config,
});
}
@@ -281,7 +314,7 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
run_cargo(
builder,
cargo,
- lint_args(builder, &[]),
+ lint_args(builder, &self.config, &[]),
&stamp,
vec![],
true,
@@ -319,3 +352,58 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
Tidy, "src/tools/tidy", "tidy";
TestFloatParse, "src/etc/test-float-parse", "test-float-parse";
);
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CI {
+ target: TargetSelection,
+ config: LintConfig,
+}
+
+impl Step for CI {
+ type Output = ();
+ const DEFAULT: bool = false;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.alias("ci")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ let config = LintConfig::new(run.builder);
+ run.builder.ensure(CI { target: run.target, config });
+ }
+
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ builder.ensure(Bootstrap {
+ target: self.target,
+ config: self.config.merge(&LintConfig {
+ allow: vec![],
+ warn: vec![],
+ deny: vec!["warnings".into()],
+ forbid: vec![],
+ }),
+ });
+ let library_clippy_cfg = LintConfig {
+ allow: vec!["clippy::all".into()],
+ warn: vec![],
+ deny: vec!["clippy::correctness".into()],
+ forbid: vec![],
+ };
+ let compiler_clippy_cfg = LintConfig {
+ allow: vec!["clippy::all".into()],
+ warn: vec![],
+ deny: vec!["clippy::correctness".into(), "clippy::clone_on_ref_ptr".into()],
+ forbid: vec![],
+ };
+
+ builder.ensure(Std {
+ target: self.target,
+ config: self.config.merge(&library_clippy_cfg),
+ crates: vec![],
+ });
+ builder.ensure(Rustc {
+ target: self.target,
+ config: self.config.merge(&compiler_clippy_cfg),
+ crates: vec![],
+ });
+ }
+}
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index f1b3cf6..d59e0fa 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -839,6 +839,7 @@ macro_rules! describe {
clippy::RustInstaller,
clippy::TestFloatParse,
clippy::Tidy,
+ clippy::CI,
),
Kind::Check | Kind::Fix => describe!(
check::Std,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 2d5ea54..95b1303 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1681,11 +1681,33 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
let mut debuginfo_level_tools = None;
let mut debuginfo_level_tests = None;
let mut optimize = None;
- let mut omit_git_hash = None;
let mut lld_enabled = None;
let mut std_features = None;
- let mut is_user_configured_rust_channel = false;
+ let is_user_configured_rust_channel =
+ if let Some(channel) = toml.rust.as_ref().and_then(|r| r.channel.clone()) {
+ config.channel = channel;
+ true
+ } else {
+ false
+ };
+
+ let default = config.channel == "dev";
+ config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default);
+
+ config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
+ config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo"));
+ config.rust_analyzer_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer"));
+ config.clippy_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy"));
+ config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri"));
+ config.rustfmt_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt"));
+ config.enzyme_info =
+ GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme"));
+ config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project"));
+ config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc"));
if let Some(rust) = toml.rust {
let Rust {
@@ -1708,14 +1730,14 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
parallel_compiler,
randomize_layout,
default_linker,
- channel,
+ channel: _, // already handled above
description,
musl_root,
rpath,
verbose_tests,
optimize_tests,
codegen_tests,
- omit_git_hash: omit_git_hash_toml,
+ omit_git_hash: _, // already handled above
dist_src,
save_toolstates,
codegen_backends,
@@ -1745,9 +1767,6 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
std_features: std_features_toml,
} = rust;
- is_user_configured_rust_channel = channel.is_some();
- set(&mut config.channel, channel.clone());
-
config.download_rustc_commit =
config.download_ci_rustc_commit(download_rustc, config.llvm_assertions);
@@ -1766,7 +1785,6 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
std_features = std_features_toml;
optimize = optimize_toml;
- omit_git_hash = omit_git_hash_toml;
config.rust_new_symbol_mangling = new_symbol_mangling;
set(&mut config.rust_optimize_tests, optimize_tests);
set(&mut config.codegen_tests, codegen_tests);
@@ -1848,24 +1866,6 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
config.reproducible_artifacts = flags.reproducible_artifact;
- // rust_info must be set before is_ci_llvm_available() is called.
- let default = config.channel == "dev";
- config.omit_git_hash = omit_git_hash.unwrap_or(default);
- config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
-
- config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo"));
- config.rust_analyzer_info =
- GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer"));
- config.clippy_info =
- GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy"));
- config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri"));
- config.rustfmt_info =
- GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt"));
- config.enzyme_info =
- GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme"));
- config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project"));
- config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc"));
-
// We need to override `rust.channel` if it's manually specified when using the CI rustc.
// This is because if the compiler uses a different channel than the one specified in config.toml,
// tests may fail due to using a different channel than the one used by the compiler during tests.
@@ -2782,9 +2782,19 @@ fn download_ci_rustc_commit(
// If `download-rustc` is not set, default to rebuilding.
let if_unchanged = match download_rustc {
- None | Some(StringOrBool::Bool(false)) => return None,
+ None => self.rust_info.is_managed_git_subrepository(),
+ Some(StringOrBool::Bool(false)) => return None,
Some(StringOrBool::Bool(true)) => false,
- Some(StringOrBool::String(s)) if s == "if-unchanged" => true,
+ Some(StringOrBool::String(s)) if s == "if-unchanged" => {
+ if !self.rust_info.is_managed_git_subrepository() {
+ println!(
+ "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources."
+ );
+ crate::exit!(1);
+ }
+
+ true
+ }
Some(StringOrBool::String(other)) => {
panic!("unrecognized option for download-rustc: {other}")
}
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 0145552..24f932a 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -9,7 +9,7 @@
use super::flags::Flags;
use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
-use crate::core::build_steps::clippy::get_clippy_rules_in_order;
+use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
use crate::core::build_steps::llvm;
use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
@@ -135,6 +135,7 @@ fn override_toml() {
[rust]
lto = "off"
deny-warnings = true
+download-rustc=false
[build]
gdb = "foo"
@@ -200,6 +201,8 @@ fn override_toml() {
.collect(),
"setting dictionary value"
);
+ assert!(!config.llvm_from_ci);
+ assert!(!config.download_rustc());
}
#[test]
@@ -306,9 +309,10 @@ fn order_of_clippy_rules() {
];
let config = Config::parse(Flags::parse(&args));
- let actual = match &config.cmd {
+ let actual = match config.cmd.clone() {
crate::Subcommand::Clippy { allow, deny, warn, forbid, .. } => {
- get_clippy_rules_in_order(&args, &allow, &deny, &warn, &forbid)
+ let cfg = LintConfig { allow, deny, warn, forbid };
+ get_clippy_rules_in_order(&args, &cfg)
}
_ => panic!("invalid subcommand"),
};
@@ -329,9 +333,10 @@ fn clippy_rule_separate_prefix() {
vec!["clippy".to_string(), "-A clippy:all".to_string(), "-W clippy::style".to_string()];
let config = Config::parse(Flags::parse(&args));
- let actual = match &config.cmd {
+ let actual = match config.cmd.clone() {
crate::Subcommand::Clippy { allow, deny, warn, forbid, .. } => {
- get_clippy_rules_in_order(&args, &allow, &deny, &warn, &forbid)
+ let cfg = LintConfig { allow, deny, warn, forbid };
+ get_clippy_rules_in_order(&args, &cfg)
}
_ => panic!("invalid subcommand"),
};
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 7162007..3fb2330 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -145,7 +145,7 @@ fn symlink_dir_inner(original: &Path, link: &Path) -> io::Result<()> {
#[cfg(windows)]
fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
- junction::create(&target, &junction)
+ junction::create(target, junction)
}
}
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index fdc8a73..f0afb57 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -50,9 +50,7 @@
python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \
/scripts/check-default-config-profiles.sh && \
python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
- python3 ../x.py clippy bootstrap -Dwarnings && \
- python3 ../x.py clippy library -Aclippy::all -Dclippy::correctness && \
- python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness -Dclippy::clone_on_ref_ptr && \
+ python3 ../x.py clippy ci && \
python3 ../x.py build --stage 0 src/tools/build-manifest && \
python3 ../x.py test --stage 0 src/tools/compiletest && \
python3 ../x.py test --stage 0 core alloc std test proc_macro && \
diff --git a/src/ci/run.sh b/src/ci/run.sh
index d9c58d9..5690d8e 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -115,7 +115,12 @@
if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo"
- RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level-std=1"
+
+ if [ "$DEPLOY_ALT" != "" ]; then
+ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level=2"
+ else
+ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --debuginfo-level-std=1"
+ fi
if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 97529e4..5ddd618 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -134,11 +134,7 @@ pub(crate) fn try_inline(
})
}
Res::Def(DefKind::Macro(kind), did) => {
- let is_doc_hidden = cx.tcx.is_doc_hidden(did)
- || attrs_without_docs
- .map(|(attrs, _)| attrs)
- .is_some_and(|attrs| utils::attrs_have_doc_flag(attrs.iter(), sym::hidden));
- let mac = build_macro(cx, did, name, import_def_id, kind, is_doc_hidden);
+ let mac = build_macro(cx, did, name, kind);
let type_kind = match kind {
MacroKind::Bang => ItemType::Macro,
@@ -740,18 +736,14 @@ fn build_macro(
cx: &mut DocContext<'_>,
def_id: DefId,
name: Symbol,
- import_def_id: Option<LocalDefId>,
macro_kind: MacroKind,
- is_doc_hidden: bool,
) -> clean::ItemKind {
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
LoadedMacro::MacroDef { def, .. } => match macro_kind {
- MacroKind::Bang => {
- let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
- clean::MacroItem(clean::Macro {
- source: utils::display_macro_source(cx, name, &def, def_id, vis, is_doc_hidden),
- })
- }
+ MacroKind::Bang => clean::MacroItem(clean::Macro {
+ source: utils::display_macro_source(cx, name, &def),
+ macro_rules: def.macro_rules,
+ }),
MacroKind::Derive | MacroKind::Attr => {
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6b6142a..9e11360 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2119,7 +2119,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
})
.collect::<Vec<_>>();
- let bindings = obj
+ let constraints = obj
.projection_bounds()
.map(|pb| AssocItemConstraint {
assoc: projection_to_path_segment(
@@ -2155,7 +2155,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
.collect();
let late_bound_regions = late_bound_regions.into_iter().collect();
- let path = clean_middle_path(cx, did, false, bindings, args);
+ let path = clean_middle_path(cx, did, false, constraints, args);
bounds.insert(0, PolyTrait { trait_: path, generic_params: late_bound_regions });
DynTrait(bounds, lifetime)
@@ -2787,13 +2787,10 @@ fn clean_maybe_renamed_item<'tcx>(
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
}),
ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx),
- ItemKind::Macro(macro_def, MacroKind::Bang) => {
- let ty_vis = cx.tcx.visibility(def_id);
- MacroItem(Macro {
- // FIXME this shouldn't be false
- source: display_macro_source(cx, name, macro_def, def_id, ty_vis, false),
- })
- }
+ ItemKind::Macro(macro_def, MacroKind::Bang) => MacroItem(Macro {
+ source: display_macro_source(cx, name, macro_def),
+ macro_rules: macro_def.macro_rules,
+ }),
ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
// proc macros can have a name set by attributes
ItemKind::Fn(ref sig, generics, body_id) => {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e5c9539..e3a0dbe 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2543,6 +2543,8 @@ pub(crate) struct ImportSource {
#[derive(Clone, Debug)]
pub(crate) struct Macro {
pub(crate) source: String,
+ /// Whether the macro was defined via `macro_rules!` as opposed to `macro`.
+ pub(crate) macro_rules: bool,
}
#[derive(Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 5608311..e551e01 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -24,7 +24,6 @@
clean_middle_ty, inline,
};
use crate::core::DocContext;
-use crate::html::format::visibility_to_src_with_space;
#[cfg(test)]
mod tests;
@@ -112,7 +111,6 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
return None;
}
- // Elide internal host effect args.
let param = generics.param_at(index, cx.tcx);
let arg = ty::Binder::bind_with_vars(arg, bound_vars);
@@ -201,35 +199,30 @@ fn clean_middle_generic_args_with_constraints<'tcx>(
cx: &mut DocContext<'tcx>,
did: DefId,
has_self: bool,
- constraints: ThinVec<AssocItemConstraint>,
- ty_args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
+ mut constraints: ThinVec<AssocItemConstraint>,
+ args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
) -> GenericArgs {
- let args = clean_middle_generic_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did);
-
- if cx.tcx.is_trait(did) && cx.tcx.trait_def(did).paren_sugar {
- let ty = ty_args
+ if cx.tcx.is_trait(did)
+ && cx.tcx.trait_def(did).paren_sugar
+ && let ty::Tuple(tys) = args.skip_binder().type_at(has_self as usize).kind()
+ {
+ let inputs = tys
.iter()
- .nth(if has_self { 1 } else { 0 })
- .unwrap()
- .map_bound(|arg| arg.expect_ty());
- let inputs =
- // The trait's first substitution is the one after self, if there is one.
- match ty.skip_binder().kind() {
- ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None, None)).collect::<Vec<_>>().into(),
- _ => return GenericArgs::AngleBracketed { args: args.into(), constraints },
- };
- let output = constraints.into_iter().next().and_then(|binding| match binding.kind {
- AssocItemConstraintKind::Equality { term: Term::Type(ty) }
- if ty != Type::Tuple(Vec::new()) =>
- {
+ .map(|ty| clean_middle_ty(args.rebind(ty), cx, None, None))
+ .collect::<Vec<_>>()
+ .into();
+ let output = constraints.pop().and_then(|constraint| match constraint.kind {
+ AssocItemConstraintKind::Equality { term: Term::Type(ty) } if !ty.is_unit() => {
Some(Box::new(ty))
}
_ => None,
});
- GenericArgs::Parenthesized { inputs, output }
- } else {
- GenericArgs::AngleBracketed { args: args.into(), constraints }
+ return GenericArgs::Parenthesized { inputs, output };
}
+
+ let args = clean_middle_generic_args(cx, args.map_bound(|args| &args[..]), has_self, did);
+
+ GenericArgs::AngleBracketed { args: args.into(), constraints }
}
pub(super) fn clean_middle_path<'tcx>(
@@ -599,7 +592,7 @@ pub(crate) fn attrs_have_doc_flag<'a>(
/// Render a sequence of macro arms in a format suitable for displaying to the user
/// as part of an item declaration.
-pub(super) fn render_macro_arms<'a>(
+fn render_macro_arms<'a>(
tcx: TyCtxt<'_>,
matchers: impl Iterator<Item = &'a TokenTree>,
arm_delim: &str,
@@ -620,9 +613,6 @@ pub(super) fn display_macro_source(
cx: &mut DocContext<'_>,
name: Symbol,
def: &ast::MacroDef,
- def_id: DefId,
- vis: ty::Visibility<DefId>,
- is_doc_hidden: bool,
) -> String {
// Extract the spans of all matchers. They represent the "interface" of the macro.
let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
@@ -632,18 +622,13 @@ pub(super) fn display_macro_source(
} else {
if matchers.len() <= 1 {
format!(
- "{vis}macro {name}{matchers} {{\n ...\n}}",
- vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
+ "macro {name}{matchers} {{\n ...\n}}",
matchers = matchers
.map(|matcher| render_macro_matcher(cx.tcx, matcher))
.collect::<String>(),
)
} else {
- format!(
- "{vis}macro {name} {{\n{arms}}}",
- vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id, is_doc_hidden),
- arms = render_macro_arms(cx.tcx, matchers, ","),
- )
+ format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ","))
}
}
}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index e9d5ba2..2f9e797 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1615,47 +1615,6 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
})
}
-/// This function is the same as print_with_space, except that it renders no links.
-/// It's used for macros' rendered source view, which is syntax highlighted and cannot have
-/// any HTML in it.
-pub(crate) fn visibility_to_src_with_space<'a, 'tcx: 'a>(
- visibility: Option<ty::Visibility<DefId>>,
- tcx: TyCtxt<'tcx>,
- item_did: DefId,
- is_doc_hidden: bool,
-) -> impl Display + 'a + Captures<'tcx> {
- let vis: Cow<'static, str> = match visibility {
- None => "".into(),
- Some(ty::Visibility::Public) => "pub ".into(),
- Some(ty::Visibility::Restricted(vis_did)) => {
- // FIXME(camelid): This may not work correctly if `item_did` is a module.
- // However, rustdoc currently never displays a module's
- // visibility, so it shouldn't matter.
- let parent_module = find_nearest_parent_module(tcx, item_did);
-
- if vis_did.is_crate_root() {
- "pub(crate) ".into()
- } else if parent_module == Some(vis_did) {
- // `pub(in foo)` where `foo` is the parent module
- // is the same as no visibility modifier
- "".into()
- } else if parent_module.and_then(|parent| find_nearest_parent_module(tcx, parent))
- == Some(vis_did)
- {
- "pub(super) ".into()
- } else {
- format!("pub(in {}) ", tcx.def_path_str(vis_did)).into()
- }
- }
- };
- display_fn(move |f| {
- if is_doc_hidden {
- f.write_str("#[doc(hidden)] ")?;
- }
- f.write_str(&vis)
- })
-}
-
pub(crate) trait PrintWithSpace {
fn print_with_space(&self) -> &str;
}
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index b68b729..4def807 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -58,13 +58,6 @@ pub(crate) fn render_example_with_highlighting(
write_footer(out, playground_button);
}
-/// Highlights `src` as an item-decl, returning the HTML output.
-pub(crate) fn render_item_decl_with_highlighting(src: &str, out: &mut Buffer) {
- write!(out, "<pre class=\"rust item-decl\">");
- write_code(out, src, None, None);
- write!(out, "</pre>");
-}
-
fn write_header(
out: &mut Buffer,
class: &str,
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 7826a5d..1d42ec8 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1333,12 +1333,14 @@ pub fn into_string(self) -> String {
let mut s = String::with_capacity(md.len() * 3 / 2);
- let p = HeadingLinks::new(p, None, ids, heading_offset);
- let p = footnotes::Footnotes::new(p);
- let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
- let p = TableWrapper::new(p);
- let p = CodeBlocks::new(p, codes, edition, playground);
- html::push_html(&mut s, p);
+ ids.handle_footnotes(|ids, existing_footnotes| {
+ let p = HeadingLinks::new(p, None, ids, heading_offset);
+ let p = footnotes::Footnotes::new(p, existing_footnotes);
+ let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
+ let p = TableWrapper::new(p);
+ let p = CodeBlocks::new(p, codes, edition, playground);
+ html::push_html(&mut s, p);
+ });
s
}
@@ -1367,13 +1369,13 @@ pub(crate) fn into_parts(self) -> (Toc, String) {
let mut toc = TocBuilder::new();
- {
+ ids.handle_footnotes(|ids, existing_footnotes| {
let p = HeadingLinks::new(p, Some(&mut toc), ids, HeadingOffset::H1);
- let p = footnotes::Footnotes::new(p);
+ let p = footnotes::Footnotes::new(p, existing_footnotes);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
let p = CodeBlocks::new(p, codes, edition, playground);
html::push_html(&mut s, p);
- }
+ });
(toc.into_toc(), s)
}
@@ -1401,13 +1403,15 @@ pub(crate) fn into_string(self) -> String {
let mut s = String::with_capacity(md.len() * 3 / 2);
- let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
- let p = footnotes::Footnotes::new(p);
- let p = TableWrapper::new(p.map(|(ev, _)| ev));
- let p = p.filter(|event| {
- !matches!(event, Event::Start(Tag::Paragraph) | Event::End(TagEnd::Paragraph))
+ ids.handle_footnotes(|ids, existing_footnotes| {
+ let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
+ let p = footnotes::Footnotes::new(p, existing_footnotes);
+ let p = TableWrapper::new(p.map(|(ev, _)| ev));
+ let p = p.filter(|event| {
+ !matches!(event, Event::Start(Tag::Paragraph) | Event::End(TagEnd::Paragraph))
+ });
+ html::push_html(&mut s, p);
});
- html::push_html(&mut s, p);
s
}
@@ -1882,6 +1886,7 @@ pub(crate) fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<Rust
#[derive(Clone, Default, Debug)]
pub struct IdMap {
map: FxHashMap<Cow<'static, str>, usize>,
+ existing_footnotes: usize,
}
// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
@@ -1943,7 +1948,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
impl IdMap {
pub fn new() -> Self {
- IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone() }
+ IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 }
}
pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
@@ -1959,4 +1964,13 @@ pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> Strin
self.map.insert(id.clone().into(), 1);
id
}
+
+ /// Method to handle `existing_footnotes` increment automatically (to prevent forgetting
+ /// about it).
+ pub(crate) fn handle_footnotes<F: FnOnce(&mut Self, &mut usize)>(&mut self, closure: F) {
+ let mut existing_footnotes = self.existing_footnotes;
+
+ closure(self, &mut existing_footnotes);
+ self.existing_footnotes = existing_footnotes;
+ }
}
diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs
index 3f0e586..fcb8a17 100644
--- a/src/librustdoc/html/markdown/footnotes.rs
+++ b/src/librustdoc/html/markdown/footnotes.rs
@@ -1,60 +1,83 @@
//! Markdown footnote handling.
use std::fmt::Write as _;
-use pulldown_cmark::{Event, Tag, TagEnd, html};
+use pulldown_cmark::{CowStr, Event, Tag, TagEnd, html};
use rustc_data_structures::fx::FxIndexMap;
use super::SpannedEvent;
/// Moves all footnote definitions to the end and add back links to the
/// references.
-pub(super) struct Footnotes<'a, I> {
+pub(super) struct Footnotes<'a, 'b, I> {
inner: I,
footnotes: FxIndexMap<String, FootnoteDef<'a>>,
+ existing_footnotes: &'b mut usize,
}
/// The definition of a single footnote.
struct FootnoteDef<'a> {
content: Vec<Event<'a>>,
/// The number that appears in the footnote reference and list.
- id: u16,
+ id: usize,
}
-impl<'a, I> Footnotes<'a, I> {
- pub(super) fn new(iter: I) -> Self {
- Footnotes { inner: iter, footnotes: FxIndexMap::default() }
+impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, 'b, I> {
+ pub(super) fn new(iter: I, existing_footnotes: &'b mut usize) -> Self {
+ Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes }
}
- fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, u16) {
- let new_id = self.footnotes.len() + 1;
+ fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) {
+ let new_id = self.footnotes.len() + 1 + *self.existing_footnotes;
let key = key.to_owned();
- let FootnoteDef { content, id } = self
- .footnotes
- .entry(key)
- .or_insert(FootnoteDef { content: Vec::new(), id: new_id as u16 });
+ let FootnoteDef { content, id } =
+ self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id });
// Don't allow changing the ID of existing entrys, but allow changing the contents.
(content, *id)
}
+
+ fn handle_footnote_reference(&mut self, reference: &CowStr<'a>) -> Event<'a> {
+ // When we see a reference (to a footnote we may not know) the definition of,
+ // reserve a number for it, and emit a link to that number.
+ let (_, id) = self.get_entry(reference);
+ let reference = format!(
+ "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{1}</a></sup>",
+ id,
+ // Although the ID count is for the whole page, the footnote reference
+ // are local to the item so we make this ID "local" when displayed.
+ id - *self.existing_footnotes
+ );
+ Event::Html(reference.into())
+ }
+
+ fn collect_footnote_def(&mut self) -> Vec<Event<'a>> {
+ let mut content = Vec::new();
+ while let Some((event, _)) = self.inner.next() {
+ match event {
+ Event::End(TagEnd::FootnoteDefinition) => break,
+ Event::FootnoteReference(ref reference) => {
+ content.push(self.handle_footnote_reference(reference));
+ }
+ event => content.push(event),
+ }
+ }
+ content
+ }
}
-impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
+impl<'a, 'b, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, 'b, I> {
type Item = SpannedEvent<'a>;
fn next(&mut self) -> Option<Self::Item> {
loop {
- match self.inner.next() {
+ let next = self.inner.next();
+ match next {
Some((Event::FootnoteReference(ref reference), range)) => {
- // When we see a reference (to a footnote we may not know) the definition of,
- // reserve a number for it, and emit a link to that number.
- let (_, id) = self.get_entry(reference);
- let reference =
- format!("<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>", id);
- return Some((Event::Html(reference.into()), range));
+ return Some((self.handle_footnote_reference(reference), range));
}
Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => {
// When we see a footnote definition, collect the assocated content, and store
// that for rendering later.
- let content = collect_footnote_def(&mut self.inner);
+ let content = self.collect_footnote_def();
let (entry_content, _) = self.get_entry(&def);
*entry_content = content;
}
@@ -64,6 +87,7 @@ fn next(&mut self) -> Option<Self::Item> {
// After all the markdown is emmited, emit an <hr> then all the footnotes
// in a list.
let defs: Vec<_> = self.footnotes.drain(..).map(|(_, x)| x).collect();
+ *self.existing_footnotes += defs.len();
let defs_html = render_footnotes_defs(defs);
return Some((Event::Html(defs_html.into()), 0..0));
} else {
@@ -75,17 +99,6 @@ fn next(&mut self) -> Option<Self::Item> {
}
}
-fn collect_footnote_def<'a>(events: impl Iterator<Item = SpannedEvent<'a>>) -> Vec<Event<'a>> {
- let mut content = Vec::new();
- for (event, _) in events {
- if let Event::End(TagEnd::FootnoteDefinition) = event {
- break;
- }
- content.push(event);
- }
- content
-}
-
fn render_footnotes_defs(mut footnotes: Vec<FootnoteDef<'_>>) -> String {
let mut ret = String::from("<div class=\"footnotes\"><hr><ol>");
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index dc4d45e..5f255c1 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -76,9 +76,9 @@ pub(crate) struct Context<'tcx> {
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(not(windows), target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 184);
-#[cfg(all(windows, target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 192);
+#[cfg(all(windows, target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Context<'_>, 200);
/// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index c6a2d87..d247e90 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -35,7 +35,6 @@
Buffer, Ending, PrintWithSpace, display_fn, join_with_double_colon, print_abi_with_space,
print_constness_with_space, print_where_clause, visibility_print_with_space,
};
-use crate::html::highlight;
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
use crate::html::render::{document_full, document_item_info};
use crate::html::url_parts_builder::UrlPartsBuilder;
@@ -1745,7 +1744,13 @@ fn item_variants(
}
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
- highlight::render_item_decl_with_highlighting(&t.source, w);
+ wrap_item(w, |w| {
+ // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
+ if !t.macro_rules {
+ write!(w, "{}", visibility_print_with_space(it, cx));
+ }
+ write!(w, "{}", Escape(&t.source));
+ });
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
}
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 4e1bbbb..6d118ae 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1106,6 +1106,153 @@
}
}
+/**
+ * A prefix tree, used for name-based search.
+ *
+ * This data structure is used to drive prefix matches,
+ * such as matching the query "link" to `LinkedList`,
+ * and Lev-distance matches, such as matching the
+ * query "hahsmap" to `HashMap`. Substring matches,
+ * such as "list" to `LinkedList`, are done with a
+ * tailTable that deep-links into this trie.
+ *
+ * children
+ * : A [sparse array] of subtrees. The array index
+ * is a charCode.
+ *
+ * [sparse array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/
+ * Indexed_collections#sparse_arrays
+ *
+ * matches
+ * : A list of search index IDs for this node.
+ *
+ * @typedef {{
+ * children: [NameTrie],
+ * matches: [number],
+ * }}
+ */
+class NameTrie {
+ constructor() {
+ this.children = [];
+ this.matches = [];
+ }
+ insert(name, id, tailTable) {
+ this.insertSubstring(name, 0, id, tailTable);
+ }
+ insertSubstring(name, substart, id, tailTable) {
+ const l = name.length;
+ if (substart === l) {
+ this.matches.push(id);
+ } else {
+ const sb = name.charCodeAt(substart);
+ let child;
+ if (this.children[sb] !== undefined) {
+ child = this.children[sb];
+ } else {
+ child = new NameTrie();
+ this.children[sb] = child;
+ let sste;
+ if (substart >= 2) {
+ const tail = name.substring(substart - 2, substart + 1);
+ if (tailTable.has(tail)) {
+ sste = tailTable.get(tail);
+ } else {
+ sste = [];
+ tailTable.set(tail, sste);
+ }
+ sste.push(child);
+ }
+ }
+ child.insertSubstring(name, substart + 1, id, tailTable);
+ }
+ }
+ search(name, tailTable) {
+ const results = new Set();
+ this.searchSubstringPrefix(name, 0, results);
+ if (results.size < MAX_RESULTS && name.length >= 3) {
+ const levParams = name.length >= 6 ?
+ new Lev2TParametricDescription(name.length) :
+ new Lev1TParametricDescription(name.length);
+ this.searchLev(name, 0, levParams, results);
+ const tail = name.substring(0, 3);
+ if (tailTable.has(tail)) {
+ for (const entry of tailTable.get(tail)) {
+ entry.searchSubstringPrefix(name, 3, results);
+ }
+ }
+ }
+ return [...results];
+ }
+ searchSubstringPrefix(name, substart, results) {
+ const l = name.length;
+ if (substart === l) {
+ for (const match of this.matches) {
+ results.add(match);
+ }
+ // breadth-first traversal orders prefix matches by length
+ let unprocessedChildren = [];
+ for (const child of this.children) {
+ if (child) {
+ unprocessedChildren.push(child);
+ }
+ }
+ let nextSet = [];
+ while (unprocessedChildren.length !== 0) {
+ const next = unprocessedChildren.pop();
+ for (const child of next.children) {
+ if (child) {
+ nextSet.push(child);
+ }
+ }
+ for (const match of next.matches) {
+ results.add(match);
+ }
+ if (unprocessedChildren.length === 0) {
+ const tmp = unprocessedChildren;
+ unprocessedChildren = nextSet;
+ nextSet = tmp;
+ }
+ }
+ } else {
+ const sb = name.charCodeAt(substart);
+ if (this.children[sb] !== undefined) {
+ this.children[sb].searchSubstringPrefix(name, substart + 1, results);
+ }
+ }
+ }
+ searchLev(name, substart, levParams, results) {
+ const stack = [[this, 0]];
+ const n = levParams.n;
+ while (stack.length !== 0) {
+ const [trie, levState] = stack.pop();
+ for (const [charCode, child] of trie.children.entries()) {
+ if (!child) {
+ continue;
+ }
+ const levPos = levParams.getPosition(levState);
+ const vector = levParams.getVector(
+ name,
+ charCode,
+ levPos,
+ Math.min(name.length, levPos + (2 * n) + 1),
+ );
+ const newLevState = levParams.transition(
+ levState,
+ levPos,
+ vector,
+ );
+ if (newLevState >= 0) {
+ stack.push([child, newLevState]);
+ if (levParams.isAccept(newLevState)) {
+ for (const match of child.matches) {
+ results.add(match);
+ }
+ }
+ }
+ }
+ }
+ }
+}
class DocSearch {
constructor(rawSearchIndex, rootPath, searchState) {
@@ -1211,6 +1358,20 @@
this.TYPES_POOL = new Map();
/**
+ * A trie for finding items by name.
+ * This is used for edit distance and prefix finding.
+ *
+ * @type {NameTrie}
+ */
+ this.nameTrie = new NameTrie();
+
+ /**
+ * Find items by 3-substring. This is a map from three-char
+ * prefixes into lists of subtries.
+ */
+ this.tailTable = new Map();
+
+ /**
* @type {Array<Row>}
*/
this.searchIndex = this.buildIndex(rawSearchIndex);
@@ -1613,6 +1774,7 @@
// This object should have exactly the same set of fields as the "row"
// object defined below. Your JavaScript runtime will thank you.
// https://mathiasbynens.be/notes/shapes-ics
+ let normalizedName = crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, "");
const crateRow = {
crate,
ty: 3, // == ExternCrate
@@ -1627,10 +1789,11 @@
paramNames: lastParamNames,
id,
word: crate,
- normalizedName: crate.indexOf("_") === -1 ? crate : crate.replace(/_/g, ""),
+ normalizedName,
bitIndex: 0,
implDisambiguator: null,
};
+ this.nameTrie.insert(normalizedName, id, this.tailTable);
id += 1;
searchIndex.push(crateRow);
currentIndex += 1;
@@ -1749,6 +1912,7 @@
// This object should have exactly the same set of fields as the "crateRow"
// object defined above.
const itemParentIdx = itemParentIdxDecoder.next();
+ normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, "");
const row = {
crate,
ty: itemTypes.charCodeAt(i) - 65, // 65 = "A"
@@ -1763,11 +1927,12 @@
paramNames,
id,
word,
- normalizedName: word.indexOf("_") === -1 ? word : word.replace(/_/g, ""),
+ normalizedName,
bitIndex,
implDisambiguator: implDisambiguator.has(i) ?
implDisambiguator.get(i) : null,
};
+ this.nameTrie.insert(normalizedName, id, this.tailTable);
id += 1;
searchIndex.push(row);
lastPath = row.path;
@@ -2060,6 +2225,7 @@
"/index.html#reexport." + name;
} else if (type === "primitive" || type === "keyword") {
displayPath = "";
+ exactPath = "";
href = this.rootPath + path.replace(/::/g, "/") +
"/" + type + "." + name + ".html";
} else if (type === "externcrate") {
@@ -2075,6 +2241,7 @@
if (parentType === "primitive") {
displayPath = myparent.name + "::";
+ exactPath = myparent.name;
} else if (type === "structfield" && parentType === "variant") {
// Structfields belonging to variants are special: the
// final path element is the enum name.
@@ -2500,6 +2667,7 @@
const sortResults = async(results, typeInfo, preferredCrate) => {
const userQuery = parsedQuery.userQuery;
const normalizedUserQuery = parsedQuery.userQuery.toLowerCase();
+ const isMixedCase = normalizedUserQuery !== userQuery;
const result_list = [];
for (const result of results.values()) {
result.item = this.searchIndex[result.id];
@@ -2511,10 +2679,12 @@
let a, b;
// sort by exact case-sensitive match
- a = (aaa.item.name !== userQuery);
- b = (bbb.item.name !== userQuery);
- if (a !== b) {
- return a - b;
+ if (isMixedCase) {
+ a = (aaa.item.name !== userQuery);
+ b = (bbb.item.name !== userQuery);
+ if (a !== b) {
+ return a - b;
+ }
}
// sort by exact match with regard to the last word (mismatch goes later)
@@ -3589,96 +3759,6 @@
}
/**
- * This function is called in case the query is only one element (with or without generics).
- * This element will be compared to arguments' and returned values' items and also to items.
- *
- * Other important thing to note: since there is only one element, we use edit
- * distance for name comparisons.
- *
- * @param {Row} row
- * @param {integer} pos - Position in the `searchIndex`.
- * @param {QueryElement} elem - The element from the parsed query.
- * @param {Results} results_others - Unqualified results (not in arguments nor in
- * returned values).
- * @param {Results} results_in_args - Matching arguments results.
- * @param {Results} results_returned - Matching returned arguments results.
- */
- function handleSingleArg(
- row,
- pos,
- elem,
- results_others,
- results_in_args,
- results_returned,
- maxEditDistance,
- ) {
- if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
- return;
- }
- let path_dist = 0;
- const fullId = row.id;
-
- // fpDist is a minimum possible type distance, where "type distance" is the number of
- // atoms in the function not present in the query
- const tfpDist = compareTypeFingerprints(
- fullId,
- parsedQuery.typeFingerprint,
- );
- if (tfpDist !== null) {
- const in_args = row.type && row.type.inputs
- && checkIfInList(row.type.inputs, elem, row.type.where_clause, null, 0);
- const returned = row.type && row.type.output
- && checkIfInList(row.type.output, elem, row.type.where_clause, null, 0);
- if (in_args) {
- results_in_args.max_dist = Math.max(results_in_args.max_dist || 0, tfpDist);
- const maxDist = results_in_args.size < MAX_RESULTS ?
- (tfpDist + 1) :
- results_in_args.max_dist;
- addIntoResults(results_in_args, fullId, pos, -1, tfpDist, 0, maxDist);
- }
- if (returned) {
- results_returned.max_dist = Math.max(results_returned.max_dist || 0, tfpDist);
- const maxDist = results_returned.size < MAX_RESULTS ?
- (tfpDist + 1) :
- results_returned.max_dist;
- addIntoResults(results_returned, fullId, pos, -1, tfpDist, 0, maxDist);
- }
- }
-
- if (!typePassesFilter(elem.typeFilter, row.ty)) {
- return;
- }
-
- let index = row.word.indexOf(elem.pathLast);
- const normalizedIndex = row.normalizedName.indexOf(elem.pathLast);
- if (index === -1 || (index > normalizedIndex && normalizedIndex !== -1)) {
- index = normalizedIndex;
- }
-
- if (elem.fullPath.length > 1) {
- path_dist = checkPath(elem.pathWithoutLast, row);
- if (path_dist === null) {
- return;
- }
- }
-
- if (parsedQuery.literalSearch) {
- if (row.word === elem.pathLast) {
- addIntoResults(results_others, fullId, pos, index, 0, path_dist);
- }
- return;
- }
-
- const dist = editDistance(row.normalizedName, elem.normalizedPathLast, maxEditDistance);
-
- if (index === -1 && dist > maxEditDistance) {
- return;
- }
-
- addIntoResults(results_others, fullId, pos, index, dist, path_dist, maxEditDistance);
- }
-
- /**
* This function is called in case the query has more than one element. In this case, it'll
* try to match the items which validates all the elements. For `aa -> bb` will look for
* functions which have a parameter `aa` and has `bb` in its returned values.
@@ -3893,23 +3973,79 @@
}
if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) {
- if (parsedQuery.elems.length === 1) {
- const elem = parsedQuery.elems[0];
- const length = this.searchIndex.length;
- for (let i = 0, nSearchIndex = length; i < nSearchIndex; ++i) {
- // It means we want to check for this element everywhere (in names, args and
- // returned).
- handleSingleArg(
- this.searchIndex[i],
- i,
- elem,
+ const elem = parsedQuery.elems[0];
+ for (const id of this.nameTrie.search(elem.normalizedPathLast, this.tailTable)) {
+ const row = this.searchIndex[id];
+ if (!typePassesFilter(elem.typeFilter, row.ty) ||
+ (filterCrates !== null && row.crate !== filterCrates)) {
+ continue;
+ }
+
+ let pathDist = 0;
+ if (elem.fullPath.length > 1) {
+ pathDist = checkPath(elem.pathWithoutLast, row);
+ if (pathDist === null) {
+ continue;
+ }
+ }
+
+ if (parsedQuery.literalSearch) {
+ if (row.word === elem.pathLast) {
+ addIntoResults(results_others, row.id, id, 0, 0, pathDist);
+ }
+ } else {
+ addIntoResults(
results_others,
- results_in_args,
- results_returned,
+ row.id,
+ id,
+ row.normalizedName.indexOf(elem.normalizedPathLast),
+ editDistance(
+ row.normalizedName,
+ elem.normalizedPathLast,
+ maxEditDistance,
+ ),
+ pathDist,
maxEditDistance,
);
}
}
+ const length = this.searchIndex.length;
+ for (let i = 0, nSearchIndex = length; i < nSearchIndex; ++i) {
+ const row = this.searchIndex[i];
+ if (filterCrates !== null && row.crate !== filterCrates) {
+ continue;
+ }
+ const tfpDist = compareTypeFingerprints(
+ row.id,
+ parsedQuery.typeFingerprint,
+ );
+ if (tfpDist !== null) {
+ const in_args = row.type && row.type.inputs
+ && checkIfInList(row.type.inputs, elem, row.type.where_clause, null, 0);
+ const returned = row.type && row.type.output
+ && checkIfInList(row.type.output, elem, row.type.where_clause, null, 0);
+ if (in_args) {
+ results_in_args.max_dist = Math.max(
+ results_in_args.max_dist || 0,
+ tfpDist,
+ );
+ const maxDist = results_in_args.size < MAX_RESULTS ?
+ (tfpDist + 1) :
+ results_in_args.max_dist;
+ addIntoResults(results_in_args, row.id, i, -1, tfpDist, 0, maxDist);
+ }
+ if (returned) {
+ results_returned.max_dist = Math.max(
+ results_returned.max_dist || 0,
+ tfpDist,
+ );
+ const maxDist = results_returned.size < MAX_RESULTS ?
+ (tfpDist + 1) :
+ results_returned.max_dist;
+ addIntoResults(results_returned, row.id, i, -1, tfpDist, 0, maxDist);
+ }
+ }
+ }
} else if (parsedQuery.foundElems > 0) {
// Sort input and output so that generic type variables go first and
// types with generic parameters go last.
@@ -4653,3 +4789,477 @@
// exports.
initSearch(new Map());
}
+
+// Parts of this code are based on Lucene, which is licensed under the
+// Apache/2.0 license.
+// More information found here:
+// https://fossies.org/linux/lucene/lucene/core/src/java/org/apache/lucene/util/automaton/
+// LevenshteinAutomata.java
+class ParametricDescription {
+ constructor(w, n, minErrors) {
+ this.w = w;
+ this.n = n;
+ this.minErrors = minErrors;
+ }
+ isAccept(absState) {
+ const state = Math.floor(absState / (this.w + 1));
+ const offset = absState % (this.w + 1);
+ return this.w - offset + this.minErrors[state] <= this.n;
+ }
+ getPosition(absState) {
+ return absState % (this.w + 1);
+ }
+ getVector(name, charCode, pos, end) {
+ let vector = 0;
+ for (let i = pos; i < end; i += 1) {
+ vector = vector << 1;
+ if (name.charCodeAt(i) === charCode) {
+ vector |= 1;
+ }
+ }
+ return vector;
+ }
+ unpack(data, index, bitsPerValue) {
+ const bitLoc = (bitsPerValue * index);
+ const dataLoc = bitLoc >> 5;
+ const bitStart = bitLoc & 31;
+ if (bitStart + bitsPerValue <= 32) {
+ // not split
+ return ((data[dataLoc] >> bitStart) & this.MASKS[bitsPerValue - 1]);
+ } else {
+ // split
+ const part = 32 - bitStart;
+ return ~~(((data[dataLoc] >> bitStart) & this.MASKS[part - 1]) +
+ ((data[1 + dataLoc] & this.MASKS[bitsPerValue - part - 1]) << part));
+ }
+ }
+}
+ParametricDescription.prototype.MASKS = new Int32Array([
+ 0x1, 0x3, 0x7, 0xF,
+ 0x1F, 0x3F, 0x7F, 0xFF,
+ 0x1FF, 0x3F, 0x7FF, 0xFFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,
+ 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF,
+ 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF,
+ 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF,
+ 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,
+]);
+
+// The following code was generated with the moman/finenight pkg
+// This package is available under the MIT License, see NOTICE.txt
+// for more details.
+// This class is auto-generated, Please do not modify it directly.
+// You should modify the https://gitlab.com/notriddle/createAutomata.py instead.
+// The following code was generated with the moman/finenight pkg
+// This package is available under the MIT License, see NOTICE.txt
+// for more details.
+// This class is auto-generated, Please do not modify it directly.
+// You should modify https://gitlab.com/notriddle/moman-rustdoc instead.
+
+class Lev2TParametricDescription extends ParametricDescription {
+ /**
+ * @param {number} absState
+ * @param {number} position
+ * @param {number} vector
+ * @returns {number}
+ */
+ transition(absState, position, vector) {
+ let state = Math.floor(absState / (this.w + 1));
+ let offset = absState % (this.w + 1);
+
+ if (position === this.w) {
+ if (state < 3) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 3) + state;
+ offset += this.unpack(this.offsetIncrs0, loc, 1);
+ state = this.unpack(this.toStates0, loc, 2) - 1;
+ }
+ } else if (position === this.w - 1) {
+ if (state < 5) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 5) + state;
+ offset += this.unpack(this.offsetIncrs1, loc, 1);
+ state = this.unpack(this.toStates1, loc, 3) - 1;
+ }
+ } else if (position === this.w - 2) {
+ if (state < 13) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 13) + state;
+ offset += this.unpack(this.offsetIncrs2, loc, 2);
+ state = this.unpack(this.toStates2, loc, 4) - 1;
+ }
+ } else if (position === this.w - 3) {
+ if (state < 28) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 28) + state;
+ offset += this.unpack(this.offsetIncrs3, loc, 2);
+ state = this.unpack(this.toStates3, loc, 5) - 1;
+ }
+ } else if (position === this.w - 4) {
+ if (state < 45) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 45) + state;
+ offset += this.unpack(this.offsetIncrs4, loc, 3);
+ state = this.unpack(this.toStates4, loc, 6) - 1;
+ }
+ } else {
+ if (state < 45) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 45) + state;
+ offset += this.unpack(this.offsetIncrs5, loc, 3);
+ state = this.unpack(this.toStates5, loc, 6) - 1;
+ }
+ }
+
+ if (state === -1) {
+ // null state
+ return -1;
+ } else {
+ // translate back to abs
+ return Math.imul(state, this.w + 1) + offset;
+ }
+ }
+
+ // state map
+ // 0 -> [(0, 0)]
+ // 1 -> [(0, 1)]
+ // 2 -> [(0, 2)]
+ // 3 -> [(0, 1), (1, 1)]
+ // 4 -> [(0, 2), (1, 2)]
+ // 5 -> [(0, 1), (1, 1), (2, 1)]
+ // 6 -> [(0, 2), (1, 2), (2, 2)]
+ // 7 -> [(0, 1), (2, 1)]
+ // 8 -> [(0, 1), (2, 2)]
+ // 9 -> [(0, 2), (2, 1)]
+ // 10 -> [(0, 2), (2, 2)]
+ // 11 -> [t(0, 1), (0, 1), (1, 1), (2, 1)]
+ // 12 -> [t(0, 2), (0, 2), (1, 2), (2, 2)]
+ // 13 -> [(0, 2), (1, 2), (2, 2), (3, 2)]
+ // 14 -> [(0, 1), (1, 1), (3, 2)]
+ // 15 -> [(0, 1), (2, 2), (3, 2)]
+ // 16 -> [(0, 1), (3, 2)]
+ // 17 -> [(0, 1), t(1, 2), (2, 2), (3, 2)]
+ // 18 -> [(0, 2), (1, 2), (3, 1)]
+ // 19 -> [(0, 2), (1, 2), (3, 2)]
+ // 20 -> [(0, 2), (1, 2), t(1, 2), (2, 2), (3, 2)]
+ // 21 -> [(0, 2), (2, 1), (3, 1)]
+ // 22 -> [(0, 2), (2, 2), (3, 2)]
+ // 23 -> [(0, 2), (3, 1)]
+ // 24 -> [(0, 2), (3, 2)]
+ // 25 -> [(0, 2), t(1, 2), (1, 2), (2, 2), (3, 2)]
+ // 26 -> [t(0, 2), (0, 2), (1, 2), (2, 2), (3, 2)]
+ // 27 -> [t(0, 2), (0, 2), (1, 2), (3, 1)]
+ // 28 -> [(0, 2), (1, 2), (2, 2), (3, 2), (4, 2)]
+ // 29 -> [(0, 2), (1, 2), (2, 2), (4, 2)]
+ // 30 -> [(0, 2), (1, 2), (2, 2), t(2, 2), (3, 2), (4, 2)]
+ // 31 -> [(0, 2), (1, 2), (3, 2), (4, 2)]
+ // 32 -> [(0, 2), (1, 2), (4, 2)]
+ // 33 -> [(0, 2), (1, 2), t(1, 2), (2, 2), (3, 2), (4, 2)]
+ // 34 -> [(0, 2), (1, 2), t(2, 2), (2, 2), (3, 2), (4, 2)]
+ // 35 -> [(0, 2), (2, 1), (4, 2)]
+ // 36 -> [(0, 2), (2, 2), (3, 2), (4, 2)]
+ // 37 -> [(0, 2), (2, 2), (4, 2)]
+ // 38 -> [(0, 2), (3, 2), (4, 2)]
+ // 39 -> [(0, 2), (4, 2)]
+ // 40 -> [(0, 2), t(1, 2), (1, 2), (2, 2), (3, 2), (4, 2)]
+ // 41 -> [(0, 2), t(2, 2), (2, 2), (3, 2), (4, 2)]
+ // 42 -> [t(0, 2), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2)]
+ // 43 -> [t(0, 2), (0, 2), (1, 2), (2, 2), (4, 2)]
+ // 44 -> [t(0, 2), (0, 2), (1, 2), (2, 2), t(2, 2), (3, 2), (4, 2)]
+
+
+ /** @param {number} w - length of word being checked */
+ constructor(w) {
+ super(w, 2, new Int32Array([
+ 0,1,2,0,1,-1,0,-1,0,-1,0,-1,0,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-2,
+ -1,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
+ ]));
+ }
+}
+
+Lev2TParametricDescription.prototype.toStates0 = /*2 bits per value */ new Int32Array([
+ 0xe,
+]);
+Lev2TParametricDescription.prototype.offsetIncrs0 = /*1 bits per value */ new Int32Array([
+ 0x0,
+]);
+
+Lev2TParametricDescription.prototype.toStates1 = /*3 bits per value */ new Int32Array([
+ 0x1a688a2c,
+]);
+Lev2TParametricDescription.prototype.offsetIncrs1 = /*1 bits per value */ new Int32Array([
+ 0x3e0,
+]);
+
+Lev2TParametricDescription.prototype.toStates2 = /*4 bits per value */ new Int32Array([
+ 0x70707054,0xdc07035,0x3dd3a3a,0x2323213a,
+ 0x15435223,0x22545432,0x5435,
+]);
+Lev2TParametricDescription.prototype.offsetIncrs2 = /*2 bits per value */ new Int32Array([
+ 0x80000,0x55582088,0x55555555,0x55,
+]);
+
+Lev2TParametricDescription.prototype.toStates3 = /*5 bits per value */ new Int32Array([
+ 0x1c0380a4,0x700a570,0xca529c0,0x180a00,
+ 0xa80af180,0xc5498e60,0x5a546398,0x8c4300e8,
+ 0xac18c601,0xd8d43501,0x863500ad,0x51976d6a,
+ 0x8ca0180a,0xc3501ac2,0xb0c5be16,0x76dda8a5,
+ 0x18c4519,0xc41294a,0xe248d231,0x1086520c,
+ 0xce31ac42,0x13946358,0x2d0348c4,0x6732d494,
+ 0x1ad224a5,0xd635ad4b,0x520c4139,0xce24948,
+ 0x22110a52,0x58ce729d,0xc41394e3,0x941cc520,
+ 0x90e732d4,0x4729d224,0x39ce35ad,
+]);
+Lev2TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new Int32Array([
+ 0x80000,0xc0c830,0x300f3c30,0x2200fcff,
+ 0xcaa00a08,0x3c2200a8,0xa8fea00a,0x55555555,
+ 0x55555555,0x55555555,0x55555555,0x55555555,
+ 0x55555555,0x55555555,
+]);
+
+Lev2TParametricDescription.prototype.toStates4 = /*6 bits per value */ new Int32Array([
+ 0x801c0144,0x1453803,0x14700038,0xc0005145,
+ 0x1401,0x14,0x140000,0x0,
+ 0x510000,0x6301f007,0x301f00d1,0xa186178,
+ 0xc20ca0c3,0xc20c30,0xc30030c,0xc00c00cd,
+ 0xf0c00c30,0x4c054014,0xc30944c3,0x55150c34,
+ 0x8300550,0x430c0143,0x50c31,0xc30850c,
+ 0xc3143000,0x50053c50,0x5130d301,0x850d30c2,
+ 0x30a08608,0xc214414,0x43142145,0x21450031,
+ 0x1400c314,0x4c143145,0x32832803,0x28014d6c,
+ 0xcd34a0c3,0x1c50c76,0x1c314014,0x430c30c3,
+ 0x1431,0xc300500,0xca00d303,0xd36d0e40,
+ 0x90b0e400,0xcb2abb2c,0x70c20ca1,0x2c32ca2c,
+ 0xcd2c70cb,0x31c00c00,0x34c2c32c,0x5583280,
+ 0x558309b7,0x6cd6ca14,0x430850c7,0x51c51401,
+ 0x1430c714,0xc3087,0x71451450,0xca00d30,
+ 0xc26dc156,0xb9071560,0x1cb2abb2,0xc70c2144,
+ 0xb1c51ca1,0x1421c70c,0xc51c00c3,0x30811c51,
+ 0x24324308,0xc51031c2,0x70820820,0x5c33830d,
+ 0xc33850c3,0x30c30c30,0xc30c31c,0x451450c3,
+ 0x20c20c20,0xda0920d,0x5145914f,0x36596114,
+ 0x51965865,0xd9643653,0x365a6590,0x51964364,
+ 0x43081505,0x920b2032,0x2c718b28,0xd7242249,
+ 0x35cb28b0,0x2cb3872c,0x972c30d7,0xb0c32cb2,
+ 0x4e1c75c,0xc80c90c2,0x62ca2482,0x4504171c,
+ 0xd65d9610,0x33976585,0xd95cb5d,0x4b5ca5d7,
+ 0x73975c36,0x10308138,0xc2245105,0x41451031,
+ 0x14e24208,0xc35c3387,0x51453851,0x1c51c514,
+ 0xc70c30c3,0x20451450,0x14f1440c,0x4f0da092,
+ 0x4513d41,0x6533944d,0x1350e658,0xe1545055,
+ 0x64365a50,0x5519383,0x51030815,0x28920718,
+ 0x441c718b,0x714e2422,0x1c35cb28,0x4e1c7387,
+ 0xb28e1c51,0x5c70c32c,0xc204e1c7,0x81c61440,
+ 0x1c62ca24,0xd04503ce,0x85d63944,0x39338e65,
+ 0x8e154387,0x364b5ca3,0x38739738,
+]);
+Lev2TParametricDescription.prototype.offsetIncrs4 = /*3 bits per value */ new Int32Array([
+ 0x10000000,0xc00000,0x60061,0x400,
+ 0x0,0x80010008,0x249248a4,0x8229048,
+ 0x2092,0x6c3603,0xb61b6c30,0x6db6036d,
+ 0xdb6c0,0x361b0180,0x91b72000,0xdb11b71b,
+ 0x6db6236,0x1008200,0x12480012,0x24924906,
+ 0x48200049,0x80410002,0x24000900,0x4924a489,
+ 0x10822492,0x20800125,0x48360,0x9241b692,
+ 0x6da4924,0x40009268,0x241b010,0x291b4900,
+ 0x6d249249,0x49493423,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x2492,
+]);
+
+Lev2TParametricDescription.prototype.toStates5 = /*6 bits per value */ new Int32Array([
+ 0x801c0144,0x1453803,0x14700038,0xc0005145,
+ 0x1401,0x14,0x140000,0x0,
+ 0x510000,0x4e00e007,0xe0051,0x3451451c,
+ 0xd015000,0x30cd0000,0xc30c30c,0xc30c30d4,
+ 0x40c30c30,0x7c01c014,0xc03458c0,0x185e0c07,
+ 0x2830c286,0x830c3083,0xc30030,0x33430c,
+ 0x30c3003,0x70051030,0x16301f00,0x8301f00d,
+ 0x30a18617,0xc20ca0c,0x431420c3,0xb1450c51,
+ 0x14314315,0x4f143145,0x34c05401,0x4c30944c,
+ 0x55150c3,0x30830055,0x1430c014,0xc00050c3,
+ 0xc30850,0xc314300,0x150053c5,0x25130d30,
+ 0x5430d30c,0xc0354154,0x300d0c90,0x1cb2cd0c,
+ 0xc91cb0c3,0x72c30cb2,0x14f1cb2c,0xc34c0540,
+ 0x34c30944,0x82182214,0x851050c2,0x50851430,
+ 0x1400c50c,0x30c5085,0x50c51450,0x150053c,
+ 0xc25130d3,0x8850d30,0x1430a086,0x450c2144,
+ 0x51cb1c21,0x1c91c70c,0xc71c314b,0x34c1cb1,
+ 0x6c328328,0xc328014d,0x76cd34a0,0x1401c50c,
+ 0xc31c3140,0x31430c30,0x14,0x30c3005,
+ 0xa0ca00d3,0x535b0c,0x4d2830ca,0x514369b3,
+ 0xc500d01,0x5965965a,0x30d46546,0x6435030c,
+ 0x8034c659,0xdb439032,0x2c390034,0xcaaecb24,
+ 0x30832872,0xcb28b1c,0x4b1c32cb,0x70030033,
+ 0x30b0cb0c,0xe40ca00d,0x400d36d0,0xb2c90b0e,
+ 0xca1cb2ab,0xa2c70c20,0x6575d95c,0x4315b5ce,
+ 0x95c53831,0x28034c5d,0x9b705583,0xa1455830,
+ 0xc76cd6c,0x40143085,0x71451c51,0x871430c,
+ 0x450000c3,0xd3071451,0x1560ca00,0x560c26dc,
+ 0xb35b2851,0xc914369,0x1a14500d,0x46593945,
+ 0xcb2c939,0x94507503,0x328034c3,0x9b70558,
+ 0xe41c5583,0x72caaeca,0x1c308510,0xc7147287,
+ 0x50871c32,0x1470030c,0xd307147,0xc1560ca0,
+ 0x1560c26d,0xabb2b907,0x21441cb2,0x38a1c70c,
+ 0x8e657394,0x314b1c93,0x39438738,0x43083081,
+ 0x31c22432,0x820c510,0x830d7082,0x50c35c33,
+ 0xc30c338,0xc31c30c3,0x50c30c30,0xc204514,
+ 0x890c90c2,0x31440c70,0xa8208208,0xea0df0c3,
+ 0x8a231430,0xa28a28a2,0x28a28a1e,0x1861868a,
+ 0x48308308,0xc3682483,0x14516453,0x4d965845,
+ 0xd4659619,0x36590d94,0xd969964,0x546590d9,
+ 0x20c20541,0x920d20c,0x5914f0da,0x96114514,
+ 0x65865365,0xe89d3519,0x99e7a279,0x9e89e89e,
+ 0x81821827,0xb2032430,0x18b28920,0x422492c7,
+ 0xb28b0d72,0x3872c35c,0xc30d72cb,0x32cb2972,
+ 0x1c75cb0c,0xc90c204e,0xa2482c80,0x24b1c62c,
+ 0xc3a89089,0xb0ea2e42,0x9669a31c,0xa4966a28,
+ 0x59a8a269,0x8175e7a,0xb203243,0x718b2892,
+ 0x4114105c,0x17597658,0x74ce5d96,0x5c36572d,
+ 0xd92d7297,0xe1ce5d70,0xc90c204,0xca2482c8,
+ 0x4171c62,0x5d961045,0x976585d6,0x79669533,
+ 0x964965a2,0x659689e6,0x308175e7,0x24510510,
+ 0x451031c2,0xe2420841,0x5c338714,0x453851c3,
+ 0x51c51451,0xc30c31c,0x451450c7,0x41440c20,
+ 0xc708914,0x82105144,0xf1c58c90,0x1470ea0d,
+ 0x61861863,0x8a1e85e8,0x8687a8a2,0x3081861,
+ 0x24853c51,0x5053c368,0x1341144f,0x96194ce5,
+ 0x1544d439,0x94385514,0xe0d90d96,0x5415464,
+ 0x4f1440c2,0xf0da0921,0x4513d414,0x533944d0,
+ 0x350e6586,0x86082181,0xe89e981d,0x18277689,
+ 0x10308182,0x89207185,0x41c718b2,0x14e24224,
+ 0xc35cb287,0xe1c73871,0x28e1c514,0xc70c32cb,
+ 0x204e1c75,0x1c61440c,0xc62ca248,0x90891071,
+ 0x2e41c58c,0xa31c70ea,0xe86175e7,0xa269a475,
+ 0x5e7a57a8,0x51030817,0x28920718,0xf38718b,
+ 0xe5134114,0x39961758,0xe1ce4ce,0x728e3855,
+ 0x5ce0d92d,0xc204e1ce,0x81c61440,0x1c62ca24,
+ 0xd04503ce,0x85d63944,0x75338e65,0x5d86075e,
+ 0x89e69647,0x75e76576,
+]);
+Lev2TParametricDescription.prototype.offsetIncrs5 = /*3 bits per value */ new Int32Array([
+ 0x10000000,0xc00000,0x60061,0x400,
+ 0x0,0x60000008,0x6b003080,0xdb6ab6db,
+ 0x2db6,0x800400,0x49245240,0x11482412,
+ 0x104904,0x40020000,0x92292000,0xa4b25924,
+ 0x9649658,0xd80c000,0xdb0c001b,0x80db6d86,
+ 0x6db01b6d,0xc0600003,0x86000d86,0x6db6c36d,
+ 0xddadb6ed,0x300001b6,0x6c360,0xe37236e4,
+ 0x46db6236,0xdb6c,0x361b018,0xb91b7200,
+ 0x6dbb1b71,0x6db763,0x20100820,0x61248001,
+ 0x92492490,0x24820004,0x8041000,0x92400090,
+ 0x24924830,0x555b6a49,0x2080012,0x20004804,
+ 0x49252449,0x84112492,0x4000928,0x240201,
+ 0x92922490,0x58924924,0x49456,0x120d8082,
+ 0x6da4800,0x69249249,0x249a01b,0x6c04100,
+ 0x6d240009,0x92492483,0x24d5adb4,0x60208001,
+ 0x92000483,0x24925236,0x6846da49,0x10400092,
+ 0x241b0,0x49291b49,0x636d2492,0x92494935,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,0x49249249,
+ 0x92492492,0x24924924,0x49249249,0x92492492,
+ 0x24924924,0x49249249,0x92492492,0x24924924,
+ 0x49249249,0x92492492,0x24924924,
+]);
+
+class Lev1TParametricDescription extends ParametricDescription {
+ /**
+ * @param {number} absState
+ * @param {number} position
+ * @param {number} vector
+ * @returns {number}
+ */
+ transition(absState, position, vector) {
+ let state = Math.floor(absState / (this.w + 1));
+ let offset = absState % (this.w + 1);
+
+ if (position === this.w) {
+ if (state < 2) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 2) + state;
+ offset += this.unpack(this.offsetIncrs0, loc, 1);
+ state = this.unpack(this.toStates0, loc, 2) - 1;
+ }
+ } else if (position === this.w - 1) {
+ if (state < 3) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 3) + state;
+ offset += this.unpack(this.offsetIncrs1, loc, 1);
+ state = this.unpack(this.toStates1, loc, 2) - 1;
+ }
+ } else if (position === this.w - 2) {
+ if (state < 6) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 6) + state;
+ offset += this.unpack(this.offsetIncrs2, loc, 2);
+ state = this.unpack(this.toStates2, loc, 3) - 1;
+ }
+ } else {
+ if (state < 6) { // eslint-disable-line no-lonely-if
+ const loc = Math.imul(vector, 6) + state;
+ offset += this.unpack(this.offsetIncrs3, loc, 2);
+ state = this.unpack(this.toStates3, loc, 3) - 1;
+ }
+ }
+
+ if (state === -1) {
+ // null state
+ return -1;
+ } else {
+ // translate back to abs
+ return Math.imul(state, this.w + 1) + offset;
+ }
+ }
+
+ // state map
+ // 0 -> [(0, 0)]
+ // 1 -> [(0, 1)]
+ // 2 -> [(0, 1), (1, 1)]
+ // 3 -> [(0, 1), (1, 1), (2, 1)]
+ // 4 -> [(0, 1), (2, 1)]
+ // 5 -> [t(0, 1), (0, 1), (1, 1), (2, 1)]
+
+
+ /** @param {number} w - length of word being checked */
+ constructor(w) {
+ super(w, 1, new Int32Array([0,1,0,-1,-1,-1]));
+ }
+}
+
+Lev1TParametricDescription.prototype.toStates0 = /*2 bits per value */ new Int32Array([
+ 0x2,
+]);
+Lev1TParametricDescription.prototype.offsetIncrs0 = /*1 bits per value */ new Int32Array([
+ 0x0,
+]);
+
+Lev1TParametricDescription.prototype.toStates1 = /*2 bits per value */ new Int32Array([
+ 0xa43,
+]);
+Lev1TParametricDescription.prototype.offsetIncrs1 = /*1 bits per value */ new Int32Array([
+ 0x38,
+]);
+
+Lev1TParametricDescription.prototype.toStates2 = /*3 bits per value */ new Int32Array([
+ 0x12180003,0xb45a4914,0x69,
+]);
+Lev1TParametricDescription.prototype.offsetIncrs2 = /*2 bits per value */ new Int32Array([
+ 0x558a0000,0x5555,
+]);
+
+Lev1TParametricDescription.prototype.toStates3 = /*3 bits per value */ new Int32Array([
+ 0x900c0003,0xa1904864,0x45a49169,0x5a6d196a,
+ 0x9634,
+]);
+Lev1TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new Int32Array([
+ 0xa0fc0000,0x5555ba08,0x55555555,
+]);
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 161fa63..dd3124e 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6071,6 +6071,7 @@
[`unnecessary_literal_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_bound
[`unnecessary_literal_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_literal_unwrap
[`unnecessary_map_on_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_on_constructor
+[`unnecessary_map_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_map_or
[`unnecessary_min_or_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_min_or_max
[`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed
[`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation
diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
index 204f4af..a37c873 100644
--- a/src/tools/clippy/clippy_dev/src/setup/vscode.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
@@ -84,7 +84,7 @@ fn delete_vs_task_file(path: &Path) -> bool {
/// It may fail silently.
fn try_delete_vs_directory_if_empty() {
let path = Path::new(VSCODE_DIR);
- if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) {
+ if path.read_dir().is_ok_and(|mut iter| iter.next().is_none()) {
// The directory is empty. We just try to delete it but allow a silence
// fail as an empty `.vscode` directory is still valid
let _silence_result = fs::remove_dir(path);
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index dc5a685..e218535 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
return;
}
if let Some(lint_list) = &attr.meta_item_list() {
- if attr.ident().map_or(false, |ident| is_lint_level(ident.name, attr.id)) {
+ if attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) {
for lint in lint_list {
match item.kind {
ItemKind::Use(..) => {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
index 9b10ae8..3bb0268 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs
@@ -50,7 +50,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_
block
.expr
.as_ref()
- .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)),
+ .is_some_and(|e| is_relevant_expr(cx, typeck_results, e)),
|stmt| match &stmt.kind {
StmtKind::Let(_) => true,
StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr),
@@ -60,7 +60,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_
}
fn is_relevant_expr(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_>, expr: &Expr<'_>) -> bool {
- if macro_backtrace(expr.span).last().map_or(false, |macro_call| {
+ if macro_backtrace(expr.span).last().is_some_and(|macro_call| {
is_panic(cx, macro_call.def_id) || cx.tcx.item_name(macro_call.def_id) == sym::unreachable
}) {
return false;
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index db57921..7d89195 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -60,8 +60,8 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -
trait_id,
)
})
- .map_or(false, |assoc_item| {
- let proj = Ty::new_projection_from_args(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, []));
+ .is_some_and(|assoc_item| {
+ let proj = Ty::new_projection(cx.tcx, assoc_item.def_id, cx.tcx.mk_args_trait(ty, []));
let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
nty.is_bool()
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 26a20bc..896bd5f 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -667,5 +667,5 @@ fn implements_ord(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
let ty = cx.typeck_results().expr_ty(expr);
cx.tcx
.get_diagnostic_item(sym::Ord)
- .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ .is_some_and(|id| implements_trait(cx, ty, id, &[]))
}
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index bf1d077..a1ca23e 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -45,7 +45,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
// And that method is `new`
&& seg.ident.name == sym::new
// And the call is that of a `Box` method
- && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
+ && path_def_id(cx, ty).is_some_and(|id| Some(id) == cx.tcx.lang_items().owned_box())
// And the single argument to the call is another function call
// This is the `T::default()` (or default equivalent) of `Box::new(T::default())`
&& let ExprKind::Call(arg_path, _) = arg.kind
@@ -83,9 +83,9 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
}
fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) -> bool {
- macro_backtrace(expr.span).next().map_or(false, |call| {
- cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span)
- })
+ macro_backtrace(expr.span)
+ .next()
+ .is_some_and(|call| cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id) && call.span.eq_ctxt(ref_expr.span))
}
#[derive(Default)]
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index abd80ab..332e897 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -159,8 +159,7 @@ pub(super) fn check<'tcx>(
// The same is true if the expression encompassing the cast expression is a unary
// expression or an addressof expression.
let needs_block = matches!(cast_expr.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..))
- || get_parent_expr(cx, expr)
- .map_or(false, |e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)));
+ || get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Unary(..) | ExprKind::AddrOf(..)));
span_lint_and_sugg(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index b9baf9a..c85e350 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -110,7 +110,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let is_ord = cx
.tcx
.get_diagnostic_item(sym::Ord)
- .map_or(false, |id| implements_trait(cx, ty, id, &[]));
+ .is_some_and(|id| implements_trait(cx, ty, id, &[]));
if !is_ord {
return;
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index c4afdc7..3ecd36d 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -345,7 +345,7 @@ fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool {
let mut i = 0usize;
let mut res = true;
l.pat.each_binding_or_first(&mut |_, _, _, name| {
- if names.get(i).map_or(false, |&(_, n)| n == name.name) {
+ if names.get(i).is_some_and(|&(_, n)| n == name.name) {
i += 1;
} else {
res = false;
@@ -389,12 +389,10 @@ fn eq_stmts(
let new_bindings = &moved_bindings[old_count..];
blocks
.iter()
- .all(|b| get_stmt(b).map_or(false, |s| eq_binding_names(s, new_bindings)))
+ .all(|b| get_stmt(b).is_some_and(|s| eq_binding_names(s, new_bindings)))
} else {
true
- }) && blocks
- .iter()
- .all(|b| get_stmt(b).map_or(false, |s| eq.eq_stmt(s, stmt)))
+ }) && blocks.iter().all(|b| get_stmt(b).is_some_and(|s| eq.eq_stmt(s, stmt)))
}
#[expect(clippy::too_many_lines)]
@@ -451,9 +449,7 @@ fn scan_block_for_eq<'tcx>(
// x + 50
let expr_hash_eq = if let Some(e) = block.expr {
let hash = hash_expr(cx, e);
- blocks
- .iter()
- .all(|b| b.expr.map_or(false, |e| hash_expr(cx, e) == hash))
+ blocks.iter().all(|b| b.expr.is_some_and(|e| hash_expr(cx, e) == hash))
} else {
blocks.iter().all(|b| b.expr.is_none())
};
@@ -514,7 +510,7 @@ fn scan_block_for_eq<'tcx>(
});
if let Some(e) = block.expr {
for block in blocks {
- if block.expr.map_or(false, |expr| !eq.eq_expr(expr, e)) {
+ if block.expr.is_some_and(|expr| !eq.eq_expr(expr, e)) {
moved_locals.truncate(moved_locals_at_start);
return BlockEq {
start_end_eq,
@@ -533,7 +529,7 @@ fn scan_block_for_eq<'tcx>(
}
fn check_for_warn_of_moved_symbol(cx: &LateContext<'_>, symbols: &[(HirId, Symbol)], if_expr: &Expr<'_>) -> bool {
- get_enclosing_block(cx, if_expr.hir_id).map_or(false, |block| {
+ get_enclosing_block(cx, if_expr.hir_id).is_some_and(|block| {
let ignore_span = block.span.shrink_to_lo().to(if_expr.span);
symbols
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index edb5285..dff60f7 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -481,6 +481,7 @@
crate::methods::UNNECESSARY_JOIN_INFO,
crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO,
crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO,
+ crate::methods::UNNECESSARY_MAP_OR_INFO,
crate::methods::UNNECESSARY_MIN_OR_MAX_INFO,
crate::methods::UNNECESSARY_RESULT_MAP_OR_ELSE_INFO,
crate::methods::UNNECESSARY_SORT_BY_INFO,
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 4808c37..ef6b141 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -253,6 +253,6 @@ fn from(v: Ty<'tcx>) -> Self {
impl<'tcx> From<Option<Ty<'tcx>>> for ExplicitTyBound {
fn from(v: Option<Ty<'tcx>>) -> Self {
- Self(v.map_or(false, Ty::is_numeric))
+ Self(v.is_some_and(Ty::is_numeric))
}
}
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index 2b6bfaf..767dda5 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -81,7 +81,7 @@ fn is_path_self(e: &Expr<'_>) -> bool {
fn contains_trait_object(ty: Ty<'_>) -> bool {
match ty.kind() {
ty::Ref(_, ty, _) => contains_trait_object(*ty),
- ty::Adt(def, args) => def.is_box() && args[0].as_type().map_or(false, contains_trait_object),
+ ty::Adt(def, args) => def.is_box() && args[0].as_type().is_some_and(contains_trait_object),
ty::Dynamic(..) => true,
_ => false,
}
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index e569c4d..0db6a82 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -327,7 +327,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
// there's a Copy impl for any instance of the adt.
if !is_copy(cx, ty) {
if ty_subs.non_erasable_generics().next().is_some() {
- let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).map_or(false, |impls| {
+ let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).is_some_and(|impls| {
impls.iter().any(|&id| {
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)
if ty_adt.did() == adt.did())
diff --git a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
index c917303..40377dd 100644
--- a/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/missing_headers.rs
@@ -47,7 +47,7 @@ pub fn check(
),
_ => (),
}
- if !headers.panics && panic_info.map_or(false, |el| !el.1) {
+ if !headers.panics && panic_info.is_some_and(|el| !el.1) {
span_lint_and_note(
cx,
MISSING_PANICS_DOC,
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 c7dd729..55afdbf 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -112,7 +112,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
MEM_FORGET,
Cow::Owned(format!(
"usage of `mem::forget` on {}",
- if arg_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) {
+ if arg_ty.ty_adt_def().is_some_and(|def| def.has_dtor(cx.tcx)) {
"`Drop` type"
} else {
"type with `Drop` fields"
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index de10b7b..6c87a05 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -196,7 +196,7 @@ fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tc
{
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| {
+ if path_to_local(callee).is_some_and(|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,
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index c2b40ae..4986a31 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -87,7 +87,7 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<HirId> {
}
fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) {
- if path_to_local(arg).map_or(false, |id| raw_ptrs.contains(&id)) {
+ if path_to_local(arg).is_some_and(|id| raw_ptrs.contains(&id)) {
span_lint(
cx,
NOT_UNSAFE_PTR_ARG_DEREF,
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 48874d6..d3aade31f 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -171,13 +171,13 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
if let ExprKind::Path(ref qpath) = path.kind {
cx.qpath_res(qpath, path.hir_id)
.opt_def_id()
- .map_or(false, |id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
+ .is_some_and(|id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
.into()
} else {
Finite
}
},
- ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
+ ExprKind::Struct(..) => higher::Range::hir(expr).is_some_and(|r| r.end.is_none()).into(),
_ => Finite,
}
}
@@ -228,9 +228,7 @@ fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
let not_double_ended = cx
.tcx
.get_diagnostic_item(sym::DoubleEndedIterator)
- .map_or(false, |id| {
- !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[])
- });
+ .is_some_and(|id| !implements_trait(cx, cx.typeck_results().expr_ty(receiver), id, &[]));
if not_double_ended {
return is_infinite(cx, receiver);
}
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index dd90e2a..6363f71 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -309,8 +309,8 @@ fn check_enum_start(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>
let item_name_chars = item_name.chars().count();
if count_match_start(item_name, name).char_count == item_name_chars
- && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
- && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
+ && name.chars().nth(item_name_chars).is_some_and(|c| !c.is_lowercase())
+ && name.chars().nth(item_name_chars + 1).is_some_and(|c| !c.is_numeric())
{
span_lint_hir(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
index b19b348..2510581 100644
--- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs
@@ -75,7 +75,7 @@ fn check_sig(cx: &LateContext<'_>, name: Symbol, sig: &FnSig<'_>, fn_id: LocalDe
if cx
.tcx
.get_diagnostic_item(sym::Iterator)
- .map_or(false, |iter_id| !implements_trait(cx, ret_ty, iter_id, &[]))
+ .is_some_and(|iter_id| !implements_trait(cx, ret_ty, iter_id, &[]))
{
span_lint(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 44b9d6a..c5a2760 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -56,7 +56,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
&& !item.span.from_expansion()
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let ty::Array(element_type, cst) = ty.kind()
- && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx.try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree()
+ && let Some((ty::ValTree::Leaf(element_count), _)) = cx.tcx
+ .try_normalize_erasing_regions(ParamEnv::empty(), *cst).unwrap_or(*cst).try_to_valtree()
&& let element_count = element_count.to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size)
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 ab3d19f..4f22931 100644
--- a/src/tools/clippy/clippy_lints/src/large_include_file.rs
+++ b/src/tools/clippy/clippy_lints/src/large_include_file.rs
@@ -94,6 +94,8 @@ fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &Attribute) {
// Currently, rustc limits the usage of macro at the top-level of attributes,
// so we don't need to recurse into each level.
&& let AttrKind::Normal(ref normal) = attr.kind
+ && let Some(doc) = attr.doc_str()
+ && doc.as_str().len() as u64 > self.max_file_size
&& let AttrArgs::Eq(_, AttrArgsEq::Hir(ref meta)) = normal.item.args
&& !attr.span.contains(meta.span)
// Since the `include_str` is already expanded at this point, we can only take the
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index b7887ef..3ea758e 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -622,7 +622,7 @@ fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
let ty = &cx.typeck_results().expr_ty(expr).peel_refs();
match ty.kind() {
- ty::Dynamic(tt, ..) => tt.principal().map_or(false, |principal| {
+ ty::Dynamic(tt, ..) => tt.principal().is_some_and(|principal| {
let is_empty = sym!(is_empty);
cx.tcx
.associated_items(principal.def_id())
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index d55be2b..ce0e1a2 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -737,7 +737,7 @@ fn elision_suggestions(
suggestions.extend(
usages
.iter()
- .filter(|usage| named_lifetime(usage).map_or(false, |id| elidable_lts.contains(&id)))
+ .filter(|usage| named_lifetime(usage).is_some_and(|id| elidable_lts.contains(&id)))
.map(|usage| {
match cx.tcx.parent_hir_node(usage.hir_id) {
Node::Ty(Ty {
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index bfe2e68..1721f56 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(
.tcx
.lang_items()
.copy_trait()
- .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ .is_some_and(|id| implements_trait(cx, ty, id, &[]))
{
snippet.push_str(
&format!(
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index af08945..701567a 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -416,7 +416,7 @@ fn get_assignments<'a, 'tcx>(
.chain(*expr)
.filter(move |e| {
if let ExprKind::AssignOp(_, place, _) = e.kind {
- path_to_local(place).map_or(false, |id| {
+ path_to_local(place).is_some_and(|id| {
!loop_counters
.iter()
// skip the first item which should be `StartKind::Range`
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 094b194..39e5e14 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -126,7 +126,7 @@ pub fn is_found(cx: &LateContext<'_>, hir_id: HirId) -> bool {
break_after_expr: false,
};
- get_enclosing_block(cx, hir_id).map_or(false, |block| {
+ get_enclosing_block(cx, hir_id).is_some_and(|block| {
visitor.visit_block(block);
visitor.break_after_expr
})
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index d255fea..951ebc9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -50,7 +50,7 @@ fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>, ctxt:
.tcx
.lang_items()
.clone_trait()
- .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ .is_some_and(|id| implements_trait(cx, ty, id, &[]))
{
// Make sure that the push does not involve possibly mutating values
match pushed_item.kind {
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index c4c504e..51fde52 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -256,9 +256,10 @@ fn is_conditional(expr: &Expr<'_>) -> bool {
/// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
/// actual `Iterator` that the loop uses.
pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String {
- let impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
- implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
- });
+ let impls_iterator = cx
+ .tcx
+ .get_diagnostic_item(sym::Iterator)
+ .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[]));
if impls_iterator {
format!(
"{}",
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
index fd66cac..016ec73 100644
--- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -226,7 +226,7 @@ fn is_clampable<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<TypeClampa
} else if cx
.tcx
.get_diagnostic_item(sym::Ord)
- .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ .is_some_and(|id| implements_trait(cx, ty, id, &[]))
{
Some(TypeClampability::Ord)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 828c5a3..3f401ef 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -162,9 +162,9 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t
..
}) = expr.kind
{
- constant_length(cx, pattern).map_or(false, |length| *n == length)
+ constant_length(cx, pattern).is_some_and(|length| *n == length)
} else {
- len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg))
+ len_arg(cx, expr).is_some_and(|arg| eq_expr_value(cx, pattern, arg))
}
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 6d62b53..47472ab 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -74,7 +74,7 @@ fn find_matches_sugg<'a, 'b, I>(
&& b0 != b1
&& (first_guard.is_none() || iter.len() == 0)
&& first_attrs.is_empty()
- && iter.all(|arm| find_bool_lit(&arm.2.kind).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty())
+ && iter.all(|arm| find_bool_lit(&arm.2.kind).is_some_and(|b| b == b0) && arm.3.is_none() && arm.0.is_empty())
{
if let Some(last_pat) = last_pat_opt {
if !is_wild(last_pat) {
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index ca45ed6..264458a 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -447,7 +447,7 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
.tcx
.lang_items()
.get(expected_lang_item)
- .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
+ .is_some_and(|expected_id| cx.tcx.parent(id) == expected_id),
Item::Diag(expected_ty, expected_variant) => {
let ty = cx.typeck_results().pat_ty(pat);
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 2aea25b..95a4bf6 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -175,7 +175,7 @@ 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);
+ self.has_enum |= self.typeck.pat_ty(pat).ty_adt_def().is_some_and(AdtDef::is_enum);
walk_pat(self, pat)
}
}
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 c7e1b70..6c02207 100644
--- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
@@ -58,7 +58,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
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(_))) {
+ let ret_prefix = if get_parent_expr(cx, expr).is_some_and(|e| matches!(e.kind, ExprKind::Ret(_))) {
"" // already returns
} else {
"return "
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index c288dbd..6dc48c2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -83,7 +83,7 @@ fn can_be_static_str(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
hir::ExprKind::MethodCall(..) => {
cx.typeck_results()
.type_dependent_def_id(arg.hir_id)
- .map_or(false, |method_id| {
+ .is_some_and(|method_id| {
matches!(
cx.tcx.fn_sig(method_id).instantiate_identity().output().skip_binder().kind(),
ty::Ref(re, ..) if re.is_static()
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
index e697ba6..6c1a14f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
@@ -32,9 +32,10 @@ pub(super) fn check<'tcx>(
filter_arg: &'tcx hir::Expr<'_>,
) {
// lint if caller of `.filter().next()` is an Iterator
- let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
- implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[])
- });
+ let recv_impls_iterator = cx
+ .tcx
+ .get_diagnostic_item(sym::Iterator)
+ .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[]));
if recv_impls_iterator {
let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
`.find(..)` instead";
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
index 5f3fec5..9a03559 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
@@ -19,9 +19,7 @@ pub(super) fn check<'tcx>(
if cx
.tcx
.get_diagnostic_item(sym::DoubleEndedIterator)
- .map_or(false, |double_ended_iterator| {
- implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])
- })
+ .is_some_and(|double_ended_iterator| implements_trait(cx, rev_recv_ty, double_ended_iterator, &[]))
&& is_trait_method(cx, rev_call, sym::Iterator)
&& is_trait_method(cx, expr, sym::Iterator)
{
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
index 61e7436..098721d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -36,8 +36,8 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
} else {
let ty = cx.typeck_results().expr_ty(e);
if is_type_lang_item(cx, ty, LangItem::String)
- || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, Ty::is_str))
- || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, Ty::is_str))
+ || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).is_some_and(Ty::is_str))
+ || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).is_some_and(Ty::is_str))
{
Some(RepeatKind::String)
} else {
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 515d4a1..d5594b2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -70,7 +70,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_
if ident_eq(name, obj) && method.ident.name == sym::clone
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
&& let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
- && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+ && cx.tcx.lang_items().clone_trait() == Some(trait_id)
// no autoderefs
&& !cx.typeck_results().expr_adjustments(obj).iter()
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index b180979..795e041 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -121,6 +121,7 @@
mod unnecessary_join;
mod unnecessary_lazy_eval;
mod unnecessary_literal_unwrap;
+mod unnecessary_map_or;
mod unnecessary_min_or_max;
mod unnecessary_result_map_or_else;
mod unnecessary_sort_by;
@@ -4101,6 +4102,33 @@
declare_clippy_lint! {
/// ### What it does
+ /// Converts some constructs mapping an Enum value for equality comparison.
+ ///
+ /// ### Why is this bad?
+ /// Calls such as `opt.map_or(false, |val| val == 5)` are needlessly long and cumbersome,
+ /// and can be reduced to, for example, `opt == Some(5)` assuming `opt` implements `PartialEq`.
+ /// This lint offers readability and conciseness improvements.
+ ///
+ /// ### Example
+ /// ```no_run
+ /// pub fn a(x: Option<i32>) -> bool {
+ /// x.map_or(false, |n| n == 5)
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```no_run
+ /// pub fn a(x: Option<i32>) -> bool {
+ /// x == Some(5)
+ /// }
+ /// ```
+ #[clippy::version = "1.75.0"]
+ pub UNNECESSARY_MAP_OR,
+ style,
+ "reduce unnecessary pattern matching for constructs that implement `PartialEq`"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
/// Checks if an iterator is used to check if a string is ascii.
///
/// ### Why is this bad?
@@ -4417,6 +4445,7 @@ pub fn new(conf: &'static Conf, format_args: FormatArgsStorage) -> Self {
NEEDLESS_AS_BYTES,
MAP_ALL_ANY_IDENTITY,
MAP_WITH_UNUSED_ARGUMENT_OVER_RANGES,
+ UNNECESSARY_MAP_OR,
]);
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4950,6 +4979,7 @@ fn check_methods<'tcx>(&self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
option_map_or_none::check(cx, expr, recv, def, map);
manual_ok_or::check(cx, expr, recv, def, map);
option_map_or_err_ok::check(cx, expr, recv, def, map);
+ unnecessary_map_or::check(cx, expr, recv, def, map, &self.msrv);
},
("map_or_else", [def, map]) => {
result_map_or_else_none::check(cx, expr, recv, def, map);
@@ -5343,7 +5373,7 @@ fn matches_value<'a>(cx: &LateContext<'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> boo
boxed_ty == parent_ty
} else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) {
if let ty::Adt(_, args) = ty.kind() {
- args.types().next().map_or(false, |t| t == parent_ty)
+ args.types().next() == Some(parent_ty)
} else {
false
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 0551070..9c41528 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -193,7 +193,7 @@ fn check_collect_into_intoiterator<'tcx>(
/// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
- cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
+ cx.typeck_results().type_dependent_def_id(call_id).is_some_and(|id| {
let sig = cx.tcx.fn_sig(id).instantiate_identity().skip_binder();
sig.inputs().len() == 1 && sig.output().is_bool()
})
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 389e020..998bdee 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -45,7 +45,7 @@ pub(super) fn check(
hir::ExprKind::Path(ref expr_qpath) => {
cx.qpath_res(expr_qpath, map_arg.hir_id)
.opt_def_id()
- .map_or(false, |fun_def_id| {
+ .is_some_and(|fun_def_id| {
cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
|| cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
|| deref_aliases
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index b685a46..6b39b75 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -59,9 +59,7 @@ fn check_unwrap_or_default(
let output_ty = cx.tcx.fn_sig(def_id).instantiate(cx.tcx, args).skip_binder().output();
cx.tcx
.get_diagnostic_item(sym::Default)
- .map_or(false, |default_trait_id| {
- implements_trait(cx, output_ty, default_trait_id, &[])
- })
+ .is_some_and(|default_trait_id| implements_trait(cx, output_ty, default_trait_id, &[]))
} else {
false
}
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 a2a7de9..1cee28e1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -348,7 +348,7 @@ fn parse_iter_usage<'tcx>(
&& cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
- .map_or(false, |id| is_diag_item_method(cx, id, sym::Option)) =>
+ .is_some_and(|id| is_diag_item_method(cx, id, sym::Option)) =>
{
(Some(UnwrapKind::Unwrap), e.span)
},
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
new file mode 100644
index 0000000..adc27cd
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_map_or.rs
@@ -0,0 +1,131 @@
+use std::borrow::Cow;
+
+use clippy_config::msrvs::{self, Msrv};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::eager_or_lazy::switch_to_eager_eval;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::sugg::{Sugg, make_binop};
+use clippy_utils::ty::{get_type_diagnostic_name, implements_trait};
+use clippy_utils::visitors::is_local_used;
+use clippy_utils::{is_from_proc_macro, path_to_local_id};
+use rustc_ast::LitKind::Bool;
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Expr, ExprKind, PatKind};
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+use super::UNNECESSARY_MAP_OR;
+
+pub(super) enum Variant {
+ Ok,
+ Some,
+}
+impl Variant {
+ pub fn variant_name(&self) -> &'static str {
+ match self {
+ Variant::Ok => "Ok",
+ Variant::Some => "Some",
+ }
+ }
+
+ pub fn method_name(&self) -> &'static str {
+ match self {
+ Variant::Ok => "is_ok_and",
+ Variant::Some => "is_some_and",
+ }
+ }
+}
+
+pub(super) fn check<'a>(
+ cx: &LateContext<'a>,
+ expr: &Expr<'a>,
+ recv: &Expr<'_>,
+ def: &Expr<'_>,
+ map: &Expr<'_>,
+ msrv: &Msrv,
+) {
+ let ExprKind::Lit(def_kind) = def.kind else {
+ return;
+ };
+
+ let recv_ty = cx.typeck_results().expr_ty(recv);
+
+ let Bool(def_bool) = def_kind.node else {
+ return;
+ };
+
+ let variant = match get_type_diagnostic_name(cx, recv_ty) {
+ Some(sym::Option) => Variant::Some,
+ Some(sym::Result) => Variant::Ok,
+ Some(_) | None => return,
+ };
+
+ let (sugg, method) = if let ExprKind::Closure(map_closure) = map.kind
+ && let closure_body = cx.tcx.hir().body(map_closure.body)
+ && let closure_body_value = closure_body.value.peel_blocks()
+ && let ExprKind::Binary(op, l, r) = closure_body_value.kind
+ && let Some(param) = closure_body.params.first()
+ && let PatKind::Binding(_, hir_id, _, _) = param.pat.kind
+ // checking that map_or is one of the following:
+ // .map_or(false, |x| x == y)
+ // .map_or(false, |x| y == x) - swapped comparison
+ // .map_or(true, |x| x != y)
+ // .map_or(true, |x| y != x) - swapped comparison
+ && ((BinOpKind::Eq == op.node && !def_bool) || (BinOpKind::Ne == op.node && def_bool))
+ && let non_binding_location = if path_to_local_id(l, hir_id) { r } else { l }
+ && switch_to_eager_eval(cx, non_binding_location)
+ // xor, because if its both then thats a strange edge case and
+ // we can just ignore it, since by default clippy will error on this
+ && (path_to_local_id(l, hir_id) ^ path_to_local_id(r, hir_id))
+ && !is_local_used(cx, non_binding_location, hir_id)
+ && let typeck_results = cx.typeck_results()
+ && typeck_results.expr_ty(l) == typeck_results.expr_ty(r)
+ && let Some(partial_eq) = cx.tcx.get_diagnostic_item(sym::PartialEq)
+ && implements_trait(cx, recv_ty, partial_eq, &[recv_ty.into()])
+ {
+ let wrap = variant.variant_name();
+
+ // we may need to add parens around the suggestion
+ // in case the parent expression has additional method calls,
+ // since for example `Some(5).map_or(false, |x| x == 5).then(|| 1)`
+ // being converted to `Some(5) == Some(5).then(|| 1)` isnt
+ // the same thing
+
+ let inner_non_binding = Sugg::NonParen(Cow::Owned(format!(
+ "{wrap}({})",
+ Sugg::hir(cx, non_binding_location, "")
+ )));
+
+ let binop = make_binop(op.node, &Sugg::hir(cx, recv, ".."), &inner_non_binding)
+ .maybe_par()
+ .into_string();
+
+ (binop, "a standard comparison")
+ } else if !def_bool
+ && msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND)
+ && let Some(recv_callsite) = snippet_opt(cx, recv.span.source_callsite())
+ && let Some(span_callsite) = snippet_opt(cx, map.span.source_callsite())
+ {
+ let suggested_name = variant.method_name();
+ (
+ format!("{recv_callsite}.{suggested_name}({span_callsite})",),
+ suggested_name,
+ )
+ } else {
+ return;
+ };
+
+ if is_from_proc_macro(cx, expr) {
+ return;
+ }
+
+ span_lint_and_sugg(
+ cx,
+ UNNECESSARY_MAP_OR,
+ expr.span,
+ "this `map_or` is redundant",
+ format!("use {method} instead"),
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index 6911da6..603916e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -166,9 +166,10 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Exp
},
)) = &left_expr.kind
&& left_name == left_ident
- && cx.tcx.get_diagnostic_item(sym::Ord).map_or(false, |id| {
- implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[])
- })
+ && cx
+ .tcx
+ .get_diagnostic_item(sym::Ord)
+ .is_some_and(|id| implements_trait(cx, cx.typeck_results().expr_ty(left_expr), id, &[]))
{
return Some(LintTrigger::Sort(SortDetection { vec_name }));
}
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 c309e77..8231325 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -124,7 +124,7 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
&& let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
&& let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
// We check it's the `Clone` trait.
- && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+ && cx.tcx.lang_items().clone_trait().is_some_and(|id| id == trait_id)
// no autoderefs
&& !cx.typeck_results().expr_adjustments(obj).iter()
.any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index 4cba13a..37d7427 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -427,7 +427,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
// See <https://github.com/rust-lang/rust-clippy/issues/4507> for a regression.
// FIXME: Find a better way to detect those cases.
let lit_snip = match snippet_opt(cx, span) {
- Some(snip) if snip.chars().next().map_or(false, |c| c.is_ascii_digit()) => snip,
+ Some(snip) if snip.chars().next().is_some_and(|c| c.is_ascii_digit()) => snip,
_ => return,
};
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 f7fa31d..c1424b9 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
@@ -134,9 +134,11 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
}
fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &Body<'_>) {
- if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| {
- local_def_id == cx.tcx.hir().body_owner_def_id(body.id())
- }) {
+ if self
+ .possible_borrowers
+ .last()
+ .is_some_and(|&(local_def_id, _)| local_def_id == cx.tcx.hir().body_owner_def_id(body.id()))
+ {
self.possible_borrowers.pop();
}
}
@@ -232,7 +234,7 @@ fn needless_borrow_count<'tcx>(
let mut check_reference_and_referent = |reference: &Expr<'tcx>, referent: &Expr<'tcx>| {
if let ExprKind::Field(base, _) = &referent.kind {
let base_ty = cx.typeck_results().expr_ty(base);
- if drop_trait_def_id.map_or(false, |id| implements_trait(cx, base_ty, id, &[])) {
+ if drop_trait_def_id.is_some_and(|id| implements_trait(cx, base_ty, id, &[])) {
return false;
}
}
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index c483677..c48232f 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -153,7 +153,7 @@ fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>)
}
fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool {
- block.stmts.first().map_or(false, |stmt| match stmt.kind {
+ block.stmts.first().is_some_and(|stmt| match stmt.kind {
ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
if let ast::ExprKind::Continue(ref l) = e.kind {
compare_labels(label, l.as_ref())
@@ -390,7 +390,7 @@ fn check_and_warn(cx: &EarlyContext<'_>, expr: &ast::Expr) {
#[must_use]
fn erode_from_back(s: &str) -> String {
let mut ret = s.to_string();
- while ret.pop().map_or(false, |c| c != '}') {}
+ while ret.pop().is_some_and(|c| c != '}') {}
while let Some(c) = ret.pop() {
if !c.is_whitespace() {
ret.push(c);
diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
index a13391a..83f7d93 100644
--- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
@@ -88,7 +88,7 @@ fn is_offending_macro(cx: &EarlyContext<'_>, span: Span, mac_braces: &MacroBrace
|| span
.macro_backtrace()
.last()
- .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
+ .is_some_and(|e| e.macro_def_id.is_some_and(DefId::is_local))
};
let span_call_site = span.ctxt().outer_expn_data().call_site;
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind
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 372128a..13b3d24 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
@@ -290,7 +290,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) {
Some((Node::Expr(parent), child_id)) => match parent.kind {
// Recursive call. Track which index the parameter is used in.
ExprKind::Call(callee, args)
- if path_def_id(cx, callee).map_or(false, |id| {
+ if path_def_id(cx, callee).is_some_and(|id| {
id == param.fn_id && has_matching_args(param.fn_kind, typeck.node_args(callee.hir_id))
}) =>
{
@@ -300,7 +300,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) {
return;
},
ExprKind::MethodCall(_, receiver, args, _)
- if typeck.type_dependent_def_id(parent.hir_id).map_or(false, |id| {
+ if typeck.type_dependent_def_id(parent.hir_id).is_some_and(|id| {
id == param.fn_id && has_matching_args(param.fn_kind, typeck.node_args(parent.hir_id))
}) =>
{
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 8b9f899..65ef56f 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
@@ -325,7 +325,7 @@ fn manage_unary_ops<'tcx>(
fn should_skip_expr<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) -> bool {
is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
|| self.expr_span.is_some()
- || self.const_span.map_or(false, |sp| sp.contains(expr.span))
+ || self.const_span.is_some_and(|sp| sp.contains(expr.span))
}
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
index 208b20a..b0d872e 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -42,14 +42,12 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
if typeck
.type_dependent_def_id(expr.hir_id)
.and_then(|id| cx.tcx.trait_of_item(id))
- .map_or(false, |id| {
- matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned))
- }) =>
+ .is_some_and(|id| matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ToString | sym::ToOwned))) =>
{
(arg, arg.span)
},
ExprKind::Call(path, [arg])
- if path_def_id(cx, path).map_or(false, |did| {
+ if path_def_id(cx, path).is_some_and(|did| {
if cx.tcx.is_diagnostic_item(sym::from_str_method, did) {
true
} else if cx.tcx.is_diagnostic_item(sym::from_fn, did) {
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 830be50..1c2d6e9 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -42,83 +42,43 @@ pub(crate) fn check<'tcx>(
match op {
BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
- let _ = check_op(
- cx,
- left,
- 0,
- expr.span,
- peeled_right_span,
- needs_parenthesis(cx, expr, right),
- right_is_coerced_to_value,
- ) || check_op(
- cx,
- right,
- 0,
- expr.span,
- peeled_left_span,
- Parens::Unneeded,
- left_is_coerced_to_value,
- );
+ if is_redundant_op(cx, left, 0) {
+ let paren = needs_parenthesis(cx, expr, right);
+ span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value);
+ } else if is_redundant_op(cx, right, 0) {
+ let paren = needs_parenthesis(cx, expr, left);
+ span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+ }
},
BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
- let _ = check_op(
- cx,
- right,
- 0,
- expr.span,
- peeled_left_span,
- Parens::Unneeded,
- left_is_coerced_to_value,
- );
+ if is_redundant_op(cx, right, 0) {
+ let paren = needs_parenthesis(cx, expr, left);
+ span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+ }
},
BinOpKind::Mul => {
- let _ = check_op(
- cx,
- left,
- 1,
- expr.span,
- peeled_right_span,
- needs_parenthesis(cx, expr, right),
- right_is_coerced_to_value,
- ) || check_op(
- cx,
- right,
- 1,
- expr.span,
- peeled_left_span,
- Parens::Unneeded,
- left_is_coerced_to_value,
- );
+ if is_redundant_op(cx, left, 1) {
+ let paren = needs_parenthesis(cx, expr, right);
+ span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value);
+ } else if is_redundant_op(cx, right, 1) {
+ let paren = needs_parenthesis(cx, expr, left);
+ span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+ }
},
BinOpKind::Div => {
- let _ = check_op(
- cx,
- right,
- 1,
- expr.span,
- peeled_left_span,
- Parens::Unneeded,
- left_is_coerced_to_value,
- );
+ if is_redundant_op(cx, right, 1) {
+ let paren = needs_parenthesis(cx, expr, left);
+ span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+ }
},
BinOpKind::BitAnd => {
- let _ = check_op(
- cx,
- left,
- -1,
- expr.span,
- peeled_right_span,
- needs_parenthesis(cx, expr, right),
- right_is_coerced_to_value,
- ) || check_op(
- cx,
- right,
- -1,
- expr.span,
- peeled_left_span,
- Parens::Unneeded,
- left_is_coerced_to_value,
- );
+ if is_redundant_op(cx, left, -1) {
+ let paren = needs_parenthesis(cx, expr, right);
+ span_ineffective_operation(cx, expr.span, peeled_right_span, paren, right_is_coerced_to_value);
+ } else if is_redundant_op(cx, right, -1) {
+ let paren = needs_parenthesis(cx, expr, left);
+ span_ineffective_operation(cx, expr.span, peeled_left_span, paren, left_is_coerced_to_value);
+ }
},
BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
_ => (),
@@ -138,43 +98,70 @@ enum Parens {
Unneeded,
}
-/// Checks if `left op right` needs parenthesis when reduced to `right`
+/// Checks if a binary expression needs parenthesis when reduced to just its
+/// right or left child.
+///
+/// e.g. `-(x + y + 0)` cannot be reduced to `-x + y`, as the behavior changes silently.
+/// e.g. `1u64 + ((x + y + 0i32) as u64)` cannot be reduced to `1u64 + x + y as u64`, since
+/// the the cast expression will not apply to the same expression.
/// e.g. `0 + if b { 1 } else { 2 } + if b { 3 } else { 4 }` cannot be reduced
/// to `if b { 1 } else { 2 } + if b { 3 } else { 4 }` where the `if` could be
-/// interpreted as a statement
+/// interpreted as a statement. The same behavior happens for `match`, `loop`,
+/// and blocks.
+/// e.g. `2 * (0 + { a })` can be reduced to `2 * { a }` without the need for parenthesis,
+/// but `1 * ({ a } + 4)` cannot be reduced to `{ a } + 4`, as a block at the start of a line
+/// will be interpreted as a statement instead of an expression.
///
-/// See #8724
-fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>) -> Parens {
- match right.kind {
+/// See #8724, #13470
+fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, child: &Expr<'_>) -> Parens {
+ match child.kind {
ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) => {
- // ensure we're checking against the leftmost expression of `right`
- //
- // ~~~ `lhs`
- // 0 + {4} * 2
- // ~~~~~~~ `right`
- return needs_parenthesis(cx, binary, lhs);
+ // For casts and binary expressions, we want to add parenthesis if
+ // the parent HIR node is an expression, or if the parent HIR node
+ // is a Block or Stmt, and the new left hand side would need
+ // parenthesis be treated as a statement rather than an expression.
+ if let Some((_, parent)) = cx.tcx.hir().parent_iter(binary.hir_id).next() {
+ match parent {
+ Node::Expr(_) => return Parens::Needed,
+ Node::Block(_) | Node::Stmt(_) => {
+ // ensure we're checking against the leftmost expression of `child`
+ //
+ // ~~~~~~~~~~~ `binary`
+ // ~~~ `lhs`
+ // 0 + {4} * 2
+ // ~~~~~~~ `child`
+ return needs_parenthesis(cx, binary, lhs);
+ },
+ _ => return Parens::Unneeded,
+ }
+ }
},
- ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Block(..) | ExprKind::Loop(..) => {},
- _ => return Parens::Unneeded,
+ ExprKind::If(..) | ExprKind::Match(..) | ExprKind::Block(..) | ExprKind::Loop(..) => {
+ // For if, match, block, and loop expressions, we want to add parenthesis if
+ // the closest ancestor node that is not an expression is a block or statement.
+ // This would mean that the rustfix suggestion will appear at the start of a line, which causes
+ // these expressions to be interpreted as statements if they do not have parenthesis.
+ let mut prev_id = binary.hir_id;
+ for (_, parent) in cx.tcx.hir().parent_iter(binary.hir_id) {
+ if let Node::Expr(expr) = parent
+ && let ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) | ExprKind::Unary(_, lhs) = expr.kind
+ && lhs.hir_id == prev_id
+ {
+ // keep going until we find a node that encompasses left of `binary`
+ prev_id = expr.hir_id;
+ continue;
+ }
+
+ match parent {
+ Node::Block(_) | Node::Stmt(_) => return Parens::Needed,
+ _ => return Parens::Unneeded,
+ };
+ }
+ },
+ _ => {
+ return Parens::Unneeded;
+ },
}
-
- let mut prev_id = binary.hir_id;
- for (_, node) in cx.tcx.hir().parent_iter(binary.hir_id) {
- if let Node::Expr(expr) = node
- && let ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) = expr.kind
- && lhs.hir_id == prev_id
- {
- // keep going until we find a node that encompasses left of `binary`
- prev_id = expr.hir_id;
- continue;
- }
-
- match node {
- Node::Block(_) | Node::Stmt(_) => break,
- _ => return Parens::Unneeded,
- };
- }
-
Parens::Needed
}
@@ -199,7 +186,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 {
+fn is_redundant_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8) -> bool {
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),
@@ -212,7 +199,6 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa
1 => v == 1,
_ => unreachable!(),
} {
- span_ineffective_operation(cx, span, arg, parens, is_erased);
return true;
}
}
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 565294b..d369978 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -14,7 +14,7 @@ pub struct Context {
}
impl Context {
fn skip_expr(&mut self, e: &hir::Expr<'_>) -> bool {
- self.expr_id.is_some() || self.const_span.map_or(false, |span| span.contains(e.span))
+ self.expr_id.is_some() || self.const_span.is_some_and(|span| span.contains(e.span))
}
pub fn check_binary<'tcx>(
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 1bddfab..b208948 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -192,7 +192,7 @@ fn check_poly_fn(&mut self, cx: &LateContext<'_>, def_id: LocalDefId, decl: &FnD
continue;
}
}
- let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) {
+ let value_type = if fn_body.and_then(|body| body.params.get(index)).is_some_and(is_self) {
"self".into()
} else {
snippet(cx, decl_ty.span, "_").into()
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index a548c6e..ecc095f 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -727,9 +727,8 @@ fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutabili
fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
if let ExprKind::Call(pathexp, []) = expr.kind {
- path_def_id(cx, pathexp).map_or(false, |id| {
- matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ptr_null | sym::ptr_null_mut))
- })
+ path_def_id(cx, pathexp)
+ .is_some_and(|id| matches!(cx.tcx.get_diagnostic_name(id), Some(sym::ptr_null | sym::ptr_null_mut)))
} else {
false
}
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index cb374fc..a00fd01 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -8,18 +8,18 @@
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{
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,
+ pat_and_expr_can_be_question_mark, path_res, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
+ span_contains_cfg, span_contains_comment,
};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::def::Res;
use rustc_hir::{
- BindingMode, Block, Body, ByRef, Expr, ExprKind, LetStmt, Mutability, Node, PatKind, PathSegment, QPath, Stmt,
- StmtKind,
+ Arm, BindingMode, Block, Body, ByRef, Expr, ExprKind, FnRetTy, HirId, LetStmt, MatchSource, Mutability, Node, Pat,
+ PatKind, PathSegment, QPath, Stmt, StmtKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{self, Ty};
use rustc_session::impl_lint_pass;
use rustc_span::sym;
use rustc_span::symbol::Symbol;
@@ -58,6 +58,9 @@ pub struct QuestionMark {
/// if it is greater than zero.
/// As for why we need this in the first place: <https://github.com/rust-lang/rust-clippy/issues/8628>
try_block_depth_stack: Vec<u32>,
+ /// Keeps track of the number of inferred return type closures we are inside, to avoid problems
+ /// with the `Err(x.into())` expansion being ambiguious.
+ inferred_ret_closure_stack: u16,
}
impl_lint_pass!(QuestionMark => [QUESTION_MARK, MANUAL_LET_ELSE]);
@@ -68,6 +71,7 @@ pub fn new(conf: &'static Conf) -> Self {
msrv: conf.msrv.clone(),
matches_behaviour: conf.matches_for_let_else,
try_block_depth_stack: Vec::new(),
+ inferred_ret_closure_stack: 0,
}
}
}
@@ -125,7 +129,7 @@ fn init_expr_can_use_question_mark(cx: &LateContext<'_>, init_expr: &Expr<'_>) -
cx.tcx
.lang_items()
.try_trait()
- .map_or(false, |did| implements_trait(cx, init_ty, did, &[]))
+ .is_some_and(|did| implements_trait(cx, init_ty, did, &[]))
}
if let StmtKind::Let(LetStmt {
@@ -271,6 +275,135 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
}
}
+#[derive(Clone, Copy, Debug)]
+enum TryMode {
+ Result,
+ Option,
+}
+
+fn find_try_mode<'tcx>(cx: &LateContext<'tcx>, scrutinee: &Expr<'tcx>) -> Option<TryMode> {
+ let scrutinee_ty = cx.typeck_results().expr_ty_adjusted(scrutinee);
+ let ty::Adt(scrutinee_adt_def, _) = scrutinee_ty.kind() else {
+ return None;
+ };
+
+ match cx.tcx.get_diagnostic_name(scrutinee_adt_def.did())? {
+ sym::Result => Some(TryMode::Result),
+ sym::Option => Some(TryMode::Option),
+ _ => None,
+ }
+}
+
+// Check that `pat` is `{ctor_lang_item}(val)`, returning `val`.
+fn extract_ctor_call<'a, 'tcx>(
+ cx: &LateContext<'tcx>,
+ expected_ctor: LangItem,
+ pat: &'a Pat<'tcx>,
+) -> Option<&'a Pat<'tcx>> {
+ if let PatKind::TupleStruct(variant_path, [val_binding], _) = &pat.kind
+ && is_res_lang_ctor(cx, cx.qpath_res(variant_path, pat.hir_id), expected_ctor)
+ {
+ Some(val_binding)
+ } else {
+ None
+ }
+}
+
+// Extracts the local ID of a plain `val` pattern.
+fn extract_binding_pat(pat: &Pat<'_>) -> Option<HirId> {
+ if let PatKind::Binding(BindingMode::NONE, binding, _, None) = pat.kind {
+ Some(binding)
+ } else {
+ None
+ }
+}
+
+fn check_arm_is_some_or_ok<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm: &Arm<'tcx>) -> bool {
+ let happy_ctor = match mode {
+ TryMode::Result => ResultOk,
+ TryMode::Option => OptionSome,
+ };
+
+ // Check for `Ok(val)` or `Some(val)`
+ if arm.guard.is_none()
+ && let Some(val_binding) = extract_ctor_call(cx, happy_ctor, arm.pat)
+ // Extract out `val`
+ && let Some(binding) = extract_binding_pat(val_binding)
+ // Check body is just `=> val`
+ && path_to_local_id(peel_blocks(arm.body), binding)
+ {
+ true
+ } else {
+ false
+ }
+}
+
+fn check_arm_is_none_or_err<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm: &Arm<'tcx>) -> bool {
+ if arm.guard.is_some() {
+ return false;
+ }
+
+ let arm_body = peel_blocks(arm.body);
+ match mode {
+ TryMode::Result => {
+ // Check that pat is Err(val)
+ if let Some(ok_pat) = extract_ctor_call(cx, ResultErr, arm.pat)
+ && let Some(ok_val) = extract_binding_pat(ok_pat)
+ // check `=> return Err(...)`
+ && let ExprKind::Ret(Some(wrapped_ret_expr)) = arm_body.kind
+ && let ExprKind::Call(ok_ctor, [ret_expr]) = wrapped_ret_expr.kind
+ && is_res_lang_ctor(cx, path_res(cx, ok_ctor), ResultErr)
+ // check `...` is `val` from binding
+ && path_to_local_id(ret_expr, ok_val)
+ {
+ true
+ } else {
+ false
+ }
+ },
+ TryMode::Option => {
+ // Check the pat is `None`
+ if is_res_lang_ctor(cx, path_res(cx, arm.pat), OptionNone)
+ // Check `=> return None`
+ && let ExprKind::Ret(Some(ret_expr)) = arm_body.kind
+ && is_res_lang_ctor(cx, path_res(cx, ret_expr), OptionNone)
+ && !ret_expr.span.from_expansion()
+ {
+ true
+ } else {
+ false
+ }
+ },
+ }
+}
+
+fn check_arms_are_try<'tcx>(cx: &LateContext<'tcx>, mode: TryMode, arm1: &Arm<'tcx>, arm2: &Arm<'tcx>) -> bool {
+ (check_arm_is_some_or_ok(cx, mode, arm1) && check_arm_is_none_or_err(cx, mode, arm2))
+ || (check_arm_is_some_or_ok(cx, mode, arm2) && check_arm_is_none_or_err(cx, mode, arm1))
+}
+
+fn check_if_try_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+ if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal | MatchSource::Postfix) = expr.kind
+ && !expr.span.from_expansion()
+ && let Some(mode) = find_try_mode(cx, scrutinee)
+ && !span_contains_cfg(cx, expr.span)
+ && check_arms_are_try(cx, mode, arm1, arm2)
+ {
+ let mut applicability = Applicability::MachineApplicable;
+ let snippet = snippet_with_applicability(cx, scrutinee.span.source_callsite(), "..", &mut applicability);
+
+ span_lint_and_sugg(
+ cx,
+ QUESTION_MARK,
+ expr.span,
+ "this `match` expression can be replaced with `?`",
+ "try instead",
+ snippet.into_owned() + "?",
+ applicability,
+ );
+ }
+}
+
fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
if let Some(higher::IfLet {
let_pat,
@@ -339,6 +472,17 @@ fn is_try_block(cx: &LateContext<'_>, bl: &Block<'_>) -> bool {
}
}
+fn is_inferred_ret_closure(expr: &Expr<'_>) -> bool {
+ let ExprKind::Closure(closure) = expr.kind else {
+ return false;
+ };
+
+ match closure.fn_decl.output {
+ FnRetTy::Return(ret_ty) => ret_ty.is_suggestable_infer_ty(),
+ FnRetTy::DefaultReturn(_) => true,
+ }
+}
+
impl<'tcx> LateLintPass<'tcx> for QuestionMark {
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) {
@@ -350,11 +494,27 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
}
self.check_manual_let_else(cx, stmt);
}
+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ if is_inferred_ret_closure(expr) {
+ self.inferred_ret_closure_stack += 1;
+ return;
+ }
+
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);
+
+ if self.inferred_ret_closure_stack == 0 {
+ check_if_try_match(cx, expr);
+ }
+ }
+ }
+
+ fn check_expr_post(&mut self, _: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if is_inferred_ret_closure(expr) {
+ self.inferred_ret_closure_stack -= 1;
}
}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 030df53..dc66fb2 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -85,7 +85,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
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 needs_parens_for_prefix = parent_expr.is_some_and(|parent| parent.precedence().order() > PREC_PREFIX);
if expr_ty == indexed_ty {
if expr_ref_count > indexed_ref_count {
@@ -107,7 +107,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
kind: ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, _),
..
})
- ) || cx.typeck_results().expr_adjustments(expr).first().map_or(false, |a| {
+ ) || cx.typeck_results().expr_adjustments(expr).first().is_some_and(|a| {
matches!(
a.kind,
Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::Mut { .. }))
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 2336250..78f0b7d 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -412,9 +412,7 @@ fn is_used_slice_indexed(swap_index: &Expr<'_>, idx_ident: Ident) -> bool {
}
Self::is_used_slice_indexed(lhs, idx_ident) || Self::is_used_slice_indexed(rhs, idx_ident)
},
- ExprKind::Path(QPath::Resolved(_, path)) => {
- path.segments.first().map_or(false, |idx| idx.ident == idx_ident)
- },
+ ExprKind::Path(QPath::Resolved(_, path)) => path.segments.first().is_some_and(|idx| idx.ident == idx_ident),
_ => false,
}
}
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 eb7ffbb..bde88ab 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -51,8 +51,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
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) =>
+ if get_bounds_if_impl_trait(cx, qpath, inner.hir_id).is_some_and(|bounds| bounds.len() > 1) =>
{
format!("&{ltopt}({inner_snippet})")
},
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index 1a1284c..6eef582 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
return;
}
- if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
+ if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer))
|| matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
&& expr_needs_inferred_result(cx, init)
{
diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
index 91dff5a..cbc6885 100644
--- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs
@@ -98,7 +98,7 @@ fn display_err(&self, cx: &LateContext<'_>) {
needs_mut |= cx.typeck_results().expr_ty_adjusted(last_place).ref_mutability()
== Some(Mutability::Mut)
|| get_parent_expr(cx, last_place)
- .map_or(false, |e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _)));
+ .is_some_and(|e| matches!(e.kind, ExprKind::AddrOf(_, Mutability::Mut, _)));
},
ExprKind::MethodCall(_, recv, ..)
if recv.hir_id == e.hir_id
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 1dd46ed..a42ddcd 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -295,7 +295,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
.opts
.crate_name
.as_ref()
- .map_or(false, |crate_name| crate_name == "build_script_build");
+ .is_some_and(|crate_name| crate_name == "build_script_build");
let allowed_in_tests = self.allow_print_in_tests && is_in_test(cx.tcx, expr.hir_id);
match diag_name {
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 75169e0..3269bf7 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -51,7 +51,7 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
return false;
};
let end = span.hi() - pos.sf.start_pos;
- src.get(pos.pos.0 as usize..end.0 as usize).map_or(false, |s| {
+ src.get(pos.pos.0 as usize..end.0 as usize).is_some_and(|s| {
// Spans can be wrapped in a mixture or parenthesis, whitespace, and trailing commas.
let start_str = s.trim_start_matches(|c: char| c.is_whitespace() || c == '(');
let end_str = s.trim_end_matches(|c: char| c.is_whitespace() || c == ')' || c == ',');
@@ -60,13 +60,13 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
Pat::MultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
Pat::Sym(sym) => start_str.starts_with(sym.as_str()),
- Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit),
+ Pat::Num => start_str.as_bytes().first().is_some_and(u8::is_ascii_digit),
} && match end_pat {
Pat::Str(text) => end_str.ends_with(text),
Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)),
Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)),
Pat::Sym(sym) => end_str.ends_with(sym.as_str()),
- Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit),
+ Pat::Num => end_str.as_bytes().last().is_some_and(u8::is_ascii_hexdigit),
})
})
}
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index cb69f8e..c73ab4b 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -258,7 +258,7 @@ fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
}
fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
- macro_backtrace(expr.span).last().map_or(false, |macro_call| {
+ macro_backtrace(expr.span).last().is_some_and(|macro_call| {
matches!(
&self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
Some(sym::todo_macro | sym::unimplemented_macro)
@@ -322,7 +322,7 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
(&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r),
(&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => {
l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
- || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| {
+ || swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| {
l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
})
},
@@ -444,7 +444,7 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
) => false,
};
(is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
- || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right))
+ || self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right))
}
fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool {
@@ -724,7 +724,7 @@ fn swap_binop<'a>(
/// `eq_fn`.
pub fn both<X>(l: Option<&X>, r: Option<&X>, mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool {
l.as_ref()
- .map_or_else(|| r.is_none(), |x| r.as_ref().map_or(false, |y| eq_fn(x, y)))
+ .map_or_else(|| r.is_none(), |x| r.as_ref().is_some_and(|y| eq_fn(x, y)))
}
/// Checks if two slices are equal as per `eq_fn`.
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 50d334a..19316a9 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -342,10 +342,9 @@ pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
/// Checks if the method call given in `expr` belongs to the given trait.
/// This is a deprecated function, consider using [`is_trait_method`].
pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
- cx.typeck_results()
- .type_dependent_def_id(expr.hir_id)
- .and_then(|defid| cx.tcx.trait_of_item(defid))
- .map_or(false, |trt_id| match_def_path(cx, trt_id, path))
+ let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
+ let trt_id = cx.tcx.trait_of_item(def_id);
+ trt_id.is_some_and(|trt_id| match_def_path(cx, trt_id, path))
}
/// Checks if the given method call expression calls an inherent method.
@@ -379,7 +378,7 @@ pub fn is_diag_trait_item(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol
pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
cx.typeck_results()
.type_dependent_def_id(expr.hir_id)
- .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
+ .is_some_and(|did| is_diag_trait_item(cx, did, diag_item))
}
/// Checks if the `def_id` belongs to a function that is part of a trait impl.
@@ -406,7 +405,7 @@ pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -
if let ExprKind::Path(ref qpath) = expr.kind {
cx.qpath_res(qpath, expr.hir_id)
.opt_def_id()
- .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
+ .is_some_and(|def_id| is_diag_trait_item(cx, def_id, diag_item))
} else {
false
}
@@ -466,13 +465,13 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
///
/// Please use `is_path_diagnostic_item` if the target is a diagnostic item.
pub fn is_expr_path_def_path(cx: &LateContext<'_>, expr: &Expr<'_>, segments: &[&str]) -> bool {
- path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, segments))
+ path_def_id(cx, expr).is_some_and(|id| match_def_path(cx, id, segments))
}
/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
/// it matches the given lang item.
pub fn is_path_lang_item<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>, lang_item: LangItem) -> bool {
- path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.lang_items().get(lang_item) == Some(id))
+ path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.lang_items().get(lang_item) == Some(id))
}
/// If `maybe_path` is a path node which resolves to an item, resolves it to a `DefId` and checks if
@@ -482,7 +481,7 @@ pub fn is_path_diagnostic_item<'tcx>(
maybe_path: &impl MaybePath<'tcx>,
diag_item: Symbol,
) -> bool {
- path_def_id(cx, maybe_path).map_or(false, |id| cx.tcx.is_diagnostic_item(diag_item, id))
+ path_def_id(cx, maybe_path).is_some_and(|id| cx.tcx.is_diagnostic_item(diag_item, id))
}
/// THIS METHOD IS DEPRECATED. Matches a `Path` against a slice of segment string literals.
@@ -1315,7 +1314,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec
pub fn is_entrypoint_fn(cx: &LateContext<'_>, def_id: DefId) -> bool {
cx.tcx
.entry_fn(())
- .map_or(false, |(entry_fn_def_id, _)| def_id == entry_fn_def_id)
+ .is_some_and(|(entry_fn_def_id, _)| def_id == entry_fn_def_id)
}
/// Returns `true` if the expression is in the program's `#[panic_handler]`.
@@ -1753,8 +1752,8 @@ fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>,
match pat.kind {
PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
- PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
- PatKind::Box(pat) | PatKind::Deref(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
+ PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
+ PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
PatKind::Or(pats) => {
// TODO: should be the honest check, that pats is exhaustive set
@@ -1778,7 +1777,7 @@ fn are_refutable<'a, I: IntoIterator<Item = &'a Pat<'a>>>(cx: &LateContext<'_>,
},
}
},
- PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) => true,
+ PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) | PatKind::Deref(_) => true,
}
}
@@ -2021,7 +2020,7 @@ pub fn match_libc_symbol(cx: &LateContext<'_>, did: DefId, name: &str) -> bool {
let path = cx.get_def_path(did);
// libc is meant to be used as a flat list of names, but they're all actually defined in different
// modules based on the target platform. Ignore everything but crate name and the item name.
- path.first().map_or(false, |s| s.as_str() == "libc") && path.last().map_or(false, |s| s.as_str() == name)
+ path.first().is_some_and(|s| s.as_str() == "libc") && path.last().is_some_and(|s| s.as_str() == name)
}
/// Returns the list of condition expressions and the list of blocks in a
@@ -2104,7 +2103,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
_ => None,
};
- did.map_or(false, |did| cx.tcx.has_attr(did, sym::must_use))
+ did.is_some_and(|did| cx.tcx.has_attr(did, sym::must_use))
}
/// Checks if a function's body represents the identity function. Looks for bodies of the form:
@@ -2211,7 +2210,7 @@ pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>)
pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
match expr.kind {
ExprKind::Closure(&Closure { body, .. }) => is_body_identity_function(cx, cx.tcx.hir().body(body)),
- _ => path_def_id(cx, expr).map_or(false, |id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
+ _ => path_def_id(cx, expr).is_some_and(|id| cx.tcx.is_diagnostic_item(sym::convert_identity, id)),
}
}
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index c5a3416..2c49df9 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -53,7 +53,7 @@ pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<
.trim_start()
.chars()
.next()
- .map_or(false, |c| c.is_ascii_digit())
+ .is_some_and(|c| c.is_ascii_digit())
{
let (unsuffixed, suffix) = split_suffix(src, lit_kind);
let float = matches!(lit_kind, LitKind::Float(..));
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 3255c51..25ebe87 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -905,7 +905,7 @@ fn func_takes_arg_by_double_ref(&self, parent_expr: &'tcx hir::Expr<'_>, cmt_hir
_ => return false,
};
- ty.map_or(false, |ty| matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref()))
+ ty.is_some_and(|ty| matches!(ty.kind(), ty::Ref(_, inner, _) if inner.is_ref()))
}
}
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index ce1a20e..770cd9c 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -45,7 +45,7 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
pub fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
cx.tcx
.get_diagnostic_item(sym::Debug)
- .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
+ .is_some_and(|debug| implements_trait(cx, ty, debug, &[]))
}
/// Checks whether a type can be partially moved.
@@ -487,7 +487,7 @@ fn needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &m
.tcx
.lang_items()
.drop_trait()
- .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ .is_some_and(|id| implements_trait(cx, ty, id, &[]))
{
// This type doesn't implement drop, so no side effects here.
// Check if any component type has any.
@@ -718,7 +718,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<ExprFnSig<'t
{
let output = bounds
.projection_bounds()
- .find(|p| lang_items.fn_once_output().map_or(false, |id| id == p.item_def_id()))
+ .find(|p| lang_items.fn_once_output().is_some_and(|id| id == p.item_def_id()))
.map(|p| p.map_bound(|p| p.term.expect_type()));
Some(ExprFnSig::Trait(bound.map_bound(|b| b.args.type_at(0)), output, None))
},
@@ -753,7 +753,7 @@ fn sig_from_bounds<'tcx>(
&& p.self_ty() == ty =>
{
let i = pred.kind().rebind(p.trait_ref.args.type_at(1));
- if inputs.map_or(false, |inputs| i != inputs) {
+ if inputs.is_some_and(|inputs| i != inputs) {
// Multiple different fn trait impls. Is this even allowed?
return None;
}
@@ -794,7 +794,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option
{
let i = pred.kind().rebind(p.trait_ref.args.type_at(1));
- if inputs.map_or(false, |inputs| inputs != i) {
+ if inputs.is_some_and(|inputs| inputs != i) {
// Multiple different fn trait impls. Is this even allowed?
return None;
}
@@ -1291,7 +1291,7 @@ pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>
/// Checks if the type is `core::mem::ManuallyDrop<_>`
pub fn is_manually_drop(ty: Ty<'_>) -> bool {
- ty.ty_adt_def().map_or(false, AdtDef::is_manually_drop)
+ ty.ty_adt_def().is_some_and(AdtDef::is_manually_drop)
}
/// Returns the deref chain of a type, starting with the type itself.
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 8f5ec18..a79be5c 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -344,13 +344,13 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
.cx
.qpath_res(p, hir_id)
.opt_def_id()
- .map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
+ .is_some_and(|id| self.cx.tcx.is_const_fn(id)) => {},
ExprKind::MethodCall(..)
if self
.cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
- .map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
+ .is_some_and(|id| self.cx.tcx.is_const_fn(id)) => {},
ExprKind::Binary(_, lhs, rhs)
if self.cx.typeck_results().expr_ty(lhs).peel_refs().is_primitive_ty()
&& self.cx.typeck_results().expr_ty(rhs).peel_refs().is_primitive_ty() => {},
@@ -426,9 +426,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
.cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
- .map_or(false, |id| {
- self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe
- }) =>
+ .is_some_and(|id| self.cx.tcx.fn_sig(id).skip_binder().safety() == Safety::Unsafe) =>
{
ControlFlow::Break(())
},
@@ -444,7 +442,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) -> Self::Result {
.cx
.qpath_res(p, e.hir_id)
.opt_def_id()
- .map_or(false, |id| self.cx.tcx.is_mutable_static(id)) =>
+ .is_some_and(|id| self.cx.tcx.is_mutable_static(id)) =>
{
ControlFlow::Break(())
},
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 37d9cce..e32e0cb 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,4 +1,4 @@
[toolchain]
-channel = "nightly-2024-11-07"
+channel = "nightly-2024-11-14"
components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
profile = "minimal"
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
index 0a99484..d3fab60 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -1,6 +1,7 @@
//@aux-build:paths.rs
#![deny(clippy::internal)]
#![feature(rustc_private)]
+#![allow(clippy::unnecessary_map_or)]
extern crate clippy_utils;
extern crate paths;
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
index ba68de6..1b36f6b 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
@@ -1,6 +1,7 @@
//@aux-build:paths.rs
#![deny(clippy::internal)]
#![feature(rustc_private)]
+#![allow(clippy::unnecessary_map_or)]
extern crate clippy_utils;
extern crate paths;
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
index 79da173..79521c5 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
@@ -1,5 +1,5 @@
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:36:13
+ --> tests/ui-internal/unnecessary_def_path.rs:37:13
|
LL | let _ = match_type(cx, ty, &OPTION);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
@@ -12,61 +12,61 @@
= note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:37:13
+ --> tests/ui-internal/unnecessary_def_path.rs:38:13
|
LL | let _ = match_type(cx, ty, RESULT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:38:13
+ --> tests/ui-internal/unnecessary_def_path.rs:39:13
|
LL | let _ = match_type(cx, ty, &["core", "result", "Result"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:42:13
+ --> tests/ui-internal/unnecessary_def_path.rs:43:13
|
LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:44:13
+ --> tests/ui-internal/unnecessary_def_path.rs:45:13
|
LL | let _ = match_type(cx, ty, &paths::OPTION);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:45:13
+ --> tests/ui-internal/unnecessary_def_path.rs:46:13
|
LL | let _ = match_type(cx, ty, paths::RESULT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
error: use of a def path to a `LangItem`
- --> tests/ui-internal/unnecessary_def_path.rs:47:13
+ --> tests/ui-internal/unnecessary_def_path.rs:48:13
|
LL | let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:48:13
+ --> tests/ui-internal/unnecessary_def_path.rs:49:13
|
LL | let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)`
error: use of a def path to a `LangItem`
- --> tests/ui-internal/unnecessary_def_path.rs:50:13
+ --> tests/ui-internal/unnecessary_def_path.rs:51:13
|
LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:51:13
+ --> tests/ui-internal/unnecessary_def_path.rs:52:13
|
LL | let _ = match_def_path(cx, did, &["core", "option", "Option"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)`
error: use of a def path to a `LangItem`
- --> tests/ui-internal/unnecessary_def_path.rs:52:13
+ --> tests/ui-internal/unnecessary_def_path.rs:53:13
|
LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)`
@@ -74,25 +74,25 @@
= help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:54:13
+ --> tests/ui-internal/unnecessary_def_path.rs:55:13
|
LL | let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)`
error: use of a def path to a diagnostic item
- --> tests/ui-internal/unnecessary_def_path.rs:56:13
+ --> tests/ui-internal/unnecessary_def_path.rs:57:13
|
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)`
error: use of a def path to a `LangItem`
- --> tests/ui-internal/unnecessary_def_path.rs:57:13
+ --> tests/ui-internal/unnecessary_def_path.rs:58:13
|
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))`
error: use of a def path to a `LangItem`
- --> tests/ui-internal/unnecessary_def_path.rs:58:13
+ --> tests/ui-internal/unnecessary_def_path.rs:59:13
|
LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)`
diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/empty.txt b/src/tools/clippy/tests/ui-toml/large_include_file/empty.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/large_include_file/empty.txt
diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs
index dc9349f..8a6dd36 100644
--- a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs
+++ b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.rs
@@ -15,5 +15,9 @@
const TOO_BIG_INCLUDE_STR: &str = include_str!("too_big.txt");
//~^ large_include_file
-#[doc = include_str!("too_big.txt")] //~ large_include_file
+#[doc = include_str!("too_big.txt")]
+//~^ large_include_file
+// Should not lint!
+// Regression test for <https://github.com/rust-lang/rust-clippy/issues/13670>.
+#[doc = include_str!("empty.txt")]
fn main() {}
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
index 8b4a165a..c4d77f2 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.fixed
@@ -1,4 +1,5 @@
#![warn(clippy::case_sensitive_file_extension_comparisons)]
+#![allow(clippy::unnecessary_map_or)]
use std::string::String;
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
index e4b8178..690e93c 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.rs
@@ -1,4 +1,5 @@
#![warn(clippy::case_sensitive_file_extension_comparisons)]
+#![allow(clippy::unnecessary_map_or)]
use std::string::String;
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
index d203f91..e21815f 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
@@ -1,5 +1,5 @@
error: case-sensitive file extension comparison
- --> tests/ui/case_sensitive_file_extension_comparisons.rs:13:5
+ --> tests/ui/case_sensitive_file_extension_comparisons.rs:14:5
|
LL | filename.ends_with(".rs")
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@
|
error: case-sensitive file extension comparison
- --> tests/ui/case_sensitive_file_extension_comparisons.rs:18:13
+ --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13
|
LL | let _ = String::new().ends_with(".ext12");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@
|
error: case-sensitive file extension comparison
- --> tests/ui/case_sensitive_file_extension_comparisons.rs:19:13
+ --> tests/ui/case_sensitive_file_extension_comparisons.rs:20:13
|
LL | let _ = "str".ends_with(".ext12");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@
|
error: case-sensitive file extension comparison
- --> tests/ui/case_sensitive_file_extension_comparisons.rs:23:17
+ --> tests/ui/case_sensitive_file_extension_comparisons.rs:24:17
|
LL | let _ = "str".ends_with(".ext12");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@
|
error: case-sensitive file extension comparison
- --> tests/ui/case_sensitive_file_extension_comparisons.rs:30:13
+ --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13
|
LL | let _ = String::new().ends_with(".EXT12");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@
|
error: case-sensitive file extension comparison
- --> tests/ui/case_sensitive_file_extension_comparisons.rs:31:13
+ --> tests/ui/case_sensitive_file_extension_comparisons.rs:32:13
|
LL | let _ = "str".ends_with(".EXT12");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index b18d856..2e8e236 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -116,7 +116,7 @@
//~^ ERROR: this operation has no effect
(match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 };
//~^ ERROR: this operation has no effect
- (if b { 1 } else { 2 });
+ ((if b { 1 } else { 2 }));
//~^ ERROR: this operation has no effect
({ a }) + 3;
@@ -212,3 +212,47 @@
//~^ ERROR: this operation has no effect
}
}
+
+fn issue_13470() {
+ let x = 1i32;
+ let y = 1i32;
+ // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works
+ let _: u64 = (x + y) as u64;
+ //~^ ERROR: this operation has no effect
+ // both of the next two lines should look the same after rustfix
+ let _: u64 = 1u64 & (x + y) as u64;
+ //~^ ERROR: this operation has no effect
+ // Same as above, but with extra redundant parenthesis
+ let _: u64 = 1u64 & ((x + y)) as u64;
+ //~^ ERROR: this operation has no effect
+ // Should maintain parenthesis even if the surrounding expr has the same precedence
+ let _: u64 = 5u64 + ((x + y)) as u64;
+ //~^ ERROR: this operation has no effect
+
+ // If we don't maintain the parens here, the behavior changes
+ let _ = -(x + y);
+ //~^ ERROR: this operation has no effect
+ // Similarly, we need to maintain parens here
+ let _ = -(x / y);
+ //~^ ERROR: this operation has no effect
+ // Maintain parenthesis if the parent expr is of higher precedence
+ let _ = 2i32 * (x + y);
+ //~^ ERROR: this operation has no effect
+ // Maintain parenthesis if the parent expr is the same precedence
+ // as not all operations are associative
+ let _ = 2i32 - (x - y);
+ //~^ ERROR: this operation has no effect
+ // But make sure that inner parens still exist
+ let z = 1i32;
+ let _ = 2 + (x + (y * z));
+ //~^ ERROR: this operation has no effect
+ // Maintain parenthesis if the parent expr is of lower precedence
+ // This is for clarity, and clippy will not warn on these being unnecessary
+ let _ = 2i32 + (x * y);
+ //~^ ERROR: this operation has no effect
+
+ let x = 1i16;
+ let y = 1i16;
+ let _: u64 = 1u64 + ((x as i32 + y as i32) as u64);
+ //~^ ERROR: this operation has no effect
+}
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index f1f01b4..3e20fa6 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -212,3 +212,47 @@ fn issue_12050() {
//~^ ERROR: this operation has no effect
}
}
+
+fn issue_13470() {
+ let x = 1i32;
+ let y = 1i32;
+ // Removes the + 0i32 while keeping the parentheses around x + y so the cast operation works
+ let _: u64 = (x + y + 0i32) as u64;
+ //~^ ERROR: this operation has no effect
+ // both of the next two lines should look the same after rustfix
+ let _: u64 = 1u64 & (x + y + 0i32) as u64;
+ //~^ ERROR: this operation has no effect
+ // Same as above, but with extra redundant parenthesis
+ let _: u64 = 1u64 & ((x + y) + 0i32) as u64;
+ //~^ ERROR: this operation has no effect
+ // Should maintain parenthesis even if the surrounding expr has the same precedence
+ let _: u64 = 5u64 + ((x + y) + 0i32) as u64;
+ //~^ ERROR: this operation has no effect
+
+ // If we don't maintain the parens here, the behavior changes
+ let _ = -(x + y + 0i32);
+ //~^ ERROR: this operation has no effect
+ // Similarly, we need to maintain parens here
+ let _ = -(x / y / 1i32);
+ //~^ ERROR: this operation has no effect
+ // Maintain parenthesis if the parent expr is of higher precedence
+ let _ = 2i32 * (x + y + 0i32);
+ //~^ ERROR: this operation has no effect
+ // Maintain parenthesis if the parent expr is the same precedence
+ // as not all operations are associative
+ let _ = 2i32 - (x - y - 0i32);
+ //~^ ERROR: this operation has no effect
+ // But make sure that inner parens still exist
+ let z = 1i32;
+ let _ = 2 + (x + (y * z) + 0);
+ //~^ ERROR: this operation has no effect
+ // Maintain parenthesis if the parent expr is of lower precedence
+ // This is for clarity, and clippy will not warn on these being unnecessary
+ let _ = 2i32 + (x * y * 1i32);
+ //~^ ERROR: this operation has no effect
+
+ let x = 1i16;
+ let y = 1i16;
+ let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64);
+ //~^ ERROR: this operation has no effect
+}
diff --git a/src/tools/clippy/tests/ui/identity_op.stderr b/src/tools/clippy/tests/ui/identity_op.stderr
index 9fff86b..99a58ef 100644
--- a/src/tools/clippy/tests/ui/identity_op.stderr
+++ b/src/tools/clippy/tests/ui/identity_op.stderr
@@ -149,7 +149,7 @@
--> tests/ui/identity_op.rs:119:5
|
LL | (if b { 1 } else { 2 }) + 0;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((if b { 1 } else { 2 }))`
error: this operation has no effect
--> tests/ui/identity_op.rs:122:5
@@ -313,5 +313,71 @@
LL | let _: i32 = **&&*&x + 0;
| ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x`
-error: aborting due to 52 previous errors
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:220:18
+ |
+LL | let _: u64 = (x + y + 0i32) as u64;
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:223:25
+ |
+LL | let _: u64 = 1u64 & (x + y + 0i32) as u64;
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:226:25
+ |
+LL | let _: u64 = 1u64 & ((x + y) + 0i32) as u64;
+ | ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:229:25
+ |
+LL | let _: u64 = 5u64 + ((x + y) + 0i32) as u64;
+ | ^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x + y))`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:233:14
+ |
+LL | let _ = -(x + y + 0i32);
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:236:14
+ |
+LL | let _ = -(x / y / 1i32);
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x / y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:239:20
+ |
+LL | let _ = 2i32 * (x + y + 0i32);
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x + y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:243:20
+ |
+LL | let _ = 2i32 - (x - y - 0i32);
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x - y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:247:17
+ |
+LL | let _ = 2 + (x + (y * z) + 0);
+ | ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(x + (y * z))`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:251:20
+ |
+LL | let _ = 2i32 + (x * y * 1i32);
+ | ^^^^^^^^^^^^^^ help: consider reducing it to: `(x * y)`
+
+error: this operation has no effect
+ --> tests/ui/identity_op.rs:256:25
+ |
+LL | let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x as i32 + y as i32) as u64)`
+
+error: aborting due to 63 previous errors
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 6793883..b6e148e 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -96,12 +96,42 @@
}
fn func() -> Option<i32> {
+ macro_rules! opt_none {
+ () => {
+ None
+ };
+ }
+
fn f() -> Option<String> {
Some(String::new())
}
f()?;
+ let _val = f()?;
+
+ let s: &str = match &Some(String::new()) {
+ Some(v) => v,
+ None => return None,
+ };
+
+ f()?;
+
+ opt_none!()?;
+
+ match f() {
+ Some(x) => x,
+ None => return opt_none!(),
+ };
+
+ match f() {
+ Some(val) => {
+ println!("{val}");
+ val
+ },
+ None => return None,
+ };
+
Some(0)
}
@@ -114,6 +144,10 @@
x?;
+ let _val = func_returning_result()?;
+
+ func_returning_result()?;
+
// No warning
let y = if let Ok(x) = x {
x
@@ -157,6 +191,28 @@
Ok(y)
}
+fn infer_check() {
+ let closure = |x: Result<u8, ()>| {
+ // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+ let _val = match x {
+ Ok(val) => val,
+ Err(val) => return Err(val),
+ };
+
+ Ok(())
+ };
+
+ let closure = |x: Result<u8, ()>| -> Result<(), _> {
+ // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+ let _val = match x {
+ Ok(val) => val,
+ Err(val) => return Err(val),
+ };
+
+ Ok(())
+ };
+}
+
// see issue #8019
pub enum NotOption {
None,
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 601ab78..48dc9eb 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -124,6 +124,12 @@ pub fn if_let_mov_func(self) -> Option<Vec<u32>> {
}
fn func() -> Option<i32> {
+ macro_rules! opt_none {
+ () => {
+ None
+ };
+ }
+
fn f() -> Option<String> {
Some(String::new())
}
@@ -132,6 +138,39 @@ fn f() -> Option<String> {
return None;
}
+ let _val = match f() {
+ Some(val) => val,
+ None => return None,
+ };
+
+ let s: &str = match &Some(String::new()) {
+ Some(v) => v,
+ None => return None,
+ };
+
+ match f() {
+ Some(val) => val,
+ None => return None,
+ };
+
+ match opt_none!() {
+ Some(x) => x,
+ None => return None,
+ };
+
+ match f() {
+ Some(x) => x,
+ None => return opt_none!(),
+ };
+
+ match f() {
+ Some(val) => {
+ println!("{val}");
+ val
+ },
+ None => return None,
+ };
+
Some(0)
}
@@ -146,6 +185,16 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
return x;
}
+ let _val = match func_returning_result() {
+ Ok(val) => val,
+ Err(err) => return Err(err),
+ };
+
+ match func_returning_result() {
+ Ok(val) => val,
+ Err(err) => return Err(err),
+ };
+
// No warning
let y = if let Ok(x) = x {
x
@@ -189,6 +238,28 @@ fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
Ok(y)
}
+fn infer_check() {
+ let closure = |x: Result<u8, ()>| {
+ // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+ let _val = match x {
+ Ok(val) => val,
+ Err(val) => return Err(val),
+ };
+
+ Ok(())
+ };
+
+ let closure = |x: Result<u8, ()>| -> Result<(), _> {
+ // `?` would fail here, as it expands to `Err(val.into())` which is not constrained.
+ let _val = match x {
+ Ok(val) => val,
+ Err(val) => return Err(val),
+ };
+
+ Ok(())
+ };
+}
+
// see issue #8019
pub enum NotOption {
None,
diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr
index 5f26a7e..0a48c4e 100644
--- a/src/tools/clippy/tests/ui/question_mark.stderr
+++ b/src/tools/clippy/tests/ui/question_mark.stderr
@@ -94,29 +94,76 @@
| |_________^ help: replace it with: `self.opt?`
error: this block may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:131:5
+ --> tests/ui/question_mark.rs:137:5
|
LL | / if f().is_none() {
LL | | return None;
LL | | }
| |_____^ help: replace it with: `f()?;`
+error: this `match` expression can be replaced with `?`
+ --> tests/ui/question_mark.rs:141:16
+ |
+LL | let _val = match f() {
+ | ________________^
+LL | | Some(val) => val,
+LL | | None => return None,
+LL | | };
+ | |_____^ help: try instead: `f()?`
+
+error: this `match` expression can be replaced with `?`
+ --> tests/ui/question_mark.rs:151:5
+ |
+LL | / match f() {
+LL | | Some(val) => val,
+LL | | None => return None,
+LL | | };
+ | |_____^ help: try instead: `f()?`
+
+error: this `match` expression can be replaced with `?`
+ --> tests/ui/question_mark.rs:156:5
+ |
+LL | / match opt_none!() {
+LL | | Some(x) => x,
+LL | | None => return None,
+LL | | };
+ | |_____^ help: try instead: `opt_none!()?`
+
error: this block may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:143:13
+ --> tests/ui/question_mark.rs:182:13
|
LL | let _ = if let Ok(x) = x { x } else { return x };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
error: this block may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:145:5
+ --> tests/ui/question_mark.rs:184:5
|
LL | / if x.is_err() {
LL | | return x;
LL | | }
| |_____^ help: replace it with: `x?;`
+error: this `match` expression can be replaced with `?`
+ --> tests/ui/question_mark.rs:188:16
+ |
+LL | let _val = match func_returning_result() {
+ | ________________^
+LL | | Ok(val) => val,
+LL | | Err(err) => return Err(err),
+LL | | };
+ | |_____^ help: try instead: `func_returning_result()?`
+
+error: this `match` expression can be replaced with `?`
+ --> tests/ui/question_mark.rs:193:5
+ |
+LL | / match func_returning_result() {
+LL | | Ok(val) => val,
+LL | | Err(err) => return Err(err),
+LL | | };
+ | |_____^ help: try instead: `func_returning_result()?`
+
error: this block may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:213:5
+ --> tests/ui/question_mark.rs:284:5
|
LL | / if let Err(err) = func_returning_result() {
LL | | return Err(err);
@@ -124,7 +171,7 @@
| |_____^ help: replace it with: `func_returning_result()?;`
error: this block may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:220:5
+ --> tests/ui/question_mark.rs:291:5
|
LL | / if let Err(err) = func_returning_result() {
LL | | return Err(err);
@@ -132,7 +179,7 @@
| |_____^ help: replace it with: `func_returning_result()?;`
error: this block may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:297:13
+ --> tests/ui/question_mark.rs:368:13
|
LL | / if a.is_none() {
LL | | return None;
@@ -142,12 +189,12 @@
| |_____________^ help: replace it with: `a?;`
error: this `let...else` may be rewritten with the `?` operator
- --> tests/ui/question_mark.rs:357:5
+ --> tests/ui/question_mark.rs:428:5
|
LL | / let Some(v) = bar.foo.owned.clone() else {
LL | | return None;
LL | | };
| |______^ help: replace it with: `let v = bar.foo.owned.clone()?;`
-error: aborting due to 17 previous errors
+error: aborting due to 22 previous errors
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.fixed b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
new file mode 100644
index 0000000..2d932a7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.fixed
@@ -0,0 +1,64 @@
+//@aux-build:proc_macros.rs
+#![warn(clippy::unnecessary_map_or)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::eq_op)]
+#![allow(clippy::unnecessary_lazy_evaluations)]
+#[clippy::msrv = "1.70.0"]
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+ // should trigger
+ let _ = (Some(5) == Some(5));
+ let _ = (Some(5) != Some(5));
+ let _ = (Some(5) == Some(5));
+ let _ = Some(5).is_some_and(|n| {
+ let _ = n;
+ 6 >= 5
+ });
+ let _ = Some(vec![5]).is_some_and(|n| n == [5]);
+ let _ = Some(vec![1]).is_some_and(|n| vec![2] == n);
+ let _ = Some(5).is_some_and(|n| n == n);
+ let _ = Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 });
+ let _ = Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5]);
+ let _ = (Ok::<i32, i32>(5) == Ok(5));
+ let _ = (Some(5) == Some(5)).then(|| 1);
+
+ // shouldnt trigger
+ let _ = Some(5).map_or(true, |n| n == 5);
+ let _ = Some(5).map_or(true, |n| 5 == n);
+ macro_rules! x {
+ () => {
+ Some(1)
+ };
+ }
+ // methods lints dont fire on macros
+ let _ = x!().map_or(false, |n| n == 1);
+ let _ = x!().map_or(false, |n| n == vec![1][0]);
+
+ msrv_1_69();
+
+ external! {
+ let _ = Some(5).map_or(false, |n| n == 5);
+ }
+
+ with_span! {
+ let _ = Some(5).map_or(false, |n| n == 5);
+ }
+
+ // check for presence of PartialEq, and alter suggestion to use `is_ok_and` if absent
+ struct S;
+ let r: Result<i32, S> = Ok(3);
+ let _ = r.is_ok_and(|x| x == 7);
+
+ #[derive(PartialEq)]
+ struct S2;
+ let r: Result<i32, S2> = Ok(4);
+ let _ = (r == Ok(8));
+}
+
+#[clippy::msrv = "1.69.0"]
+fn msrv_1_69() {
+ // is_some_and added in 1.70.0
+ let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.rs b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
new file mode 100644
index 0000000..4a9d69b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.rs
@@ -0,0 +1,67 @@
+//@aux-build:proc_macros.rs
+#![warn(clippy::unnecessary_map_or)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::eq_op)]
+#![allow(clippy::unnecessary_lazy_evaluations)]
+#[clippy::msrv = "1.70.0"]
+#[macro_use]
+extern crate proc_macros;
+
+fn main() {
+ // should trigger
+ let _ = Some(5).map_or(false, |n| n == 5);
+ let _ = Some(5).map_or(true, |n| n != 5);
+ let _ = Some(5).map_or(false, |n| {
+ let _ = 1;
+ n == 5
+ });
+ let _ = Some(5).map_or(false, |n| {
+ let _ = n;
+ 6 >= 5
+ });
+ let _ = Some(vec![5]).map_or(false, |n| n == [5]);
+ let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
+ let _ = Some(5).map_or(false, |n| n == n);
+ let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+ let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]);
+ let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5);
+ let _ = Some(5).map_or(false, |n| n == 5).then(|| 1);
+
+ // shouldnt trigger
+ let _ = Some(5).map_or(true, |n| n == 5);
+ let _ = Some(5).map_or(true, |n| 5 == n);
+ macro_rules! x {
+ () => {
+ Some(1)
+ };
+ }
+ // methods lints dont fire on macros
+ let _ = x!().map_or(false, |n| n == 1);
+ let _ = x!().map_or(false, |n| n == vec![1][0]);
+
+ msrv_1_69();
+
+ external! {
+ let _ = Some(5).map_or(false, |n| n == 5);
+ }
+
+ with_span! {
+ let _ = Some(5).map_or(false, |n| n == 5);
+ }
+
+ // check for presence of PartialEq, and alter suggestion to use `is_ok_and` if absent
+ struct S;
+ let r: Result<i32, S> = Ok(3);
+ let _ = r.map_or(false, |x| x == 7);
+
+ #[derive(PartialEq)]
+ struct S2;
+ let r: Result<i32, S2> = Ok(4);
+ let _ = r.map_or(false, |x| x == 8);
+}
+
+#[clippy::msrv = "1.69.0"]
+fn msrv_1_69() {
+ // is_some_and added in 1.70.0
+ let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_map_or.stderr b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
new file mode 100644
index 0000000..299a4e5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_map_or.stderr
@@ -0,0 +1,99 @@
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:12:13
+ |
+LL | let _ = Some(5).map_or(false, |n| n == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))`
+ |
+ = note: `-D clippy::unnecessary-map-or` implied by `-D warnings`
+ = help: to override `-D warnings` add `#[allow(clippy::unnecessary_map_or)]`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:13:13
+ |
+LL | let _ = Some(5).map_or(true, |n| n != 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) != Some(5))`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:14:13
+ |
+LL | let _ = Some(5).map_or(false, |n| {
+ | _____________^
+LL | | let _ = 1;
+LL | | n == 5
+LL | | });
+ | |______^ help: use a standard comparison instead: `(Some(5) == Some(5))`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:18:13
+ |
+LL | let _ = Some(5).map_or(false, |n| {
+ | _____________^
+LL | | let _ = n;
+LL | | 6 >= 5
+LL | | });
+ | |______^
+ |
+help: use is_some_and instead
+ |
+LL ~ let _ = Some(5).is_some_and(|n| {
+LL + let _ = n;
+LL + 6 >= 5
+LL ~ });
+ |
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:22:13
+ |
+LL | let _ = Some(vec![5]).map_or(false, |n| n == [5]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![5]).is_some_and(|n| n == [5])`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:23:13
+ |
+LL | let _ = Some(vec![1]).map_or(false, |n| vec![2] == n);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(vec![1]).is_some_and(|n| vec![2] == n)`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:24:13
+ |
+LL | let _ = Some(5).map_or(false, |n| n == n);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == n)`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:25:13
+ |
+LL | let _ = Some(5).map_or(false, |n| n == if 2 > 1 { n } else { 0 });
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_some_and instead: `Some(5).is_some_and(|n| n == if 2 > 1 { n } else { 0 })`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:26:13
+ |
+LL | let _ = Ok::<Vec<i32>, i32>(vec![5]).map_or(false, |n| n == [5]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `Ok::<Vec<i32>, i32>(vec![5]).is_ok_and(|n| n == [5])`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:27:13
+ |
+LL | let _ = Ok::<i32, i32>(5).map_or(false, |n| n == 5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Ok::<i32, i32>(5) == Ok(5))`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:28:13
+ |
+LL | let _ = Some(5).map_or(false, |n| n == 5).then(|| 1);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(Some(5) == Some(5))`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:55:13
+ |
+LL | let _ = r.map_or(false, |x| x == 7);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use is_ok_and instead: `r.is_ok_and(|x| x == 7)`
+
+error: this `map_or` is redundant
+ --> tests/ui/unnecessary_map_or.rs:60:13
+ |
+LL | let _ = r.map_or(false, |x| x == 8);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a standard comparison instead: `(r == Ok(8))`
+
+error: aborting due to 13 previous errors
+
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 4a102f0..bdd0b80 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -25,6 +25,7 @@
"dont-check-failure-status",
"edition",
"error-pattern",
+ "exact-llvm-major-version",
"exec-env",
"failure-status",
"filecheck-flags",
@@ -119,6 +120,7 @@
"incremental",
"known-bug",
"llvm-cov-flags",
+ "max-llvm-major-version",
"min-cdb-version",
"min-gdb-version",
"min-lldb-version",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 300a03e..3539e85 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1547,6 +1547,20 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
};
}
} else if let Some(version_string) =
+ config.parse_name_value_directive(line, "max-llvm-major-version")
+ {
+ let max_version = extract_llvm_version(&version_string);
+ // Ignore if actual major version is larger than the maximum required major version.
+ if actual_version.major > max_version.major {
+ return IgnoreDecision::Ignore {
+ reason: format!(
+ "ignored when the LLVM version ({actual_version}) is newer than major\
+ version {}",
+ max_version.major
+ ),
+ };
+ }
+ } else if let Some(version_string) =
config.parse_name_value_directive(line, "min-system-llvm-version")
{
let min_version = extract_llvm_version(&version_string);
@@ -1585,6 +1599,19 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
};
}
}
+ } else if let Some(version_string) =
+ config.parse_name_value_directive(line, "exact-llvm-major-version")
+ {
+ // Syntax is "exact-llvm-major-version: <version>"
+ let version = extract_llvm_version(&version_string);
+ if actual_version.major != version.major {
+ return IgnoreDecision::Ignore {
+ reason: format!(
+ "ignored when the actual LLVM major version is {}, but the test only targets major version {}",
+ actual_version.major, version.major
+ ),
+ };
+ }
}
}
IgnoreDecision::Continue
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c3fb8d4..4d75c38 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -284,6 +284,30 @@ fn llvm_version() {
let config: Config = cfg().llvm_version("10.0.0").build();
assert!(!check_ignore(&config, "//@ min-llvm-version: 9.0"));
+
+ let config: Config = cfg().llvm_version("10.0.0").build();
+ assert!(check_ignore(&config, "//@ exact-llvm-major-version: 9.0"));
+
+ let config: Config = cfg().llvm_version("9.0.0").build();
+ assert!(check_ignore(&config, "//@ exact-llvm-major-version: 10.0"));
+
+ let config: Config = cfg().llvm_version("10.0.0").build();
+ assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10.0"));
+
+ let config: Config = cfg().llvm_version("10.0.0").build();
+ assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10"));
+
+ let config: Config = cfg().llvm_version("10.6.2").build();
+ assert!(!check_ignore(&config, "//@ exact-llvm-major-version: 10"));
+
+ let config: Config = cfg().llvm_version("19.0.0").build();
+ assert!(!check_ignore(&config, "//@ max-llvm-major-version: 19"));
+
+ let config: Config = cfg().llvm_version("19.1.2").build();
+ assert!(!check_ignore(&config, "//@ max-llvm-major-version: 19"));
+
+ let config: Config = cfg().llvm_version("20.0.0").build();
+ assert!(check_ignore(&config, "//@ max-llvm-major-version: 19"));
}
#[test]
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 914b03c..9e54934 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -47,9 +47,9 @@
[[package]]
name = "anstream"
-version = "0.6.15"
+version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -62,43 +62,43 @@
[[package]]
name = "anstyle"
-version = "1.0.8"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.4"
+version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
-version = "1.0.89"
+version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
+checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
[[package]]
name = "autocfg"
@@ -161,9 +161,9 @@
[[package]]
name = "cc"
-version = "1.1.22"
+version = "1.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
+checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9"
dependencies = [
"shlex",
]
@@ -185,14 +185,14 @@
"js-sys",
"num-traits",
"wasm-bindgen",
- "windows-targets 0.52.6",
+ "windows-targets",
]
[[package]]
name = "clap"
-version = "4.5.18"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -200,9 +200,9 @@
[[package]]
name = "clap_builder"
-version = "4.5.18"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
@@ -213,9 +213,9 @@
[[package]]
name = "clap_complete"
-version = "4.5.29"
+version = "4.5.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8937760c3f4c60871870b8c3ee5f9b30771f792a7045c48bcbba999d7d6b3b8e"
+checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2"
dependencies = [
"clap",
]
@@ -240,9 +240,9 @@
[[package]]
name = "colorchoice"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "core-foundation-sys"
@@ -456,9 +456,9 @@
[[package]]
name = "hashbrown"
-version = "0.14.5"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
name = "heck"
@@ -536,9 +536,9 @@
[[package]]
name = "indexmap"
-version = "2.5.0"
+version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
dependencies = [
"equivalent",
"hashbrown",
@@ -558,9 +558,9 @@
[[package]]
name = "js-sys"
-version = "0.3.70"
+version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
@@ -573,9 +573,9 @@
[[package]]
name = "libc"
-version = "0.2.159"
+version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "libdbus-sys"
@@ -789,9 +789,9 @@
[[package]]
name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "onig"
@@ -847,14 +847,14 @@
"libc",
"redox_syscall",
"smallvec",
- "windows-targets 0.52.6",
+ "windows-targets",
]
[[package]]
name = "pathdiff"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
+checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361"
[[package]]
name = "percent-encoding"
@@ -864,9 +864,9 @@
[[package]]
name = "pest"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9"
+checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
dependencies = [
"memchr",
"thiserror",
@@ -875,9 +875,9 @@
[[package]]
name = "pest_derive"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0"
+checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
dependencies = [
"pest",
"pest_generator",
@@ -885,9 +885,9 @@
[[package]]
name = "pest_generator"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e"
+checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
dependencies = [
"pest",
"pest_meta",
@@ -898,9 +898,9 @@
[[package]]
name = "pest_meta"
-version = "2.7.13"
+version = "2.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f"
+checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
dependencies = [
"once_cell",
"pest",
@@ -996,9 +996,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
@@ -1099,18 +1099,18 @@
[[package]]
name = "redox_syscall"
-version = "0.5.6"
+version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "regex"
-version = "1.10.6"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
@@ -1120,9 +1120,9 @@
[[package]]
name = "regex-automata"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
@@ -1131,9 +1131,9 @@
[[package]]
name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustbook"
@@ -1150,9 +1150,9 @@
[[package]]
name = "rustix"
-version = "0.38.37"
+version = "0.38.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
+checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
dependencies = [
"bitflags 2.6.0",
"errno",
@@ -1190,18 +1190,18 @@
[[package]]
name = "serde"
-version = "1.0.210"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
+checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.210"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
+checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
@@ -1210,9 +1210,9 @@
[[package]]
name = "serde_json"
-version = "1.0.128"
+version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"itoa",
"memchr",
@@ -1292,9 +1292,9 @@
[[package]]
name = "syn"
-version = "2.0.79"
+version = "2.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
+checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
dependencies = [
"proc-macro2",
"quote",
@@ -1347,12 +1347,12 @@
[[package]]
name = "terminal_size"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
+checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
dependencies = [
"rustix",
- "windows-sys 0.48.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1363,18 +1363,18 @@
[[package]]
name = "thiserror"
-version = "1.0.64"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
+checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.64"
+version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
+checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5"
dependencies = [
"proc-macro2",
"quote",
@@ -1453,24 +1453,21 @@
[[package]]
name = "ucd-trie"
-version = "0.1.6"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "unicase"
-version = "2.7.0"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
-dependencies = [
- "version_check",
-]
+checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
[[package]]
name = "unicode-bidi"
-version = "0.3.15"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
[[package]]
name = "unicode-ident"
@@ -1540,9 +1537,9 @@
[[package]]
name = "wasm-bindgen"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
"once_cell",
@@ -1551,9 +1548,9 @@
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
@@ -1566,9 +1563,9 @@
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1576,9 +1573,9 @@
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
@@ -1589,9 +1586,9 @@
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.93"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
+checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "winapi"
@@ -1630,16 +1627,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[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",
+ "windows-targets",
]
[[package]]
@@ -1648,7 +1636,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
]
[[package]]
@@ -1657,22 +1645,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
-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",
+ "windows-targets",
]
[[package]]
@@ -1681,48 +1654,30 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
"windows_i686_gnullvm",
- "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",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
-[[package]]
-name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
-[[package]]
-name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
-[[package]]
-name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
@@ -1735,48 +1690,24 @@
[[package]]
name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
-[[package]]
-name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
-[[package]]
-name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
-
-[[package]]
-name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 8e12db4..e065f01 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -24,6 +24,7 @@
"BSD-2-Clause OR Apache-2.0 OR MIT", // zerocopy
"ISC",
"MIT / Apache-2.0",
+ "MIT AND (MIT OR Apache-2.0)",
"MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)", // compiler-builtins
"MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc
"MIT OR Apache-2.0 OR Zlib", // tinyvec_macros
@@ -92,6 +93,7 @@
("constant_time_eq", "CC0-1.0 OR MIT-0 OR Apache-2.0"), // rustc
("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps)
("fluent-langneg", "Apache-2.0"), // rustc (fluent translations)
+ ("foldhash", "Zlib"), // rustc
("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot
("mdbook", "MPL-2.0"), // mdbook
("option-ext", "MPL-2.0"), // cargo-miri (via `directories`)
@@ -283,6 +285,7 @@
"fluent-langneg",
"fluent-syntax",
"fnv",
+ "foldhash",
"generic-array",
"getopts",
"getrandom",
diff --git a/src/tools/tidy/src/known_bug.rs b/src/tools/tidy/src/known_bug.rs
index 182a81c..a877165 100644
--- a/src/tools/tidy/src/known_bug.rs
+++ b/src/tools/tidy/src/known_bug.rs
@@ -6,8 +6,22 @@
pub fn check(filepath: &Path, bad: &mut bool) {
walk(filepath, |path, _is_dir| filter_not_rust(path), &mut |entry, contents| {
- let file = entry.path();
- if !contents.lines().any(|line| line.starts_with("//@ known-bug: ")) {
+ let file: &Path = entry.path();
+
+ // files in "auxiliary" do not need to crash by themselves
+ let test_path_segments =
+ file.iter().map(|s| s.to_string_lossy().into()).collect::<Vec<String>>();
+ let test_path_segments_str =
+ test_path_segments.iter().map(|s| s.as_str()).collect::<Vec<&str>>();
+
+ if !matches!(test_path_segments_str[..], [
+ ..,
+ "tests",
+ "crashes",
+ "auxiliary",
+ _aux_file_rs
+ ]) && !contents.lines().any(|line| line.starts_with("//@ known-bug: "))
+ {
tidy_error!(
bad,
"{} crash/ice test does not have a \"//@ known-bug: \" directive",
diff --git a/tests/assembly/riscv-soft-abi-with-float-features.rs b/tests/assembly/riscv-soft-abi-with-float-features.rs
index 6d6001a..8ccfa72 100644
--- a/tests/assembly/riscv-soft-abi-with-float-features.rs
+++ b/tests/assembly/riscv-soft-abi-with-float-features.rs
@@ -2,7 +2,7 @@
//@ compile-flags: --target riscv64imac-unknown-none-elf -Ctarget-feature=+f,+d
//@ needs-llvm-components: riscv
//@ revisions: LLVM-PRE-20 LLVM-POST-20
-//@ [LLVM-PRE-20] ignore-llvm-version: 20 - 99
+//@ [LLVM-PRE-20] max-llvm-major-version: 19
//@ [LLVM-POST-20] min-llvm-version: 20
#![feature(no_core, lang_items, f16)]
diff --git a/tests/assembly/x86_64-cmp.rs b/tests/assembly/x86_64-cmp.rs
index 67b7ff9..8cccab7 100644
--- a/tests/assembly/x86_64-cmp.rs
+++ b/tests/assembly/x86_64-cmp.rs
@@ -1,7 +1,7 @@
//@ revisions: DEBUG LLVM-PRE-20-OPTIM LLVM-20-OPTIM
//@ [DEBUG] compile-flags: -C opt-level=0
//@ [LLVM-PRE-20-OPTIM] compile-flags: -C opt-level=3
-//@ [LLVM-PRE-20-OPTIM] ignore-llvm-version: 20 - 99
+//@ [LLVM-PRE-20-OPTIM] max-llvm-major-version: 19
//@ [LLVM-20-OPTIM] compile-flags: -C opt-level=3
//@ [LLVM-20-OPTIM] min-llvm-version: 20
//@ assembly-output: emit-asm
diff --git a/tests/codegen/branch-protection-old-llvm.rs b/tests/codegen/branch-protection-old-llvm.rs
index bb3c7a4..1846f35 100644
--- a/tests/codegen/branch-protection-old-llvm.rs
+++ b/tests/codegen/branch-protection-old-llvm.rs
@@ -7,7 +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
-//@ ignore-llvm-version: 19 - 99
+//@ max-llvm-major-version: 18
#![crate_type = "lib"]
#![feature(no_core, lang_items)]
diff --git a/tests/codegen/call-metadata.rs b/tests/codegen/call-metadata.rs
index 73c4b33..b986b44 100644
--- a/tests/codegen/call-metadata.rs
+++ b/tests/codegen/call-metadata.rs
@@ -2,7 +2,7 @@
// scalar value.
//@ compile-flags: -O -C no-prepopulate-passes
-//@ ignore-llvm-version: 19 - 99
+//@ max-llvm-major-version: 18
#![crate_type = "lib"]
diff --git a/tests/codegen/integer-cmp.rs b/tests/codegen/integer-cmp.rs
index 8df68d8..9bbf243 100644
--- a/tests/codegen/integer-cmp.rs
+++ b/tests/codegen/integer-cmp.rs
@@ -3,7 +3,7 @@
//@ revisions: llvm-pre-20 llvm-20
//@ [llvm-20] min-llvm-version: 20
-//@ [llvm-pre-20] ignore-llvm-version: 20 - 99
+//@ [llvm-pre-20] max-llvm-major-version: 19
//@ compile-flags: -C opt-level=3
#![crate_type = "lib"]
diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs
index b68ecce..36a0d90 100644
--- a/tests/codegen/try_question_mark_nop.rs
+++ b/tests/codegen/try_question_mark_nop.rs
@@ -2,8 +2,7 @@
//@ only-x86_64
// FIXME: Remove the `min-llvm-version`.
//@ revisions: NINETEEN TWENTY
-//@[NINETEEN] min-llvm-version: 19
-//@[NINETEEN] ignore-llvm-version: 20-99
+//@[NINETEEN] exact-llvm-major-version: 19
//@[TWENTY] min-llvm-version: 20
//@ min-llvm-version: 19
diff --git a/tests/rustdoc-js-std/deduplication.js b/tests/rustdoc-js-std/deduplication.js
index 51279dd..95049d0 100644
--- a/tests/rustdoc-js-std/deduplication.js
+++ b/tests/rustdoc-js-std/deduplication.js
@@ -5,6 +5,5 @@
'others': [
{ 'path': 'std::f32', 'name': 'is_nan' },
{ 'path': 'std::f64', 'name': 'is_nan' },
- { 'path': 'std::option::Option', 'name': 'is_none' },
],
};
diff --git a/tests/rustdoc-js-std/path-maxeditdistance.js b/tests/rustdoc-js-std/path-maxeditdistance.js
index 632df65..af71713 100644
--- a/tests/rustdoc-js-std/path-maxeditdistance.js
+++ b/tests/rustdoc-js-std/path-maxeditdistance.js
@@ -3,16 +3,8 @@
const EXPECTED = [
{
query: 'vec::intoiterator',
- others: [
- // trait std::iter::IntoIterator is not the first result
- { 'path': 'std::vec', 'name': 'IntoIter' },
- { 'path': 'std::vec::Vec', 'name': 'into_iter' },
- { 'path': 'std::vec::Drain', 'name': 'into_iter' },
- { 'path': 'std::vec::IntoIter', 'name': 'into_iter' },
- { 'path': 'std::vec::ExtractIf', 'name': 'into_iter' },
- { 'path': 'std::vec::Splice', 'name': 'into_iter' },
- { 'path': 'std::collections::vec_deque::VecDeque', 'name': 'into_iter' },
- ],
+ // trait std::iter::IntoIterator is not the first result
+ others: [],
},
{
query: 'vec::iter',
diff --git a/tests/rustdoc-js-std/write.js b/tests/rustdoc-js-std/write.js
new file mode 100644
index 0000000..4a94751
--- /dev/null
+++ b/tests/rustdoc-js-std/write.js
@@ -0,0 +1,24 @@
+const EXPECTED = [
+ {
+ 'query': 'write',
+ 'others': [
+ { 'path': 'std::fmt', 'name': 'write' },
+ { 'path': 'std::fs', 'name': 'write' },
+ { 'path': 'std::ptr', 'name': 'write' },
+ { 'path': 'std::fmt', 'name': 'Write' },
+ { 'path': 'std::io', 'name': 'Write' },
+ { 'path': 'std::hash::Hasher', 'name': 'write' },
+ ],
+ },
+ {
+ 'query': 'Write',
+ 'others': [
+ { 'path': 'std::fmt', 'name': 'Write' },
+ { 'path': 'std::io', 'name': 'Write' },
+ { 'path': 'std::fmt', 'name': 'write' },
+ { 'path': 'std::fs', 'name': 'write' },
+ { 'path': 'std::ptr', 'name': 'write' },
+ { 'path': 'std::hash::Hasher', 'name': 'write' },
+ ],
+ },
+];
diff --git a/tests/rustdoc-js/case.js b/tests/rustdoc-js/case.js
new file mode 100644
index 0000000..22b970e
--- /dev/null
+++ b/tests/rustdoc-js/case.js
@@ -0,0 +1,17 @@
+const EXPECTED = [
+ {
+ 'query': 'Foo',
+ 'others': [
+ { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' },
+ { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' },
+ ],
+ },
+ {
+ 'query': 'foo',
+ 'others': [
+ // https://github.com/rust-lang/rust/issues/133017
+ { 'path': 'case', 'name': 'Foo', 'desc': 'Docs for Foo' },
+ { 'path': 'case', 'name': 'foo', 'desc': 'Docs for foo' },
+ ],
+ },
+];
diff --git a/tests/rustdoc-js/case.rs b/tests/rustdoc-js/case.rs
new file mode 100644
index 0000000..532edd5
--- /dev/null
+++ b/tests/rustdoc-js/case.rs
@@ -0,0 +1,7 @@
+#![allow(nonstandard_style)]
+
+/// Docs for Foo
+pub struct Foo;
+
+/// Docs for foo
+pub struct foo;
diff --git a/tests/rustdoc-js/non-english-identifier.js b/tests/rustdoc-js/non-english-identifier.js
index 6a2c4cc..f2180b4 100644
--- a/tests/rustdoc-js/non-english-identifier.js
+++ b/tests/rustdoc-js/non-english-identifier.js
@@ -133,16 +133,6 @@
path: "non_english_identifier",
href: "../non_english_identifier/trait.加法.html",
desc: "Add"
- },
- {
- name: "中文名称的加法宏",
- path: "non_english_identifier",
- href: "../non_english_identifier/macro.中文名称的加法宏.html",
- },
- {
- name: "中文名称的加法API",
- path: "non_english_identifier",
- href: "../non_english_identifier/fn.中文名称的加法API.html",
}],
in_args: [{
name: "加上",
@@ -151,6 +141,28 @@
}],
returned: [],
},
+ { // levensthein and substring checking only kick in at three characters
+ query: '加法宏',
+ others: [
+ {
+ name: "中文名称的加法宏",
+ path: "non_english_identifier",
+ href: "../non_english_identifier/macro.中文名称的加法宏.html",
+ }],
+ in_args: [],
+ returned: [],
+ },
+ { // levensthein and substring checking only kick in at three characters
+ query: '加法A',
+ others: [
+ {
+ name: "中文名称的加法API",
+ path: "non_english_identifier",
+ href: "../non_english_identifier/fn.中文名称的加法API.html",
+ }],
+ in_args: [],
+ returned: [],
+ },
{ // Extensive type-based search is still buggy, experimental & work-in-progress.
query: '可迭代->可选',
others: [{
diff --git a/tests/rustdoc-js/path-maxeditdistance.js b/tests/rustdoc-js/path-maxeditdistance.js
index 73b24a6..cf70019 100644
--- a/tests/rustdoc-js/path-maxeditdistance.js
+++ b/tests/rustdoc-js/path-maxeditdistance.js
@@ -14,21 +14,38 @@
],
},
{
- // swap br/rb; that's edit distance 2, where maxPathEditDistance = 3 (11 / 3)
+ // swap br/rb; that's edit distance 1, where maxPathEditDistance = 2
'query': 'arbacadarba::hocuspocusprestidigitation',
'others': [
{ 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' },
],
},
{
- // truncate 5 chars, where maxEditDistance = 7 (21 / 3)
- 'query': 'abracadarba::hocusprestidigitation',
+ // swap p/o o/p, that's also edit distance 1
+ 'query': 'abracadabra::hocusopcusprestidigitation',
'others': [
{ 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' },
],
},
{
- // truncate 9 chars, where maxEditDistance = 5 (17 / 3)
+ // swap p/o o/p and gi/ig, that's edit distance 2
+ 'query': 'abracadabra::hocusopcusprestidiigtation',
+ 'others': [
+ { 'path': 'abracadabra', 'name': 'HocusPocusPrestidigitation' },
+ ],
+ },
+ {
+ // swap p/o o/p, gi/ig, and ti/it, that's edit distance 3 and not shown (we stop at 2)
+ 'query': 'abracadabra::hocusopcusprestidiigtaiton',
+ 'others': [],
+ },
+ {
+ // truncate 5 chars, where maxEditDistance = 2
+ 'query': 'abracadarba::hocusprestidigitation',
+ 'others': [],
+ },
+ {
+ // truncate 9 chars, where maxEditDistance = 2
'query': 'abracadarba::hprestidigitation',
'others': [],
},
diff --git a/tests/rustdoc-js/prototype.js b/tests/rustdoc-js/prototype.js
index da72fdc..0862acd 100644
--- a/tests/rustdoc-js/prototype.js
+++ b/tests/rustdoc-js/prototype.js
@@ -9,7 +9,9 @@
},
{
'query': '__proto__',
- 'others': [],
+ 'others': [
+ {"path": "", "name": "prototype"},
+ ],
'returned': [],
'in_args': [],
},
diff --git a/tests/rustdoc/decl_macro.rs b/tests/rustdoc/decl_macro.rs
index da471e7..040859b 100644
--- a/tests/rustdoc/decl_macro.rs
+++ b/tests/rustdoc/decl_macro.rs
@@ -48,6 +48,8 @@ mod b {
}
mod c {
//@ has decl_macro/a/b/c/macro.by_example_vis_named.html //pre 'pub(in a) macro by_example_vis_named($foo:expr) {'
+ // Regression test for <https://github.com/rust-lang/rust/issues/83000>:
+ //@ has - '//pre[@class="rust item-decl"]//a[@class="mod"]/@href' '../../index.html'
pub(in a) macro by_example_vis_named {
($foo:expr) => {}
}
diff --git a/tests/rustdoc/footnote-ids.rs b/tests/rustdoc/footnote-ids.rs
new file mode 100644
index 0000000..d3a8435
--- /dev/null
+++ b/tests/rustdoc/footnote-ids.rs
@@ -0,0 +1,41 @@
+// This test ensures that footnotes ID are not duplicated across an item page.
+// This is a regression test for <https://github.com/rust-lang/rust/issues/131901>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/struct.Foo.html'
+
+pub struct Foo;
+
+impl Foo {
+ //@ has - '//a[@href="#fn1"]' '1'
+ //@ has - '//li[@id="fn1"]' 'Hiya'
+ //@ has - '//a[@href="#fn2"]' '2'
+ //@ has - '//li[@id="fn2"]' 'Tiya'
+ /// Link 1 [^1]
+ /// Link 1.1 [^2]
+ ///
+ /// [^1]: Hiya
+ /// [^2]: Tiya
+ pub fn l1(){}
+
+ //@ has - '//a[@href="#fn3"]' '1'
+ //@ has - '//li[@id="fn3"]' 'Yiya'
+ //@ has - '//a[@href="#fn4"]' '2'
+ //@ has - '//li[@id="fn4"]' 'Biya'
+ /// Link 2 [^1]
+ /// Link 3 [^2]
+ ///
+ /// [^1]: Yiya
+ /// [^2]: Biya
+ pub fn l2() {}
+}
+
+impl Foo {
+ //@ has - '//a[@href="#fn5"]' '1'
+ //@ has - '//li[@id="fn5"]' 'Ciya'
+ /// Link 3 [^1]
+ ///
+ /// [^1]: Ciya
+ pub fn l3(){}
+}
diff --git a/tests/rustdoc/footnote-reference-in-footnote-def.rs b/tests/rustdoc/footnote-reference-in-footnote-def.rs
new file mode 100644
index 0000000..db3f9a5
--- /dev/null
+++ b/tests/rustdoc/footnote-reference-in-footnote-def.rs
@@ -0,0 +1,20 @@
+// Checks that footnote references in footnote definitions are correctly generated.
+// Regression test for <https://github.com/rust-lang/rust/issues/131946>.
+
+#![crate_name = "foo"]
+
+//@ has 'foo/index.html'
+//@ has - '//*[@class="docblock"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1'
+//@ has - '//li[@id="fn1"]/p' 'meow'
+//@ has - '//li[@id="fn1"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2'
+//@ has - '//li[@id="fn1"]//a[@href="#fn2"]' '2'
+//@ has - '//li[@id="fn2"]/p' 'uwu'
+//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1'
+//@ has - '//li[@id="fn2"]//a[@href="#fn1"]' '1'
+
+//! # footnote-hell
+//!
+//! Hello [^a].
+//!
+//! [^a]: meow [^b]
+//! [^b]: uwu [^a]
diff --git a/tests/rustdoc/macro_rules-matchers.rs b/tests/rustdoc/macro_rules-matchers.rs
index c3ee8fe..2c9fb50 100644
--- a/tests/rustdoc/macro_rules-matchers.rs
+++ b/tests/rustdoc/macro_rules-matchers.rs
@@ -3,29 +3,17 @@
#![crate_name = "foo"]
-//@ has 'foo/macro.todo.html'
-//@ has - '//span[@class="macro"]' 'macro_rules!'
-//@ hasraw - ' todo {'
-
-//@ hasraw - '{ () => { ... }; ($('
-//@ has - '//span[@class="macro-nonterminal"]' '$'
-//@ has - '//span[@class="macro-nonterminal"]' 'arg'
-//@ hasraw - ':tt)+'
-//@ hasraw - ') => { ... }; }'
+//@ has 'foo/macro.todo.html' '//pre' 'macro_rules! todo { \
+// () => { ... }; \
+// ($($arg:tt)+) => { ... }; \
+// }'
pub use std::todo;
mod mod1 {
- //@ has 'foo/macro.macro1.html'
- //@ hasraw - 'macro_rules!'
- //@ hasraw - 'macro1'
- //@ hasraw - '{ () => { ... }; ($('
- //@ has - '//span[@class="macro-nonterminal"]' '$'
- //@ has - '//span[@class="macro-nonterminal"]' 'arg'
- //@ hasraw - ':'
- //@ hasraw - 'expr'
- //@ hasraw - '),'
- //@ hasraw - '+'
- //@ hasraw - ') => { ... }; }'
+ //@ has 'foo/macro.macro1.html' '//pre' 'macro_rules! macro1 { \
+ // () => { ... }; \
+ // ($($arg:expr),+) => { ... }; \
+ // }'
#[macro_export]
macro_rules! macro1 {
() => {};
diff --git a/tests/ui/asan-odr-win/asan_odr_windows.rs b/tests/ui/asan-odr-win/asan_odr_windows.rs
new file mode 100644
index 0000000..c618ac0
--- /dev/null
+++ b/tests/ui/asan-odr-win/asan_odr_windows.rs
@@ -0,0 +1,18 @@
+//! Check that crates can be linked together with `-Z sanitizer=address` on msvc.
+//! See <https://github.com/rust-lang/rust/issues/124390>.
+
+//@ run-pass
+//@ compile-flags:-Zsanitizer=address
+//@ aux-build: asan_odr_win-2.rs
+//@ only-windows-msvc
+
+extern crate othercrate;
+
+fn main() {
+ let result = std::panic::catch_unwind(|| {
+ println!("hello!");
+ });
+ assert!(result.is_ok());
+
+ othercrate::exposed_func();
+}
diff --git a/tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs b/tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs
new file mode 100644
index 0000000..75488a2
--- /dev/null
+++ b/tests/ui/asan-odr-win/auxiliary/asan_odr_win-2.rs
@@ -0,0 +1,11 @@
+//@ no-prefer-dynamic
+//@ compile-flags: -Z sanitizer=address
+#![crate_name = "othercrate"]
+#![crate_type = "rlib"]
+
+pub fn exposed_func() {
+ let result = std::panic::catch_unwind(|| {
+ println!("hello!");
+ });
+ assert!(result.is_ok());
+}
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
index 347fa3f..4cfe51e 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-multi-variant-diagnostics.stderr
@@ -11,10 +11,6 @@
|
LL | if let MultiVariant::Point(ref mut x, _) = point {
| ^^^^^
-help: consider mutably borrowing `c`
- |
-LL | let a = &mut c;
- | ++++
error: aborting due to 1 previous error
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
index c9b27e7..2ed611d 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-single-variant-diagnostics.stderr
@@ -11,10 +11,6 @@
|
LL | let SingleVariant::Point(ref mut x, _) = point;
| ^^^^^
-help: consider mutably borrowing `c`
- |
-LL | let b = &mut c;
- | ++++
error: aborting due to 1 previous error
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
index 079a9ab..47db2c7 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-struct-diagnostics.stderr
@@ -11,10 +11,6 @@
|
LL | x.y.a += 1;
| ^^^^^
-help: consider mutably borrowing `hello`
- |
-LL | let b = &mut hello;
- | ++++
error: aborting due to 1 previous error
diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
index 0bf7174..9db64ec 100644
--- a/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
+++ b/tests/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics-1.stderr
@@ -11,10 +11,6 @@
|
LL | x.0 += 1;
| ^^^
-help: consider mutably borrowing `hello`
- |
-LL | let b = &mut hello;
- | ++++
error: aborting due to 1 previous error
diff --git a/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs
new file mode 100644
index 0000000..346ef64
--- /dev/null
+++ b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.rs
@@ -0,0 +1,21 @@
+// Regression test for #132955 checking that we handle anon consts with
+// inference variables in their generic arguments correctly.
+//
+// This arose via diagnostics where we would have some failing goal such
+// as `[u8; AnonConst<Self>]: PartialEq<Self::A>`, then as part of diagnostics
+// we would replace all generic parameters with inference vars which would yield
+// a self type of `[u8; AnonConst<?x>]` and then attempt to normalize `AnonConst<?x>`.
+
+pub trait T {
+ type A;
+ const P: Self::A;
+
+ fn a() {
+ [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+ //~^ ERROR: can't compare
+ //~| ERROR: constant expression depends on a generic parameter
+ //~| ERROR: constant expression depends on a generic parameter
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr
new file mode 100644
index 0000000..12de4f1
--- /dev/null
+++ b/tests/ui/const-generics/failing_goal_with_repeat_expr_anon_const.stderr
@@ -0,0 +1,31 @@
+error: constant expression depends on a generic parameter
+ --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:15
+ |
+LL | [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+ --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47
+ |
+LL | [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+ | ^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error[E0277]: can't compare `[u8; std::mem::size_of::<Self::A>()]` with `<Self as T>::A`
+ --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47
+ |
+LL | [0u8; std::mem::size_of::<Self::A>()] == Self::P;
+ | ^^ no implementation for `[u8; std::mem::size_of::<Self::A>()] == <Self as T>::A`
+ |
+ = help: the trait `PartialEq<<Self as T>::A>` is not implemented for `[u8; std::mem::size_of::<Self::A>()]`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+ |
+LL | pub trait T where [u8; std::mem::size_of::<Self::A>()]: PartialEq<<Self as T>::A> {
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/extern-flag/auxiliary/panic_handler.rs b/tests/ui/extern-flag/auxiliary/panic_handler.rs
index 5ca32fa..9140cee 100644
--- a/tests/ui/extern-flag/auxiliary/panic_handler.rs
+++ b/tests/ui/extern-flag/auxiliary/panic_handler.rs
@@ -1,14 +1,10 @@
-#![feature(lang_items)]
+#![feature(lang_items, panic_unwind)]
#![no_std]
-// Since `rustc` generally passes `-nodefaultlibs` to the linker,
-// Rust programs link necessary system libraries via `#[link()]`
-// attributes in the `libc` crate. `libc` is a dependency of `std`,
-// but as we are `#![no_std]`, we need to include it manually.
-// Except on windows-msvc.
-#![feature(rustc_private)]
-#[cfg(not(all(windows, target_env = "msvc")))]
-extern crate libc;
+// Since the `unwind` crate is a dependency of the `std` crate, and we have
+// `#![no_std]`, the unwinder is not included in the link command by default.
+// We need to include crate `unwind` manually.
+extern crate unwind;
#[panic_handler]
pub fn begin_panic_handler(_info: &core::panic::PanicInfo<'_>) -> ! {
diff --git a/tests/ui/inline-const/cross_const_control_flow.rs b/tests/ui/inline-const/cross_const_control_flow.rs
new file mode 100644
index 0000000..109764a
--- /dev/null
+++ b/tests/ui/inline-const/cross_const_control_flow.rs
@@ -0,0 +1,46 @@
+//@edition:2021
+
+fn foo() {
+ const { return }
+ //~^ ERROR: return statement outside of function body
+}
+
+fn labelled_block_break() {
+ 'a: { const { break 'a } }
+ //~^ ERROR: `break` outside of a loop or labeled block
+ //~| ERROR: use of unreachable label
+}
+
+fn loop_break() {
+ loop {
+ const { break }
+ //~^ ERROR: `break` outside of a loop or labeled block
+ }
+}
+
+fn continue_to_labelled_block() {
+ 'a: { const { continue 'a } }
+ //~^ ERROR: `continue` outside of a loop
+ //~| ERROR: use of unreachable label
+}
+
+fn loop_continue() {
+ loop {
+ const { continue }
+ //~^ ERROR: `continue` outside of a loop
+ }
+}
+
+async fn await_across_const_block() {
+ const { async {}.await }
+ //~^ ERROR: `await` is only allowed inside `async` functions and blocks
+}
+
+fn reference_to_non_constant_in_const_block() {
+ let x = 1;
+ const { &x };
+ //~^ ERROR: attempt to use a non-constant value in a constant
+}
+
+
+fn main() {}
diff --git a/tests/ui/inline-const/cross_const_control_flow.stderr b/tests/ui/inline-const/cross_const_control_flow.stderr
new file mode 100644
index 0000000..ecfa921
--- /dev/null
+++ b/tests/ui/inline-const/cross_const_control_flow.stderr
@@ -0,0 +1,78 @@
+error[E0767]: use of unreachable label `'a`
+ --> $DIR/cross_const_control_flow.rs:9:25
+ |
+LL | 'a: { const { break 'a } }
+ | -- ^^ unreachable label `'a`
+ | |
+ | unreachable label defined here
+ |
+ = note: labels are unreachable through functions, closures, async blocks and modules
+
+error[E0767]: use of unreachable label `'a`
+ --> $DIR/cross_const_control_flow.rs:22:28
+ |
+LL | 'a: { const { continue 'a } }
+ | -- ^^ unreachable label `'a`
+ | |
+ | unreachable label defined here
+ |
+ = note: labels are unreachable through functions, closures, async blocks and modules
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/cross_const_control_flow.rs:41:14
+ |
+LL | const { &x };
+ | ^ non-constant value
+ |
+help: consider using `const` instead of `let`
+ |
+LL | const x: /* Type */ = 1;
+ | ~~~~~ ++++++++++++
+
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/cross_const_control_flow.rs:35:22
+ |
+LL | const { async {}.await }
+ | -----------^^^^^--
+ | | |
+ | | only allowed inside `async` functions and blocks
+ | this is not `async`
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/cross_const_control_flow.rs:9:19
+ |
+LL | 'a: { const { break 'a } }
+ | ^^^^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/cross_const_control_flow.rs:16:17
+ |
+LL | const { break }
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `continue` outside of a loop
+ --> $DIR/cross_const_control_flow.rs:22:19
+ |
+LL | 'a: { const { continue 'a } }
+ | ^^^^^^^^^^^ cannot `continue` outside of a loop
+
+error[E0268]: `continue` outside of a loop
+ --> $DIR/cross_const_control_flow.rs:29:17
+ |
+LL | const { continue }
+ | ^^^^^^^^ cannot `continue` outside of a loop
+
+error[E0572]: return statement outside of function body
+ --> $DIR/cross_const_control_flow.rs:4:13
+ |
+LL | / fn foo() {
+LL | | const { return }
+ | | --^^^^^^-- the return is part of this body...
+LL | |
+LL | | }
+ | |_- ...not the enclosing function body
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0268, E0435, E0572, E0728, E0767.
+For more information about an error, try `rustc --explain E0268`.
diff --git a/tests/ui/moves/auxiliary/suggest-borrow-for-generic-arg-aux.rs b/tests/ui/moves/auxiliary/suggest-borrow-for-generic-arg-aux.rs
new file mode 100644
index 0000000..c71238b
--- /dev/null
+++ b/tests/ui/moves/auxiliary/suggest-borrow-for-generic-arg-aux.rs
@@ -0,0 +1,20 @@
+//! auxiliary definitons for suggest-borrow-for-generic-arg.rs, to ensure the suggestion works on
+//! functions defined in other crates.
+
+use std::io::{self, Read, Write};
+use std::iter::Sum;
+
+pub fn write_stuff<W: Write>(mut writer: W) -> io::Result<()> {
+ writeln!(writer, "stuff")
+}
+
+pub fn read_and_discard<R: Read>(mut reader: R) -> io::Result<()> {
+ let mut buf = Vec::new();
+ reader.read_to_end(&mut buf).map(|_| ())
+}
+
+pub fn sum_three<I: IntoIterator>(iter: I) -> <I as IntoIterator>::Item
+ where <I as IntoIterator>::Item: Sum
+{
+ iter.into_iter().take(3).sum()
+}
diff --git a/tests/ui/moves/borrow-closures-instead-of-move.rs b/tests/ui/moves/borrow-closures-instead-of-move.rs
index e4bca54..869aa65 100644
--- a/tests/ui/moves/borrow-closures-instead-of-move.rs
+++ b/tests/ui/moves/borrow-closures-instead-of-move.rs
@@ -1,4 +1,4 @@
-fn takes_fn(f: impl Fn()) { //~ HELP if `impl Fn()` implemented `Clone`
+fn takes_fn(f: impl Fn()) {
loop {
takes_fnonce(f);
//~^ ERROR use of moved value
diff --git a/tests/ui/moves/borrow-closures-instead-of-move.stderr b/tests/ui/moves/borrow-closures-instead-of-move.stderr
index ab6ff41..ea145f3 100644
--- a/tests/ui/moves/borrow-closures-instead-of-move.stderr
+++ b/tests/ui/moves/borrow-closures-instead-of-move.stderr
@@ -8,21 +8,6 @@
LL | takes_fnonce(f);
| ^ value moved here, in previous iteration of loop
|
-note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary
- --> $DIR/borrow-closures-instead-of-move.rs:34:20
- |
-LL | fn takes_fnonce(_: impl FnOnce()) {}
- | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value
- | |
- | in this function
-help: if `impl Fn()` implemented `Clone`, you could clone the value
- --> $DIR/borrow-closures-instead-of-move.rs:1:16
- |
-LL | fn takes_fn(f: impl Fn()) {
- | ^^^^^^^^^ consider constraining this type parameter with `Clone`
-LL | loop {
-LL | takes_fnonce(f);
- | - you could clone this value
help: consider borrowing `f`
|
LL | takes_fnonce(&f);
@@ -40,13 +25,6 @@
LL | takes_fnonce(m);
| ^ value used here after move
|
-note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary
- --> $DIR/borrow-closures-instead-of-move.rs:34:20
- |
-LL | fn takes_fnonce(_: impl FnOnce()) {}
- | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value
- | |
- | in this function
help: if `impl FnMut()` implemented `Clone`, you could clone the value
--> $DIR/borrow-closures-instead-of-move.rs:9:20
|
diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.stderr b/tests/ui/moves/moved-value-on-as-ref-arg.stderr
index 4004b7a..a99bdb4 100644
--- a/tests/ui/moves/moved-value-on-as-ref-arg.stderr
+++ b/tests/ui/moves/moved-value-on-as-ref-arg.stderr
@@ -8,7 +8,7 @@
LL | let _baa = bar;
| ^^^ value used here after move
|
-help: borrow the value to avoid moving it
+help: consider borrowing `bar`
|
LL | foo(&bar);
| +
@@ -31,7 +31,7 @@
...
LL | qux(bar);
| --- you could clone this value
-help: borrow the value to avoid moving it
+help: consider mutably borrowing `bar`
|
LL | qux(&mut bar);
| ++++
@@ -46,7 +46,7 @@
LL | let _baa = bar;
| ^^^ value used here after move
|
-help: borrow the value to avoid moving it
+help: consider borrowing `bar`
|
LL | bat(&bar);
| +
@@ -69,7 +69,7 @@
...
LL | baz(bar);
| --- you could clone this value
-help: borrow the value to avoid moving it
+help: consider mutably borrowing `bar`
|
LL | baz(&mut bar);
| ++++
diff --git a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
index a8473bb..a4c8401 100644
--- a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
+++ b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr
@@ -24,10 +24,6 @@
| ^ consider constraining this type parameter with `Clone`
LL | let mut r = R {c: Box::new(f)};
| - you could clone this value
-help: consider mutably borrowing `f`
- |
-LL | let mut r = R {c: Box::new(&mut f)};
- | ++++
error: aborting due to 2 previous errors
diff --git a/tests/ui/moves/suggest-borrow-for-generic-arg.fixed b/tests/ui/moves/suggest-borrow-for-generic-arg.fixed
new file mode 100644
index 0000000..b5e0b46
--- /dev/null
+++ b/tests/ui/moves/suggest-borrow-for-generic-arg.fixed
@@ -0,0 +1,46 @@
+//! Test suggetions to borrow generic arguments instead of moving. Tests for other instances of this
+//! can be found in `moved-value-on-as-ref-arg.rs` and `borrow-closures-instead-of-move.rs`
+//@ run-rustfix
+//@ aux-crate:aux=suggest-borrow-for-generic-arg-aux.rs
+//@ edition: 2021
+
+#![allow(unused_mut)]
+use std::io::{self, Write};
+
+// test for `std::io::Write` (#131413)
+fn test_write() -> io::Result<()> {
+ let mut stdout = io::stdout();
+ aux::write_stuff(&stdout)?; //~ HELP consider borrowing `stdout`
+ writeln!(stdout, "second line")?; //~ ERROR borrow of moved value: `stdout`
+
+ let mut buf = Vec::new();
+ aux::write_stuff(&mut buf.clone())?; //~ HELP consider mutably borrowing `buf`
+ //~^ HELP consider cloning the value
+ writeln!(buf, "second_line") //~ ERROR borrow of moved value: `buf`
+}
+
+/// test for `std::io::Read` (#131413)
+fn test_read() -> io::Result<()> {
+ let stdin = io::stdin();
+ aux::read_and_discard(&stdin)?; //~ HELP consider borrowing `stdin`
+ aux::read_and_discard(stdin)?; //~ ERROR use of moved value: `stdin`
+
+ let mut bytes = std::collections::VecDeque::from([1, 2, 3, 4, 5, 6]);
+ aux::read_and_discard(&mut bytes.clone())?; //~ HELP consider mutably borrowing `bytes`
+ //~^ HELP consider cloning the value
+ aux::read_and_discard(bytes) //~ ERROR use of moved value: `bytes`
+}
+
+/// test that suggestions work with projection types in the callee's signature
+fn test_projections() {
+ let mut iter = [1, 2, 3, 4, 5, 6].into_iter();
+ let _six: usize = aux::sum_three(&mut iter.clone()); //~ HELP consider mutably borrowing `iter`
+ //~^ HELP consider cloning the value
+ let _fifteen: usize = aux::sum_three(iter); //~ ERROR use of moved value: `iter`
+}
+
+fn main() {
+ test_write().unwrap();
+ test_read().unwrap();
+ test_projections();
+}
diff --git a/tests/ui/moves/suggest-borrow-for-generic-arg.rs b/tests/ui/moves/suggest-borrow-for-generic-arg.rs
new file mode 100644
index 0000000..e08978d
--- /dev/null
+++ b/tests/ui/moves/suggest-borrow-for-generic-arg.rs
@@ -0,0 +1,46 @@
+//! Test suggetions to borrow generic arguments instead of moving. Tests for other instances of this
+//! can be found in `moved-value-on-as-ref-arg.rs` and `borrow-closures-instead-of-move.rs`
+//@ run-rustfix
+//@ aux-crate:aux=suggest-borrow-for-generic-arg-aux.rs
+//@ edition: 2021
+
+#![allow(unused_mut)]
+use std::io::{self, Write};
+
+// test for `std::io::Write` (#131413)
+fn test_write() -> io::Result<()> {
+ let mut stdout = io::stdout();
+ aux::write_stuff(stdout)?; //~ HELP consider borrowing `stdout`
+ writeln!(stdout, "second line")?; //~ ERROR borrow of moved value: `stdout`
+
+ let mut buf = Vec::new();
+ aux::write_stuff(buf)?; //~ HELP consider mutably borrowing `buf`
+ //~^ HELP consider cloning the value
+ writeln!(buf, "second_line") //~ ERROR borrow of moved value: `buf`
+}
+
+/// test for `std::io::Read` (#131413)
+fn test_read() -> io::Result<()> {
+ let stdin = io::stdin();
+ aux::read_and_discard(stdin)?; //~ HELP consider borrowing `stdin`
+ aux::read_and_discard(stdin)?; //~ ERROR use of moved value: `stdin`
+
+ let mut bytes = std::collections::VecDeque::from([1, 2, 3, 4, 5, 6]);
+ aux::read_and_discard(bytes)?; //~ HELP consider mutably borrowing `bytes`
+ //~^ HELP consider cloning the value
+ aux::read_and_discard(bytes) //~ ERROR use of moved value: `bytes`
+}
+
+/// test that suggestions work with projection types in the callee's signature
+fn test_projections() {
+ let mut iter = [1, 2, 3, 4, 5, 6].into_iter();
+ let _six: usize = aux::sum_three(iter); //~ HELP consider mutably borrowing `iter`
+ //~^ HELP consider cloning the value
+ let _fifteen: usize = aux::sum_three(iter); //~ ERROR use of moved value: `iter`
+}
+
+fn main() {
+ test_write().unwrap();
+ test_read().unwrap();
+ test_projections();
+}
diff --git a/tests/ui/moves/suggest-borrow-for-generic-arg.stderr b/tests/ui/moves/suggest-borrow-for-generic-arg.stderr
new file mode 100644
index 0000000..07e24f5
--- /dev/null
+++ b/tests/ui/moves/suggest-borrow-for-generic-arg.stderr
@@ -0,0 +1,93 @@
+error[E0382]: borrow of moved value: `stdout`
+ --> $DIR/suggest-borrow-for-generic-arg.rs:14:14
+ |
+LL | let mut stdout = io::stdout();
+ | ---------- move occurs because `stdout` has type `Stdout`, which does not implement the `Copy` trait
+LL | aux::write_stuff(stdout)?;
+ | ------ value moved here
+LL | writeln!(stdout, "second line")?;
+ | ^^^^^^ value borrowed here after move
+ |
+help: consider borrowing `stdout`
+ |
+LL | aux::write_stuff(&stdout)?;
+ | +
+
+error[E0382]: borrow of moved value: `buf`
+ --> $DIR/suggest-borrow-for-generic-arg.rs:19:14
+ |
+LL | let mut buf = Vec::new();
+ | ------- move occurs because `buf` has type `Vec<u8>`, which does not implement the `Copy` trait
+LL | aux::write_stuff(buf)?;
+ | --- value moved here
+LL |
+LL | writeln!(buf, "second_line")
+ | ^^^ value borrowed here after move
+ |
+help: consider mutably borrowing `buf`
+ |
+LL | aux::write_stuff(&mut buf)?;
+ | ++++
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL | aux::write_stuff(buf.clone())?;
+ | ++++++++
+
+error[E0382]: use of moved value: `stdin`
+ --> $DIR/suggest-borrow-for-generic-arg.rs:26:27
+ |
+LL | let stdin = io::stdin();
+ | ----- move occurs because `stdin` has type `Stdin`, which does not implement the `Copy` trait
+LL | aux::read_and_discard(stdin)?;
+ | ----- value moved here
+LL | aux::read_and_discard(stdin)?;
+ | ^^^^^ value used here after move
+ |
+help: consider borrowing `stdin`
+ |
+LL | aux::read_and_discard(&stdin)?;
+ | +
+
+error[E0382]: use of moved value: `bytes`
+ --> $DIR/suggest-borrow-for-generic-arg.rs:31:27
+ |
+LL | let mut bytes = std::collections::VecDeque::from([1, 2, 3, 4, 5, 6]);
+ | --------- move occurs because `bytes` has type `VecDeque<u8>`, which does not implement the `Copy` trait
+LL | aux::read_and_discard(bytes)?;
+ | ----- value moved here
+LL |
+LL | aux::read_and_discard(bytes)
+ | ^^^^^ value used here after move
+ |
+help: consider mutably borrowing `bytes`
+ |
+LL | aux::read_and_discard(&mut bytes)?;
+ | ++++
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL | aux::read_and_discard(bytes.clone())?;
+ | ++++++++
+
+error[E0382]: use of moved value: `iter`
+ --> $DIR/suggest-borrow-for-generic-arg.rs:39:42
+ |
+LL | let mut iter = [1, 2, 3, 4, 5, 6].into_iter();
+ | -------- move occurs because `iter` has type `std::array::IntoIter<usize, 6>`, which does not implement the `Copy` trait
+LL | let _six: usize = aux::sum_three(iter);
+ | ---- value moved here
+LL |
+LL | let _fifteen: usize = aux::sum_three(iter);
+ | ^^^^ value used here after move
+ |
+help: consider mutably borrowing `iter`
+ |
+LL | let _six: usize = aux::sum_three(&mut iter);
+ | ++++
+help: consider cloning the value if the performance cost is acceptable
+ |
+LL | let _six: usize = aux::sum_three(iter.clone());
+ | ++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/not-copy-closure.stderr b/tests/ui/not-copy-closure.stderr
index 50e25a2..60cb135 100644
--- a/tests/ui/not-copy-closure.stderr
+++ b/tests/ui/not-copy-closure.stderr
@@ -11,10 +11,6 @@
|
LL | a += 1;
| ^
-help: consider mutably borrowing `hello`
- |
-LL | let b = &mut hello;
- | ++++
error: aborting due to 1 previous error
diff --git a/tests/ui/parser/unnecessary-let.stderr b/tests/ui/parser/unnecessary-let.stderr
index c6ac0d5..05ac1fa 100644
--- a/tests/ui/parser/unnecessary-let.stderr
+++ b/tests/ui/parser/unnecessary-let.stderr
@@ -2,12 +2,12 @@
--> $DIR/unnecessary-let.rs:2:9
|
LL | for let x of [1, 2, 3] {}
- | ^^^
+ | ^^^^
|
help: remove the unnecessary `let` keyword
|
LL - for let x of [1, 2, 3] {}
-LL + for x of [1, 2, 3] {}
+LL + for x of [1, 2, 3] {}
|
error: missing `in` in `for` loop
@@ -25,12 +25,12 @@
--> $DIR/unnecessary-let.rs:7:9
|
LL | let 1 => {}
- | ^^^
+ | ^^^^
|
help: remove the unnecessary `let` keyword
|
LL - let 1 => {}
-LL + 1 => {}
+LL + 1 => {}
|
error: aborting due to 3 previous errors
diff --git a/tests/ui/simd-abi-checks-empty-list.rs b/tests/ui/simd-abi-checks-empty-list.rs
new file mode 100644
index 0000000..c178505
--- /dev/null
+++ b/tests/ui/simd-abi-checks-empty-list.rs
@@ -0,0 +1,19 @@
+//@ needs-llvm-components: sparc
+//@ compile-flags: --target=sparc-unknown-none-elf --crate-type=rlib
+//@ build-pass
+//@ ignore-pass (test emits codegen-time warnings)
+#![no_core]
+#![feature(no_core, lang_items, repr_simd)]
+#![allow(improper_ctypes_definitions)]
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[repr(simd)]
+pub struct SimdVec([i32; 4]);
+
+pub extern "C" fn pass_by_vec(_: SimdVec) {}
+//~^ this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
+//~| WARNING this was previously accepted by the compiler
diff --git a/tests/ui/simd-abi-checks-empty-list.stderr b/tests/ui/simd-abi-checks-empty-list.stderr
new file mode 100644
index 0000000..d7ce52e
--- /dev/null
+++ b/tests/ui/simd-abi-checks-empty-list.stderr
@@ -0,0 +1,12 @@
+warning: this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
+ --> $DIR/simd-abi-checks-empty-list.rs:17:1
+ |
+LL | pub extern "C" fn pass_by_vec(_: SimdVec) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
+ |
+ = 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 #116558 <https://github.com/rust-lang/rust/issues/116558>
+ = note: `#[warn(abi_unsupported_vector_types)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/simd-abi-checks.rs b/tests/ui/simd-abi-checks.rs
index 094c899..9e3af26 100644
--- a/tests/ui/simd-abi-checks.rs
+++ b/tests/ui/simd-abi-checks.rs
@@ -12,19 +12,19 @@
struct Wrapper(__m256);
unsafe extern "C" fn w(_: Wrapper) {
- //~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
+ //~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
todo!()
}
unsafe extern "C" fn f(_: __m256) {
- //~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
+ //~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
todo!()
}
unsafe extern "C" fn g() -> __m256 {
- //~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
+ //~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
todo!()
}
@@ -53,16 +53,16 @@ unsafe fn test() {
fn main() {
unsafe {
f(g());
- //~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
- //~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+ //~^ WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+ //~| WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
}
unsafe {
gavx(favx());
- //~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
- //~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+ //~^ WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+ //~| WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
}
@@ -73,8 +73,8 @@ fn main() {
unsafe {
w(Wrapper(g()));
- //~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
- //~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+ //~^ WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
+ //~| WARNING this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
//~| WARNING this was previously accepted by the compiler
//~| WARNING this was previously accepted by the compiler
}
diff --git a/tests/ui/simd-abi-checks.stderr b/tests/ui/simd-abi-checks.stderr
index aa7e940..7d2915f 100644
--- a/tests/ui/simd-abi-checks.stderr
+++ b/tests/ui/simd-abi-checks.stderr
@@ -1,4 +1,4 @@
-warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:55:11
|
LL | f(g());
@@ -9,7 +9,7 @@
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
= note: `#[warn(abi_unsupported_vector_types)]` on by default
-warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:55:9
|
LL | f(g());
@@ -19,7 +19,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:63:14
|
LL | gavx(favx());
@@ -29,7 +29,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:63:9
|
LL | gavx(favx());
@@ -39,7 +39,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:75:19
|
LL | w(Wrapper(g()));
@@ -49,7 +49,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller
+warning: this function call uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
--> $DIR/simd-abi-checks.rs:75:9
|
LL | w(Wrapper(g()));
@@ -59,7 +59,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
+warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
--> $DIR/simd-abi-checks.rs:26:1
|
LL | unsafe extern "C" fn g() -> __m256 {
@@ -69,7 +69,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
+warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
--> $DIR/simd-abi-checks.rs:20:1
|
LL | unsafe extern "C" fn f(_: __m256) {
@@ -79,7 +79,7 @@
= note: for more information, see issue #116558 <https://github.com/rust-lang/rust/issues/116558>
= help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
-warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled
+warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `avx` target feature, which is not enabled
--> $DIR/simd-abi-checks.rs:14:1
|
LL | unsafe extern "C" fn w(_: Wrapper) {
diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-abi-checks.rs
index d2afd38..c453e91 100644
--- a/tests/ui/sse-abi-checks.rs
+++ b/tests/ui/sse-abi-checks.rs
@@ -19,6 +19,6 @@ trait Copy {}
#[no_mangle]
pub unsafe extern "C" fn f(_: SseVector) {
- //~^ ABI error: this function definition uses a vector type that requires the `sse` target feature, which is not enabled
+ //~^ this function definition uses a SIMD vector type that (with the chosen ABI) requires the `sse` target feature, which is not enabled
//~| WARNING this was previously accepted by the compiler
}
diff --git a/tests/ui/sse-abi-checks.stderr b/tests/ui/sse-abi-checks.stderr
index 77c4e1f..7dd13af 100644
--- a/tests/ui/sse-abi-checks.stderr
+++ b/tests/ui/sse-abi-checks.stderr
@@ -1,4 +1,4 @@
-warning: ABI error: this function definition uses a vector type that requires the `sse` target feature, which is not enabled
+warning: this function definition uses a SIMD vector type that (with the chosen ABI) requires the `sse` target feature, which is not enabled
--> $DIR/sse-abi-checks.rs:21:1
|
LL | pub unsafe extern "C" fn f(_: SseVector) {
diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.current.stderr
similarity index 85%
rename from tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr
rename to tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.current.stderr
index 5554f0c..ef63681 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr
+++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.current.stderr
@@ -1,5 +1,5 @@
warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/normalize-self-type-constrains-trait-args.rs:5:12
+ --> $DIR/normalize-self-type-constrains-trait-args.rs:8:12
|
LL | #![feature(lazy_type_alias)]
| ^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr
similarity index 85%
copy from tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr
copy to tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr
index 5554f0c..ef63681 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr
+++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr
@@ -1,5 +1,5 @@
warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/normalize-self-type-constrains-trait-args.rs:5:12
+ --> $DIR/normalize-self-type-constrains-trait-args.rs:8:12
|
LL | #![feature(lazy_type_alias)]
| ^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs
index 0ece8f8..c2a0167 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs
+++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs
@@ -1,3 +1,6 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
//@ check-pass
// This goal is also possible w/ a GAT, but lazy_type_alias
diff --git a/triagebot.toml b/triagebot.toml
index 462d5df..d5bc549 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -975,9 +975,9 @@
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
- "jieyouxu",
"jyn514",
"oli-obk",
+ "onur-ozkan",
]
[assign.adhoc_groups]