diff --git a/Cargo.lock b/Cargo.lock index 9cca91c25df0..b98c4fd0642d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,7 +41,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", "once_cell", "version_check", "zerocopy", @@ -112,9 +111,9 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ version = "0.4.2" 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 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[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 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.4.7", + "regex-automata 0.4.8", "serde", ] @@ -357,9 +356,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[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 @@ version = "0.1.0" [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -557,7 +556,7 @@ dependencies = [ "rustc_tools_util", "serde", "serde_json", - "syn 2.0.79", + "syn 2.0.87", "tempfile", "termize", "tokio", @@ -600,7 +599,7 @@ dependencies = [ "itertools", "quine-mc_cluskey", "regex", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", "semver", "serde", "serde_json", @@ -665,7 +664,7 @@ dependencies = [ "nom", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -682,9 +681,9 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -901,7 +900,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -938,38 +937,38 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" 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 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1059,7 +1058,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1260,6 +1259,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" 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" @@ -1296,9 +1301,9 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ [[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 @@ dependencies = [ "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]] @@ -1513,6 +1518,15 @@ dependencies = [ "serde", ] +[[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" @@ -1574,7 +1588,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1706,7 +1720,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1747,7 +1761,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.7", + "regex-automata 0.4.8", "same-file", "walkdir", "winapi-util", @@ -1761,12 +1775,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[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 @@ dependencies = [ [[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 @@ checksum = "baff4b617f7df3d896f97fe922b64817f6cd9a756bb81d40f8883f2f66dcb401" [[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 @@ dependencies = [ [[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" @@ -2223,12 +2237,9 @@ dependencies = [ [[package]] name = "minifier" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa3f302fe0f8de065d4a2d1ed64f60204623cac58b80cd3c2a83a25d5a7d437" -dependencies = [ - "clap", -] +checksum = "bd559bbf5d350ac7f2c1cf92ed71a869b847a92bce0c1318b47932a5b5f65cdd" [[package]] name = "minimal-lexical" @@ -2454,17 +2465,17 @@ dependencies = [ [[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]] @@ -2478,21 +2489,9 @@ dependencies = [ [[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" @@ -2514,9 +2513,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[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", @@ -2620,9 +2619,9 @@ dependencies = [ [[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" @@ -2641,9 +2640,9 @@ dependencies = [ [[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", @@ -2652,9 +2651,9 @@ dependencies = [ [[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", @@ -2662,22 +2661,22 @@ dependencies = [ [[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", @@ -2743,9 +2742,9 @@ dependencies = [ [[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" @@ -2815,9 +2814,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[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", ] @@ -2960,9 +2959,9 @@ dependencies = [ [[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", ] @@ -2980,14 +2979,14 @@ dependencies = [ [[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]] @@ -3010,13 +3009,13 @@ dependencies = [ [[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]] @@ -3033,9 +3032,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[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" @@ -3055,41 +3054,39 @@ dependencies = [ [[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", @@ -3109,9 +3106,9 @@ version = "0.2.0" 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", @@ -3410,7 +3407,7 @@ dependencies = [ "itertools", "libc", "measureme", - "object 0.36.4", + "object 0.36.5", "rustc-demangle", "rustc_abi", "rustc_ast", @@ -3450,7 +3447,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object 0.36.4", + "object 0.36.5", "pathdiff", "regex", "rustc_abi", @@ -3698,7 +3695,7 @@ dependencies = [ "fluent-syntax", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "unic-langid", ] @@ -3833,7 +3830,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3981,7 +3978,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "synstructure", ] @@ -4446,7 +4443,7 @@ name = "rustc_target" 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", @@ -4568,7 +4565,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "synstructure", ] @@ -4657,7 +4654,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -4691,9 +4688,9 @@ dependencies = [ [[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", @@ -4704,9 +4701,9 @@ dependencies = [ [[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" @@ -4734,9 +4731,9 @@ dependencies = [ [[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", ] @@ -4779,29 +4776,29 @@ dependencies = [ [[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", @@ -5052,9 +5049,9 @@ dependencies = [ [[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", @@ -5069,7 +5066,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5095,9 +5092,9 @@ dependencies = [ [[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", @@ -5150,12 +5147,12 @@ dependencies = [ [[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]] @@ -5187,22 +5184,22 @@ checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[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]] @@ -5212,8 +5209,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "813ba76597db32dc4f6992fd8bf8f394715b88d352fd97401da67dab6283b4c6" dependencies = [ "gimli 0.30.0", - "hashbrown", - "object 0.36.4", + "hashbrown 0.14.5", + "object 0.36.5", "tracing", ] @@ -5315,9 +5312,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[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", @@ -5393,7 +5390,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5495,9 +5492,9 @@ dependencies = [ [[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" @@ -5564,24 +5561,21 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b" 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" @@ -5600,9 +5594,9 @@ dependencies = [ [[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" @@ -5699,9 +5693,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[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", ] @@ -5742,15 +5736,15 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[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", @@ -5759,24 +5753,24 @@ dependencies = [ [[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", @@ -5784,22 +5778,22 @@ dependencies = [ [[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" @@ -5812,7 +5806,7 @@ dependencies = [ "lexopt", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.219.0", + "wasmparser 0.219.1", "wat", "wit-component", "wit-parser", @@ -5836,19 +5830,19 @@ dependencies = [ [[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", @@ -5856,8 +5850,8 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.219.0", - "wasmparser 0.219.0", + "wasm-encoder 0.219.1", + "wasmparser 0.219.1", ] [[package]] @@ -5872,13 +5866,22 @@ dependencies = [ [[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", @@ -5886,22 +5889,22 @@ dependencies = [ [[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", ] @@ -5957,7 +5960,7 @@ dependencies = [ "rayon", "serde", "serde_json", - "syn 2.0.79", + "syn 2.0.87", "windows-metadata", ] @@ -5990,7 +5993,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -6001,7 +6004,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -6178,9 +6181,9 @@ dependencies = [ [[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", @@ -6189,17 +6192,17 @@ dependencies = [ "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", @@ -6210,7 +6213,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.219.0", + "wasmparser 0.219.1", ] [[package]] @@ -6268,7 +6271,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "synstructure", ] @@ -6290,7 +6293,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -6310,7 +6313,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "synstructure", ] @@ -6333,5 +6336,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] diff --git a/Cargo.toml b/Cargo.toml index e1d667bf0157..b773030b4cab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,12 +2,12 @@ resolver = "2" members = [ "compiler/rustc", + "src/build_helper", "src/etc/test-float-parse", "src/rustc-std-workspace/rustc-std-workspace-core", "src/rustc-std-workspace/rustc-std-workspace-alloc", "src/rustc-std-workspace/rustc-std-workspace-std", "src/rustdoc-json-types", - "src/tools/build_helper", "src/tools/cargotest", "src/tools/clippy", "src/tools/clippy/clippy_dev", diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index a2fc9d5c408e..f85c30ac7ec5 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -31,5 +31,4 @@ jemalloc = ['dep:jemalloc-sys'] llvm = ['rustc_driver_impl/llvm'] max_level_info = ['rustc_driver_impl/max_level_info'] rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts'] -rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler'] # tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 997c44cffff0..5f71fb97d768 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1194,7 +1194,7 @@ impl Expr { /// /// Does not ensure that the path resolves to a const param, the caller should check this. pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool { - let this = if strip_identity_block { self.maybe_unwrap_block().1 } else { self }; + let this = if strip_identity_block { self.maybe_unwrap_block() } else { self }; if let ExprKind::Path(None, path) = &this.kind && path.is_potential_trivial_const_arg() @@ -1206,14 +1206,41 @@ impl Expr { } /// Returns an expression with (when possible) *one* outter brace removed - pub fn maybe_unwrap_block(&self) -> (bool, &Expr) { + pub fn maybe_unwrap_block(&self) -> &Expr { if let ExprKind::Block(block, None) = &self.kind && let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind { - (true, expr) + expr } else { - (false, self) + self + } + } + + /// Determines whether this expression is a macro call optionally wrapped in braces . If + /// `already_stripped_block` is set then we do not attempt to peel off a layer of braces. + /// + /// Returns the [`NodeId`] of the macro call and whether a layer of braces has been peeled + /// either before, or part of, this function. + pub fn optionally_braced_mac_call( + &self, + already_stripped_block: bool, + ) -> Option<(bool, NodeId)> { + match &self.kind { + ExprKind::Block(block, None) + if let [stmt] = &*block.stmts + && !already_stripped_block => + { + match &stmt.kind { + StmtKind::MacCall(_) => Some((true, stmt.id)), + StmtKind::Expr(expr) if let ExprKind::MacCall(_) = &expr.kind => { + Some((true, expr.id)) + } + _ => None, + } + } + ExprKind::MacCall(_) => Some((already_stripped_block, self.id)), + _ => None, } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index d5c2bc1c7f63..0b4bfc0b36a0 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -38,7 +38,6 @@ pub enum TokenTree { } // Ensure all fields of `TokenTree` are `DynSend` and `DynSync`. -#[cfg(parallel_compiler)] fn _dummy() where Token: sync::DynSend + sync::DynSync, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2f8115441de9..58497d70a241 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -200,8 +200,8 @@ pub trait Visitor<'ast>: Sized { fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result { walk_param_bound(self, bounds) } - fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) { - walk_precise_capturing_arg(self, arg); + fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) -> Self::Result { + walk_precise_capturing_arg(self, arg) } fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result { walk_poly_trait_ref(self, t) @@ -730,14 +730,10 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>( visitor: &mut V, arg: &'a PreciseCapturingArg, -) { +) -> V::Result { match arg { - PreciseCapturingArg::Lifetime(lt) => { - visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg); - } - PreciseCapturingArg::Arg(path, id) => { - visitor.visit_path(path, *id); - } + PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg), + PreciseCapturingArg::Arg(path, id) => visitor.visit_path(path, *id), } } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 3acca94a54bd..215e6d84d0f0 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -45,6 +45,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | asm::InlineAsmArch::X86_64 | asm::InlineAsmArch::Arm | asm::InlineAsmArch::AArch64 + | asm::InlineAsmArch::Arm64EC | asm::InlineAsmArch::RiscV32 | asm::InlineAsmArch::RiscV64 | asm::InlineAsmArch::LoongArch64 diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index d646150a620c..be6f2c152a4d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -204,6 +204,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "meant for internal use only" { keyword => rustdoc_internals fake_variadic => rustdoc_internals + search_unbox => rustdoc_internals } ); } @@ -522,9 +523,18 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "consider removing `for<...>`" ); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); - for &span in spans.get(&sym::yield_expr).iter().copied().flatten() { - if !span.at_least_rust_2024() { - gate!(&visitor, coroutines, span, "yield syntax is experimental"); + // yield can be enabled either by `coroutines` or `gen_blocks` + if let Some(spans) = spans.get(&sym::yield_expr) { + for span in spans { + if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) + && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) + { + #[allow(rustc::untranslatable_diagnostic)] + // Don't know which of the two features to include in the + // error message, so I am arbitrarily picking one. + feature_err(&visitor.sess, sym::coroutines, *span, "yield syntax is experimental") + .emit(); + } } } gate_all!(gen_blocks, "gen blocks are experimental"); diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 2753ac529d12..94f9727eb7fb 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::parse::feature_err; use rustc_session::{RustcVersion, Session}; +use rustc_span::Span; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{Symbol, kw, sym}; -use rustc_span::{DUMMY_SP, Span}; use crate::fluent_generated; use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause}; @@ -92,9 +92,7 @@ impl Stability { #[derive(HashStable_Generic)] pub struct ConstStability { pub level: StabilityLevel, - /// This can be `None` for functions that do not have an explicit const feature. - /// We still track them for recursive const stability checks. - pub feature: Option, + pub feature: Symbol, /// This is true iff the `const_stable_indirect` attribute is present. pub const_stable_indirect: bool, /// whether the function has a `#[rustc_promotable]` attribute @@ -272,22 +270,19 @@ pub fn find_stability( /// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable` /// attributes in `attrs`. Returns `None` if no stability attributes are found. -/// -/// `is_const_fn` indicates whether this is a function marked as `const`. pub fn find_const_stability( sess: &Session, attrs: &[Attribute], item_sp: Span, - is_const_fn: bool, ) -> Option<(ConstStability, Span)> { let mut const_stab: Option<(ConstStability, Span)> = None; let mut promotable = false; - let mut const_stable_indirect = None; + let mut const_stable_indirect = false; for attr in attrs { match attr.name_or_empty() { sym::rustc_promotable => promotable = true, - sym::rustc_const_stable_indirect => const_stable_indirect = Some(attr.span), + sym::rustc_const_stable_indirect => const_stable_indirect = true, sym::rustc_const_unstable => { if const_stab.is_some() { sess.dcx() @@ -299,7 +294,7 @@ pub fn find_const_stability( const_stab = Some(( ConstStability { level, - feature: Some(feature), + feature, const_stable_indirect: false, promotable: false, }, @@ -317,7 +312,7 @@ pub fn find_const_stability( const_stab = Some(( ConstStability { level, - feature: Some(feature), + feature, const_stable_indirect: false, promotable: false, }, @@ -340,7 +335,7 @@ pub fn find_const_stability( } } } - if const_stable_indirect.is_some() { + if const_stable_indirect { match &mut const_stab { Some((stab, _)) => { if stab.is_const_unstable() { @@ -351,36 +346,37 @@ pub fn find_const_stability( }) } } - _ => {} + _ => { + // This function has no const stability attribute, but has `const_stable_indirect`. + // We ignore that; unmarked functions are subject to recursive const stability + // checks by default so we do carry out the user's intent. + } } } - // Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const - // fn` get *some* marker, since we are a staged_api crate and therefore will do recursive const - // stability checks for them. We need to do this because the default for whether an unmarked - // function enforces recursive stability differs between staged-api crates and force-unmarked - // crates: in force-unmarked crates, only functions *explicitly* marked `const_stable_indirect` - // enforce recursive stability. Therefore when `lookup_const_stability` is `None`, we have to - // assume the function does not have recursive stability. All functions that *do* have recursive - // stability must explicitly record this, and so that's what we do for all `const fn` in a - // staged_api crate. - if (is_const_fn || const_stable_indirect.is_some()) && const_stab.is_none() { - let c = ConstStability { - feature: None, - const_stable_indirect: const_stable_indirect.is_some(), - promotable: false, - level: StabilityLevel::Unstable { - reason: UnstableReason::Default, - issue: None, - is_soft: false, - implied_by: None, - }, - }; - const_stab = Some((c, const_stable_indirect.unwrap_or(DUMMY_SP))); - } const_stab } +/// Calculates the const stability for a const function in a `-Zforce-unstable-if-unmarked` crate +/// without the `staged_api` feature. +pub fn unmarked_crate_const_stab( + _sess: &Session, + attrs: &[Attribute], + regular_stab: Stability, +) -> ConstStability { + assert!(regular_stab.level.is_unstable()); + // The only attribute that matters here is `rustc_const_stable_indirect`. + // We enforce recursive const stability rules for those functions. + let const_stable_indirect = + attrs.iter().any(|a| a.name_or_empty() == sym::rustc_const_stable_indirect); + ConstStability { + feature: regular_stab.feature, + const_stable_indirect, + promotable: false, + level: regular_stab.level, + } +} + /// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`. /// Returns `None` if no stability attributes are found. pub fn find_body_stability( diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml index e6cfb4887c91..c35556dcf5bf 100644 --- a/compiler/rustc_baked_icu_data/Cargo.toml +++ b/compiler/rustc_baked_icu_data/Cargo.toml @@ -8,11 +8,6 @@ edition = "2021" icu_list = "1.2" icu_locid = "1.2" icu_locid_transform = "1.3.2" -icu_provider = "1.2" +icu_provider = { version = "1.2", features = ["sync"] } zerovec = "0.10.0" # tidy-alphabetical-end - -[features] -# tidy-alphabetical-start -rustc_use_parallel_compiler = ['icu_provider/sync'] -# tidy-alphabetical-end diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index e5b28289faa4..454fd14ea748 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::mir::{ }; 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_span::{BytePos, Span, Symbol}; 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } 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(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(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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); } } - 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); } + /// 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 { + 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 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); } - 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_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs index bfd7e83501c7..d77c53a39844 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs @@ -4,15 +4,16 @@ use std::ops::ControlFlow; use either::Either; +use itertools::Itertools as _; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diag}; +use rustc_errors::{Diag, Subdiagnostic}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::mir::{self, ConstraintCategory, Location}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::Symbol; +use rustc_trait_selection::errors::impl_trait_overcapture_suggestion; use crate::MirBorrowckCtxt; use crate::borrow_set::BorrowData; @@ -61,6 +62,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // *does* mention. We'll use that for the `+ use<'a>` suggestion below. let mut visitor = CheckExplicitRegionMentionAndCollectGenerics { tcx, + generics: tcx.generics_of(opaque_def_id), offending_region_idx, seen_opaques: [opaque_def_id].into_iter().collect(), seen_lifetimes: Default::default(), @@ -83,34 +85,50 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { "this call may capture more lifetimes than intended, \ because Rust 2024 has adjusted the `impl Trait` lifetime capture rules", ); - let mut seen_generics: Vec<_> = - visitor.seen_lifetimes.iter().map(ToString::to_string).collect(); - // Capture all in-scope ty/const params. - seen_generics.extend( - ty::GenericArgs::identity_for_item(tcx, opaque_def_id) - .iter() - .filter(|arg| { - matches!( - arg.unpack(), - ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_) - ) - }) - .map(|arg| arg.to_string()), - ); - if opaque_def_id.is_local() { - diag.span_suggestion_verbose( - tcx.def_span(opaque_def_id).shrink_to_hi(), - "add a precise capturing bound to avoid overcapturing", - format!(" + use<{}>", seen_generics.join(", ")), - Applicability::MaybeIncorrect, - ); + let mut captured_args = visitor.seen_lifetimes; + // Add in all of the type and const params, too. + // Ordering here is kinda strange b/c we're walking backwards, + // but we're trying to provide *a* suggestion, not a nice one. + let mut next_generics = Some(visitor.generics); + let mut any_synthetic = false; + while let Some(generics) = next_generics { + for param in &generics.own_params { + if param.kind.is_ty_or_const() { + captured_args.insert(param.def_id); + } + if param.kind.is_synthetic() { + any_synthetic = true; + } + } + next_generics = generics.parent.map(|def_id| tcx.generics_of(def_id)); + } + + if let Some(opaque_def_id) = opaque_def_id.as_local() + && let hir::OpaqueTyOrigin::FnReturn { parent, .. } = + tcx.hir().expect_opaque_ty(opaque_def_id).origin + { + if let Some(sugg) = impl_trait_overcapture_suggestion( + tcx, + opaque_def_id, + parent, + captured_args, + ) { + sugg.add_to_diag(diag); + } } else { diag.span_help( tcx.def_span(opaque_def_id), format!( "if you can modify this crate, add a precise \ capturing bound to avoid overcapturing: `+ use<{}>`", - seen_generics.join(", ") + if any_synthetic { + "/* Args */".to_string() + } else { + captured_args + .into_iter() + .map(|def_id| tcx.item_name(def_id)) + .join(", ") + } ), ); } @@ -182,9 +200,10 @@ impl<'tcx> TypeVisitor> for FindOpaqueRegion<'_, 'tcx> { struct CheckExplicitRegionMentionAndCollectGenerics<'tcx> { tcx: TyCtxt<'tcx>, + generics: &'tcx ty::Generics, offending_region_idx: usize, seen_opaques: FxIndexSet, - seen_lifetimes: FxIndexSet, + seen_lifetimes: FxIndexSet, } impl<'tcx> TypeVisitor> for CheckExplicitRegionMentionAndCollectGenerics<'tcx> { @@ -214,7 +233,7 @@ impl<'tcx> TypeVisitor> for CheckExplicitRegionMentionAndCollectGen if param.index as usize == self.offending_region_idx { ControlFlow::Break(()) } else { - self.seen_lifetimes.insert(param.name); + self.seen_lifetimes.insert(self.generics.region_param(param, self.tcx).def_id); ControlFlow::Continue(()) } } diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index b686a8cf935c..f419c1e776b8 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -39,50 +39,10 @@ pub(crate) fn cfg_eval( let features = Some(features); CfgEval(StripUnconfigured { sess, features, config_tokens: true, lint_node_id }) .configure_annotatable(annotatable) - // Since the item itself has already been configured by the `InvocationCollector`, - // we know that fold result vector will contain exactly one element. - .unwrap() } struct CfgEval<'a>(StripUnconfigured<'a>); -fn flat_map_annotatable( - vis: &mut impl MutVisitor, - annotatable: Annotatable, -) -> Option { - match annotatable { - Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item), - Annotatable::AssocItem(item, ctxt) => { - Some(Annotatable::AssocItem(vis.flat_map_assoc_item(item, ctxt).pop()?, ctxt)) - } - Annotatable::ForeignItem(item) => { - vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem) - } - Annotatable::Stmt(stmt) => { - vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt) - } - Annotatable::Expr(mut expr) => { - vis.visit_expr(&mut expr); - Some(Annotatable::Expr(expr)) - } - Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm), - Annotatable::ExprField(field) => { - vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField) - } - Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField), - Annotatable::GenericParam(param) => { - vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam) - } - Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param), - Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef), - Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant), - Annotatable::Crate(mut krate) => { - vis.visit_crate(&mut krate); - Some(Annotatable::Crate(krate)) - } - } -} - fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { struct CfgFinder; @@ -106,14 +66,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool { Annotatable::ForeignItem(item) => CfgFinder.visit_foreign_item(item), Annotatable::Stmt(stmt) => CfgFinder.visit_stmt(stmt), Annotatable::Expr(expr) => CfgFinder.visit_expr(expr), - Annotatable::Arm(arm) => CfgFinder.visit_arm(arm), - Annotatable::ExprField(field) => CfgFinder.visit_expr_field(field), - Annotatable::PatField(field) => CfgFinder.visit_pat_field(field), - Annotatable::GenericParam(param) => CfgFinder.visit_generic_param(param), - Annotatable::Param(param) => CfgFinder.visit_param(param), - Annotatable::FieldDef(field) => CfgFinder.visit_field_def(field), - Annotatable::Variant(variant) => CfgFinder.visit_variant(variant), - Annotatable::Crate(krate) => CfgFinder.visit_crate(krate), + _ => unreachable!(), }; res.is_break() } @@ -123,11 +76,11 @@ impl CfgEval<'_> { self.0.configure(node) } - fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option { + fn configure_annotatable(mut self, annotatable: Annotatable) -> Annotatable { // Tokenizing and re-parsing the `Annotatable` can have a significant // performance impact, so try to avoid it if possible if !has_cfg_or_cfg_attr(&annotatable) { - return Some(annotatable); + return annotatable; } // The majority of parsed attribute targets will never need to have early cfg-expansion @@ -140,39 +93,6 @@ impl CfgEval<'_> { // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - let parse_annotatable_with: for<'a> fn(&mut Parser<'a>) -> PResult<'a, _> = - match annotatable { - Annotatable::Item(_) => { - |parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap())) - } - Annotatable::AssocItem(_, AssocCtxt::Trait) => |parser| { - Ok(Annotatable::AssocItem( - parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(), - AssocCtxt::Trait, - )) - }, - Annotatable::AssocItem(_, AssocCtxt::Impl) => |parser| { - Ok(Annotatable::AssocItem( - parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(), - AssocCtxt::Impl, - )) - }, - Annotatable::ForeignItem(_) => |parser| { - Ok(Annotatable::ForeignItem( - parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(), - )) - }, - Annotatable::Stmt(_) => |parser| { - Ok(Annotatable::Stmt(P(parser - .parse_stmt_without_recovery(false, ForceCollect::Yes)? - .unwrap()))) - }, - Annotatable::Expr(_) => { - |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?)) - } - _ => unreachable!(), - }; - // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) // to `None`-delimited groups containing the corresponding tokens. This // is normally delayed until the proc-macro server actually needs to @@ -191,19 +111,56 @@ impl CfgEval<'_> { // Re-parse the tokens, setting the `capture_cfg` flag to save extra information // to the captured `AttrTokenStream` (specifically, we capture // `AttrTokenTree::AttrsTarget` for all occurrences of `#[cfg]` and `#[cfg_attr]`) + // + // After that we have our re-parsed `AttrTokenStream`, recursively configuring + // our attribute target will correctly configure the tokens as well. let mut parser = Parser::new(&self.0.sess.psess, orig_tokens, None); parser.capture_cfg = true; - match parse_annotatable_with(&mut parser) { - Ok(a) => annotatable = a, + let res: PResult<'_, Annotatable> = try { + match annotatable { + Annotatable::Item(_) => { + let item = parser.parse_item(ForceCollect::Yes)?.unwrap(); + Annotatable::Item(self.flat_map_item(item).pop().unwrap()) + } + Annotatable::AssocItem(_, AssocCtxt::Trait) => { + let item = parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(); + Annotatable::AssocItem( + self.flat_map_assoc_item(item, AssocCtxt::Trait).pop().unwrap(), + AssocCtxt::Trait, + ) + } + Annotatable::AssocItem(_, AssocCtxt::Impl) => { + let item = parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(); + Annotatable::AssocItem( + self.flat_map_assoc_item(item, AssocCtxt::Impl).pop().unwrap(), + AssocCtxt::Impl, + ) + } + Annotatable::ForeignItem(_) => { + let item = parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(); + Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap()) + } + Annotatable::Stmt(_) => { + let stmt = + parser.parse_stmt_without_recovery(false, ForceCollect::Yes)?.unwrap(); + Annotatable::Stmt(P(self.flat_map_stmt(stmt).pop().unwrap())) + } + Annotatable::Expr(_) => { + let mut expr = parser.parse_expr_force_collect()?; + self.visit_expr(&mut expr); + Annotatable::Expr(expr) + } + _ => unreachable!(), + } + }; + + match res { + Ok(ann) => ann, Err(err) => { err.emit(); - return Some(annotatable); + annotatable } } - - // Now that we have our re-parsed `AttrTokenStream`, recursively configuring - // our attribute target will correctly configure the tokens as well. - flat_map_annotatable(self, annotatable) } } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 82baaca9a464..79c198ed2d08 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -680,6 +680,12 @@ impl<'a> TraitDef<'a> { param_clone } }) + .map(|mut param| { + // Remove all attributes, because there might be helper attributes + // from other macros that will not be valid in the expanded implementation. + param.attrs.clear(); + param + }) .collect(); // and similarly for where clauses diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs deleted file mode 100644 index c7725e49c944..000000000000 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ /dev/null @@ -1,12 +0,0 @@ -use rustc_codegen_ssa::back::archive::{ - ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, -}; -use rustc_session::Session; - -pub(crate) struct ArArchiveBuilderBuilder; - -impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { - fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { - Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER)) - } -} diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 19a1de53d1dd..b506b1f57315 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -43,7 +43,6 @@ use rustc_codegen_ssa::CodegenResults; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_errors::ErrorGuaranteed; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::Session; @@ -56,7 +55,6 @@ use crate::prelude::*; mod abi; mod allocator; mod analyze; -mod archive; mod base; mod cast; mod codegen_i128; @@ -249,17 +247,6 @@ impl CodegenBackend for CraneliftCodegenBackend { self.config.borrow().as_ref().unwrap(), ) } - - fn link( - &self, - sess: &Session, - codegen_results: CodegenResults, - outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed> { - use rustc_codegen_ssa::back::link::link_binary; - - link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) - } } fn target_triple(sess: &Session) -> target_lexicon::Triple { diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs deleted file mode 100644 index 82e98370b376..000000000000 --- a/compiler/rustc_codegen_gcc/src/archive.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::path::Path; - -use rustc_codegen_ssa::back::archive::{ - ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, - ImportLibraryItem, -}; -use rustc_session::Session; - -pub(crate) struct ArArchiveBuilderBuilder; - -impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { - fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { - Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER)) - } - - fn create_dll_import_lib( - &self, - _sess: &Session, - _lib_name: &str, - _items: Vec, - _output_path: &Path, - ) { - unimplemented!("creating dll imports is not yet supported"); - } -} diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 9d62ccc95d56..5d8c5c199b12 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -52,6 +52,10 @@ impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { fn clear_dbg_loc(&mut self) { self.location = None; } + + fn get_dbg_loc(&self) -> Option { + self.location + } } /// Generate the `debug_context` in an MIR Body. diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index f70dc94b2674..452e92bffa23 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -58,7 +58,6 @@ extern crate rustc_driver; mod abi; mod allocator; -mod archive; mod asm; mod attributes; mod back; @@ -103,7 +102,7 @@ use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBacken use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::IntoDynSyncSend; -use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed}; +use rustc_errors::DiagCtxtHandle; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; @@ -261,17 +260,6 @@ impl CodegenBackend for GccCodegenBackend { .join(sess) } - fn link( - &self, - sess: &Session, - codegen_results: CodegenResults, - outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed> { - use rustc_codegen_ssa::back::link::link_binary; - - link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs) - } - fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec { target_features(sess, allow_unstable, &self.target_info) } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 751b2235dc85..ac76b781218a 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1574,6 +1574,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { cfi::typeid_for_fnabi(self.tcx, fn_abi, options) }; let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap(); + let dbg_loc = self.get_dbg_loc(); // Test whether the function pointer is associated with the type identifier. let cond = self.type_test(llfn, typeid_metadata); @@ -1582,10 +1583,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.cond_br(cond, bb_pass, bb_fail); self.switch_to_block(bb_fail); + if let Some(dbg_loc) = dbg_loc { + self.set_dbg_loc(dbg_loc); + } self.abort(); self.unreachable(); self.switch_to_block(bb_pass); + if let Some(dbg_loc) = dbg_loc { + self.set_dbg_loc(dbg_loc); + } } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index ba863d9d74b5..3a7c7efe03b9 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -274,8 +274,12 @@ pub(crate) unsafe fn create_module<'ll>( } } - // Control Flow Guard is currently only supported by the MSVC linker on Windows. - if sess.target.is_like_msvc { + // Control Flow Guard is currently only supported by MSVC and LLVM on Windows. + if sess.target.is_like_msvc + || (sess.target.options.os == "windows" + && sess.target.options.env == "gnu" + && sess.target.options.abi == "llvm") + { match sess.opts.cg.control_flow_guard { CFGuard::Disabled => {} CFGuard::NoChecks => { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index feac97f3e2b6..a6e07ea2a60e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,5 +1,7 @@ use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion}; +use crate::coverageinfo::mapgen::LocalFileId; + /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] @@ -137,8 +139,12 @@ pub(crate) struct CoverageSpan { } impl CoverageSpan { - pub(crate) fn from_source_region(file_id: u32, code_region: &SourceRegion) -> Self { - let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + pub(crate) fn from_source_region( + local_file_id: LocalFileId, + code_region: &SourceRegion, + ) -> Self { + let file_id = local_file_id.as_u32(); + let &SourceRegion { start_line, start_col, end_line, end_col } = code_region; // Internally, LLVM uses the high bit of `end_col` to distinguish between // code regions and gap regions, so it can't be used by the column number. assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}"); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 5ed640b840e7..e3c0df278836 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -6,7 +6,6 @@ use rustc_middle::mir::coverage::{ SourceRegion, }; use rustc_middle::ty::Instance; -use rustc_span::Symbol; use tracing::{debug, instrument}; use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; @@ -180,7 +179,7 @@ impl<'tcx> FunctionCoverageCollector<'tcx> { } pub(crate) struct FunctionCoverage<'tcx> { - function_coverage_info: &'tcx FunctionCoverageInfo, + pub(crate) function_coverage_info: &'tcx FunctionCoverageInfo, is_used: bool, counters_seen: BitSet, @@ -199,11 +198,6 @@ impl<'tcx> FunctionCoverage<'tcx> { if self.is_used { self.function_coverage_info.function_source_hash } else { 0 } } - /// Returns an iterator over all filenames used by this function's mappings. - pub(crate) fn all_file_names(&self) -> impl Iterator + Captures<'_> { - self.function_coverage_info.mappings.iter().map(|mapping| mapping.source_region.file_name) - } - /// Convert this function's coverage expression data into a form that can be /// passed through FFI to LLVM. pub(crate) fn counter_expressions( diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index bb2f634cb259..b582dd967a70 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -12,8 +12,10 @@ use rustc_index::IndexVec; use rustc_middle::mir::coverage::MappingKind; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; -use rustc_span::Symbol; +use rustc_session::RemapFileNameExt; +use rustc_session::config::RemapPathScopeComponents; use rustc_span::def_id::DefIdSet; +use rustc_span::{Span, Symbol}; use rustc_target::spec::HasTargetSpec; use tracing::debug; @@ -70,8 +72,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { .map(|(instance, function_coverage)| (instance, function_coverage.into_finished())) .collect::>(); - let all_file_names = - function_coverage_entries.iter().flat_map(|(_, fn_cov)| fn_cov.all_file_names()); + let all_file_names = function_coverage_entries + .iter() + .map(|(_, fn_cov)| fn_cov.function_coverage_info.body_span) + .map(|span| span_file_name(tcx, span)); let global_file_table = GlobalFileTable::new(all_file_names); // Encode all filenames referenced by coverage mappings in this CGU. @@ -96,7 +100,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { let is_used = function_coverage.is_used(); let coverage_mapping_buffer = - encode_mappings_for_function(&global_file_table, &function_coverage); + encode_mappings_for_function(tcx, &global_file_table, &function_coverage); if coverage_mapping_buffer.is_empty() { if function_coverage.is_used() { @@ -164,13 +168,13 @@ impl GlobalFileTable { Self { raw_file_table } } - fn global_file_id_for_file_name(&self, file_name: Symbol) -> u32 { + fn global_file_id_for_file_name(&self, file_name: Symbol) -> GlobalFileId { let raw_id = self.raw_file_table.get_index_of(&file_name).unwrap_or_else(|| { bug!("file name not found in prepared global file table: {file_name}"); }); // The raw file table doesn't include an entry for the working dir // (which has ID 0), so add 1 to get the correct ID. - (raw_id + 1) as u32 + GlobalFileId::from_usize(raw_id + 1) } fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec { @@ -196,19 +200,27 @@ impl GlobalFileTable { } rustc_index::newtype_index! { - struct LocalFileId {} + /// An index into the CGU's overall list of file paths. The underlying paths + /// will be embedded in the `__llvm_covmap` linker section. + struct GlobalFileId {} +} +rustc_index::newtype_index! { + /// An index into a function's list of global file IDs. That underlying list + /// of local-to-global mappings will be embedded in the function's record in + /// the `__llvm_covfun` linker section. + pub(crate) struct LocalFileId {} } /// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) /// file IDs. #[derive(Default)] struct VirtualFileMapping { - local_to_global: IndexVec, - global_to_local: FxIndexMap, + local_to_global: IndexVec, + global_to_local: FxIndexMap, } impl VirtualFileMapping { - fn local_id_for_global(&mut self, global_file_id: u32) -> LocalFileId { + fn local_id_for_global(&mut self, global_file_id: GlobalFileId) -> LocalFileId { *self .global_to_local .entry(global_file_id) @@ -216,16 +228,26 @@ impl VirtualFileMapping { } fn into_vec(self) -> Vec { - self.local_to_global.raw + // This conversion should be optimized away to ~zero overhead. + // In any case, it's probably not hot enough to worry about. + self.local_to_global.into_iter().map(|global| global.as_u32()).collect() } } +fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol { + let source_file = tcx.sess.source_map().lookup_source_file(span.lo()); + let name = + source_file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(); + Symbol::intern(&name) +} + /// Using the expressions and counter regions collected for a single function, /// generate the variable-sized payload of its corresponding `__llvm_covfun` /// entry. The payload is returned as a vector of bytes. /// /// Newly-encountered filenames will be added to the global file table. fn encode_mappings_for_function( + tcx: TyCtxt<'_>, global_file_table: &GlobalFileTable, function_coverage: &FunctionCoverage<'_>, ) -> Vec { @@ -242,53 +264,45 @@ fn encode_mappings_for_function( let mut mcdc_branch_regions = vec![]; let mut mcdc_decision_regions = vec![]; - // Group mappings into runs with the same filename, preserving the order - // yielded by `FunctionCoverage`. - // Prepare file IDs for each filename, and prepare the mapping data so that - // we can pass it through FFI to LLVM. - for (file_name, counter_regions_for_file) in - &counter_regions.group_by(|(_, region)| region.file_name) - { - // Look up the global file ID for this filename. - let global_file_id = global_file_table.global_file_id_for_file_name(file_name); + // Currently a function's mappings must all be in the same file as its body span. + let file_name = span_file_name(tcx, function_coverage.function_coverage_info.body_span); - // Associate that global file ID with a local file ID for this function. - let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); - debug!(" file id: {local_file_id:?} => global {global_file_id} = '{file_name:?}'"); + // Look up the global file ID for that filename. + let global_file_id = global_file_table.global_file_id_for_file_name(file_name); - // For each counter/region pair in this function+file, convert it to a - // form suitable for FFI. - for (mapping_kind, region) in counter_regions_for_file { - debug!("Adding counter {mapping_kind:?} to map for {region:?}"); - let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region); - match mapping_kind { - MappingKind::Code(term) => { - code_regions - .push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); - } - MappingKind::Branch { true_term, false_term } => { - branch_regions.push(ffi::BranchRegion { - span, - true_counter: ffi::Counter::from_term(true_term), - false_counter: ffi::Counter::from_term(false_term), - }); - } - MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { - mcdc_branch_regions.push(ffi::MCDCBranchRegion { - span, - true_counter: ffi::Counter::from_term(true_term), - false_counter: ffi::Counter::from_term(false_term), - mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), - }); - } - MappingKind::MCDCDecision(mcdc_decision_params) => { - mcdc_decision_regions.push(ffi::MCDCDecisionRegion { - span, - mcdc_decision_params: ffi::mcdc::DecisionParameters::from( - mcdc_decision_params, - ), - }); - } + // Associate that global file ID with a local file ID for this function. + let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id); + debug!(" file id: {local_file_id:?} => {global_file_id:?} = '{file_name:?}'"); + + // For each counter/region pair in this function+file, convert it to a + // form suitable for FFI. + for (mapping_kind, region) in counter_regions { + debug!("Adding counter {mapping_kind:?} to map for {region:?}"); + let span = ffi::CoverageSpan::from_source_region(local_file_id, region); + match mapping_kind { + MappingKind::Code(term) => { + code_regions.push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); + } + MappingKind::Branch { true_term, false_term } => { + branch_regions.push(ffi::BranchRegion { + span, + true_counter: ffi::Counter::from_term(true_term), + false_counter: ffi::Counter::from_term(false_term), + }); + } + MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { + mcdc_branch_regions.push(ffi::MCDCBranchRegion { + span, + true_counter: ffi::Counter::from_term(true_term), + false_counter: ffi::Counter::from_term(false_term), + mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), + }); + } + MappingKind::MCDCDecision(mcdc_decision_params) => { + mcdc_decision_regions.push(ffi::MCDCDecisionRegion { + span, + mcdc_decision_params: ffi::mcdc::DecisionParameters::from(mcdc_decision_params), + }); } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 9e1e5127e80f..89492e4b9fe5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -206,6 +206,10 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { } } + fn get_dbg_loc(&self) -> Option<&'ll DILocation> { + unsafe { llvm::LLVMGetCurrentDebugLocation2(self.llbuilder) } + } + fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { gdb::insert_reference_to_gdb_debug_scripts_section_global(self) } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 49e616b53713..3dfb86d422dd 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -382,7 +382,7 @@ impl CodegenBackend for LlvmCodegenBackend { // Run the linker on any artifacts that resulted from the LLVM run. // This should produce either a finished executable or library. - link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs) + link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs) } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 75a5ec44c228..7f59264824e4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1063,6 +1063,7 @@ unsafe extern "C" { // Metadata pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: *const Metadata); + pub fn LLVMGetCurrentDebugLocation2<'a>(Builder: &Builder<'a>) -> Option<&'a Metadata>; // Terminators pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value; diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c382242d8d07..db2b03d9aeda 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -344,15 +344,23 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec { }) { if enabled { + // Also add all transitively implied features. features.extend(sess.target.implied_target_features(std::iter::once(feature))); } else { + // Remove transitively reverse-implied features. + // We don't care about the order in `features` since the only thing we use it for is the // `features.contains` below. #[allow(rustc::potential_query_instability)] features.retain(|f| { - // Keep a feature if it does not imply `feature`. Or, equivalently, - // remove the reverse-dependencies of `feature`. - !sess.target.implied_target_features(std::iter::once(*f)).contains(&feature) + if sess.target.implied_target_features(std::iter::once(*f)).contains(&feature) { + // If `f` if implies `feature`, then `!feature` implies `!f`, so we have to + // remove `f`. (This is the standard logical contraposition principle.) + false + } else { + // We can keep `f`. + true + } }); } } diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index e83bfa7b70d9..d4836eb7a1de 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -304,6 +304,14 @@ pub trait ArchiveBuilder { fn build(self: Box, output: &Path) -> bool; } +pub struct ArArchiveBuilderBuilder; + +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { + Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER)) + } +} + #[must_use = "must call build() to finish building the archive"] pub struct ArArchiveBuilder<'a> { sess: &'a Session, diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 3120b5bf0af6..fd1126e85284 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -69,7 +69,7 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { pub fn link_binary( sess: &Session, archive_builder_builder: &dyn ArchiveBuilderBuilder, - codegen_results: &CodegenResults, + codegen_results: CodegenResults, outputs: &OutputFilenames, ) -> Result<(), ErrorGuaranteed> { let _timer = sess.timer("link_binary"); @@ -116,7 +116,7 @@ pub fn link_binary( link_rlib( sess, archive_builder_builder, - codegen_results, + &codegen_results, RlibFlavor::Normal, &path, )? @@ -126,7 +126,7 @@ pub fn link_binary( link_staticlib( sess, archive_builder_builder, - codegen_results, + &codegen_results, &out_filename, &path, )?; @@ -137,7 +137,7 @@ pub fn link_binary( archive_builder_builder, crate_type, &out_filename, - codegen_results, + &codegen_results, path.as_ref(), )?; } @@ -1647,7 +1647,7 @@ fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> Pat return file_path; } } - for search_path in sess.target_filesearch(PathKind::Native).search_paths() { + for search_path in sess.target_filesearch().search_paths(PathKind::Native) { let file_path = search_path.dir.join(name); if file_path.exists() { return file_path; diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 676fb181d67c..cbf214763b42 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -16,6 +16,8 @@ use rustc_span::symbol::Symbol; use super::CodegenObject; use super::write::WriteBackendMethods; +use crate::back::archive::ArArchiveBuilderBuilder; +use crate::back::link::link_binary; use crate::back::write::TargetMachineFactoryFn; use crate::{CodegenResults, ModuleCodegen}; @@ -87,7 +89,9 @@ pub trait CodegenBackend { sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed>; + ) -> Result<(), ErrorGuaranteed> { + link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs) + } /// Returns `true` if this backend can be safely called from multiple threads. /// diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index 670433a6c330..fe135e911fb3 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -81,6 +81,7 @@ pub trait DebugInfoBuilderMethods: BackendTypes { ); fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation); fn clear_dbg_loc(&mut self); + fn get_dbg_loc(&self) -> Option; fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); fn set_var_name(&mut self, value: Self::Value, name: &str); } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 8cd0ecb3e4e6..ffe32acb3165 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -3,6 +3,7 @@ use std::assert_matches::assert_matches; use std::borrow::Cow; use std::mem; +use std::num::NonZero; use std::ops::Deref; use rustc_attr::{ConstStability, StabilityLevel}; @@ -271,9 +272,18 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { /// context. pub fn check_op_spanned>(&mut self, op: O, span: Span) { let gate = match op.status_in_item(self.ccx) { - Status::Unstable { gate, safe_to_expose_on_stable, is_function_call } - if self.tcx.features().enabled(gate) => - { + Status::Unstable { + gate, + safe_to_expose_on_stable, + is_function_call, + gate_already_checked, + } if gate_already_checked || self.tcx.features().enabled(gate) => { + if gate_already_checked { + assert!( + !safe_to_expose_on_stable, + "setting `gate_already_checked` without `safe_to_expose_on_stable` makes no sense" + ); + } // Generally this is allowed since the feature gate is enabled -- except // if this function wants to be safe-to-expose-on-stable. if !safe_to_expose_on_stable @@ -709,6 +719,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Intrinsics are language primitives, not regular calls, so treat them separately. if let Some(intrinsic) = tcx.intrinsic(callee) { + if !tcx.is_const_fn(callee) { + // Non-const intrinsic. + self.check_op(ops::IntrinsicNonConst { name: intrinsic.name }); + // If we allowed this, we're in miri-unleashed mode, so we might + // as well skip the remaining checks. + return; + } // We use `intrinsic.const_stable` to determine if this can be safely exposed to // stable code, rather than `const_stable_indirect`. This is to make // `#[rustc_const_stable_indirect]` an attribute that is always safe to add. @@ -716,17 +733,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // fallback body is safe to expose on stable. let is_const_stable = intrinsic.const_stable || (!intrinsic.must_be_overridden - && tcx.is_const_fn(callee) && is_safe_to_expose_on_stable_const_fn(tcx, callee)); match tcx.lookup_const_stability(callee) { None => { - // Non-const intrinsic. - self.check_op(ops::IntrinsicNonConst { name: intrinsic.name }); - } - Some(ConstStability { feature: None, .. }) => { - // Intrinsic does not need a separate feature gate (we rely on the - // regular stability checker). However, we have to worry about recursive - // const stability. + // This doesn't need a separate const-stability check -- const-stability equals + // regular stability, and regular stability is checked separately. + // However, we *do* have to worry about *recursive* const stability. if !is_const_stable && self.enforce_recursive_const_stability() { self.dcx().emit_err(errors::UnmarkedIntrinsicExposed { span: self.span, @@ -735,14 +747,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } Some(ConstStability { - feature: Some(feature), level: StabilityLevel::Unstable { .. }, + feature, .. }) => { self.check_op(ops::IntrinsicUnstable { name: intrinsic.name, feature, - const_stable: is_const_stable, + const_stable_indirect: is_const_stable, }); } Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { @@ -773,7 +785,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { // All good. } - None | Some(ConstStability { feature: None, .. }) => { + None => { // This doesn't need a separate const-stability check -- const-stability equals // regular stability, and regular stability is checked separately. // However, we *do* have to worry about *recursive* const stability. @@ -787,8 +799,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } } Some(ConstStability { - feature: Some(feature), - level: StabilityLevel::Unstable { implied_by: implied_feature, .. }, + level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. }, + feature, .. }) => { // An unstable const fn with a feature gate. @@ -797,6 +809,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // We only honor `span.allows_unstable` aka `#[allow_internal_unstable]` if // the callee is safe to expose, to avoid bypassing recursive stability. + // This is not ideal since it means the user sees an error, not the macro + // author, but that's also the case if one forgets to set + // `#[allow_internal_unstable]` in the first place. Note that this cannot be + // integrated in the check below since we want to enforce + // `callee_safe_to_expose_on_stable` even if + // `!self.enforce_recursive_const_stability()`. if (self.span.allows_unstable(feature) || implied_feature.is_some_and(|f| self.span.allows_unstable(f))) && callee_safe_to_expose_on_stable @@ -810,16 +828,30 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // to allow this. let feature_enabled = callee.is_local() || tcx.features().enabled(feature) - || implied_feature.is_some_and(|f| tcx.features().enabled(f)); - // We do *not* honor this if we are in the "danger zone": we have to enforce - // recursive const-stability and the callee is not safe-to-expose. In that - // case we need `check_op` to do the check. - let danger_zone = !callee_safe_to_expose_on_stable - && self.enforce_recursive_const_stability(); - if danger_zone || !feature_enabled { + || implied_feature.is_some_and(|f| tcx.features().enabled(f)) + || { + // When we're compiling the compiler itself we may pull in + // crates from crates.io, but those crates may depend on other + // crates also pulled in from crates.io. We want to ideally be + // able to compile everything without requiring upstream + // modifications, so in the case that this looks like a + // `rustc_private` crate (e.g., a compiler crate) and we also have + // the `-Z force-unstable-if-unmarked` flag present (we're + // compiling a compiler crate), then let this missing feature + // annotation slide. + // This matches what we do in `eval_stability_allow_unstable` for + // regular stability. + feature == sym::rustc_private + && issue == NonZero::new(27812) + && self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked + }; + // Even if the feature is enabled, we still need check_op to double-check + // this if the callee is not safe to expose on stable. + if !feature_enabled || !callee_safe_to_expose_on_stable { self.check_op(ops::FnCallUnstable { def_id: callee, feature, + feature_enabled, safe_to_expose_on_stable: callee_safe_to_expose_on_stable, }); } diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index dcdaafaecc21..ebdd55a4f70c 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -53,10 +53,11 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { } pub fn enforce_recursive_const_stability(&self) -> bool { - // We can skip this if `staged_api` is not enabled, since in such crates - // `lookup_const_stability` will always be `None`. + // We can skip this if neither `staged_api` nor `-Zforce-unstable-if-unmarked` are enabled, + // since in such crates `lookup_const_stability` will always be `None`. self.const_kind == Some(hir::ConstContext::ConstFn) - && self.tcx.features().staged_api() + && (self.tcx.features().staged_api() + || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked) && is_safe_to_expose_on_stable_const_fn(self.tcx, self.def_id().to_def_id()) } @@ -109,14 +110,15 @@ pub fn is_safe_to_expose_on_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> b match tcx.lookup_const_stability(def_id) { None => { - // Only marked functions can be trusted. Note that this may be a function in a - // non-staged-API crate where no recursive checks were done! - false + // In a `staged_api` crate, we do enforce recursive const stability for all unmarked + // functions, so we can trust local functions. But in another crate we don't know which + // rules were applied, so we can't trust that. + def_id.is_local() && tcx.features().staged_api() } Some(stab) => { - // We consider things safe-to-expose if they are stable, if they don't have any explicit - // const stability attribute, or if they are marked as `const_stable_indirect`. - stab.is_const_stable() || stab.feature.is_none() || stab.const_stable_indirect + // We consider things safe-to-expose if they are stable or if they are marked as + // `const_stable_indirect`. + stab.is_const_stable() || stab.const_stable_indirect } } } diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 036ca7632804..ca95e42dd2ba 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -28,6 +28,9 @@ pub enum Status { Unstable { /// The feature that must be enabled to use this operation. gate: Symbol, + /// Whether the feature gate was already checked (because the logic is a bit more + /// complicated than just checking a single gate). + gate_already_checked: bool, /// Whether it is allowed to use this operation from stable `const fn`. /// This will usually be `false`. safe_to_expose_on_stable: bool, @@ -82,6 +85,7 @@ impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> { // We use the `const_trait_impl` gate for all conditionally-const calls. Status::Unstable { gate: sym::const_trait_impl, + gate_already_checked: false, safe_to_expose_on_stable: false, // We don't want the "mark the callee as `#[rustc_const_stable_indirect]`" hint is_function_call: false, @@ -330,6 +334,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { pub(crate) struct FnCallUnstable { pub def_id: DefId, pub feature: Symbol, + /// If this is true, then the feature is enabled, but we need to still check if it is safe to + /// expose on stable. + pub feature_enabled: bool, pub safe_to_expose_on_stable: bool, } @@ -337,12 +344,14 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable { gate: self.feature, + gate_already_checked: self.feature_enabled, safe_to_expose_on_stable: self.safe_to_expose_on_stable, is_function_call: true, } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { + assert!(!self.feature_enabled); let mut err = ccx.dcx().create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(self.def_id), @@ -376,14 +385,15 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst { pub(crate) struct IntrinsicUnstable { pub name: Symbol, pub feature: Symbol, - pub const_stable: bool, + pub const_stable_indirect: bool, } impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable { fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable { gate: self.feature, - safe_to_expose_on_stable: self.const_stable, + gate_already_checked: false, + safe_to_expose_on_stable: self.const_stable_indirect, // We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`, // that's not a trivial change! is_function_call: false, @@ -410,6 +420,7 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine { { Status::Unstable { gate: sym::const_async_blocks, + gate_already_checked: false, safe_to_expose_on_stable: false, is_function_call: false, } diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 5a477143a623..c8ecddb046cd 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -10,11 +10,11 @@ bitflags = "2.4.1" either = "1.0" elsa = "=1.7.1" ena = "0.14.3" -indexmap = { version = "2.4.0" } +indexmap = { version = "2.4.0", features = ["rustc-rayon"] } jobserver_crate = { version = "0.1.28", package = "jobserver" } measureme = "11" rustc-hash = "2.0.0" -rustc-rayon = { version = "0.5.0", optional = true } +rustc-rayon = "0.5.0" rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_graphviz = { path = "../rustc_graphviz" } @@ -53,8 +53,3 @@ memmap2 = "0.2.1" [target.'cfg(not(target_has_atomic = "64"))'.dependencies] portable-atomic = "1.5.1" - -[features] -# tidy-alphabetical-start -rustc_use_parallel_compiler = ["indexmap/rustc-rayon", "dep:rustc-rayon"] -# tidy-alphabetical-end diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index afac08ae6f81..bede4c497036 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,7 +10,6 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(not(parallel_compiler), feature(cell_leak))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 83fdaff515b0..2b629024bfe4 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,194 +1,162 @@ -cfg_match! { - cfg(not(parallel_compiler)) => { - pub auto trait DynSend {} - pub auto trait DynSync {} +#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ + Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")] +// This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()` +// is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a +// `Send` type in `IntoDynSyncSend` will create a `DynSend` type. +pub unsafe auto trait DynSend {} - impl DynSend for T {} - impl DynSync for T {} - } - _ => { - #[rustc_on_unimplemented( - message = "`{Self}` doesn't implement `DynSend`. \ - Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`" - )] - // This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()` - // is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a - // `Send` type in `IntoDynSyncSend` will create a `DynSend` type. - pub unsafe auto trait DynSend {} +#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSync`. \ + Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`")] +// This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()` +// is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a +// `Sync` type in `IntoDynSyncSend` will create a `DynSync` type. +pub unsafe auto trait DynSync {} - #[rustc_on_unimplemented( - message = "`{Self}` doesn't implement `DynSync`. \ - Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`" - )] - // This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()` - // is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a - // `Sync` type in `IntoDynSyncSend` will create a `DynSync` type. - pub unsafe auto trait DynSync {} +// Same with `Sync` and `Send`. +unsafe impl DynSend for &T {} - // Same with `Sync` and `Send`. - unsafe impl DynSend for &T {} - - macro_rules! impls_dyn_send_neg { - ($([$t1: ty $(where $($generics1: tt)*)?])*) => { - $(impl$(<$($generics1)*>)? !DynSend for $t1 {})* - }; - } - - // Consistent with `std` - impls_dyn_send_neg!( - [std::env::Args] - [std::env::ArgsOs] - [*const T where T: ?Sized] - [*mut T where T: ?Sized] - [std::ptr::NonNull where T: ?Sized] - [std::rc::Rc where T: ?Sized] - [std::rc::Weak where T: ?Sized] - [std::sync::MutexGuard<'_, T> where T: ?Sized] - [std::sync::RwLockReadGuard<'_, T> where T: ?Sized] - [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized] - [std::io::StdoutLock<'_>] - [std::io::StderrLock<'_>] - ); - - #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] - // Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms - impl !DynSend for std::env::VarsOs {} - - macro_rules! already_send { - ($([$ty: ty])*) => { - $(unsafe impl DynSend for $ty where $ty: Send {})* - }; - } - - // These structures are already `Send`. - already_send!( - [std::backtrace::Backtrace] - [std::io::Stdout] - [std::io::Stderr] - [std::io::Error] - [std::fs::File] - [rustc_arena::DroplessArena] - [crate::memmap::Mmap] - [crate::profiling::SelfProfiler] - [crate::owned_slice::OwnedSlice] - ); - - macro_rules! impl_dyn_send { - ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => { - $(unsafe impl<$($generics2)*> DynSend for $ty {})* - }; - } - - impl_dyn_send!( - [std::sync::atomic::AtomicPtr where T] - [std::sync::Mutex where T: ?Sized+ DynSend] - [std::sync::mpsc::Sender where T: DynSend] - [std::sync::Arc where T: ?Sized + DynSync + DynSend] - [std::sync::LazyLock where T: DynSend, F: DynSend] - [std::collections::HashSet where K: DynSend, S: DynSend] - [std::collections::HashMap where K: DynSend, V: DynSend, S: DynSend] - [std::collections::BTreeMap where K: DynSend, V: DynSend, A: std::alloc::Allocator + Clone + DynSend] - [Vec where T: DynSend, A: std::alloc::Allocator + DynSend] - [Box where T: ?Sized + DynSend, A: std::alloc::Allocator + DynSend] - [crate::sync::RwLock where T: DynSend] - [crate::tagged_ptr::CopyTaggedPtr where P: Send + crate::tagged_ptr::Pointer, T: Send + crate::tagged_ptr::Tag, const CP: bool] - [rustc_arena::TypedArena where T: DynSend] - [indexmap::IndexSet where V: DynSend, S: DynSend] - [indexmap::IndexMap where K: DynSend, V: DynSend, S: DynSend] - [thin_vec::ThinVec where T: DynSend] - [smallvec::SmallVec where A: smallvec::Array + DynSend] - ); - - macro_rules! impls_dyn_sync_neg { - ($([$t1: ty $(where $($generics1: tt)*)?])*) => { - $(impl$(<$($generics1)*>)? !DynSync for $t1 {})* - }; - } - - // Consistent with `std` - impls_dyn_sync_neg!( - [std::env::Args] - [std::env::ArgsOs] - [*const T where T: ?Sized] - [*mut T where T: ?Sized] - [std::cell::Cell where T: ?Sized] - [std::cell::RefCell where T: ?Sized] - [std::cell::UnsafeCell where T: ?Sized] - [std::ptr::NonNull where T: ?Sized] - [std::rc::Rc where T: ?Sized] - [std::rc::Weak where T: ?Sized] - [std::cell::OnceCell where T] - [std::sync::mpsc::Receiver where T] - [std::sync::mpsc::Sender where T] - ); - - #[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] - // Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms - impl !DynSync for std::env::VarsOs {} - - macro_rules! already_sync { - ($([$ty: ty])*) => { - $(unsafe impl DynSync for $ty where $ty: Sync {})* - }; - } - - // These structures are already `Sync`. - already_sync!( - [std::sync::atomic::AtomicBool] - [std::sync::atomic::AtomicUsize] - [std::sync::atomic::AtomicU8] - [std::sync::atomic::AtomicU32] - [std::backtrace::Backtrace] - [std::io::Error] - [std::fs::File] - [jobserver_crate::Client] - [crate::memmap::Mmap] - [crate::profiling::SelfProfiler] - [crate::owned_slice::OwnedSlice] - ); - - // Use portable AtomicU64 for targets without native 64-bit atomics - #[cfg(target_has_atomic = "64")] - already_sync!( - [std::sync::atomic::AtomicU64] - ); - - #[cfg(not(target_has_atomic = "64"))] - already_sync!( - [portable_atomic::AtomicU64] - ); - - macro_rules! impl_dyn_sync { - ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => { - $(unsafe impl<$($generics2)*> DynSync for $ty {})* - }; - } - - impl_dyn_sync!( - [std::sync::atomic::AtomicPtr where T] - [std::sync::OnceLock where T: DynSend + DynSync] - [std::sync::Mutex where T: ?Sized + DynSend] - [std::sync::Arc where T: ?Sized + DynSync + DynSend] - [std::sync::LazyLock where T: DynSend + DynSync, F: DynSend] - [std::collections::HashSet where K: DynSync, S: DynSync] - [std::collections::HashMap where K: DynSync, V: DynSync, S: DynSync] - [std::collections::BTreeMap where K: DynSync, V: DynSync, A: std::alloc::Allocator + Clone + DynSync] - [Vec where T: DynSync, A: std::alloc::Allocator + DynSync] - [Box where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync] - [crate::sync::RwLock where T: DynSend + DynSync] - [crate::sync::WorkerLocal where T: DynSend] - [crate::intern::Interned<'a, T> where 'a, T: DynSync] - [crate::tagged_ptr::CopyTaggedPtr where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool] - [parking_lot::lock_api::Mutex where R: DynSync, T: ?Sized + DynSend] - [parking_lot::lock_api::RwLock where R: DynSync, T: ?Sized + DynSend + DynSync] - [indexmap::IndexSet where V: DynSync, S: DynSync] - [indexmap::IndexMap where K: DynSync, V: DynSync, S: DynSync] - [smallvec::SmallVec where A: smallvec::Array + DynSync] - [thin_vec::ThinVec where T: DynSync] - ); - } +macro_rules! impls_dyn_send_neg { + ($([$t1: ty $(where $($generics1: tt)*)?])*) => { + $(impl$(<$($generics1)*>)? !DynSend for $t1 {})* + }; } +// Consistent with `std` +impls_dyn_send_neg!( + [std::env::Args] + [std::env::ArgsOs] + [*const T where T: ?Sized] + [*mut T where T: ?Sized] + [std::ptr::NonNull where T: ?Sized] + [std::rc::Rc where T: ?Sized] + [std::rc::Weak where T: ?Sized] + [std::sync::MutexGuard<'_, T> where T: ?Sized] + [std::sync::RwLockReadGuard<'_, T> where T: ?Sized] + [std::sync::RwLockWriteGuard<'_, T> where T: ?Sized] + [std::io::StdoutLock<'_>] + [std::io::StderrLock<'_>] +); + +#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] +// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms +impl !DynSend for std::env::VarsOs {} + +macro_rules! already_send { + ($([$ty: ty])*) => { + $(unsafe impl DynSend for $ty where $ty: Send {})* + }; +} + +// These structures are already `Send`. +already_send!( + [std::backtrace::Backtrace][std::io::Stdout][std::io::Stderr][std::io::Error][std::fs::File] + [rustc_arena::DroplessArena][crate::memmap::Mmap][crate::profiling::SelfProfiler] + [crate::owned_slice::OwnedSlice] +); + +macro_rules! impl_dyn_send { + ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => { + $(unsafe impl<$($generics2)*> DynSend for $ty {})* + }; +} + +impl_dyn_send!( + [std::sync::atomic::AtomicPtr where T] + [std::sync::Mutex where T: ?Sized+ DynSend] + [std::sync::mpsc::Sender where T: DynSend] + [std::sync::Arc where T: ?Sized + DynSync + DynSend] + [std::sync::LazyLock where T: DynSend, F: DynSend] + [std::collections::HashSet where K: DynSend, S: DynSend] + [std::collections::HashMap where K: DynSend, V: DynSend, S: DynSend] + [std::collections::BTreeMap where K: DynSend, V: DynSend, A: std::alloc::Allocator + Clone + DynSend] + [Vec where T: DynSend, A: std::alloc::Allocator + DynSend] + [Box where T: ?Sized + DynSend, A: std::alloc::Allocator + DynSend] + [crate::sync::RwLock where T: DynSend] + [crate::tagged_ptr::CopyTaggedPtr where P: Send + crate::tagged_ptr::Pointer, T: Send + crate::tagged_ptr::Tag, const CP: bool] + [rustc_arena::TypedArena where T: DynSend] + [indexmap::IndexSet where V: DynSend, S: DynSend] + [indexmap::IndexMap where K: DynSend, V: DynSend, S: DynSend] + [thin_vec::ThinVec where T: DynSend] + [smallvec::SmallVec where A: smallvec::Array + DynSend] +); + +macro_rules! impls_dyn_sync_neg { + ($([$t1: ty $(where $($generics1: tt)*)?])*) => { + $(impl$(<$($generics1)*>)? !DynSync for $t1 {})* + }; +} + +// Consistent with `std` +impls_dyn_sync_neg!( + [std::env::Args] + [std::env::ArgsOs] + [*const T where T: ?Sized] + [*mut T where T: ?Sized] + [std::cell::Cell where T: ?Sized] + [std::cell::RefCell where T: ?Sized] + [std::cell::UnsafeCell where T: ?Sized] + [std::ptr::NonNull where T: ?Sized] + [std::rc::Rc where T: ?Sized] + [std::rc::Weak where T: ?Sized] + [std::cell::OnceCell where T] + [std::sync::mpsc::Receiver where T] + [std::sync::mpsc::Sender where T] +); + +#[cfg(any(unix, target_os = "hermit", target_os = "wasi", target_os = "solid_asp3"))] +// Consistent with `std`, `os_imp::Env` is `!Sync` in these platforms +impl !DynSync for std::env::VarsOs {} + +macro_rules! already_sync { + ($([$ty: ty])*) => { + $(unsafe impl DynSync for $ty where $ty: Sync {})* + }; +} + +// These structures are already `Sync`. +already_sync!( + [std::sync::atomic::AtomicBool][std::sync::atomic::AtomicUsize][std::sync::atomic::AtomicU8] + [std::sync::atomic::AtomicU32][std::backtrace::Backtrace][std::io::Error][std::fs::File] + [jobserver_crate::Client][crate::memmap::Mmap][crate::profiling::SelfProfiler] + [crate::owned_slice::OwnedSlice] +); + +// Use portable AtomicU64 for targets without native 64-bit atomics +#[cfg(target_has_atomic = "64")] +already_sync!([std::sync::atomic::AtomicU64]); + +#[cfg(not(target_has_atomic = "64"))] +already_sync!([portable_atomic::AtomicU64]); + +macro_rules! impl_dyn_sync { + ($($($attr: meta)* [$ty: ty where $($generics2: tt)*])*) => { + $(unsafe impl<$($generics2)*> DynSync for $ty {})* + }; +} + +impl_dyn_sync!( + [std::sync::atomic::AtomicPtr where T] + [std::sync::OnceLock where T: DynSend + DynSync] + [std::sync::Mutex where T: ?Sized + DynSend] + [std::sync::Arc where T: ?Sized + DynSync + DynSend] + [std::sync::LazyLock where T: DynSend + DynSync, F: DynSend] + [std::collections::HashSet where K: DynSync, S: DynSync] + [std::collections::HashMap where K: DynSync, V: DynSync, S: DynSync] + [std::collections::BTreeMap where K: DynSync, V: DynSync, A: std::alloc::Allocator + Clone + DynSync] + [Vec where T: DynSync, A: std::alloc::Allocator + DynSync] + [Box where T: ?Sized + DynSync, A: std::alloc::Allocator + DynSync] + [crate::sync::RwLock where T: DynSend + DynSync] + [crate::sync::WorkerLocal where T: DynSend] + [crate::intern::Interned<'a, T> where 'a, T: DynSync] + [crate::tagged_ptr::CopyTaggedPtr where P: Sync + crate::tagged_ptr::Pointer, T: Sync + crate::tagged_ptr::Tag, const CP: bool] + [parking_lot::lock_api::Mutex where R: DynSync, T: ?Sized + DynSend] + [parking_lot::lock_api::RwLock where R: DynSync, T: ?Sized + DynSend + DynSync] + [indexmap::IndexSet where V: DynSync, S: DynSync] + [indexmap::IndexMap where K: DynSync, V: DynSync, S: DynSync] + [smallvec::SmallVec where A: smallvec::Array + DynSync] + [thin_vec::ThinVec where T: DynSync] +); + pub fn assert_dyn_sync() {} pub fn assert_dyn_send() {} pub fn assert_dyn_send_val(_t: &T) {} @@ -203,7 +171,6 @@ impl FromDyn { // Check that `sync::is_dyn_thread_safe()` is true on creation so we can // implement `Send` and `Sync` for this structure when `T` // implements `DynSend` and `DynSync` respectively. - #[cfg(parallel_compiler)] assert!(crate::sync::is_dyn_thread_safe()); FromDyn(val) } @@ -215,11 +182,9 @@ impl FromDyn { } // `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true. -#[cfg(parallel_compiler)] unsafe impl Send for FromDyn {} // `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true. -#[cfg(parallel_compiler)] unsafe impl Sync for FromDyn {} impl std::ops::Deref for FromDyn { @@ -237,9 +202,7 @@ impl std::ops::Deref for FromDyn { #[derive(Copy, Clone)] pub struct IntoDynSyncSend(pub T); -#[cfg(parallel_compiler)] unsafe impl DynSend for IntoDynSyncSend {} -#[cfg(parallel_compiler)] unsafe impl DynSync for IntoDynSyncSend {} impl std::ops::Deref for IntoDynSyncSend { diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs index bbe6691e548d..c8be0ab52e9d 100644 --- a/compiler/rustc_data_structures/src/owned_slice.rs +++ b/compiler/rustc_data_structures/src/owned_slice.rs @@ -139,11 +139,9 @@ impl Borrow<[u8]> for OwnedSlice { } // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc)`, which is `Send` -#[cfg(parallel_compiler)] unsafe impl sync::Send for OwnedSlice {} // Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc)`, which is `Sync` -#[cfg(parallel_compiler)] unsafe impl sync::Sync for OwnedSlice {} #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index d0b6fe2bc6fd..65488c73d3cd 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -3,27 +3,22 @@ use std::collections::hash_map::RawEntryMut; use std::hash::{Hash, Hasher}; use std::{iter, mem}; -#[cfg(parallel_compiler)] use either::Either; use crate::fx::{FxHashMap, FxHasher}; -#[cfg(parallel_compiler)] -use crate::sync::{CacheAligned, is_dyn_thread_safe}; -use crate::sync::{Lock, LockGuard, Mode}; +use crate::sync::{CacheAligned, Lock, LockGuard, Mode, is_dyn_thread_safe}; // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, // but this should be tested on higher core count CPUs. How the `Sharded` type gets used // may also affect the ideal number of shards. const SHARD_BITS: usize = 5; -#[cfg(parallel_compiler)] const SHARDS: usize = 1 << SHARD_BITS; /// An array of cache-line aligned inner locked structures with convenience methods. /// A single field is used when the compiler uses only one thread. pub enum Sharded { Single(Lock), - #[cfg(parallel_compiler)] Shards(Box<[CacheAligned>; SHARDS]>), } @@ -37,7 +32,6 @@ impl Default for Sharded { impl Sharded { #[inline] pub fn new(mut value: impl FnMut() -> T) -> Self { - #[cfg(parallel_compiler)] if is_dyn_thread_safe() { return Sharded::Shards(Box::new( [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))), @@ -52,7 +46,6 @@ impl Sharded { pub fn get_shard_by_value(&self, _val: &K) -> &Lock { match self { Self::Single(single) => single, - #[cfg(parallel_compiler)] Self::Shards(..) => self.get_shard_by_hash(make_hash(_val)), } } @@ -66,7 +59,6 @@ impl Sharded { pub fn get_shard_by_index(&self, _i: usize) -> &Lock { match self { Self::Single(single) => single, - #[cfg(parallel_compiler)] Self::Shards(shards) => { // SAFETY: The index gets ANDed with the shard mask, ensuring it is always inbounds. unsafe { &shards.get_unchecked(_i & (SHARDS - 1)).0 } @@ -87,7 +79,6 @@ impl Sharded { // `might_be_dyn_thread_safe` was also false. unsafe { single.lock_assume(Mode::NoSync) } } - #[cfg(parallel_compiler)] Self::Shards(..) => self.lock_shard_by_hash(make_hash(_val)), } } @@ -110,7 +101,6 @@ impl Sharded { // `might_be_dyn_thread_safe` was also false. unsafe { single.lock_assume(Mode::NoSync) } } - #[cfg(parallel_compiler)] Self::Shards(shards) => { // Synchronization is enabled so use the `lock_assume_sync` method optimized // for that case. @@ -127,11 +117,7 @@ impl Sharded { #[inline] pub fn lock_shards(&self) -> impl Iterator> { match self { - #[cfg(not(parallel_compiler))] - Self::Single(single) => iter::once(single.lock()), - #[cfg(parallel_compiler)] Self::Single(single) => Either::Left(iter::once(single.lock())), - #[cfg(parallel_compiler)] Self::Shards(shards) => Either::Right(shards.iter().map(|shard| shard.0.lock())), } } @@ -139,11 +125,7 @@ impl Sharded { #[inline] pub fn try_lock_shards(&self) -> impl Iterator>> { match self { - #[cfg(not(parallel_compiler))] - Self::Single(single) => iter::once(single.try_lock()), - #[cfg(parallel_compiler)] Self::Single(single) => Either::Left(iter::once(single.try_lock())), - #[cfg(parallel_compiler)] Self::Shards(shards) => Either::Right(shards.iter().map(|shard| shard.0.try_lock())), } } @@ -151,7 +133,6 @@ impl Sharded { #[inline] pub fn shards() -> usize { - #[cfg(parallel_compiler)] if is_dyn_thread_safe() { return SHARDS; } diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index a3491dbfec7d..7a9533031f4b 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -54,9 +54,7 @@ mod worker_local; pub use worker_local::{Registry, WorkerLocal}; mod parallel; -#[cfg(parallel_compiler)] -pub use parallel::scope; -pub use parallel::{join, par_for_each_in, par_map, parallel_guard, try_par_for_each_in}; +pub use parallel::{join, par_for_each_in, par_map, parallel_guard, scope, try_par_for_each_in}; pub use vec::{AppendOnlyIndexVec, AppendOnlyVec}; mod vec; @@ -104,226 +102,66 @@ mod mode { } } +// FIXME(parallel_compiler): Get rid of these aliases across the compiler. + +pub use std::marker::{Send, Sync}; +// Use portable AtomicU64 for targets without native 64-bit atomics +#[cfg(target_has_atomic = "64")] +pub use std::sync::atomic::AtomicU64; +pub use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize}; +pub use std::sync::{Arc as Lrc, OnceLock, Weak}; + pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode}; +pub use parking_lot::{ + MappedMutexGuard as MappedLockGuard, MappedRwLockReadGuard as MappedReadGuard, + MappedRwLockWriteGuard as MappedWriteGuard, RwLockReadGuard as ReadGuard, + RwLockWriteGuard as WriteGuard, +}; +#[cfg(not(target_has_atomic = "64"))] +pub use portable_atomic::AtomicU64; -cfg_match! { - cfg(not(parallel_compiler)) => { - use std::ops::Add; - use std::cell::Cell; - use std::sync::atomic::Ordering; +pub type LRef<'a, T> = &'a T; - pub unsafe auto trait Send {} - pub unsafe auto trait Sync {} +#[derive(Debug, Default)] +pub struct MTLock(Lock); - unsafe impl Send for T {} - unsafe impl Sync for T {} - - /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc. - /// It has explicit ordering arguments and is only intended for use with - /// the native atomic types. - /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases - /// as it's not intended to be used separately. - #[derive(Debug, Default)] - pub struct Atomic(Cell); - - impl Atomic { - #[inline] - pub fn new(v: T) -> Self { - Atomic(Cell::new(v)) - } - - #[inline] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline] - pub fn load(&self, _: Ordering) -> T { - self.0.get() - } - - #[inline] - pub fn store(&self, val: T, _: Ordering) { - self.0.set(val) - } - - #[inline] - pub fn swap(&self, val: T, _: Ordering) -> T { - self.0.replace(val) - } - } - - impl Atomic { - pub fn fetch_or(&self, val: bool, _: Ordering) -> bool { - let old = self.0.get(); - self.0.set(val | old); - old - } - pub fn fetch_and(&self, val: bool, _: Ordering) -> bool { - let old = self.0.get(); - self.0.set(val & old); - old - } - } - - impl Atomic { - #[inline] - pub fn compare_exchange(&self, - current: T, - new: T, - _: Ordering, - _: Ordering) - -> Result { - let read = self.0.get(); - if read == current { - self.0.set(new); - Ok(read) - } else { - Err(read) - } - } - } - - impl + Copy> Atomic { - #[inline] - pub fn fetch_add(&self, val: T, _: Ordering) -> T { - let old = self.0.get(); - self.0.set(old + val); - old - } - } - - pub type AtomicUsize = Atomic; - pub type AtomicBool = Atomic; - pub type AtomicU32 = Atomic; - pub type AtomicU64 = Atomic; - - pub use std::rc::Rc as Lrc; - pub use std::rc::Weak as Weak; - #[doc(no_inline)] - pub use std::cell::Ref as ReadGuard; - #[doc(no_inline)] - pub use std::cell::Ref as MappedReadGuard; - #[doc(no_inline)] - pub use std::cell::RefMut as WriteGuard; - #[doc(no_inline)] - pub use std::cell::RefMut as MappedWriteGuard; - #[doc(no_inline)] - pub use std::cell::RefMut as MappedLockGuard; - - pub use std::cell::OnceCell as OnceLock; - - use std::cell::RefCell as InnerRwLock; - - pub type LRef<'a, T> = &'a mut T; - - #[derive(Debug, Default)] - pub struct MTLock(T); - - impl MTLock { - #[inline(always)] - pub fn new(inner: T) -> Self { - MTLock(inner) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0 - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - &mut self.0 - } - - #[inline(always)] - pub fn lock(&self) -> &T { - &self.0 - } - - #[inline(always)] - pub fn lock_mut(&mut self) -> &mut T { - &mut self.0 - } - } - - // FIXME: Probably a bad idea (in the threaded case) - impl Clone for MTLock { - #[inline] - fn clone(&self) -> Self { - MTLock(self.0.clone()) - } - } +impl MTLock { + #[inline(always)] + pub fn new(inner: T) -> Self { + MTLock(Lock::new(inner)) } - _ => { - pub use std::marker::Send as Send; - pub use std::marker::Sync as Sync; - pub use parking_lot::RwLockReadGuard as ReadGuard; - pub use parking_lot::MappedRwLockReadGuard as MappedReadGuard; - pub use parking_lot::RwLockWriteGuard as WriteGuard; - pub use parking_lot::MappedRwLockWriteGuard as MappedWriteGuard; + #[inline(always)] + pub fn into_inner(self) -> T { + self.0.into_inner() + } - pub use parking_lot::MappedMutexGuard as MappedLockGuard; + #[inline(always)] + pub fn get_mut(&mut self) -> &mut T { + self.0.get_mut() + } - pub use std::sync::OnceLock; + #[inline(always)] + pub fn lock(&self) -> LockGuard<'_, T> { + self.0.lock() + } - pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32}; - - // Use portable AtomicU64 for targets without native 64-bit atomics - #[cfg(target_has_atomic = "64")] - pub use std::sync::atomic::AtomicU64; - - #[cfg(not(target_has_atomic = "64"))] - pub use portable_atomic::AtomicU64; - - pub use std::sync::Arc as Lrc; - pub use std::sync::Weak as Weak; - - pub type LRef<'a, T> = &'a T; - - #[derive(Debug, Default)] - pub struct MTLock(Lock); - - impl MTLock { - #[inline(always)] - pub fn new(inner: T) -> Self { - MTLock(Lock::new(inner)) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.0.get_mut() - } - - #[inline(always)] - pub fn lock(&self) -> LockGuard<'_, T> { - self.0.lock() - } - - #[inline(always)] - pub fn lock_mut(&self) -> LockGuard<'_, T> { - self.lock() - } - } - - use parking_lot::RwLock as InnerRwLock; - - /// This makes locks panic if they are already held. - /// It is only useful when you are running in a single thread - const ERROR_CHECKING: bool = false; + #[inline(always)] + pub fn lock_mut(&self) -> LockGuard<'_, T> { + self.lock() } } +use parking_lot::RwLock as InnerRwLock; + +/// This makes locks panic if they are already held. +/// It is only useful when you are running in a single thread +const ERROR_CHECKING: bool = false; + pub type MTLockRef<'a, T> = LRef<'a, MTLock>; #[derive(Default)] -#[cfg_attr(parallel_compiler, repr(align(64)))] +#[repr(align(64))] pub struct CacheAligned(pub T); pub trait HashMapExt { @@ -357,14 +195,6 @@ impl RwLock { self.0.get_mut() } - #[cfg(not(parallel_compiler))] - #[inline(always)] - #[track_caller] - pub fn read(&self) -> ReadGuard<'_, T> { - self.0.borrow() - } - - #[cfg(parallel_compiler)] #[inline(always)] pub fn read(&self) -> ReadGuard<'_, T> { if ERROR_CHECKING { @@ -380,26 +210,11 @@ impl RwLock { f(&*self.read()) } - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn try_write(&self) -> Result, ()> { - self.0.try_borrow_mut().map_err(|_| ()) - } - - #[cfg(parallel_compiler)] #[inline(always)] pub fn try_write(&self) -> Result, ()> { self.0.try_write().ok_or(()) } - #[cfg(not(parallel_compiler))] - #[inline(always)] - #[track_caller] - pub fn write(&self) -> WriteGuard<'_, T> { - self.0.borrow_mut() - } - - #[cfg(parallel_compiler)] #[inline(always)] pub fn write(&self) -> WriteGuard<'_, T> { if ERROR_CHECKING { @@ -427,13 +242,6 @@ impl RwLock { self.write() } - #[cfg(not(parallel_compiler))] - #[inline(always)] - pub fn leak(&self) -> &T { - ReadGuard::leak(self.read()) - } - - #[cfg(parallel_compiler)] #[inline(always)] pub fn leak(&self) -> &T { let guard = self.read(); diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs index fad5f583d1ce..5236c9fe1567 100644 --- a/compiler/rustc_data_structures/src/sync/freeze.rs +++ b/compiler/rustc_data_structures/src/sync/freeze.rs @@ -5,9 +5,7 @@ use std::ops::{Deref, DerefMut}; use std::ptr::NonNull; use std::sync::atomic::Ordering; -use crate::sync::{AtomicBool, ReadGuard, RwLock, WriteGuard}; -#[cfg(parallel_compiler)] -use crate::sync::{DynSend, DynSync}; +use crate::sync::{AtomicBool, DynSend, DynSync, ReadGuard, RwLock, WriteGuard}; /// A type which allows mutation using a lock until /// the value is frozen and can be accessed lock-free. @@ -22,7 +20,6 @@ pub struct FreezeLock { lock: RwLock<()>, } -#[cfg(parallel_compiler)] unsafe impl DynSync for FreezeLock {} impl FreezeLock { diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index 012ee7f900ea..2ccf06ccd4f0 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -1,236 +1,177 @@ //! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true. //! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits. -//! -//! When `cfg(parallel_compiler)` is not set, the lock is instead a wrapper around `RefCell`. #![allow(dead_code)] use std::fmt; -#[cfg(parallel_compiler)] -pub use maybe_sync::*; -#[cfg(not(parallel_compiler))] -pub use no_sync::*; - #[derive(Clone, Copy, PartialEq)] pub enum Mode { NoSync, Sync, } -mod maybe_sync { - use std::cell::{Cell, UnsafeCell}; - use std::intrinsics::unlikely; - use std::marker::PhantomData; - use std::mem::ManuallyDrop; - use std::ops::{Deref, DerefMut}; +use std::cell::{Cell, UnsafeCell}; +use std::intrinsics::unlikely; +use std::marker::PhantomData; +use std::mem::ManuallyDrop; +use std::ops::{Deref, DerefMut}; - use parking_lot::RawMutex; - use parking_lot::lock_api::RawMutex as _; +use parking_lot::RawMutex; +use parking_lot::lock_api::RawMutex as _; - use super::Mode; - use crate::sync::mode; - #[cfg(parallel_compiler)] - use crate::sync::{DynSend, DynSync}; +use crate::sync::{DynSend, DynSync, mode}; - /// A guard holding mutable access to a `Lock` which is in a locked state. - #[must_use = "if unused the Lock will immediately unlock"] - pub struct LockGuard<'a, T> { - lock: &'a Lock, - marker: PhantomData<&'a mut T>, +/// A guard holding mutable access to a `Lock` which is in a locked state. +#[must_use = "if unused the Lock will immediately unlock"] +pub struct LockGuard<'a, T> { + lock: &'a Lock, + marker: PhantomData<&'a mut T>, - /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it - /// to the original lock operation. - mode: Mode, + /// The synchronization mode of the lock. This is explicitly passed to let LLVM relate it + /// to the original lock operation. + mode: Mode, +} + +impl<'a, T: 'a> Deref for LockGuard<'a, T> { + type Target = T; + #[inline] + fn deref(&self) -> &T { + // SAFETY: We have shared access to the mutable access owned by this type, + // so we can give out a shared reference. + unsafe { &*self.lock.data.get() } } +} - impl<'a, T: 'a> Deref for LockGuard<'a, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - // SAFETY: We have shared access to the mutable access owned by this type, - // so we can give out a shared reference. - unsafe { &*self.lock.data.get() } - } +impl<'a, T: 'a> DerefMut for LockGuard<'a, T> { + #[inline] + fn deref_mut(&mut self) -> &mut T { + // SAFETY: We have mutable access to the data so we can give out a mutable reference. + unsafe { &mut *self.lock.data.get() } } +} - impl<'a, T: 'a> DerefMut for LockGuard<'a, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - // SAFETY: We have mutable access to the data so we can give out a mutable reference. - unsafe { &mut *self.lock.data.get() } - } - } - - impl<'a, T: 'a> Drop for LockGuard<'a, T> { - #[inline] - fn drop(&mut self) { - // SAFETY (union access): We get `self.mode` from the lock operation so it is consistent - // with the `lock.mode` state. This means we access the right union fields. - match self.mode { - Mode::NoSync => { - let cell = unsafe { &self.lock.mode_union.no_sync }; - debug_assert!(cell.get()); - cell.set(false); - } - // SAFETY (unlock): We know that the lock is locked as this type is a proof of that. - Mode::Sync => unsafe { self.lock.mode_union.sync.unlock() }, +impl<'a, T: 'a> Drop for LockGuard<'a, T> { + #[inline] + fn drop(&mut self) { + // SAFETY (union access): We get `self.mode` from the lock operation so it is consistent + // with the `lock.mode` state. This means we access the right union fields. + match self.mode { + Mode::NoSync => { + let cell = unsafe { &self.lock.mode_union.no_sync }; + debug_assert!(cell.get()); + cell.set(false); } + // SAFETY (unlock): We know that the lock is locked as this type is a proof of that. + Mode::Sync => unsafe { self.lock.mode_union.sync.unlock() }, } } +} - union ModeUnion { - /// Indicates if the cell is locked. Only used if `Lock.mode` is `NoSync`. - no_sync: ManuallyDrop>, +union ModeUnion { + /// Indicates if the cell is locked. Only used if `Lock.mode` is `NoSync`. + no_sync: ManuallyDrop>, - /// A lock implementation that's only used if `Lock.mode` is `Sync`. - sync: ManuallyDrop, + /// A lock implementation that's only used if `Lock.mode` is `Sync`. + sync: ManuallyDrop, +} + +/// The value representing a locked state for the `Cell`. +const LOCKED: bool = true; + +/// A lock which only uses synchronization if `might_be_dyn_thread_safe` is true. +/// It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync`. +pub struct Lock { + /// Indicates if synchronization is used via `mode_union.sync` if it's `Sync`, or if a + /// not thread safe cell is used via `mode_union.no_sync` if it's `NoSync`. + /// This is set on initialization and never changed. + mode: Mode, + + mode_union: ModeUnion, + data: UnsafeCell, +} + +impl Lock { + #[inline(always)] + pub fn new(inner: T) -> Self { + let (mode, mode_union) = if unlikely(mode::might_be_dyn_thread_safe()) { + // Create the lock with synchronization enabled using the `RawMutex` type. + (Mode::Sync, ModeUnion { sync: ManuallyDrop::new(RawMutex::INIT) }) + } else { + // Create the lock with synchronization disabled. + (Mode::NoSync, ModeUnion { no_sync: ManuallyDrop::new(Cell::new(!LOCKED)) }) + }; + Lock { mode, mode_union, data: UnsafeCell::new(inner) } } - /// The value representing a locked state for the `Cell`. - const LOCKED: bool = true; - - /// A lock which only uses synchronization if `might_be_dyn_thread_safe` is true. - /// It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync`. - pub struct Lock { - /// Indicates if synchronization is used via `mode_union.sync` if it's `Sync`, or if a - /// not thread safe cell is used via `mode_union.no_sync` if it's `NoSync`. - /// This is set on initialization and never changed. - mode: Mode, - - mode_union: ModeUnion, - data: UnsafeCell, + #[inline(always)] + pub fn into_inner(self) -> T { + self.data.into_inner() } - impl Lock { - #[inline(always)] - pub fn new(inner: T) -> Self { - let (mode, mode_union) = if unlikely(mode::might_be_dyn_thread_safe()) { - // Create the lock with synchronization enabled using the `RawMutex` type. - (Mode::Sync, ModeUnion { sync: ManuallyDrop::new(RawMutex::INIT) }) - } else { - // Create the lock with synchronization disabled. - (Mode::NoSync, ModeUnion { no_sync: ManuallyDrop::new(Cell::new(!LOCKED)) }) - }; - Lock { mode, mode_union, data: UnsafeCell::new(inner) } + #[inline(always)] + pub fn get_mut(&mut self) -> &mut T { + self.data.get_mut() + } + + #[inline(always)] + pub fn try_lock(&self) -> Option> { + let mode = self.mode; + // SAFETY: This is safe since the union fields are used in accordance with `self.mode`. + match mode { + Mode::NoSync => { + let cell = unsafe { &self.mode_union.no_sync }; + let was_unlocked = cell.get() != LOCKED; + if was_unlocked { + cell.set(LOCKED); + } + was_unlocked + } + Mode::Sync => unsafe { self.mode_union.sync.try_lock() }, + } + .then(|| LockGuard { lock: self, marker: PhantomData, mode }) + } + + /// This acquires the lock assuming synchronization is in a specific mode. + /// + /// Safety + /// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was + /// true on lock creation. + #[inline(always)] + #[track_caller] + pub unsafe fn lock_assume(&self, mode: Mode) -> LockGuard<'_, T> { + #[inline(never)] + #[track_caller] + #[cold] + fn lock_held() -> ! { + panic!("lock was already held") } - #[inline(always)] - pub fn into_inner(self) -> T { - self.data.into_inner() - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.data.get_mut() - } - - #[inline(always)] - pub fn try_lock(&self) -> Option> { - let mode = self.mode; - // SAFETY: This is safe since the union fields are used in accordance with `self.mode`. + // SAFETY: This is safe since the union fields are used in accordance with `mode` + // which also must match `self.mode` due to the safety precondition. + unsafe { match mode { Mode::NoSync => { - let cell = unsafe { &self.mode_union.no_sync }; - let was_unlocked = cell.get() != LOCKED; - if was_unlocked { - cell.set(LOCKED); + if unlikely(self.mode_union.no_sync.replace(LOCKED) == LOCKED) { + lock_held() } - was_unlocked } - Mode::Sync => unsafe { self.mode_union.sync.try_lock() }, + Mode::Sync => self.mode_union.sync.lock(), } - .then(|| LockGuard { lock: self, marker: PhantomData, mode }) - } - - /// This acquires the lock assuming synchronization is in a specific mode. - /// - /// Safety - /// This method must only be called with `Mode::Sync` if `might_be_dyn_thread_safe` was - /// true on lock creation. - #[inline(always)] - #[track_caller] - pub unsafe fn lock_assume(&self, mode: Mode) -> LockGuard<'_, T> { - #[inline(never)] - #[track_caller] - #[cold] - fn lock_held() -> ! { - panic!("lock was already held") - } - - // SAFETY: This is safe since the union fields are used in accordance with `mode` - // which also must match `self.mode` due to the safety precondition. - unsafe { - match mode { - Mode::NoSync => { - if unlikely(self.mode_union.no_sync.replace(LOCKED) == LOCKED) { - lock_held() - } - } - Mode::Sync => self.mode_union.sync.lock(), - } - } - LockGuard { lock: self, marker: PhantomData, mode } - } - - #[inline(always)] - #[track_caller] - pub fn lock(&self) -> LockGuard<'_, T> { - unsafe { self.lock_assume(self.mode) } } + LockGuard { lock: self, marker: PhantomData, mode } } - #[cfg(parallel_compiler)] - unsafe impl DynSend for Lock {} - #[cfg(parallel_compiler)] - unsafe impl DynSync for Lock {} -} - -mod no_sync { - use std::cell::RefCell; - #[doc(no_inline)] - pub use std::cell::RefMut as LockGuard; - - use super::Mode; - - pub struct Lock(RefCell); - - impl Lock { - #[inline(always)] - pub fn new(inner: T) -> Self { - Lock(RefCell::new(inner)) - } - - #[inline(always)] - pub fn into_inner(self) -> T { - self.0.into_inner() - } - - #[inline(always)] - pub fn get_mut(&mut self) -> &mut T { - self.0.get_mut() - } - - #[inline(always)] - pub fn try_lock(&self) -> Option> { - self.0.try_borrow_mut().ok() - } - - #[inline(always)] - #[track_caller] - // This is unsafe to match the API for the `parallel_compiler` case. - pub unsafe fn lock_assume(&self, _mode: Mode) -> LockGuard<'_, T> { - self.0.borrow_mut() - } - - #[inline(always)] - #[track_caller] - pub fn lock(&self) -> LockGuard<'_, T> { - self.0.borrow_mut() - } + #[inline(always)] + #[track_caller] + pub fn lock(&self) -> LockGuard<'_, T> { + unsafe { self.lock_assume(self.mode) } } } +unsafe impl DynSend for Lock {} +unsafe impl DynSync for Lock {} + impl Lock { #[inline(always)] #[track_caller] diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index c7df19842d6d..1ba631b86237 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -6,14 +6,11 @@ use std::any::Any; use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; -#[cfg(not(parallel_compiler))] -pub use disabled::*; -#[cfg(parallel_compiler)] -pub use enabled::*; use parking_lot::Mutex; +use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator}; use crate::FatalErrorMarker; -use crate::sync::IntoDynSyncSend; +use crate::sync::{DynSend, DynSync, FromDyn, IntoDynSyncSend, mode}; /// A guard used to hold panics that occur during a parallel section to later by unwound. /// This is used for the parallel compiler to prevent fatal errors from non-deterministically @@ -49,65 +46,23 @@ pub fn parallel_guard(f: impl FnOnce(&ParallelGuard) -> R) -> R { ret } -mod disabled { - use crate::sync::parallel_guard; - - #[macro_export] - #[cfg(not(parallel_compiler))] - macro_rules! parallel { - ($($blocks:block),*) => {{ - $crate::sync::parallel_guard(|guard| { - $(guard.run(|| $blocks);)* - }); - }} - } - - pub fn join(oper_a: A, oper_b: B) -> (RA, RB) - where - A: FnOnce() -> RA, - B: FnOnce() -> RB, - { - let (a, b) = parallel_guard(|guard| { - let a = guard.run(oper_a); - let b = guard.run(oper_b); - (a, b) - }); - (a.unwrap(), b.unwrap()) - } - - pub fn par_for_each_in(t: T, mut for_each: impl FnMut(T::Item)) { - parallel_guard(|guard| { - t.into_iter().for_each(|i| { - guard.run(|| for_each(i)); - }); - }) - } - - pub fn try_par_for_each_in( - t: T, - mut for_each: impl FnMut(T::Item) -> Result<(), E>, - ) -> Result<(), E> { - parallel_guard(|guard| { - t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) - }) - } - - pub fn par_map>( - t: T, - mut map: impl FnMut(<::IntoIter as Iterator>::Item) -> R, - ) -> C { - parallel_guard(|guard| t.into_iter().filter_map(|i| guard.run(|| map(i))).collect()) - } +pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) +where + A: FnOnce() -> RA, + B: FnOnce() -> RB, +{ + let (a, b) = parallel_guard(|guard| { + let a = guard.run(oper_a); + let b = guard.run(oper_b); + (a, b) + }); + (a.unwrap(), b.unwrap()) } -#[cfg(parallel_compiler)] -mod enabled { - use crate::sync::{DynSend, DynSync, FromDyn, mode, parallel_guard}; - - /// Runs a list of blocks in parallel. The first block is executed immediately on - /// the current thread. Use that for the longest running block. - #[macro_export] - macro_rules! parallel { +/// Runs a list of blocks in parallel. The first block is executed immediately on +/// the current thread. Use that for the longest running block. +#[macro_export] +macro_rules! parallel { (impl $fblock:block [$($c:expr,)*] [$block:expr $(, $rest:expr)*]) => { parallel!(impl $fblock [$block, $($c,)*] [$($rest),*]) }; @@ -139,92 +94,89 @@ mod enabled { }; } - // This function only works when `mode::is_dyn_thread_safe()`. - pub fn scope<'scope, OP, R>(op: OP) -> R - where - OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend, - R: DynSend, - { - let op = FromDyn::from(op); - rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() - } +// This function only works when `mode::is_dyn_thread_safe()`. +pub fn scope<'scope, OP, R>(op: OP) -> R +where + OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend, + R: DynSend, +{ + let op = FromDyn::from(op); + rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() +} - #[inline] - pub fn join(oper_a: A, oper_b: B) -> (RA, RB) - where - A: FnOnce() -> RA + DynSend, - B: FnOnce() -> RB + DynSend, - { - if mode::is_dyn_thread_safe() { - let oper_a = FromDyn::from(oper_a); - let oper_b = FromDyn::from(oper_b); - let (a, b) = parallel_guard(|guard| { - rayon::join( - move || guard.run(move || FromDyn::from(oper_a.into_inner()())), - move || guard.run(move || FromDyn::from(oper_b.into_inner()())), - ) - }); - (a.unwrap().into_inner(), b.unwrap().into_inner()) - } else { - super::disabled::join(oper_a, oper_b) - } - } - - use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator}; - - pub fn par_for_each_in + IntoParallelIterator>( - t: T, - for_each: impl Fn(I) + DynSync + DynSend, - ) { - parallel_guard(|guard| { - if mode::is_dyn_thread_safe() { - let for_each = FromDyn::from(for_each); - t.into_par_iter().for_each(|i| { - guard.run(|| for_each(i)); - }); - } else { - t.into_iter().for_each(|i| { - guard.run(|| for_each(i)); - }); - } +#[inline] +pub fn join(oper_a: A, oper_b: B) -> (RA, RB) +where + A: FnOnce() -> RA + DynSend, + B: FnOnce() -> RB + DynSend, +{ + if mode::is_dyn_thread_safe() { + let oper_a = FromDyn::from(oper_a); + let oper_b = FromDyn::from(oper_b); + let (a, b) = parallel_guard(|guard| { + rayon::join( + move || guard.run(move || FromDyn::from(oper_a.into_inner()())), + move || guard.run(move || FromDyn::from(oper_b.into_inner()())), + ) }); - } - - pub fn try_par_for_each_in< - T: IntoIterator + IntoParallelIterator::Item>, - E: Send, - >( - t: T, - for_each: impl Fn(::Item) -> Result<(), E> + DynSync + DynSend, - ) -> Result<(), E> { - parallel_guard(|guard| { - if mode::is_dyn_thread_safe() { - let for_each = FromDyn::from(for_each); - t.into_par_iter() - .filter_map(|i| guard.run(|| for_each(i))) - .reduce(|| Ok(()), Result::and) - } else { - t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) - } - }) - } - - pub fn par_map< - I, - T: IntoIterator + IntoParallelIterator, - R: std::marker::Send, - C: FromIterator + FromParallelIterator, - >( - t: T, - map: impl Fn(I) -> R + DynSync + DynSend, - ) -> C { - parallel_guard(|guard| { - if mode::is_dyn_thread_safe() { - let map = FromDyn::from(map); - t.into_par_iter().filter_map(|i| guard.run(|| map(i))).collect() - } else { - t.into_iter().filter_map(|i| guard.run(|| map(i))).collect() - } - }) + (a.unwrap().into_inner(), b.unwrap().into_inner()) + } else { + serial_join(oper_a, oper_b) } } + +pub fn par_for_each_in + IntoParallelIterator>( + t: T, + for_each: impl Fn(I) + DynSync + DynSend, +) { + parallel_guard(|guard| { + if mode::is_dyn_thread_safe() { + let for_each = FromDyn::from(for_each); + t.into_par_iter().for_each(|i| { + guard.run(|| for_each(i)); + }); + } else { + t.into_iter().for_each(|i| { + guard.run(|| for_each(i)); + }); + } + }); +} + +pub fn try_par_for_each_in< + T: IntoIterator + IntoParallelIterator::Item>, + E: Send, +>( + t: T, + for_each: impl Fn(::Item) -> Result<(), E> + DynSync + DynSend, +) -> Result<(), E> { + parallel_guard(|guard| { + if mode::is_dyn_thread_safe() { + let for_each = FromDyn::from(for_each); + t.into_par_iter() + .filter_map(|i| guard.run(|| for_each(i))) + .reduce(|| Ok(()), Result::and) + } else { + t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) + } + }) +} + +pub fn par_map< + I, + T: IntoIterator + IntoParallelIterator, + R: std::marker::Send, + C: FromIterator + FromParallelIterator, +>( + t: T, + map: impl Fn(I) -> R + DynSync + DynSend, +) -> C { + parallel_guard(|guard| { + if mode::is_dyn_thread_safe() { + let map = FromDyn::from(map); + t.into_par_iter().filter_map(|i| guard.run(|| map(i))).collect() + } else { + t.into_iter().filter_map(|i| guard.run(|| map(i))).collect() + } + }) +} diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index 314496ce9f09..21ec5cf6c13b 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -4,40 +4,23 @@ use rustc_index::Idx; #[derive(Default)] pub struct AppendOnlyIndexVec { - #[cfg(not(parallel_compiler))] - vec: elsa::vec::FrozenVec, - #[cfg(parallel_compiler)] vec: elsa::sync::LockFreeFrozenVec, _marker: PhantomData, } impl AppendOnlyIndexVec { pub fn new() -> Self { - Self { - #[cfg(not(parallel_compiler))] - vec: elsa::vec::FrozenVec::new(), - #[cfg(parallel_compiler)] - vec: elsa::sync::LockFreeFrozenVec::new(), - _marker: PhantomData, - } + Self { vec: elsa::sync::LockFreeFrozenVec::new(), _marker: PhantomData } } pub fn push(&self, val: T) -> I { - #[cfg(not(parallel_compiler))] - let i = self.vec.len(); - #[cfg(not(parallel_compiler))] - self.vec.push(val); - #[cfg(parallel_compiler)] let i = self.vec.push(val); I::new(i) } pub fn get(&self, i: I) -> Option { let i = i.index(); - #[cfg(not(parallel_compiler))] - return self.vec.get_copy(i); - #[cfg(parallel_compiler)] - return self.vec.get(i); + self.vec.get(i) } } diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index b6efcada10b7..d75af0098504 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -5,8 +5,9 @@ use std::ptr; use std::sync::Arc; use parking_lot::Mutex; -#[cfg(parallel_compiler)] -use {crate::outline, crate::sync::CacheAligned}; + +use crate::outline; +use crate::sync::CacheAligned; /// A pointer to the `RegistryData` which uniquely identifies a registry. /// This identifier can be reused if the registry gets freed. @@ -21,7 +22,6 @@ impl RegistryId { /// /// Note that there's a race possible where the identifier in `THREAD_DATA` could be reused /// so this can succeed from a different registry. - #[cfg(parallel_compiler)] fn verify(self) -> usize { let (id, index) = THREAD_DATA.with(|data| (data.registry_id.get(), data.index.get())); @@ -102,11 +102,7 @@ impl Registry { /// worker local value through the `Deref` impl on the registry associated with the thread it was /// created on. It will panic otherwise. pub struct WorkerLocal { - #[cfg(not(parallel_compiler))] - local: T, - #[cfg(parallel_compiler)] locals: Box<[CacheAligned]>, - #[cfg(parallel_compiler)] registry: Registry, } @@ -114,7 +110,6 @@ pub struct WorkerLocal { // or it will panic for threads without an associated local. So there isn't a need for `T` to do // it's own synchronization. The `verify` method on `RegistryId` has an issue where the id // can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse. -#[cfg(parallel_compiler)] unsafe impl Sync for WorkerLocal {} impl WorkerLocal { @@ -122,33 +117,17 @@ impl WorkerLocal { /// value this worker local should take for each thread in the registry. #[inline] pub fn new T>(mut initial: F) -> WorkerLocal { - #[cfg(parallel_compiler)] - { - let registry = Registry::current(); - WorkerLocal { - locals: (0..registry.0.thread_limit.get()) - .map(|i| CacheAligned(initial(i))) - .collect(), - registry, - } - } - #[cfg(not(parallel_compiler))] - { - WorkerLocal { local: initial(0) } + let registry = Registry::current(); + WorkerLocal { + locals: (0..registry.0.thread_limit.get()).map(|i| CacheAligned(initial(i))).collect(), + registry, } } /// Returns the worker-local values for each thread #[inline] pub fn into_inner(self) -> impl Iterator { - #[cfg(parallel_compiler)] - { - self.locals.into_vec().into_iter().map(|local| local.0) - } - #[cfg(not(parallel_compiler))] - { - std::iter::once(self.local) - } + self.locals.into_vec().into_iter().map(|local| local.0) } } @@ -156,13 +135,6 @@ impl Deref for WorkerLocal { type Target = T; #[inline(always)] - #[cfg(not(parallel_compiler))] - fn deref(&self) -> &T { - &self.local - } - - #[inline(always)] - #[cfg(parallel_compiler)] fn deref(&self) -> &T { // This is safe because `verify` will only return values less than // `self.registry.thread_limit` which is the size of the `self.locals` array. diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 74da0d11e4ba..81f15ebcbf80 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -77,9 +77,4 @@ rustc_randomized_layouts = [ 'rustc_index/rustc_randomized_layouts', 'rustc_middle/rustc_randomized_layouts' ] -rustc_use_parallel_compiler = [ - 'rustc_data_structures/rustc_use_parallel_compiler', - 'rustc_interface/rustc_use_parallel_compiler', - 'rustc_middle/rustc_use_parallel_compiler' -] # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 78ba841d89f4..b6f7abed6f3c 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -934,9 +934,12 @@ pub fn version_at_macro_invocation( } fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { - let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() }; let mut options = getopts::Options::new(); - for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) { + for option in config::rustc_optgroups() + .iter() + .filter(|x| verbose || !x.is_verbose_help_only) + .filter(|x| include_unstable_options || x.is_stable()) + { option.apply(&mut options); } let message = "Usage: rustc [OPTIONS] INPUT"; diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 5b6b8b3f183f..6974c12f994b 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -19,8 +19,3 @@ rustc_span = { path = "../rustc_span" } tracing = "0.1" unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end - -[features] -# tidy-alphabetical-start -rustc_use_parallel_compiler = ['rustc_baked_icu_data/rustc_use_parallel_compiler'] -# tidy-alphabetical-end diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 2ede7d805fa4..74b6d63365a5 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -8,12 +8,9 @@ // tidy-alphabetical-end use std::borrow::Cow; -#[cfg(not(parallel_compiler))] -use std::cell::LazyCell as Lazy; use std::error::Error; use std::path::{Path, PathBuf}; -#[cfg(parallel_compiler)] -use std::sync::LazyLock as Lazy; +use std::sync::LazyLock; use std::{fmt, fs, io}; use fluent_bundle::FluentResource; @@ -21,9 +18,6 @@ pub use fluent_bundle::types::FluentType; pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue}; use fluent_syntax::parser::ParserError; use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker}; -#[cfg(not(parallel_compiler))] -use intl_memoizer::IntlLangMemoizer; -#[cfg(parallel_compiler)] use intl_memoizer::concurrent::IntlLangMemoizer; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_macros::{Decodable, Encodable}; @@ -34,12 +28,6 @@ pub use unic_langid::{LanguageIdentifier, langid}; pub type FluentBundle = IntoDynSyncSend>; -#[cfg(not(parallel_compiler))] -fn new_bundle(locales: Vec) -> FluentBundle { - IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new(locales)) -} - -#[cfg(parallel_compiler)] fn new_bundle(locales: Vec) -> FluentBundle { IntoDynSyncSend(fluent_bundle::bundle::FluentBundle::new_concurrent(locales)) } @@ -217,7 +205,7 @@ fn register_functions(bundle: &mut FluentBundle) { /// Type alias for the result of `fallback_fluent_bundle` - a reference-counted pointer to a lazily /// evaluated fluent bundle. -pub type LazyFallbackBundle = Lrc FluentBundle>>; +pub type LazyFallbackBundle = Lrc FluentBundle>>; /// Return the default `FluentBundle` with standard "en-US" diagnostic messages. #[instrument(level = "trace", skip(resources))] @@ -225,7 +213,7 @@ pub fn fallback_fluent_bundle( resources: Vec<&'static str>, with_directionality_markers: bool, ) -> LazyFallbackBundle { - Lrc::new(Lazy::new(move || { + Lrc::new(LazyLock::new(move || { let mut fallback_bundle = new_bundle(vec![langid!("en-US")]); register_functions(&mut fallback_bundle); @@ -548,15 +536,6 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec>) -> FluentValu Cow::Owned(result) } - #[cfg(not(parallel_compiler))] - fn as_string_threadsafe( - &self, - _intls: &intl_memoizer::concurrent::IntlLangMemoizer, - ) -> Cow<'static, str> { - unreachable!("`as_string_threadsafe` is not used in non-parallel rustc") - } - - #[cfg(parallel_compiler)] fn as_string_threadsafe( &self, intls: &intl_memoizer::concurrent::IntlLangMemoizer, diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 41ebe4ae2673..06bae57638f3 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -36,8 +36,3 @@ features = [ "Win32_Security", "Win32_System_Threading", ] - -[features] -# tidy-alphabetical-start -rustc_use_parallel_compiler = ['rustc_error_messages/rustc_use_parallel_compiler'] -# tidy-alphabetical-end diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 6552cf224eaa..a386129e8145 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -22,7 +22,7 @@ use rustc_error_messages::{FluentArgs, SpanLabel}; use rustc_lint_defs::pluralize; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; -use rustc_span::{FileLines, FileName, SourceFile, Span, char_width}; +use rustc_span::{FileLines, FileName, SourceFile, Span, char_width, str_width}; use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use tracing::{debug, instrument, trace, warn}; @@ -44,6 +44,7 @@ const DEFAULT_COLUMN_WIDTH: usize = 140; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum HumanReadableErrorType { Default, + Unicode, AnnotateSnippet, Short, } @@ -112,8 +113,12 @@ impl Margin { fn was_cut_right(&self, line_len: usize) -> bool { let right = if self.computed_right == self.span_right || self.computed_right == self.label_right { + // FIXME: This comment refers to the only callsite of this method. + // Rephrase it or refactor it, so it can stand on its own. // Account for the "..." padding given above. Otherwise we end up with code lines // that do fit but end in "..." as if they were trimmed. + // FIXME: Don't hard-code this offset. Is this meant to represent + // `2 * str_width(self.margin())`? self.computed_right - 6 } else { self.computed_right @@ -595,6 +600,12 @@ impl ColorConfig { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum OutputTheme { + Ascii, + Unicode, +} + /// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short` #[derive(Setters)] pub struct HumanEmitter { @@ -613,6 +624,7 @@ pub struct HumanEmitter { macro_backtrace: bool, track_diagnostics: bool, terminal_url: TerminalUrl, + theme: OutputTheme, } #[derive(Debug)] @@ -637,6 +649,7 @@ impl HumanEmitter { macro_backtrace: false, track_diagnostics: false, terminal_url: TerminalUrl::No, + theme: OutputTheme::Ascii, } } @@ -664,6 +677,7 @@ impl HumanEmitter { // Create the source line we will highlight. let left = margin.left(line_len); let right = margin.right(line_len); + // FIXME: The following code looks fishy. See #132860. // On long lines, we strip the source line, accounting for unicode. let mut taken = 0; let code: String = source_string @@ -680,17 +694,19 @@ impl HumanEmitter { }) .collect(); buffer.puts(line_offset, code_offset, &code, Style::Quotation); + let placeholder = self.margin(); if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. - buffer.puts(line_offset, code_offset, "...", Style::LineNumber); + buffer.puts(line_offset, code_offset, placeholder, Style::LineNumber); } if margin.was_cut_right(line_len) { + let padding = str_width(placeholder); // We have stripped some code after the rightmost span end, make it clear we did so. - buffer.puts(line_offset, code_offset + taken - 3, "...", Style::LineNumber); + buffer.puts(line_offset, code_offset + taken - padding, placeholder, Style::LineNumber); } buffer.puts(line_offset, 0, &self.maybe_anonymized(line_index), Style::LineNumber); - draw_col_separator_no_space(buffer, line_offset, width_offset - 2); + self.draw_col_separator_no_space(buffer, line_offset, width_offset - 2); } #[instrument(level = "trace", skip(self), ret)] @@ -702,6 +718,7 @@ impl HumanEmitter { width_offset: usize, code_offset: usize, margin: Margin, + close_window: bool, ) -> Vec<(usize, Style)> { // Draw: // @@ -732,6 +749,7 @@ impl HumanEmitter { // Left trim let left = margin.left(source_string.len()); + // FIXME: This looks fishy. See #132860. // Account for unicode characters of width !=0 that were removed. let left = source_string.chars().take(left).map(|ch| char_width(ch)).sum(); @@ -767,13 +785,10 @@ impl HumanEmitter { for ann in &line.annotations { if let AnnotationType::MultilineStart(depth) = ann.annotation_type { if source_string.chars().take(ann.start_col.display).all(|c| c.is_whitespace()) { - let style = if ann.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; - annotations.push((depth, style)); - buffer_ops.push((line_offset, width_offset + depth - 1, '/', style)); + let uline = self.underline(ann.is_primary); + let chr = uline.multiline_whole_line; + annotations.push((depth, uline.style)); + buffer_ops.push((line_offset, width_offset + depth - 1, chr, uline.style)); } else { short_start = false; break; @@ -970,7 +985,7 @@ impl HumanEmitter { // 3 │ X0 Y0 Z0 // │ ┏━━━━━┛ │ │ < We are writing these lines // │ ┃┌───────┘ │ < by reverting the "depth" of - // │ ┃│┌─────────┘ < their multilne spans. + // │ ┃│┌─────────┘ < their multiline spans. // 4 │ ┃││ X1 Y1 Z1 // 5 │ ┃││ X2 Y2 Z2 // │ ┃│└────╿──│──┘ `Z` label @@ -997,7 +1012,10 @@ impl HumanEmitter { // 4 | } // | for pos in 0..=line_len { - draw_col_separator_no_space(buffer, line_offset + pos + 1, width_offset - 2); + self.draw_col_separator_no_space(buffer, line_offset + pos + 1, width_offset - 2); + } + if close_window { + self.draw_col_separator_end(buffer, line_offset + line_len + 1, width_offset - 2); } // Write the horizontal lines for multiline annotations @@ -1013,21 +1031,17 @@ impl HumanEmitter { // 4 | } // | _ for &(pos, annotation) in &annotations_position { - let style = if annotation.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; + let underline = self.underline(annotation.is_primary); let pos = pos + 1; match annotation.annotation_type { AnnotationType::MultilineStart(depth) | AnnotationType::MultilineEnd(depth) => { - draw_range( + self.draw_range( buffer, - '_', + underline.multiline_horizontal, line_offset + pos, width_offset + depth, (code_offset + annotation.start_col.display).saturating_sub(left), - style, + underline.style, ); } _ if self.teach => { @@ -1035,7 +1049,7 @@ impl HumanEmitter { line_offset, (code_offset + annotation.start_col.display).saturating_sub(left), (code_offset + annotation.end_col.display).saturating_sub(left), - style, + underline.style, annotation.is_primary, ); } @@ -1055,11 +1069,7 @@ impl HumanEmitter { // 4 | | } // | |_ for &(pos, annotation) in &annotations_position { - let style = if annotation.is_primary { - Style::UnderlinePrimary - } else { - Style::UnderlineSecondary - }; + let underline = self.underline(annotation.is_primary); let pos = pos + 1; if pos > 1 && (annotation.has_label() || annotation.takes_space()) { @@ -1067,21 +1077,64 @@ impl HumanEmitter { buffer.putc( p, (code_offset + annotation.start_col.display).saturating_sub(left), - '|', - style, + match annotation.annotation_type { + AnnotationType::MultilineLine(_) => underline.multiline_vertical, + _ => underline.vertical_text_line, + }, + underline.style, + ); + } + if let AnnotationType::MultilineStart(_) = annotation.annotation_type { + buffer.putc( + line_offset + pos, + (code_offset + annotation.start_col.display).saturating_sub(left), + underline.bottom_right, + underline.style, + ); + } + if let AnnotationType::MultilineEnd(_) = annotation.annotation_type + && annotation.has_label() + { + buffer.putc( + line_offset + pos, + (code_offset + annotation.start_col.display).saturating_sub(left), + underline.multiline_bottom_right_with_text, + underline.style, ); } } match annotation.annotation_type { AnnotationType::MultilineStart(depth) => { + buffer.putc( + line_offset + pos, + width_offset + depth - 1, + underline.top_left, + underline.style, + ); for p in line_offset + pos + 1..line_offset + line_len + 2 { - buffer.putc(p, width_offset + depth - 1, '|', style); + buffer.putc( + p, + width_offset + depth - 1, + underline.multiline_vertical, + underline.style, + ); } } AnnotationType::MultilineEnd(depth) => { - for p in line_offset..=line_offset + pos { - buffer.putc(p, width_offset + depth - 1, '|', style); + for p in line_offset..line_offset + pos { + buffer.putc( + p, + width_offset + depth - 1, + underline.multiline_vertical, + underline.style, + ); } + buffer.putc( + line_offset + pos, + width_offset + depth - 1, + underline.bottom_left, + underline.style, + ); } _ => (), } @@ -1102,7 +1155,11 @@ impl HumanEmitter { let style = if annotation.is_primary { Style::LabelPrimary } else { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, (annotation.end_col.display + 1).saturating_sub(left)) + if annotation.end_col.display == 0 { + (pos + 1, (annotation.end_col.display + 2).saturating_sub(left)) + } else { + (pos + 1, (annotation.end_col.display + 1).saturating_sub(left)) + } } else { (pos + 2, annotation.start_col.display.saturating_sub(left)) }; @@ -1135,18 +1192,60 @@ impl HumanEmitter { // 3 | // 4 | } // | _^ test - for &(_, annotation) in &annotations_position { - let (underline, style) = if annotation.is_primary { - ('^', Style::UnderlinePrimary) - } else { - ('-', Style::UnderlineSecondary) - }; + for &(pos, annotation) in &annotations_position { + let uline = self.underline(annotation.is_primary); for p in annotation.start_col.display..annotation.end_col.display { + // The default span label underline. buffer.putc( line_offset + 1, (code_offset + p).saturating_sub(left), - underline, - style, + uline.underline, + uline.style, + ); + } + + if pos == 0 + && matches!( + annotation.annotation_type, + AnnotationType::MultilineStart(_) | AnnotationType::MultilineEnd(_) + ) + { + // The beginning of a multiline span with its leftward moving line on the same line. + buffer.putc( + line_offset + 1, + (code_offset + annotation.start_col.display).saturating_sub(left), + match annotation.annotation_type { + AnnotationType::MultilineStart(_) => uline.top_right_flat, + AnnotationType::MultilineEnd(_) => uline.multiline_end_same_line, + _ => panic!("unexpected annotation type: {annotation:?}"), + }, + uline.style, + ); + } else if pos != 0 + && matches!( + annotation.annotation_type, + AnnotationType::MultilineStart(_) | AnnotationType::MultilineEnd(_) + ) + { + // The beginning of a multiline span with its leftward moving line on another line, + // so we start going down first. + buffer.putc( + line_offset + 1, + (code_offset + annotation.start_col.display).saturating_sub(left), + match annotation.annotation_type { + AnnotationType::MultilineStart(_) => uline.multiline_start_down, + AnnotationType::MultilineEnd(_) => uline.multiline_end_up, + _ => panic!("unexpected annotation type: {annotation:?}"), + }, + uline.style, + ); + } else if pos != 0 && annotation.has_label() { + // The beginning of a span label with an actual label, we'll point down. + buffer.putc( + line_offset + 1, + (code_offset + annotation.start_col.display).saturating_sub(left), + uline.label_start, + uline.style, ); } } @@ -1217,7 +1316,7 @@ impl HumanEmitter { padding: usize, label: &str, override_style: Option + + + + + error[E0308]: `match` arms have incompatible types + + ╭▸ $DIR/huge_multispan_highlight.rs:99:18 + + + + LL let _ = match true { + + ────────── `match` arms have incompatible types + + LL true => ( + + ┌─────────────────┘ + + LL // last line shown in multispan header + + + + LL + + LL ), + + └─────────┘ this is found to be of type `()` + + LL false => " + + ┏━━━━━━━━━━━━━━━━━━┛ + + + + LL + + LL ", + + ╰╴┗━━━━━━━━━┛ expected `()`, found `&str` + + + + error[E0308]: `match` arms have incompatible types + + ╭▸ $DIR/huge_multispan_highlight.rs:216:18 + + + + LL let _ = match true { + + ────────── `match` arms have incompatible types + + LL true => ( + + ┌─────────────────┘ + + LL + + LL 1 // last line shown in multispan header + + + + LL + + LL ), + + └─────────┘ this is found to be of type `{integer}` + + LL false => " + + ┏━━━━━━━━━━━━━━━━━━┛ + + LL + + LL + + LL 1 last line shown in multispan + + + + LL + + LL ", + + ╰╴┗━━━━━━━━━┛ expected integer, found `&str` + + + + error: aborting due to 2 previous errors + + + + For more information about this error, try `rustc --explain E0308`. + + + + + + diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-1.rs b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-1.rs new file mode 100644 index 000000000000..cea82722a0e6 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-1.rs @@ -0,0 +1,12 @@ +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +// Regression test for #118545 + +struct Checked; +//~^ ERROR: using function pointers as const generic parameters is forbidden + +fn foo() {} +const _: Checked = Checked::; + +pub fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-1.stderr b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-1.stderr new file mode 100644 index 000000000000..71339411c847 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-1.stderr @@ -0,0 +1,10 @@ +error: using function pointers as const generic parameters is forbidden + --> $DIR/non_valtreeable_const_arg-1.rs:6:25 + | +LL | struct Checked; + | ^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs new file mode 100644 index 000000000000..6b87ad86d4bc --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs @@ -0,0 +1,19 @@ +#![feature(generic_const_exprs, unsized_const_params)] +#![allow(incomplete_features)] + +// Regression test for 128232 + +fn function() {} + +struct Wrapper; +//~^ ERROR: using function pointers as const generic parameters is forbidden + +impl Wrapper<{ bar() }> { + //~^ ERROR: cannot find function `bar` in this scope + fn call() {} +} + +fn main() { + Wrapper::::call; + //~^ ERROR: the function or associated item `call` exists for struct `Wrapper`, +} diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr new file mode 100644 index 000000000000..b13f76eabadb --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr @@ -0,0 +1,39 @@ +error[E0425]: cannot find function `bar` in this scope + --> $DIR/non_valtreeable_const_arg-2.rs:11:16 + | +LL | impl Wrapper<{ bar() }> { + | ^^^ not found in this scope + | +help: you might be missing a const parameter + | +LL | impl Wrapper<{ bar() }> { + | +++++++++++++++++++++++ + +error[E0741]: using function pointers as const generic parameters is forbidden + --> $DIR/non_valtreeable_const_arg-2.rs:8:25 + | +LL | struct Wrapper; + | ^^^^ + +error[E0599]: the function or associated item `call` exists for struct `Wrapper`, but its trait bounds were not satisfied + --> $DIR/non_valtreeable_const_arg-2.rs:17:26 + | +LL | struct Wrapper; + | ----------------------------- function or associated item `call` not found for this struct because it doesn't satisfy `Wrapper: Fn<_>` +... +LL | Wrapper::::call; + | ^^^^ function or associated item cannot be called on `Wrapper` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Wrapper: Fn<_>` + which is required by `&Wrapper: Fn<_>` +note: the trait `Fn` must be implemented + --> $SRC_DIR/core/src/ops/function.rs:LL:COL + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `call`, perhaps you need to implement it: + candidate #1: `Fn` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0599, E0741. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs new file mode 100644 index 000000000000..bce7ac5708a5 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.rs @@ -0,0 +1,20 @@ +// Regression test for #131915 where we did not handle macro calls as +// statements correctly when determining if a const argument should +// have a `DefId` created or not. + +macro_rules! y { + ( $($matcher:tt)*) => { + x + //~^ ERROR: cannot find value `x` in this scope + }; +} + +const _: A< + //~^ ERROR: free constant item without body + //~| ERROR: cannot find type `A` in this scope + { + y! { test.tou8 } + }, +>; + +fn main() {} diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr new file mode 100644 index 000000000000..a3211b776239 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr @@ -0,0 +1,39 @@ +error: free constant item without body + --> $DIR/const_arg_trivial_macro_expansion-2.rs:12:1 + | +LL | / const _: A< +LL | | +LL | | +LL | | { +LL | | y! { test.tou8 } +LL | | }, +LL | | >; + | | ^ help: provide a definition for the constant: `= ;` + | |__| + | + +error[E0412]: cannot find type `A` in this scope + --> $DIR/const_arg_trivial_macro_expansion-2.rs:12:10 + | +LL | const _: A< + | ^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/const_arg_trivial_macro_expansion-2.rs:7:9 + | +LL | x + | ^ not found in this scope +... +LL | y! { test.tou8 } + | ---------------- in this macro invocation + | + = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might be missing a const parameter + | +LL | const _: A< + | +++++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs new file mode 100644 index 000000000000..2fdd703ab6f3 --- /dev/null +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion.rs @@ -0,0 +1,366 @@ +//@ known-bug: #132647 +//@ dont-check-compiler-stderr +#![allow(unused_braces)] + +// FIXME(bootstrap): This isn't a known bug, we just don't want to write any error annotations. +// this is hard because macro expansion errors have their span be inside the *definition* of the +// macro rather than the line *invoking* it. This means we would wind up with hundreds of error +// annotations on the macro definitions below rather than on any of the actual lines +// that act as a "test". +// +// It's also made more complicated by the fact that compiletest generates "extra" expected +// notes to give an assertable macro backtrace as otherwise there would *nothing* to annotate +// on the actual test lines. All of these extra notes result in needing to write hundreds of +// unnecessary notes on almost every line in this file. +// +// Even though this is marked `known-bug` it should still fail if this test starts ICEing which +// is "enough" in this case. + +// Test that we correctly create definitions for anon consts even when +// the trivial-ness of the expression is obscured by macro expansions. +// +// Acts as a regression test for: #131915 130321 128016 + +// macros expanding to idents + +macro_rules! unbraced_ident { + () => { + ident + }; +} + +macro_rules! braced_ident { + () => {{ ident }}; +} + +macro_rules! unbraced_unbraced_ident { + () => { + unbraced_ident!() + }; +} + +macro_rules! braced_unbraced_ident { + () => {{ unbraced_ident!() }}; +} + +macro_rules! unbraced_braced_ident { + () => { + braced_ident!() + }; +} + +macro_rules! braced_braced_ident { + () => {{ braced_ident!() }}; +} + +// macros expanding to complex expr + +macro_rules! unbraced_expr { + () => { + ident.other + }; +} + +macro_rules! braced_expr { + () => {{ ident.otherent }}; +} + +macro_rules! unbraced_unbraced_expr { + () => { + unbraced_expr!() + }; +} + +macro_rules! braced_unbraced_expr { + () => {{ unbraced_expr!() }}; +} + +macro_rules! unbraced_braced_expr { + () => { + braced_expr!() + }; +} + +macro_rules! braced_braced_expr { + () => {{ braced_expr!() }}; +} + +#[rustfmt::skip] +mod array_paren_call { + // Arrays where the expanded result is a `Res::Err` + fn array_0() -> [(); unbraced_unbraced_ident!()] { loop {} } + fn array_1() -> [(); braced_unbraced_ident!()] { loop {} } + fn array_2() -> [(); unbraced_braced_ident!()] { loop {} } + fn array_3() -> [(); braced_braced_ident!()] { loop {} } + fn array_4() -> [(); { unbraced_unbraced_ident!() }] { loop {} } + fn array_5() -> [(); { braced_unbraced_ident!() }] { loop {} } + fn array_6() -> [(); { unbraced_braced_ident!() }] { loop {} } + fn array_7() -> [(); { braced_braced_ident!() }] { loop {} } + fn array_8() -> [(); unbraced_ident!()] { loop {} } + fn array_9() -> [(); braced_ident!()] { loop {} } + fn array_10() -> [(); { unbraced_ident!() }] { loop {} } + fn array_11() -> [(); { braced_ident!() }] { loop {} } + + // Arrays where the expanded result is a `Res::ConstParam` + fn array_12() -> [(); unbraced_unbraced_ident!()] { loop {} } + fn array_13() -> [(); braced_unbraced_ident!()] { loop {} } + fn array_14() -> [(); unbraced_braced_ident!()] { loop {} } + fn array_15() -> [(); braced_braced_ident!()] { loop {} } + fn array_16() -> [(); { unbraced_unbraced_ident!() }] { loop {} } + fn array_17() -> [(); { braced_unbraced_ident!() }] { loop {} } + fn array_18() -> [(); { unbraced_braced_ident!() }] { loop {} } + fn array_19() -> [(); { braced_braced_ident!() }] { loop {} } + fn array_20() -> [(); unbraced_ident!()] { loop {} } + fn array_21() -> [(); braced_ident!()] { loop {} } + fn array_22() -> [(); { unbraced_ident!() }] { loop {} } + fn array_23() -> [(); { braced_ident!() }] { loop {} } + + // Arrays where the expanded result is a complex expr + fn array_24() -> [(); unbraced_unbraced_expr!()] { loop {} } + fn array_25() -> [(); braced_unbraced_expr!()] { loop {} } + fn array_26() -> [(); unbraced_braced_expr!()] { loop {} } + fn array_27() -> [(); braced_braced_expr!()] { loop {} } + fn array_28() -> [(); { unbraced_unbraced_expr!() }] { loop {} } + fn array_29() -> [(); { braced_unbraced_expr!() }] { loop {} } + fn array_30() -> [(); { unbraced_braced_expr!() }] { loop {} } + fn array_31() -> [(); { braced_braced_expr!() }] { loop {} } + fn array_32() -> [(); unbraced_expr!()] { loop {} } + fn array_33() -> [(); braced_expr!()] { loop {} } + fn array_34() -> [(); { unbraced_expr!() }] { loop {} } + fn array_35() -> [(); { braced_expr!() }] { loop {} } +} + +#[rustfmt::skip] +mod array_brace_call { + // Arrays where the expanded result is a `Res::Err` + fn array_0() -> [(); unbraced_unbraced_ident!{}] { loop {} } + fn array_1() -> [(); braced_unbraced_ident!{}] { loop {} } + fn array_2() -> [(); unbraced_braced_ident!{}] { loop {} } + fn array_3() -> [(); braced_braced_ident!{}] { loop {} } + fn array_4() -> [(); { unbraced_unbraced_ident!{} }] { loop {} } + fn array_5() -> [(); { braced_unbraced_ident!{} }] { loop {} } + fn array_6() -> [(); { unbraced_braced_ident!{} }] { loop {} } + fn array_7() -> [(); { braced_braced_ident!{} }] { loop {} } + fn array_8() -> [(); unbraced_ident!{}] { loop {} } + fn array_9() -> [(); braced_ident!{}] { loop {} } + fn array_10() -> [(); { unbraced_ident!{} }] { loop {} } + fn array_11() -> [(); { braced_ident!{} }] { loop {} } + + // Arrays where the expanded result is a `Res::ConstParam` + fn array_12() -> [(); unbraced_unbraced_ident!{}] { loop {} } + fn array_13() -> [(); braced_unbraced_ident!{}] { loop {} } + fn array_14() -> [(); unbraced_braced_ident!{}] { loop {} } + fn array_15() -> [(); braced_braced_ident!{}] { loop {} } + fn array_16() -> [(); { unbraced_unbraced_ident!{} }] { loop {} } + fn array_17() -> [(); { braced_unbraced_ident!{} }] { loop {} } + fn array_18() -> [(); { unbraced_braced_ident!{} }] { loop {} } + fn array_19() -> [(); { braced_braced_ident!{} }] { loop {} } + fn array_20() -> [(); unbraced_ident!{}] { loop {} } + fn array_21() -> [(); braced_ident!{}] { loop {} } + fn array_22() -> [(); { unbraced_ident!{} }] { loop {} } + fn array_23() -> [(); { braced_ident!{} }] { loop {} } + + // Arrays where the expanded result is a complex expr + fn array_24() -> [(); unbraced_unbraced_expr!{}] { loop {} } + fn array_25() -> [(); braced_unbraced_expr!{}] { loop {} } + fn array_26() -> [(); unbraced_braced_expr!{}] { loop {} } + fn array_27() -> [(); braced_braced_expr!{}] { loop {} } + fn array_28() -> [(); { unbraced_unbraced_expr!{} }] { loop {} } + fn array_29() -> [(); { braced_unbraced_expr!{} }] { loop {} } + fn array_30() -> [(); { unbraced_braced_expr!{} }] { loop {} } + fn array_31() -> [(); { braced_braced_expr!{} }] { loop {} } + fn array_32() -> [(); unbraced_expr!{}] { loop {} } + fn array_33() -> [(); braced_expr!{}] { loop {} } + fn array_34() -> [(); { unbraced_expr!{} }] { loop {} } + fn array_35() -> [(); { braced_expr!{} }] { loop {} } +} + +#[rustfmt::skip] +mod array_square_call { + // Arrays where the expanded result is a `Res::Err` + fn array_0() -> [(); unbraced_unbraced_ident![]] { loop {} } + fn array_1() -> [(); braced_unbraced_ident![]] { loop {} } + fn array_2() -> [(); unbraced_braced_ident![]] { loop {} } + fn array_3() -> [(); braced_braced_ident![]] { loop {} } + fn array_4() -> [(); { unbraced_unbraced_ident![] }] { loop {} } + fn array_5() -> [(); { braced_unbraced_ident![] }] { loop {} } + fn array_6() -> [(); { unbraced_braced_ident![] }] { loop {} } + fn array_7() -> [(); { braced_braced_ident![] }] { loop {} } + fn array_8() -> [(); unbraced_ident![]] { loop {} } + fn array_9() -> [(); braced_ident![]] { loop {} } + fn array_10() -> [(); { unbraced_ident![] }] { loop {} } + fn array_11() -> [(); { braced_ident![] }] { loop {} } + + // Arrays where the expanded result is a `Res::ConstParam` + fn array_12() -> [(); unbraced_unbraced_ident![]] { loop {} } + fn array_13() -> [(); braced_unbraced_ident![]] { loop {} } + fn array_14() -> [(); unbraced_braced_ident![]] { loop {} } + fn array_15() -> [(); braced_braced_ident![]] { loop {} } + fn array_16() -> [(); { unbraced_unbraced_ident![] }] { loop {} } + fn array_17() -> [(); { braced_unbraced_ident![] }] { loop {} } + fn array_18() -> [(); { unbraced_braced_ident![] }] { loop {} } + fn array_19() -> [(); { braced_braced_ident![] }] { loop {} } + fn array_20() -> [(); unbraced_ident![]] { loop {} } + fn array_21() -> [(); braced_ident![]] { loop {} } + fn array_22() -> [(); { unbraced_ident![] }] { loop {} } + fn array_23() -> [(); { braced_ident![] }] { loop {} } + + // Arrays where the expanded result is a complex expr + fn array_24() -> [(); unbraced_unbraced_expr![]] { loop {} } + fn array_25() -> [(); braced_unbraced_expr![]] { loop {} } + fn array_26() -> [(); unbraced_braced_expr![]] { loop {} } + fn array_27() -> [(); braced_braced_expr![]] { loop {} } + fn array_28() -> [(); { unbraced_unbraced_expr![] }] { loop {} } + fn array_29() -> [(); { braced_unbraced_expr![] }] { loop {} } + fn array_30() -> [(); { unbraced_braced_expr![] }] { loop {} } + fn array_31() -> [(); { braced_braced_expr![] }] { loop {} } + fn array_32() -> [(); unbraced_expr![]] { loop {} } + fn array_33() -> [(); braced_expr![]] { loop {} } + fn array_34() -> [(); { unbraced_expr![] }] { loop {} } + fn array_35() -> [(); { braced_expr![] }] { loop {} } +} + +struct Foo; + +#[rustfmt::skip] +mod adt_paren_call { + use super::Foo; + + // An ADT where the expanded result is a `Res::Err` + fn adt_0() -> Foo { loop {} } + fn adt_1() -> Foo { loop {} } + fn adt_2() -> Foo { loop {} } + fn adt_3() -> Foo { loop {} } + fn adt_4() -> Foo<{ unbraced_unbraced_ident!() }> { loop {} } + fn adt_5() -> Foo<{ braced_unbraced_ident!() }> { loop {} } + fn adt_6() -> Foo<{ unbraced_braced_ident!() }> { loop {} } + fn adt_7() -> Foo<{ braced_braced_ident!() }> { loop {} } + fn adt_8() -> Foo { loop {} } + fn adt_9() -> Foo { loop {} } + fn adt_10() -> Foo<{ unbraced_ident!() }> { loop {} } + fn adt_11() -> Foo<{ braced_ident!() }> { loop {} } + + // An ADT where the expanded result is a `Res::ConstParam` + fn adt_12() -> Foo { loop {} } + fn adt_13() -> Foo { loop {} } + fn adt_14() -> Foo { loop {} } + fn adt_15() -> Foo { loop {} } + fn adt_16() -> Foo<{ unbraced_unbraced_ident!() }> { loop {} } + fn adt_17() -> Foo<{ braced_unbraced_ident!() }> { loop {} } + fn adt_18() -> Foo<{ unbraced_braced_ident!() }> { loop {} } + fn adt_19() -> Foo<{ braced_braced_ident!() }> { loop {} } + fn adt_20() -> Foo { loop {} } + fn adt_21() -> Foo { loop {} } + fn adt_22() -> Foo<{ unbraced_ident!() }> { loop {} } + fn adt_23() -> Foo<{ braced_ident!() }> { loop {} } + + // An ADT where the expanded result is a complex expr + fn array_24() -> Foo { loop {} } + fn array_25() -> Foo { loop {} } + fn array_26() -> Foo { loop {} } + fn array_27() -> Foo { loop {} } + fn array_28() -> Foo<{ unbraced_unbraced_expr!() }> { loop {} } + fn array_29() -> Foo<{ braced_unbraced_expr!() }> { loop {} } + fn array_30() -> Foo<{ unbraced_braced_expr!() }> { loop {} } + fn array_31() -> Foo<{ braced_braced_expr!() }> { loop {} } + fn array_32() -> Foo { loop {} } + fn array_33() -> Foo { loop {} } + fn array_34() -> Foo<{ unbraced_expr!() }> { loop {} } + fn array_35() -> Foo<{ braced_expr!() }> { loop {} } +} + +#[rustfmt::skip] +mod adt_brace_call { + use super::Foo; + + // An ADT where the expanded result is a `Res::Err` + fn adt_0() -> Foo { loop {} } + fn adt_1() -> Foo { loop {} } + fn adt_2() -> Foo { loop {} } + fn adt_3() -> Foo { loop {} } + fn adt_4() -> Foo<{ unbraced_unbraced_ident!{} }> { loop {} } + fn adt_5() -> Foo<{ braced_unbraced_ident!{} }> { loop {} } + fn adt_6() -> Foo<{ unbraced_braced_ident!{} }> { loop {} } + fn adt_7() -> Foo<{ braced_braced_ident!{} }> { loop {} } + fn adt_8() -> Foo { loop {} } + fn adt_9() -> Foo { loop {} } + fn adt_10() -> Foo<{ unbraced_ident!{} }> { loop {} } + fn adt_11() -> Foo<{ braced_ident!{} }> { loop {} } + + // An ADT where the expanded result is a `Res::ConstParam` + fn adt_12() -> Foo { loop {} } + fn adt_13() -> Foo { loop {} } + fn adt_14() -> Foo { loop {} } + fn adt_15() -> Foo { loop {} } + fn adt_16() -> Foo<{ unbraced_unbraced_ident!{} }> { loop {} } + fn adt_17() -> Foo<{ braced_unbraced_ident!{} }> { loop {} } + fn adt_18() -> Foo<{ unbraced_braced_ident!{} }> { loop {} } + fn adt_19() -> Foo<{ braced_braced_ident!{} }> { loop {} } + fn adt_20() -> Foo { loop {} } + fn adt_21() -> Foo { loop {} } + fn adt_22() -> Foo<{ unbraced_ident!{} }> { loop {} } + fn adt_23() -> Foo<{ braced_ident!{} }> { loop {} } + + // An ADT where the expanded result is a complex expr + fn array_24() -> Foo { loop {} } + fn array_25() -> Foo { loop {} } + fn array_26() -> Foo { loop {} } + fn array_27() -> Foo { loop {} } + fn array_28() -> Foo<{ unbraced_unbraced_expr!{} }> { loop {} } + fn array_29() -> Foo<{ braced_unbraced_expr!{} }> { loop {} } + fn array_30() -> Foo<{ unbraced_braced_expr!{} }> { loop {} } + fn array_31() -> Foo<{ braced_braced_expr!{} }> { loop {} } + fn array_32() -> Foo { loop {} } + fn array_33() -> Foo { loop {} } + fn array_34() -> Foo<{ unbraced_expr!{} }> { loop {} } + fn array_35() -> Foo<{ braced_expr!{} }> { loop {} } +} + +#[rustfmt::skip] +mod adt_square_call { + use super::Foo; + + // An ADT where the expanded result is a `Res::Err` + fn adt_0() -> Foo { loop {} } + fn adt_1() -> Foo { loop {} } + fn adt_2() -> Foo { loop {} } + fn adt_3() -> Foo { loop {} } + fn adt_4() -> Foo<{ unbraced_unbraced_ident![] }> { loop {} } + fn adt_5() -> Foo<{ braced_unbraced_ident![] }> { loop {} } + fn adt_6() -> Foo<{ unbraced_braced_ident![] }> { loop {} } + fn adt_7() -> Foo<{ braced_braced_ident![] }> { loop {} } + fn adt_8() -> Foo { loop {} } + fn adt_9() -> Foo { loop {} } + fn adt_10() -> Foo<{ unbraced_ident![] }> { loop {} } + fn adt_11() -> Foo<{ braced_ident![] }> { loop {} } + + // An ADT where the expanded result is a `Res::ConstParam` + fn adt_12() -> Foo { loop {} } + fn adt_13() -> Foo { loop {} } + fn adt_14() -> Foo { loop {} } + fn adt_15() -> Foo { loop {} } + fn adt_16() -> Foo<{ unbraced_unbraced_ident![] }> { loop {} } + fn adt_17() -> Foo<{ braced_unbraced_ident![] }> { loop {} } + fn adt_18() -> Foo<{ unbraced_braced_ident![] }> { loop {} } + fn adt_19() -> Foo<{ braced_braced_ident![] }> { loop {} } + fn adt_20() -> Foo { loop {} } + fn adt_21() -> Foo { loop {} } + fn adt_22() -> Foo<{ unbraced_ident![] }> { loop {} } + fn adt_23() -> Foo<{ braced_ident![] }> { loop {} } + + // An ADT where the expanded result is a complex expr + fn array_24() -> Foo { loop {} } + fn array_25() -> Foo { loop {} } + fn array_26() -> Foo { loop {} } + fn array_27() -> Foo { loop {} } + fn array_28() -> Foo<{ unbraced_unbraced_expr![] }> { loop {} } + fn array_29() -> Foo<{ braced_unbraced_expr![] }> { loop {} } + fn array_30() -> Foo<{ unbraced_braced_expr![] }> { loop {} } + fn array_31() -> Foo<{ braced_braced_expr![] }> { loop {} } + fn array_32() -> Foo { loop {} } + fn array_33() -> Foo { loop {} } + fn array_34() -> Foo<{ unbraced_expr![] }> { loop {} } + fn array_35() -> Foo<{ braced_expr![] }> { loop {} } +} + +fn main() {} 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 000000000000..346ef64a8a6c --- /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]: PartialEq`, then as part of diagnostics +// we would replace all generic parameters with inference vars which would yield +// a self type of `[u8; AnonConst]` and then attempt to normalize `AnonConst`. + +pub trait T { + type A; + const P: Self::A; + + fn a() { + [0u8; std::mem::size_of::()] == 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 000000000000..12de4f1dc300 --- /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::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::P; + | ^^ + | + = note: this may fail depending on what value the parameter takes + +error[E0277]: can't compare `[u8; std::mem::size_of::()]` with `::A` + --> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47 + | +LL | [0u8; std::mem::size_of::()] == Self::P; + | ^^ no implementation for `[u8; std::mem::size_of::()] == ::A` + | + = help: the trait `PartialEq<::A>` is not implemented for `[u8; std::mem::size_of::()]` +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::()]: PartialEq<::A> { + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs deleted file mode 100644 index 6c0ac639612c..000000000000 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs +++ /dev/null @@ -1,36 +0,0 @@ -//@ known-bug: #110395 -//@ compile-flags: -Znext-solver -#![feature(generic_const_exprs, adt_const_params, const_trait_impl)] -#![allow(incomplete_features)] - -// test `N + N` unifies with explicit function calls for non-builtin-types -#[derive(PartialEq, Eq)] -struct Foo(u8); - -impl const std::ops::Add for Foo { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - self - } -} - -struct Evaluatable; - -fn foo(a: Evaluatable<{ N + N }>) { - bar::<{ std::ops::Add::add(N, N) }>(); -} - -fn bar() {} - -// test that `N + N` unifies with explicit function calls for builin-types -struct Evaluatable2; - -fn foo2(a: Evaluatable2<{ N + N }>) { - bar2::<{ std::ops::Add::add(N, N) }>(); - // FIXME(generic_const_exprs) make this not an error -} - -fn bar2() {} - -fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr deleted file mode 100644 index 882fdf0b228e..000000000000 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr +++ /dev/null @@ -1,93 +0,0 @@ -error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed - --> $DIR/unify-op-with-fn-call.rs:3:12 - | -LL | #![feature(generic_const_exprs, adt_const_params, const_trait_impl)] - | ^^^^^^^^^^^^^^^^^^^ - | - = help: remove one of these features - -error: const `impl` for trait `Add` which is not marked with `#[const_trait]` - --> $DIR/unify-op-with-fn-call.rs:10:12 - | -LL | impl const std::ops::Add for Foo { - | ^^^^^^^^^^^^^ - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/unify-op-with-fn-call.rs:18:29 - | -LL | struct Evaluatable; - | ^^^ - | -help: add `#[derive(ConstParamTy)]` to the struct - | -LL + #[derive(ConstParamTy)] -LL | struct Foo(u8); - | - -error[E0015]: cannot call non-const operator in constants - --> $DIR/unify-op-with-fn-call.rs:20:39 - | -LL | fn foo(a: Evaluatable<{ N + N }>) { - | ^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/unify-op-with-fn-call.rs:20:17 - | -LL | fn foo(a: Evaluatable<{ N + N }>) { - | ^^^ - | -help: add `#[derive(ConstParamTy)]` to the struct - | -LL + #[derive(ConstParamTy)] -LL | struct Foo(u8); - | - -error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/unify-op-with-fn-call.rs:24:17 - | -LL | fn bar() {} - | ^^^ - | -help: add `#[derive(ConstParamTy)]` to the struct - | -LL + #[derive(ConstParamTy)] -LL | struct Foo(u8); - | - -error[E0284]: type annotations needed: cannot normalize `foo2::{constant#0}` - --> $DIR/unify-op-with-fn-call.rs:29:28 - | -LL | fn foo2(a: Evaluatable2<{ N + N }>) { - | ^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2::{constant#0}` - -error[E0015]: cannot call non-const fn `::add` in constants - --> $DIR/unify-op-with-fn-call.rs:21:13 - | -LL | bar::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const fn `::add` in constants - --> $DIR/unify-op-with-fn-call.rs:30:14 - | -LL | bar2::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0284]: type annotations needed: cannot normalize `foo2::{constant#0}` - --> $DIR/unify-op-with-fn-call.rs:30:12 - | -LL | bar2::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `foo2::{constant#0}` - -error: aborting due to 10 previous errors - -Some errors have detailed explanations: E0015, E0284, E0741. -For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs index 61bdf57ffdb9..759d2e8b2ede 100644 --- a/tests/ui/consts/const-pattern-irrefutable.rs +++ b/tests/ui/consts/const-pattern-irrefutable.rs @@ -1,28 +1,43 @@ mod foo { pub const b: u8 = 2; - pub const d: u8 = 2; + //~^ missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable + pub const d: (u8, u8) = (2, 1); + //~^ missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable } use foo::b as c; use foo::d; const a: u8 = 2; +//~^ missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable + +#[derive(PartialEq)] +struct S { + foo: u8, +} + +const e: S = S { + foo: 0, +}; fn main() { let a = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable //~| HELP introduce a variable instead let c = 4; //~^ ERROR refutable pattern in local binding //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable //~| HELP introduce a variable instead - let d = 4; + let d = (4, 4); //~^ ERROR refutable pattern in local binding - //~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - //~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable + //~| patterns `(0_u8..=1_u8, _)` and `(3_u8..=u8::MAX, _)` not covered //~| HELP introduce a variable instead + let e = S { + //~^ ERROR refutable pattern in local binding + //~| pattern `S { foo: 1_u8..=u8::MAX }` not covered + //~| HELP introduce a variable instead + foo: 1, + }; fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr index 2aed68bdd643..afb67a3a118a 100644 --- a/tests/ui/consts/const-pattern-irrefutable.stderr +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -1,45 +1,76 @@ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:12:9 + --> $DIR/const-pattern-irrefutable.rs:24:9 | +LL | const a: u8 = 2; + | ----------- missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable +... LL | let a = 4; - | ^ - | | - | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - | missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `a_var` + | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` +help: introduce a variable instead + | +LL | let a_var = 4; + | ~~~~~ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:17:9 + --> $DIR/const-pattern-irrefutable.rs:28:9 | +LL | pub const b: u8 = 2; + | --------------- missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable +... LL | let c = 4; - | ^ - | | - | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - | missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `c_var` + | ^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `u8` +help: introduce a variable instead + | +LL | let b_var = 4; + | ~~~~~ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:22:9 + --> $DIR/const-pattern-irrefutable.rs:32:9 | -LL | let d = 4; - | ^ - | | - | patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered - | missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `d_var` +LL | pub const d: (u8, u8) = (2, 1); + | --------------------- missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable +... +LL | let d = (4, 4); + | ^ patterns `(0_u8..=1_u8, _)` and `(3_u8..=u8::MAX, _)` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: the matched value is of type `u8` + = note: the matched value is of type `(u8, u8)` +help: introduce a variable instead + | +LL | let d_var = (4, 4); + | ~~~~~ -error: aborting due to 3 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/const-pattern-irrefutable.rs:36:9 + | +LL | const e: S = S { + | ---------- missing patterns are not covered because `e` is interpreted as a constant pattern, not a new variable +... +LL | let e = S { + | ^ pattern `S { foo: 1_u8..=u8::MAX }` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `S` defined here + --> $DIR/const-pattern-irrefutable.rs:15:8 + | +LL | struct S { + | ^ + = note: the matched value is of type `S` +help: introduce a variable instead + | +LL | let e_var = S { + | ~~~~~ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs index 56b552b6a3f3..8b38067e46e7 100644 --- a/tests/ui/consts/const-unstable-intrinsic.rs +++ b/tests/ui/consts/const-unstable-intrinsic.rs @@ -16,13 +16,13 @@ const fn const_main() { unsafe { unstable_intrinsic::size_of_val(&x); //~^ERROR: unstable library feature `unstable` - //~|ERROR: cannot be (indirectly) exposed to stable + //~|ERROR: not yet stable as a const intrinsic unstable_intrinsic::min_align_of_val(&x); //~^ERROR: unstable library feature `unstable` //~|ERROR: not yet stable as a const intrinsic size_of_val(&x); - //~^ERROR: cannot be (indirectly) exposed to stable + //~^ERROR: cannot use `#[feature(local)]` min_align_of_val(&x); //~^ERROR: cannot use `#[feature(local)]` } @@ -59,6 +59,6 @@ mod fallback { #[rustc_intrinsic] const unsafe fn copy(src: *const T, _dst: *mut T, _count: usize) { super::size_of_val(src); - //~^ ERROR cannot be (indirectly) exposed to stable + //~^ ERROR cannot use `#[feature(local)]` } } diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr index 3e605f3d0037..8b61b0904a9c 100644 --- a/tests/ui/consts/const-unstable-intrinsic.stderr +++ b/tests/ui/consts/const-unstable-intrinsic.stderr @@ -18,13 +18,13 @@ LL | unstable_intrinsic::min_align_of_val(&x); = help: add `#![feature(unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable +error: `size_of_val` is not yet stable as a const intrinsic --> $DIR/const-unstable-intrinsic.rs:17:9 | LL | unstable_intrinsic::size_of_val(&x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) + = help: add `#![feature(unstable)]` to the crate attributes to enable error: `min_align_of_val` is not yet stable as a const intrinsic --> $DIR/const-unstable-intrinsic.rs:20:9 @@ -34,13 +34,22 @@ LL | unstable_intrinsic::min_align_of_val(&x); | = help: add `#![feature(unstable)]` to the crate attributes to enable -error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` --> $DIR/const-unstable-intrinsic.rs:24:9 | LL | size_of_val(&x); | ^^^^^^^^^^^^^^^ | - = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn const_main() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(local)] +LL | const fn const_main() { + | error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` --> $DIR/const-unstable-intrinsic.rs:26:9 @@ -67,13 +76,22 @@ LL | unsafe { copy(src, dst, count) } | = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) -error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]` --> $DIR/const-unstable-intrinsic.rs:61:9 | LL | super::size_of_val(src); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval) +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const unsafe fn copy(src: *const T, _dst: *mut T, _count: usize) { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(local)] +LL | const unsafe fn copy(src: *const T, _dst: *mut T, _count: usize) { + | error: aborting due to 8 previous errors diff --git a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr index bd61f43727be..c73d1f059007 100644 --- a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr +++ b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr @@ -3,8 +3,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered | LL | match &[][..] { | ^^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered +LL | +LL | E_SL => {} + | ---- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `E_SL` | = note: the matched value is of type `&[E]` +note: constant `E_SL` defined here + --> $DIR/incomplete-slice.rs:6:1 + | +LL | const E_SL: &[E] = &[E::A]; + | ^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | E_SL_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ E_SL => {}, diff --git a/tests/ui/consts/min_const_fn/auxiliary/unmarked_const_fn_crate.rs b/tests/ui/consts/min_const_fn/auxiliary/unmarked_const_fn_crate.rs new file mode 100644 index 000000000000..aec92c5ae160 --- /dev/null +++ b/tests/ui/consts/min_const_fn/auxiliary/unmarked_const_fn_crate.rs @@ -0,0 +1 @@ +pub const fn just_a_fn() {} diff --git a/tests/ui/consts/min_const_fn/auxiliary/unstable_if_unmarked_const_fn_crate.rs b/tests/ui/consts/min_const_fn/auxiliary/unstable_if_unmarked_const_fn_crate.rs new file mode 100644 index 000000000000..f102902fce3e --- /dev/null +++ b/tests/ui/consts/min_const_fn/auxiliary/unstable_if_unmarked_const_fn_crate.rs @@ -0,0 +1,8 @@ +//@ compile-flags: -Zforce-unstable-if-unmarked + +#![feature(rustc_attrs)] + +pub const fn not_stably_const() {} + +#[rustc_const_stable_indirect] +pub const fn expose_on_stable() {} diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.rs b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.rs new file mode 100644 index 000000000000..06ce406fd899 --- /dev/null +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.rs @@ -0,0 +1,21 @@ +//@ aux-build:unstable_if_unmarked_const_fn_crate.rs +//@ aux-build:unmarked_const_fn_crate.rs +#![feature(staged_api, rustc_private)] +#![stable(since = "1.0.0", feature = "stable")] + +extern crate unmarked_const_fn_crate; +extern crate unstable_if_unmarked_const_fn_crate; + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +const fn stable_fn() { + // This one is fine. + unstable_if_unmarked_const_fn_crate::expose_on_stable(); + // This one is not. + unstable_if_unmarked_const_fn_crate::not_stably_const(); + //~^ERROR: cannot use `#[feature(rustc_private)]` + unmarked_const_fn_crate::just_a_fn(); + //~^ERROR: cannot be (indirectly) exposed to stable +} + +fn main() {} diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr new file mode 100644 index 000000000000..a655c0faab62 --- /dev/null +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr @@ -0,0 +1,28 @@ +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(rustc_private)]` + --> $DIR/recursive_const_stab_unmarked_crate_imports.rs:15:5 + | +LL | unstable_if_unmarked_const_fn_crate::not_stably_const(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features +help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn stable_fn() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(rustc_private)] +LL | const fn stable_fn() { + | + +error: `just_a_fn` cannot be (indirectly) exposed to stable + --> $DIR/recursive_const_stab_unmarked_crate_imports.rs:17:5 + | +LL | unmarked_const_fn_crate::just_a_fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.rs b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.rs new file mode 100644 index 000000000000..429fa060521f --- /dev/null +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Zforce-unstable-if-unmarked +//@ edition: 2021 +#![feature(const_async_blocks, rustc_attrs)] + +pub const fn not_stably_const() { + // We need to do something const-unstable here. + // For now we use `async`, eventually we might have to add a auxiliary crate + // as a dependency just to be sure we have something const-unstable. + let _x = async { 15 }; +} + +#[rustc_const_stable_indirect] +pub const fn expose_on_stable() { + // Calling `not_stably_const` here is *not* okay. + not_stably_const(); + //~^ERROR: cannot use `#[feature(rustc_private)]` + // Also directly using const-unstable things is not okay. + let _x = async { 15 }; + //~^ERROR: cannot use `#[feature(const_async_blocks)]` +} + +fn main() { + const { expose_on_stable() }; +} diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr new file mode 100644 index 000000000000..d4ba0f9df2da --- /dev/null +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr @@ -0,0 +1,37 @@ +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(rustc_private)]` + --> $DIR/recursive_const_stab_unstable_if_unmarked.rs:15:5 + | +LL | not_stably_const(); + | ^^^^^^^^^^^^^^^^^^ + | + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features +help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | pub const fn expose_on_stable() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(rustc_private)] +LL | pub const fn expose_on_stable() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_async_blocks)]` + --> $DIR/recursive_const_stab_unstable_if_unmarked.rs:18:14 + | +LL | let _x = async { 15 }; + | ^^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | pub const fn expose_on_stable() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_async_blocks)] +LL | pub const fn expose_on_stable() { + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/consts/rustc-const-stability-require-const.rs b/tests/ui/consts/rustc-const-stability-require-const.rs index 6cc3f0f0da12..ad27fcf6cb97 100644 --- a/tests/ui/consts/rustc-const-stability-require-const.rs +++ b/tests/ui/consts/rustc-const-stability-require-const.rs @@ -56,9 +56,3 @@ const fn barfoo_unmarked() {} #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")] pub const fn barfoo_unstable() {} //~^ ERROR can only be applied to functions that are declared `#[stable]` - -// `#[rustc_const_stable_indirect]` also requires a const fn -#[rustc_const_stable_indirect] -#[unstable(feature = "unstable", issue = "none")] -pub fn not_a_const_fn() {} -//~^ ERROR require the function or method to be `const` diff --git a/tests/ui/consts/rustc-const-stability-require-const.stderr b/tests/ui/consts/rustc-const-stability-require-const.stderr index d9a7d37cbcd2..4b13826584dc 100644 --- a/tests/ui/consts/rustc-const-stability-require-const.stderr +++ b/tests/ui/consts/rustc-const-stability-require-const.stderr @@ -86,17 +86,5 @@ LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")] LL | pub const fn barfoo_unstable() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const` - --> $DIR/rustc-const-stability-require-const.rs:63:1 - | -LL | pub fn not_a_const_fn() {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -help: make the function or method const - --> $DIR/rustc-const-stability-require-const.rs:63:1 - | -LL | pub fn not_a_const_fn() {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/diagnostic-width/E0271.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr similarity index 94% rename from tests/ui/diagnostic-width/E0271.stderr rename to tests/ui/diagnostic-width/E0271.ascii.stderr index 31ec3fe366f4..e276299e9e8e 100644 --- a/tests/ui/diagnostic-width/E0271.stderr +++ b/tests/ui/diagnostic-width/E0271.ascii.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` - --> $DIR/E0271.rs:18:5 + --> $DIR/E0271.rs:20:5 | LL | / Box::new( LL | | Ok::<_, ()>( @@ -11,7 +11,7 @@ LL | | ) | |_____^ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` | note: expected this to be `Foo` - --> $DIR/E0271.rs:8:18 + --> $DIR/E0271.rs:10:18 | LL | type Error = E; | ^ diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs index d8cb24898ac3..ce41ad2952bc 100644 --- a/tests/ui/diagnostic-width/E0271.rs +++ b/tests/ui/diagnostic-width/E0271.rs @@ -1,4 +1,6 @@ -//@ compile-flags: --diagnostic-width=40 +//@ revisions: ascii unicode +//@[ascii] compile-flags: --diagnostic-width=40 +//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=40 //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" trait Future { type Error; @@ -15,7 +17,7 @@ impl Future for Option { struct Foo; fn foo() -> Box> { - Box::new( //~ ERROR E0271 + Box::new( //[ascii]~ ERROR E0271 Ok::<_, ()>( Err::<(), _>( Ok::<_, ()>( diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr new file mode 100644 index 000000000000..4a96ca36cd78 --- /dev/null +++ b/tests/ui/diagnostic-width/E0271.unicode.stderr @@ -0,0 +1,22 @@ +error[E0271]: type mismatch resolving `>, ...>>, ...>>, ...> as Future>::Error == Foo` + ╭▸ $DIR/E0271.rs:20:5 + │ +LL │ ┏ Box::new( +LL │ ┃ Ok::<_, ()>( +LL │ ┃ Err::<(), _>( +LL │ ┃ Ok::<_, ()>( + ‡ ┃ +LL │ ┃ ) +LL │ ┃ ) + │ ┗━━━━━┛ type mismatch resolving `, ...>>, ...> as Future>::Error == Foo` + ╰╴ +note: expected this to be `Foo` + ╭▸ $DIR/E0271.rs:10:18 + │ +LL │ type Error = E; + │ ━ + ╰ note: required for the cast from `Box>, ()>>, ()>>, ()>>` to `Box<(dyn Future + 'static)>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/diagnostic-width/flag-human.stderr b/tests/ui/diagnostic-width/flag-human.ascii.stderr similarity index 89% rename from tests/ui/diagnostic-width/flag-human.stderr rename to tests/ui/diagnostic-width/flag-human.ascii.stderr index eaa968410806..4593304e087d 100644 --- a/tests/ui/diagnostic-width/flag-human.stderr +++ b/tests/ui/diagnostic-width/flag-human.ascii.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/flag-human.rs:7:17 + --> $DIR/flag-human.rs:9:17 | LL | ..._: () = 42; | -- ^^ expected `()`, found integer diff --git a/tests/ui/diagnostic-width/flag-human.rs b/tests/ui/diagnostic-width/flag-human.rs index a46122ed7835..1af416591416 100644 --- a/tests/ui/diagnostic-width/flag-human.rs +++ b/tests/ui/diagnostic-width/flag-human.rs @@ -1,9 +1,11 @@ -//@ compile-flags: --diagnostic-width=20 +//@ revisions: ascii unicode +//@[ascii] compile-flags: --diagnostic-width=20 +//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode --diagnostic-width=20 // This test checks that `-Z output-width` effects the human error output by restricting it to an // arbitrarily low value so that the effect is visible. fn main() { let _: () = 42; - //~^ ERROR mismatched types + //[ascii]~^ ERROR mismatched types } diff --git a/tests/ui/diagnostic-width/flag-human.unicode.stderr b/tests/ui/diagnostic-width/flag-human.unicode.stderr new file mode 100644 index 000000000000..50176564786b --- /dev/null +++ b/tests/ui/diagnostic-width/flag-human.unicode.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + ╭▸ $DIR/flag-human.rs:9:17 + │ +LL │ …t _: () = 42; + │ ┬─ ━━ expected `()`, found integer + │ │ + ╰╴ expected due to this + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/long-E0308.stderr b/tests/ui/diagnostic-width/long-E0308.ascii.stderr similarity index 88% rename from tests/ui/diagnostic-width/long-E0308.stderr rename to tests/ui/diagnostic-width/long-E0308.ascii.stderr index eb37da037e9d..d45d6bf329bd 100644 --- a/tests/ui/diagnostic-width/long-E0308.stderr +++ b/tests/ui/diagnostic-width/long-E0308.ascii.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/long-E0308.rs:44:9 + --> $DIR/long-E0308.rs:46:9 | LL | let x: Atype< | _____________- @@ -20,11 +20,11 @@ LL | | )))))))))))))))))))))))))))))); | = note: expected struct `Atype, ...>` found enum `Result, ...>` - = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types - --> $DIR/long-E0308.rs:57:26 + --> $DIR/long-E0308.rs:59:26 | LL | ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... | __________________________^ @@ -36,11 +36,11 @@ LL | | )))))))))))))))))))))))); | = note: expected enum `Option>` found enum `Result, ...>` - = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types - --> $DIR/long-E0308.rs:88:9 + --> $DIR/long-E0308.rs:90:9 | LL | let x: Atype< | ____________- @@ -56,11 +56,11 @@ LL | | > = (); | = note: expected struct `Atype, ...>` found unit type `()` - = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error[E0308]: mismatched types - --> $DIR/long-E0308.rs:91:17 + --> $DIR/long-E0308.rs:93:17 | LL | let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O... | ____________--___^ @@ -74,7 +74,7 @@ LL | | )))))))))))))))))))))))); | = note: expected unit type `()` found enum `Result, ...>` - = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt' + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.ascii/long-E0308.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error: aborting due to 4 previous errors diff --git a/tests/ui/diagnostic-width/long-E0308.rs b/tests/ui/diagnostic-width/long-E0308.rs index 150164ba21b4..73f81f5872a6 100644 --- a/tests/ui/diagnostic-width/long-E0308.rs +++ b/tests/ui/diagnostic-width/long-E0308.rs @@ -1,4 +1,6 @@ -//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +//@ revisions: ascii unicode +//@[ascii] compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +//@[unicode] compile-flags: -Zunstable-options=yes --json=diagnostic-unicode --diagnostic-width=60 -Zwrite-long-types-to-disk=yes //@ normalize-stderr-test: "long-type-\d+" -> "long-type-hash" mod a { diff --git a/tests/ui/diagnostic-width/long-E0308.unicode.stderr b/tests/ui/diagnostic-width/long-E0308.unicode.stderr new file mode 100644 index 000000000000..3e8d881d7a6b --- /dev/null +++ b/tests/ui/diagnostic-width/long-E0308.unicode.stderr @@ -0,0 +1,82 @@ +error[E0308]: mismatched types + ╭▸ $DIR/long-E0308.rs:46:9 + │ +LL │ let x: Atype< + │ ┌─────────────┘ +LL │ │ Btype< +LL │ │ Ctype< +LL │ │ Atype< + ‡ │ +LL │ │ i32 +LL │ │ > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… + │ │┏━━━━━│━━━┛ + │ └┃─────┤ + │ ┃ expected due to this +LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O… +LL │ ┃ Ok("") +LL │ ┃ )))))))))))))))))))))))))))))) +LL │ ┃ )))))))))))))))))))))))))))))); + │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Atype, ...>`, found `Result, ...>` + │ + ├ note: expected struct `Atype, ...>` + │ found enum `Result, ...>` + ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt' + ╰ note: consider using `--verbose` to print the full type name to the console + +error[E0308]: mismatched types + ╭▸ $DIR/long-E0308.rs:59:26 + │ +LL │ ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(… + │ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┛ +LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok… +LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL │ ┃ )))))))))))))))))))))))))))))) +LL │ ┃ )))))))))))))))))))))))); + │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `Option>`, found `Result, ...>` + │ + ├ note: expected enum `Option>` + │ found enum `Result, ...>` + ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt' + ╰ note: consider using `--verbose` to print the full type name to the console + +error[E0308]: mismatched types + ╭▸ $DIR/long-E0308.rs:90:9 + │ +LL │ let x: Atype< + │ ┌────────────┘ +LL │ │ Btype< +LL │ │ Ctype< +LL │ │ Atype< + ‡ │ +LL │ │ i32 +LL │ │ > = (); + │ │ │ ━━ expected `Atype, ...>`, found `()` + │ └─────┤ + │ expected due to this + │ + ├ note: expected struct `Atype, ...>` + │ found unit type `()` + ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt' + ╰ note: consider using `--verbose` to print the full type name to the console + +error[E0308]: mismatched types + ╭▸ $DIR/long-E0308.rs:93:17 + │ +LL │ let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(… + │ ┏━━━━━━━━━━━━┬─━━━┛ + │ ┃ │ + │ ┃ expected due to this +LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok… +LL │ ┃ Ok(Ok(Ok(Ok(Ok(Ok(Ok(""))))))) +LL │ ┃ )))))))))))))))))))))))))))))) +LL │ ┃ )))))))))))))))))))))))); + │ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ expected `()`, found `Result, ...>` + │ + ├ note: expected unit type `()` + │ found enum `Result, ...>` + ├ note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308.unicode/long-E0308.long-type-hash.txt' + ╰ note: consider using `--verbose` to print the full type name to the console + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr similarity index 97% rename from tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr rename to tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr index 8f200e15c64d..4d8afb6f3ad9 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.stderr +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.ascii.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `&str` to `&str` - --> $DIR/non-1-width-unicode-multiline-label.rs:5:260 + --> $DIR/non-1-width-unicode-multiline-label.rs:7:260 | LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇...࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; | -------------- ^ -------------- &str diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs index 1989ea886359..61c4b31e03a6 100644 --- a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.rs @@ -1,7 +1,9 @@ +//@ revisions: ascii unicode +//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode // ignore-tidy-linelength fn main() { let unicode_is_fun = "؁‱ஹ௸௵꧄.ဪ꧅⸻𒈙𒐫﷽𒌄𒈟𒍼𒁎𒀱𒌧𒅃 𒈓𒍙𒊎𒄡𒅌𒁏𒀰𒐪𒐩𒈙𒐫𪚥"; let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; - //~^ ERROR cannot add `&str` to `&str` + //[ascii]~^ ERROR cannot add `&str` to `&str` } diff --git a/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr new file mode 100644 index 000000000000..ed8ce770bb7e --- /dev/null +++ b/tests/ui/diagnostic-width/non-1-width-unicode-multiline-label.unicode.stderr @@ -0,0 +1,18 @@ +error[E0369]: cannot add `&str` to `&str` + ╭▸ $DIR/non-1-width-unicode-multiline-label.rs:7:260 + │ +LL │ …ཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉…࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!"; + │ ┬───────────── ┯ ────────────── &str + │ │ │ + │ │ `+` cannot be used to concatenate two `&str` strings + │ &str + │ + ╰ note: string concatenation requires an owned `String` on the left +help: create an owned `String` from a string reference + ╭╴ +LL │ let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun.to_owned() + " really fun!"; + ╰╴ +++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr similarity index 91% rename from tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr rename to tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr index a7d5c0bfb941..70bd149545cf 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.stderr +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.ascii.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/non-whitespace-trimming-2.rs:4:311 + --> $DIR/non-whitespace-trimming-2.rs:6:311 | LL | ...13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let ... | -- ^^ expected `()`, found integer diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs index abd9e189a753..283506bd6c90 100644 --- a/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.rs @@ -1,6 +1,8 @@ +//@ revisions: ascii unicode +//@[unicode] compile-flags: -Zunstable-options=yes --error-format=human-unicode // ignore-tidy-linelength fn main() { let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _: usize = 4; let _: usize = 5; let _: usize = 6; let _: usize = 7; let _: usize = 8; let _: usize = 9; let _: usize = 10; let _: usize = 11; let _: usize = 12; let _: usize = 13; let _: usize = 14; let _: usize = 15; -//~^ ERROR mismatched types +//[ascii]~^ ERROR mismatched types } diff --git a/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr new file mode 100644 index 000000000000..600d196de167 --- /dev/null +++ b/tests/ui/diagnostic-width/non-whitespace-trimming-2.unicode.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + ╭▸ $DIR/non-whitespace-trimming-2.rs:6:311 + │ +LL │ …= 13; let _: usize = 14; let _: usize = 15; let _: () = 42; let _: usize = 0; let _: usize = 1; let _: usize = 2; let _: usize = 3; let _:… + │ ┬─ ━━ expected `()`, found integer + │ │ + ╰╴ expected due to this + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed new file mode 100644 index 000000000000..3fed16f0ee71 --- /dev/null +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -0,0 +1,52 @@ +//@ revisions: e2021 e2024 +// +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +// +//@[e2021] run-pass +//@[e2021] run-rustfix +//@[e2024] check-fail + +fn main() { + m(); + q(); + let _ = meow(); +} + +fn m() { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + let x: () = match true { + true => Default::default(), + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + false => panic!("..."), + }; + + dbg!(x); +} + +fn q() -> Option<()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + fn deserialize() -> Option { + Some(T::default()) + } + + deserialize::<()>()?; + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + + None +} + +// Make sure we turbofish the right argument +fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { + Err(()) +} +fn meow() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + help::<(), _>(1)?; + //[e2024]~^ error: the trait bound `(): From` is not satisfied + Ok(()) +} diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 79eee2a3defd..fdc97e54d4e4 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -1,5 +1,5 @@ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:15:1 + --> $DIR/never-type-fallback-breaking.rs:17:1 | LL | fn m() { | ^^^^^^ @@ -8,7 +8,7 @@ LL | fn m() { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:19:17 + --> $DIR/never-type-fallback-breaking.rs:21:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | let x: () = match true { | ++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:27:1 + --> $DIR/never-type-fallback-breaking.rs:29:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | fn q() -> Option<()> { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:34:5 + --> $DIR/never-type-fallback-breaking.rs:36:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -37,5 +37,24 @@ help: use `()` annotations to avoid fallback changes LL | deserialize::<()>()?; | ++++++ -warning: 2 warnings emitted +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:46:1 + | +LL | fn meow() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #123748 + = help: specify the types explicitly +note: in edition 2024, the requirement `(): From` will fail + --> $DIR/never-type-fallback-breaking.rs:49:5 + | +LL | help(1)?; + | ^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | help::<(), _>(1)?; + | +++++++++ + +warning: 3 warnings emitted diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index 461e4ae0bdf6..6258247f8b28 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:19:17 + --> $DIR/never-type-fallback-breaking.rs:21:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -8,7 +8,7 @@ LL | true => Default::default(), = help: did you intend to use the type `()` here instead? error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:34:5 + --> $DIR/never-type-fallback-breaking.rs:36:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -16,11 +16,34 @@ LL | deserialize()?; = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `deserialize` - --> $DIR/never-type-fallback-breaking.rs:30:23 + --> $DIR/never-type-fallback-breaking.rs:32:23 | LL | fn deserialize() -> Option { | ^^^^^^^ required by this bound in `deserialize` -error: aborting due to 2 previous errors +error[E0277]: the trait bound `(): From` is not satisfied + --> $DIR/never-type-fallback-breaking.rs:49:5 + | +LL | help(1)?; + | ^^^^^^^ the trait `From` is not implemented for `()` + | + = help: the following other types implement trait `From`: + `(T, T)` implements `From<[T; 2]>` + `(T, T, T)` implements `From<[T; 3]>` + `(T, T, T, T)` implements `From<[T; 4]>` + `(T, T, T, T, T)` implements `From<[T; 5]>` + `(T, T, T, T, T, T)` implements `From<[T; 6]>` + `(T, T, T, T, T, T, T)` implements `From<[T; 7]>` + `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` + `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` + and 4 others + = note: required for `!` to implement `Into<()>` +note: required by a bound in `help` + --> $DIR/never-type-fallback-breaking.rs:43:20 + | +LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { + | ^^^^^^^^ required by this bound in `help` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 7b4a1b1de048..71d36f3a2d92 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -5,11 +5,13 @@ //@[e2024] compile-flags: -Zunstable-options // //@[e2021] run-pass +//@[e2021] run-rustfix //@[e2024] check-fail fn main() { m(); q(); + let _ = meow(); } fn m() { @@ -36,3 +38,15 @@ fn q() -> Option<()> { None } + +// Make sure we turbofish the right argument +fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { + Err(()) +} +fn meow() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + help(1)?; + //[e2024]~^ error: the trait bound `(): From` is not satisfied + Ok(()) +} diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg index be92c00c19bd..a4019c78f484 100644 --- a/tests/ui/error-emitter/highlighting.svg +++ b/tests/ui/error-emitter/highlighting.svg @@ -49,7 +49,7 @@ LL | fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<( - | ____^^^^^_- + | ____^^^^^_- LL | | dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg index 152245da9ddc..c2378113b86f 100644 --- a/tests/ui/error-emitter/highlighting.windows.svg +++ b/tests/ui/error-emitter/highlighting.windows.svg @@ -50,7 +50,7 @@ LL | fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<( - | ____^^^^^_- + | ____^^^^^_- LL | | dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static diff --git a/tests/ui/error-emitter/unicode-output.rs b/tests/ui/error-emitter/unicode-output.rs new file mode 100644 index 000000000000..ba6db37b66c2 --- /dev/null +++ b/tests/ui/error-emitter/unicode-output.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Zunstable-options=yes --error-format=human-unicode --color=always +//@ edition:2018 +//@ only-linux + +use core::pin::Pin; +use core::future::Future; +use core::any::Any; + +fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin, String>> + Send + 'static +)>>) {} + +fn wrapped_fn<'a>(_: Box<(dyn Any + Send)>) -> Pin, String>> + Send + 'static +)>> { + Box::pin(async { Err("nope".into()) }) +} + +fn main() { + query(wrapped_fn); +} diff --git a/tests/ui/error-emitter/unicode-output.svg b/tests/ui/error-emitter/unicode-output.svg new file mode 100644 index 000000000000..f98fd8b74032 --- /dev/null +++ b/tests/ui/error-emitter/unicode-output.svg @@ -0,0 +1,72 @@ + + + + + + + error[E0308]: mismatched types + + ╭▸ $DIR/unicode-output.rs:20:11 + + + + LL query(wrapped_fn); + + ┬──── ━━━━━━━━━━ one type is more general than the other + + + + arguments to this function are incorrect + + + + note: expected fn pointer `for<'a> fn(Box<(dyn Any + Send + 'a)>) -> Pin<_>` + + found fn item `fn(Box<(dyn Any + Send + 'static)>) -> Pin<_> {wrapped_fn}` + + note: function defined here + + ╭▸ $DIR/unicode-output.rs:9:4 + + + + LL fn query(_: fn(Box<(dyn Any + Send + '_)>) -> Pin<Box<( + + ┌────━━━━━─┘ + + LL dyn Future<Output = Result<Box<(dyn Any + 'static)>, String>> + Send + 'static + + LL )>>) {} + + ╰╴└───┘ + + + + error: aborting due to 1 previous error + + + + For more information about this error, try `rustc --explain E0308`. + + + + + + diff --git a/tests/ui/extern-flag/auxiliary/panic_handler.rs b/tests/ui/extern-flag/auxiliary/panic_handler.rs index 5ca32fa992b0..9140ceed2291 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/feature-gates/feature-gate-coroutines.e2024.stderr b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr index 3bb48e4a37a4..032d7adf77ab 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr +++ b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr @@ -8,6 +8,46 @@ LL | yield true; = help: add `#![feature(coroutines)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-coroutines.rs:10:16 + | +LL | let _ = || yield true; + | ^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-coroutines.rs:18:5 + | +LL | yield; + | ^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-coroutines.rs:19:5 + | +LL | yield 0; + | ^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-coroutines.rs:5:5 + | +LL | yield true; + | ^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks --> $DIR/feature-gate-coroutines.rs:5:5 | @@ -46,7 +86,7 @@ error[E0627]: yield expression outside of coroutine literal LL | yield true; | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0627, E0658. For more information about an error, try `rustc --explain E0627`. diff --git a/tests/ui/feature-gates/feature-gate-coroutines.rs b/tests/ui/feature-gates/feature-gate-coroutines.rs index 28dce8596d39..a686357d910a 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.rs +++ b/tests/ui/feature-gates/feature-gate-coroutines.rs @@ -4,17 +4,17 @@ fn main() { yield true; //~ ERROR yield syntax is experimental //~^ ERROR yield expression outside of coroutine literal - //[none]~^^ ERROR yield syntax is experimental + //~^^ ERROR yield syntax is experimental //~^^^ ERROR `yield` can only be used let _ = || yield true; //~ ERROR yield syntax is experimental - //[none]~^ ERROR yield syntax is experimental + //~^ ERROR yield syntax is experimental //~^^ ERROR `yield` can only be used } #[cfg(FALSE)] fn foo() { // Ok in 2024 edition - yield; //[none]~ ERROR yield syntax is experimental - yield 0; //[none]~ ERROR yield syntax is experimental + yield; //~ ERROR yield syntax is experimental + yield 0; //~ ERROR yield syntax is experimental } diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs index 58306a4cfc9c..57d6b5912870 100644 --- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.rs @@ -7,4 +7,7 @@ trait Mine {} #[doc(fake_variadic)] //~ ERROR: `#[doc(fake_variadic)]` is meant for internal use only impl Mine for (T,) {} +#[doc(search_unbox)] //~ ERROR: `#[doc(search_unbox)]` is meant for internal use only +struct Wrap (T); + fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr index bbb9edd58f09..f3c00a2156bf 100644 --- a/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr +++ b/tests/ui/feature-gates/feature-gate-rustdoc_internals.stderr @@ -18,6 +18,16 @@ LL | #[doc(fake_variadic)] = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0658]: `#[doc(search_unbox)]` is meant for internal use only + --> $DIR/feature-gate-rustdoc_internals.rs:10:1 + | +LL | #[doc(search_unbox)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #90418 for more information + = help: add `#![feature(rustdoc_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr index d599523c7274..319056a9c889 100644 --- a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.stderr @@ -1,17 +1,3 @@ -error: can't mark as unstable using an already stable feature - --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 - | -LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable -LL | const fn my_fun() {} - | -------------------- the stability attribute annotates this item - | -help: consider removing the attribute - --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 - | -LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: can't mark as unstable using an already stable feature --> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1 | @@ -27,5 +13,19 @@ help: consider removing the attribute LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: can't mark as unstable using an already stable feature + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable +LL | const fn my_fun() {} + | -------------------- the stability attribute annotates this item + | +help: consider removing the attribute + --> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1 + | +LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr index 3697bd9cf021..0f5a9de7ab85 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-2.next.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `for<'a> T: Trait<'a, '_>` is not satisfied - --> $DIR/candidate-from-env-universe-err-2.rs:15:5 + --> $DIR/candidate-from-env-universe-err-2.rs:15:15 | LL | impl_hr::(); - | ^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T` + | ^ the trait `for<'a> Trait<'a, '_>` is not implemented for `T` | note: required by a bound in `impl_hr` --> $DIR/candidate-from-env-universe-err-2.rs:12:19 diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.rs b/tests/ui/impl-trait/precise-capturing/migration-note.rs index a5bade4ddc53..1d98750f6dde 100644 --- a/tests/ui/impl-trait/precise-capturing/migration-note.rs +++ b/tests/ui/impl-trait/precise-capturing/migration-note.rs @@ -187,4 +187,19 @@ fn returned() -> impl Sized { } //~^ NOTE `x` dropped here while still borrowed +fn capture_apit(x: &impl Sized) -> impl Sized {} +//~^ NOTE you could use a `use<...>` bound to explicitly specify captures, but + +fn test_apit() { + let x = String::new(); + //~^ NOTE binding `x` declared here + let y = capture_apit(&x); + //~^ NOTE borrow of `x` occurs here + //~| NOTE this call may capture more lifetimes than intended + drop(x); + //~^ ERROR cannot move out of `x` because it is borrowed + //~| NOTE move out of `x` occurs here +} +//~^ NOTE borrow might be used here, when `y` is dropped + fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.stderr b/tests/ui/impl-trait/precise-capturing/migration-note.stderr index 3ac47ed1bcd3..a859a114dbc5 100644 --- a/tests/ui/impl-trait/precise-capturing/migration-note.stderr +++ b/tests/ui/impl-trait/precise-capturing/migration-note.stderr @@ -30,7 +30,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_len(&x); | ^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len(x: &Vec) -> impl Display + use { | ++++++++ @@ -55,7 +55,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_len(&x); | ^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len(x: &Vec) -> impl Display + use { | ++++++++ @@ -80,7 +80,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_len(&x); | ^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len(x: &Vec) -> impl Display + use { | ++++++++ @@ -106,7 +106,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_len_mut(&mut x); | ^^^^^^^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len_mut(x: &mut Vec) -> impl Display + use { | ++++++++ @@ -131,7 +131,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_len_mut(&mut x); | ^^^^^^^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len_mut(x: &mut Vec) -> impl Display + use { | ++++++++ @@ -156,7 +156,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_len_mut(&mut x); | ^^^^^^^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len_mut(x: &mut Vec) -> impl Display + use { | ++++++++ @@ -182,7 +182,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_field(&s.f); | ^^^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_field(t: &T) -> impl Display + use { | ++++++++ @@ -204,7 +204,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_field(&mut s.f); | ^^^^^^^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_field(t: &T) -> impl Display + use { | ++++++++ @@ -226,7 +226,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | let a = display_field(&mut s.f); | ^^^^^^^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_field(t: &T) -> impl Display + use { | ++++++++ @@ -252,7 +252,7 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has | LL | x = display_len(&z.f); | ^^^^^^^^^^^^^^^^^ -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len(x: &Vec) -> impl Display + use { | ++++++++ @@ -273,12 +273,46 @@ note: this call may capture more lifetimes than intended, because Rust 2024 has LL | let x = { let x = display_len(&mut vec![0]); x }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) -help: add a precise capturing bound to avoid overcapturing +help: use the precise capturing `use<...>` syntax to make the captures explicit | LL | fn display_len(x: &Vec) -> impl Display + use { | ++++++++ -error: aborting due to 12 previous errors +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/migration-note.rs:199:10 + | +LL | let x = String::new(); + | - binding `x` declared here +LL | +LL | let y = capture_apit(&x); + | -- borrow of `x` occurs here +... +LL | drop(x); + | ^ move out of `x` occurs here +... +LL | } + | - borrow might be used here, when `y` is dropped and runs the destructor for type `impl Sized` + | +note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules + --> $DIR/migration-note.rs:196:13 + | +LL | let y = capture_apit(&x); + | ^^^^^^^^^^^^^^^^ +note: you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable + --> $DIR/migration-note.rs:190:21 + | +LL | fn capture_apit(x: &impl Sized) -> impl Sized {} + | ^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn capture_apit(x: &T) -> impl Sized + use {} + | ++++++++++ ~ ++++++++ +help: consider cloning the value if the performance cost is acceptable + | +LL | let y = capture_apit(&x.clone()); + | ++++++++ + +error: aborting due to 13 previous errors Some errors have detailed explanations: E0499, E0502, E0503, E0505, E0506, E0597, E0716. For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.fixed new file mode 100644 index 000000000000..960f2f1bb13f --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.fixed @@ -0,0 +1,13 @@ +//@ run-rustfix +//@ rustfix-only-machine-applicable + +// Make sure that simple overcapture suggestions remain machine applicable. + +#![allow(unused)] +#![deny(impl_trait_overcaptures)] + +fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.rs new file mode 100644 index 000000000000..dc9efbf3b95e --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.rs @@ -0,0 +1,13 @@ +//@ run-rustfix +//@ rustfix-only-machine-applicable + +// Make sure that simple overcapture suggestions remain machine applicable. + +#![allow(unused)] +#![deny(impl_trait_overcaptures)] + +fn named<'a>(x: &'a i32) -> impl Sized { *x } +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.stderr new file mode 100644 index 000000000000..35fff9ef170e --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024-machine-applicable.stderr @@ -0,0 +1,26 @@ +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcaptures-2024-machine-applicable.rs:9:29 + | +LL | fn named<'a>(x: &'a i32) -> impl Sized { *x } + | ^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcaptures-2024-machine-applicable.rs:9:10 + | +LL | fn named<'a>(x: &'a i32) -> impl Sized { *x } + | ^^ + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 +note: the lint level is defined here + --> $DIR/overcaptures-2024-machine-applicable.rs:7:9 + | +LL | #![deny(impl_trait_overcaptures)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } + | +++++++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed index 89a3f3136c82..1eb88c71d54f 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.fixed @@ -1,4 +1,5 @@ //@ run-rustfix +//@ edition: 2018 #![allow(unused)] #![deny(impl_trait_overcaptures)] @@ -29,4 +30,16 @@ fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized + use<>> {} //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 //~| WARN this changes meaning in Rust 2024 +fn apit(_: &T) -> impl Sized + use {} +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +fn apit2(_: &T, _: U) -> impl Sized + use {} +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +async fn async_fn<'a>(x: &'a ()) -> impl Sized + use<> {} +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs index 18c04f9f799c..6f1ef6a472fe 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.rs @@ -1,4 +1,5 @@ //@ run-rustfix +//@ edition: 2018 #![allow(unused)] #![deny(impl_trait_overcaptures)] @@ -29,4 +30,16 @@ fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 //~| WARN this changes meaning in Rust 2024 +fn apit(_: &impl Sized) -> impl Sized {} +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +fn apit2(_: &impl Sized, _: U) -> impl Sized {} +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +async fn async_fn<'a>(x: &'a ()) -> impl Sized {} +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr index 94dafb04d64a..63c87cd46c84 100644 --- a/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr +++ b/tests/ui/impl-trait/precise-capturing/overcaptures-2024.stderr @@ -1,5 +1,5 @@ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:6:29 + --> $DIR/overcaptures-2024.rs:7:29 | LL | fn named<'a>(x: &'a i32) -> impl Sized { *x } | ^^^^^^^^^^ @@ -7,13 +7,13 @@ LL | fn named<'a>(x: &'a i32) -> impl Sized { *x } = warning: this changes meaning in Rust 2024 = note: for more information, see note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:6:10 + --> $DIR/overcaptures-2024.rs:7:10 | LL | fn named<'a>(x: &'a i32) -> impl Sized { *x } | ^^ = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 note: the lint level is defined here - --> $DIR/overcaptures-2024.rs:4:9 + --> $DIR/overcaptures-2024.rs:5:9 | LL | #![deny(impl_trait_overcaptures)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x } | +++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:10:25 + --> $DIR/overcaptures-2024.rs:11:25 | LL | fn implicit(x: &i32) -> impl Sized { *x } | ^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | fn implicit(x: &i32) -> impl Sized { *x } = warning: this changes meaning in Rust 2024 = note: for more information, see note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:10:16 + --> $DIR/overcaptures-2024.rs:11:16 | LL | fn implicit(x: &i32) -> impl Sized { *x } | ^ @@ -42,7 +42,7 @@ LL | fn implicit(x: &i32) -> impl Sized + use<> { *x } | +++++++ error: `impl Sized + '_` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:16:33 + --> $DIR/overcaptures-2024.rs:17:33 | LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } | ^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } = warning: this changes meaning in Rust 2024 = note: for more information, see note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:16:24 + --> $DIR/overcaptures-2024.rs:17:24 | LL | fn hello(&self, x: &i32) -> impl Sized + '_ { self } | ^ @@ -61,7 +61,7 @@ LL | fn hello(&self, x: &i32) -> impl Sized + '_ + use<'_> { self } | +++++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 - --> $DIR/overcaptures-2024.rs:28:47 + --> $DIR/overcaptures-2024.rs:29:47 | LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} | ^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} = warning: this changes meaning in Rust 2024 = note: for more information, see note: specifically, this lifetime is in scope but not mentioned in the type's bounds - --> $DIR/overcaptures-2024.rs:28:23 + --> $DIR/overcaptures-2024.rs:29:23 | LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized> {} | ^^ @@ -79,5 +79,72 @@ help: use the precise capturing `use<...>` syntax to make the captures explicit LL | fn hrtb() -> impl for<'a> Higher<'a, Output = impl Sized + use<>> {} | +++++++ -error: aborting due to 4 previous errors +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcaptures-2024.rs:33:28 + | +LL | fn apit(_: &impl Sized) -> impl Sized {} + | ^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcaptures-2024.rs:33:12 + | +LL | fn apit(_: &impl Sized) -> impl Sized {} + | ^ + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 +note: you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable + --> $DIR/overcaptures-2024.rs:33:13 + | +LL | fn apit(_: &impl Sized) -> impl Sized {} + | ^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn apit(_: &T) -> impl Sized + use {} + | ++++++++++ ~ ++++++++ + +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcaptures-2024.rs:37:38 + | +LL | fn apit2(_: &impl Sized, _: U) -> impl Sized {} + | ^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcaptures-2024.rs:37:16 + | +LL | fn apit2(_: &impl Sized, _: U) -> impl Sized {} + | ^ + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 +note: you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable + --> $DIR/overcaptures-2024.rs:37:17 + | +LL | fn apit2(_: &impl Sized, _: U) -> impl Sized {} + | ^^^^^^^^^^ +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | fn apit2(_: &T, _: U) -> impl Sized + use {} + | ++++++++++ ~ +++++++++++ + +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcaptures-2024.rs:41:37 + | +LL | async fn async_fn<'a>(x: &'a ()) -> impl Sized {} + | ^^^^^^^^^^ + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcaptures-2024.rs:41:19 + | +LL | async fn async_fn<'a>(x: &'a ()) -> impl Sized {} + | ^^ + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | async fn async_fn<'a>(x: &'a ()) -> impl Sized + use<> {} + | +++++++ + +error: aborting due to 7 previous errors 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 000000000000..109764a1812d --- /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 000000000000..ecfa921edd2c --- /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/lifetimes/temporary-lifetime-extension.edition2021.run.stdout b/tests/ui/lifetimes/temporary-lifetime-extension.edition2021.run.stdout new file mode 100644 index 000000000000..864372215898 --- /dev/null +++ b/tests/ui/lifetimes/temporary-lifetime-extension.edition2021.run.stdout @@ -0,0 +1 @@ +("Hello", 1) [(("Hello", 1),)] "Hello" "Hello" "Hello" ("Hello", 1) ("Hello", 1) ("Hello", 1) diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.edition2024.run.stdout b/tests/ui/lifetimes/temporary-lifetime-extension.edition2024.run.stdout new file mode 100644 index 000000000000..864372215898 --- /dev/null +++ b/tests/ui/lifetimes/temporary-lifetime-extension.edition2024.run.stdout @@ -0,0 +1 @@ +("Hello", 1) [(("Hello", 1),)] "Hello" "Hello" "Hello" ("Hello", 1) ("Hello", 1) ("Hello", 1) diff --git a/tests/ui/lifetimes/temporary-lifetime-extension.rs b/tests/ui/lifetimes/temporary-lifetime-extension.rs index 1ecef2f3d04d..d03027cf4a32 100644 --- a/tests/ui/lifetimes/temporary-lifetime-extension.rs +++ b/tests/ui/lifetimes/temporary-lifetime-extension.rs @@ -1,4 +1,21 @@ -//@ check-pass +// This is a test for the new temporary lifetime behaviour as implemented for RFC 3606. +// In essence, with #3606 we can write the following variable initialisation without +// a borrow checking error because the temporary lifetime is automatically extended. +// ```rust +// let x = if condition() { +// &something() +// } else { +// &something_else() +// }; +// ``` +// More details can be found in https://github.com/rust-lang/rfcs/pull/3606 + +//@ run-pass +//@ check-run-results +//@ revisions: edition2021 edition2024 +//@ [edition2021] edition: 2021 +//@ [edition2024] edition: 2024 +//@ [edition2024] compile-flags: -Z unstable-options fn temp() -> (String, i32) { (String::from("Hello"), 1) @@ -13,11 +30,7 @@ fn main() { let _ = 123; &(*temp().0)[..] }; - let f = if true { - &temp() - } else { - &temp() - }; + let f = if true { &temp() } else { &temp() }; let g = match true { true => &temp(), false => { diff --git a/tests/ui/lint/unreachable_pub.fixed b/tests/ui/lint/unreachable_pub.fixed new file mode 100644 index 000000000000..163e8d24b325 --- /dev/null +++ b/tests/ui/lint/unreachable_pub.fixed @@ -0,0 +1,116 @@ +//@ check-pass +//@ edition: 2018 +//@ run-rustfix + +#![allow(unused)] +#![warn(unreachable_pub)] + +mod private_mod { + // non-leaked `pub` items in private module should be linted + pub(crate) use std::fmt; //~ WARNING unreachable_pub + pub(crate) use std::env::{Args}; // braced-use has different item spans than unbraced + //~^ WARNING unreachable_pub + + // we lint on struct definition + pub(crate) struct Hydrogen { //~ WARNING unreachable_pub + // but not on fields, even if they are `pub` as putting `pub(crate)` + // it would clutter the source code for little value + pub neutrons: usize, + pub(crate) electrons: usize + } + pub(crate) struct Calcium { + pub neutrons: usize, + } + impl Hydrogen { + // impls, too + pub(crate) fn count_neutrons(&self) -> usize { self.neutrons } //~ WARNING unreachable_pub + pub(crate) fn count_electrons(&self) -> usize { self.electrons } + } + impl Clone for Hydrogen { + fn clone(&self) -> Hydrogen { + Hydrogen { neutrons: self.neutrons, electrons: self.electrons } + } + } + + pub(crate) enum Helium {} //~ WARNING unreachable_pub + pub(crate) union Lithium { c1: usize, c2: u8 } //~ WARNING unreachable_pub + pub(crate) fn beryllium() {} //~ WARNING unreachable_pub + pub(crate) trait Boron {} //~ WARNING unreachable_pub + pub(crate) const CARBON: usize = 1; //~ WARNING unreachable_pub + pub(crate) static NITROGEN: usize = 2; //~ WARNING unreachable_pub + pub(crate) type Oxygen = bool; //~ WARNING unreachable_pub + + macro_rules! define_empty_struct_with_visibility { + ($visibility: vis, $name: ident) => { $visibility struct $name {} } + //~^ WARNING unreachable_pub + } + define_empty_struct_with_visibility!(pub(crate), Fluorine); + + extern "C" { + pub(crate) fn catalyze() -> bool; //~ WARNING unreachable_pub + } + + mod private_in_private { + pub(super) enum Helium {} //~ WARNING unreachable_pub + pub(super) fn beryllium() {} //~ WARNING unreachable_pub + } + + pub(crate) mod crate_in_private { + pub(crate) const CARBON: usize = 1; //~ WARNING unreachable_pub + } + + pub(crate) mod pub_in_private { //~ WARNING unreachable_pub + pub(crate) static NITROGEN: usize = 2; //~ WARNING unreachable_pub + } + + fn foo() { + const { + pub(crate) struct Foo; //~ WARNING unreachable_pub + }; + } + + enum Weird { + Variant = { + pub(crate) struct Foo; //~ WARNING unreachable_pub + + mod tmp { + pub(crate) struct Bar; //~ WARNING unreachable_pub + } + + let _ = tmp::Bar; + + 0 + }, + } + + pub(crate) use fpu_precision::set_precision; //~ WARNING unreachable_pub + + mod fpu_precision { + pub(crate) fn set_precision() {} //~ WARNING unreachable_pub + pub(super) fn set_micro_precision() {} //~ WARNING unreachable_pub + } + + // items leaked through signatures (see `get_neon` below) are OK + pub struct Neon {} + + // crate-visible items are OK + pub(crate) struct Sodium {} +} + +pub mod public_mod { + // module is public: these are OK, too + pub struct Magnesium {} + pub(crate) struct Aluminum {} +} + +pub fn get_neon() -> private_mod::Neon { + private_mod::Neon {} +} + +fn main() { + let _ = get_neon(); + let _ = private_mod::beryllium(); + let _ = private_mod::crate_in_private::CARBON; + let _ = private_mod::pub_in_private::NITROGEN; + let _ = unsafe { private_mod::catalyze() }; +} diff --git a/tests/ui/lint/unreachable_pub.rs b/tests/ui/lint/unreachable_pub.rs index f21f6640342c..8524820bcfbc 100644 --- a/tests/ui/lint/unreachable_pub.rs +++ b/tests/ui/lint/unreachable_pub.rs @@ -1,4 +1,6 @@ //@ check-pass +//@ edition: 2018 +//@ run-rustfix #![allow(unused)] #![warn(unreachable_pub)] @@ -48,6 +50,46 @@ mod private_mod { pub fn catalyze() -> bool; //~ WARNING unreachable_pub } + mod private_in_private { + pub enum Helium {} //~ WARNING unreachable_pub + pub fn beryllium() {} //~ WARNING unreachable_pub + } + + pub(crate) mod crate_in_private { + pub const CARBON: usize = 1; //~ WARNING unreachable_pub + } + + pub mod pub_in_private { //~ WARNING unreachable_pub + pub static NITROGEN: usize = 2; //~ WARNING unreachable_pub + } + + fn foo() { + const { + pub struct Foo; //~ WARNING unreachable_pub + }; + } + + enum Weird { + Variant = { + pub struct Foo; //~ WARNING unreachable_pub + + mod tmp { + pub struct Bar; //~ WARNING unreachable_pub + } + + let _ = tmp::Bar; + + 0 + }, + } + + pub use fpu_precision::set_precision; //~ WARNING unreachable_pub + + mod fpu_precision { + pub fn set_precision() {} //~ WARNING unreachable_pub + pub fn set_micro_precision() {} //~ WARNING unreachable_pub + } + // items leaked through signatures (see `get_neon` below) are OK pub struct Neon {} @@ -67,4 +109,8 @@ pub fn get_neon() -> private_mod::Neon { fn main() { let _ = get_neon(); + let _ = private_mod::beryllium(); + let _ = private_mod::crate_in_private::CARBON; + let _ = private_mod::pub_in_private::NITROGEN; + let _ = unsafe { private_mod::catalyze() }; } diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr index 65f45fbd8168..5173ff1f0264 100644 --- a/tests/ui/lint/unreachable_pub.stderr +++ b/tests/ui/lint/unreachable_pub.stderr @@ -1,5 +1,5 @@ warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:8:13 + --> $DIR/unreachable_pub.rs:10:13 | LL | pub use std::fmt; | --- ^^^^^^^^ @@ -8,13 +8,13 @@ LL | pub use std::fmt; | = help: or consider exporting it for use by other crates note: the lint level is defined here - --> $DIR/unreachable_pub.rs:4:9 + --> $DIR/unreachable_pub.rs:6:9 | LL | #![warn(unreachable_pub)] | ^^^^^^^^^^^^^^^ warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:9:24 + --> $DIR/unreachable_pub.rs:11:24 | LL | pub use std::env::{Args}; // braced-use has different item spans than unbraced | --- ^^^^ @@ -24,7 +24,7 @@ LL | pub use std::env::{Args}; // braced-use has different item spans than u = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:13:5 + --> $DIR/unreachable_pub.rs:15:5 | LL | pub struct Hydrogen { | ---^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | pub struct Hydrogen { = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:24:9 + --> $DIR/unreachable_pub.rs:26:9 | LL | pub fn count_neutrons(&self) -> usize { self.neutrons } | ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | pub fn count_neutrons(&self) -> usize { self.neutrons } | help: consider restricting its visibility: `pub(crate)` warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:33:5 + --> $DIR/unreachable_pub.rs:35:5 | LL | pub enum Helium {} | ---^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | pub enum Helium {} = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:34:5 + --> $DIR/unreachable_pub.rs:36:5 | LL | pub union Lithium { c1: usize, c2: u8 } | ---^^^^^^^^^^^^^^ @@ -62,7 +62,7 @@ LL | pub union Lithium { c1: usize, c2: u8 } = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:35:5 + --> $DIR/unreachable_pub.rs:37:5 | LL | pub fn beryllium() {} | ---^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | pub fn beryllium() {} = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:36:5 + --> $DIR/unreachable_pub.rs:38:5 | LL | pub trait Boron {} | ---^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | pub trait Boron {} = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:37:5 + --> $DIR/unreachable_pub.rs:39:5 | LL | pub const CARBON: usize = 1; | ---^^^^^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | pub const CARBON: usize = 1; = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:38:5 + --> $DIR/unreachable_pub.rs:40:5 | LL | pub static NITROGEN: usize = 2; | ---^^^^^^^^^^^^^^^^^^^^^^^ @@ -102,7 +102,7 @@ LL | pub static NITROGEN: usize = 2; = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:39:5 + --> $DIR/unreachable_pub.rs:41:5 | LL | pub type Oxygen = bool; | ---^^^^^^^^^^^^ @@ -112,7 +112,7 @@ LL | pub type Oxygen = bool; = help: or consider exporting it for use by other crates warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:42:47 + --> $DIR/unreachable_pub.rs:44:47 | LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | define_empty_struct_with_visibility!(pub, Fluorine); = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:48:9 + --> $DIR/unreachable_pub.rs:50:9 | LL | pub fn catalyze() -> bool; | ---^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,5 +136,115 @@ LL | pub fn catalyze() -> bool; | = help: or consider exporting it for use by other crates -warning: 13 warnings emitted +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:62:5 + | +LL | pub mod pub_in_private { + | ---^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:68:13 + | +LL | pub struct Foo; + | ---^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:74:13 + | +LL | pub struct Foo; + | ---^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:86:13 + | +LL | pub use fpu_precision::set_precision; + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:54:9 + | +LL | pub enum Helium {} + | ---^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(super)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:55:9 + | +LL | pub fn beryllium() {} + | ---^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(super)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:59:9 + | +LL | pub const CARBON: usize = 1; + | ---^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:63:9 + | +LL | pub static NITROGEN: usize = 2; + | ---^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:77:17 + | +LL | pub struct Bar; + | ---^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:89:9 + | +LL | pub fn set_precision() {} + | ---^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | + = help: or consider exporting it for use by other crates + +warning: unreachable `pub` item + --> $DIR/unreachable_pub.rs:90:9 + | +LL | pub fn set_micro_precision() {} + | ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(super)` + | + = help: or consider exporting it for use by other crates + +warning: 24 warnings emitted diff --git a/tests/ui/match/intended-binding-pattern-is-const.rs b/tests/ui/match/intended-binding-pattern-is-const.rs new file mode 100644 index 000000000000..95c8119cdb9d --- /dev/null +++ b/tests/ui/match/intended-binding-pattern-is-const.rs @@ -0,0 +1,10 @@ +fn main() { + match 1 { //~ ERROR non-exhaustive patterns + //~^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered + //~| the matched value is of type `i32` + x => {} //~ this pattern doesn't introduce a new catch-all binding + //~^ HELP ensure that all possible cases are being handled + //~| HELP if you meant to introduce a binding, use a different name + } + const x: i32 = 4; //~ NOTE constant `x` defined here +} diff --git a/tests/ui/match/intended-binding-pattern-is-const.stderr b/tests/ui/match/intended-binding-pattern-is-const.stderr new file mode 100644 index 000000000000..99af1c7a16e0 --- /dev/null +++ b/tests/ui/match/intended-binding-pattern-is-const.stderr @@ -0,0 +1,27 @@ +error[E0004]: non-exhaustive patterns: `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered + --> $DIR/intended-binding-pattern-is-const.rs:2:11 + | +LL | match 1 { + | ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered +... +LL | x => {} + | - this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `x` + | + = note: the matched value is of type `i32` +note: constant `x` defined here + --> $DIR/intended-binding-pattern-is-const.rs:9:5 + | +LL | const x: i32 = 4; + | ^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | x_var => {} + | ++++ +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL | x => {}, i32::MIN..=3_i32 | 5_i32..=i32::MAX => todo!() + | ++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/mir/enable_passes_validation.all_unknown.stderr b/tests/ui/mir/enable_passes_validation.all_unknown.stderr new file mode 100644 index 000000000000..85a942c00ede --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.all_unknown.stderr @@ -0,0 +1,14 @@ +warning: MIR pass `ThisPass` is unknown and will be ignored + +warning: MIR pass `DoesNotExist` is unknown and will be ignored + +warning: MIR pass `ThisPass` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: MIR pass `DoesNotExist` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 4 warnings emitted + diff --git a/tests/ui/mir/enable_passes_validation.empty.stderr b/tests/ui/mir/enable_passes_validation.empty.stderr new file mode 100644 index 000000000000..0e922663acc5 --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.empty.stderr @@ -0,0 +1,2 @@ +error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + diff --git a/tests/ui/mir/enable_passes_validation.mixed.stderr b/tests/ui/mir/enable_passes_validation.mixed.stderr new file mode 100644 index 000000000000..5aace86abc02 --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.mixed.stderr @@ -0,0 +1,8 @@ +warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored + +warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: 2 warnings emitted + diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs new file mode 100644 index 000000000000..957e7d4d96df --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.rs @@ -0,0 +1,21 @@ +//@ revisions: empty unprefixed all_unknown all_known mixed + +//@[empty] compile-flags: -Zmir-enable-passes= +//@[empty] error-pattern error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + +//@[unprefixed] compile-flags: -Zmir-enable-passes=CheckAlignment +//@[unprefixed] error-pattern error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + +//@[all_unknown] check-pass +//@[all_unknown] compile-flags: -Zmir-enable-passes=+ThisPass,-DoesNotExist +//@[all_unknown] error-pattern: warning: MIR pass `ThisPass` is unknown and will be ignored +//@[all_unknown] error-pattern: warning: MIR pass `DoesNotExist` is unknown and will be ignored + +//@[all_known] check-pass +//@[all_known] compile-flags: -Zmir-enable-passes=+CheckAlignment,+LowerIntrinsics + +//@[mixed] check-pass +//@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment +//@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored + +fn main() {} diff --git a/tests/ui/mir/enable_passes_validation.unprefixed.stderr b/tests/ui/mir/enable_passes_validation.unprefixed.stderr new file mode 100644 index 000000000000..697589448f4a --- /dev/null +++ b/tests/ui/mir/enable_passes_validation.unprefixed.stderr @@ -0,0 +1,2 @@ +error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected + diff --git a/tests/ui/mir/issue-112269.stderr b/tests/ui/mir/issue-112269.stderr index f5b796027979..adb662c98a7e 100644 --- a/tests/ui/mir/issue-112269.stderr +++ b/tests/ui/mir/issue-112269.stderr @@ -1,30 +1,34 @@ error[E0005]: refutable pattern in local binding --> $DIR/issue-112269.rs:3:9 | +LL | const x: i32 = 4; + | ------------ missing patterns are not covered because `x` is interpreted as a constant pattern, not a new variable LL | let x: i32 = 3; - | ^ - | | - | patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered - | missing patterns are not covered because `x` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `x_var` + | ^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` +help: introduce a variable instead + | +LL | let x_var: i32 = 3; + | ~~~~~ error[E0005]: refutable pattern in local binding --> $DIR/issue-112269.rs:7:9 | +LL | const y: i32 = 3; + | ------------ missing patterns are not covered because `y` is interpreted as a constant pattern, not a new variable LL | let y = 4; - | ^ - | | - | patterns `i32::MIN..=2_i32` and `4_i32..=i32::MAX` not covered - | missing patterns are not covered because `y` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `y_var` + | ^ patterns `i32::MIN..=2_i32` and `4_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` +help: introduce a variable instead + | +LL | let y_var = 4; + | ~~~~~ error: aborting due to 2 previous errors 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 000000000000..c71238ba0729 --- /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(mut writer: W) -> io::Result<()> { + writeln!(writer, "stuff") +} + +pub fn read_and_discard(mut reader: R) -> io::Result<()> { + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).map(|_| ()) +} + +pub fn sum_three(iter: I) -> ::Item + where ::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 e4bca54e995f..869aa654ef72 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 ab6ff417efb6..ea145f365c2d 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 | loop { 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); 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 4004b7a43bc0..a99bdb4fe9d4 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 | foo(bar); 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 | struct Bar; ... 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 | bat(bar); 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 | struct Bar; ... 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 a8473bb81983..a4c8401ce575 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 @@ LL | fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { | ^ 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 000000000000..b5e0b468aa60 --- /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 000000000000..e08978db63ae --- /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 000000000000..07e24f566cb9 --- /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`, 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`, 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`, 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 50e25a24d811..60cb13523130 100644 --- a/tests/ui/not-copy-closure.stderr +++ b/tests/ui/not-copy-closure.stderr @@ -11,10 +11,6 @@ note: closure cannot be moved more than once as it is not `Copy` due to moving t | 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/bad-char-literals.stderr b/tests/ui/parser/bad-char-literals.stderr index 1fb324a1b7e8..5a81ede0336f 100644 --- a/tests/ui/parser/bad-char-literals.stderr +++ b/tests/ui/parser/bad-char-literals.stderr @@ -15,7 +15,7 @@ error: character constant must be escaped: `\n` LL | ' | ______^ LL | | '; - | |_ + | |_^ | help: escape the character | diff --git a/tests/ui/parser/unnecessary-let.stderr b/tests/ui/parser/unnecessary-let.stderr index c6ac0d562f82..05ac1faafd4d 100644 --- a/tests/ui/parser/unnecessary-let.stderr +++ b/tests/ui/parser/unnecessary-let.stderr @@ -2,12 +2,12 @@ error: expected pattern, found `let` --> $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 @@ error: expected pattern, found `let` --> $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/pattern/usefulness/match-arm-statics-2.stderr b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr index e4dd35a59958..60b4fcca2861 100644 --- a/tests/ui/pattern/usefulness/match-arm-statics-2.stderr +++ b/tests/ui/pattern/usefulness/match-arm-statics-2.stderr @@ -3,8 +3,20 @@ error[E0004]: non-exhaustive patterns: `(true, false)` not covered | LL | match (true, false) { | ^^^^^^^^^^^^^ pattern `(true, false)` not covered +LL | +LL | TRUE_TRUE => (), + | --------- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `TRUE_TRUE` | = note: the matched value is of type `(bool, bool)` +note: constant `TRUE_TRUE` defined here + --> $DIR/match-arm-statics-2.rs:14:1 + | +LL | const TRUE_TRUE: (bool, bool) = (true, true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | TRUE_TRUE_var => (), + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ (false, true) => (), diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr index a8786d02414c..0a3991fe3d16 100644 --- a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -199,8 +199,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered +LL | +LL | CONST => {} + | ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST` | = note: the matched value is of type `&[bool]` +note: constant `CONST` defined here + --> $DIR/slice-patterns-exhaustiveness.rs:88:5 + | +LL | const CONST: &[bool] = &[true]; + | ^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | CONST_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ CONST => {}, @@ -212,8 +224,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered +LL | +LL | CONST => {} + | ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST` | = note: the matched value is of type `&[bool]` +note: constant `CONST` defined here + --> $DIR/slice-patterns-exhaustiveness.rs:88:5 + | +LL | const CONST: &[bool] = &[true]; + | ^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | CONST_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ &[false] => {}, @@ -225,8 +249,20 @@ error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered | LL | match s { | ^ patterns `&[]` and `&[_, _, ..]` not covered +... +LL | CONST => {} + | ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST` | = note: the matched value is of type `&[bool]` +note: constant `CONST` defined here + --> $DIR/slice-patterns-exhaustiveness.rs:88:5 + | +LL | const CONST: &[bool] = &[true]; + | ^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | CONST_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ CONST => {}, @@ -238,8 +274,20 @@ error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered | LL | match s { | ^ pattern `&[_, _, ..]` not covered +... +LL | CONST => {} + | ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST` | = note: the matched value is of type `&[bool]` +note: constant `CONST` defined here + --> $DIR/slice-patterns-exhaustiveness.rs:88:5 + | +LL | const CONST: &[bool] = &[true]; + | ^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | CONST_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ CONST => {}, @@ -251,8 +299,20 @@ error[E0004]: non-exhaustive patterns: `&[false]` not covered | LL | match s { | ^ pattern `&[false]` not covered +... +LL | CONST => {} + | ----- this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST` | = note: the matched value is of type `&[bool]` +note: constant `CONST` defined here + --> $DIR/slice-patterns-exhaustiveness.rs:88:5 + | +LL | const CONST: &[bool] = &[true]; + | ^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | CONST_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ &[_, _, ..] => {}, @@ -264,8 +324,20 @@ error[E0004]: non-exhaustive patterns: `&[false]` not covered | LL | match s1 { | ^^ pattern `&[false]` not covered +LL | +LL | CONST1 => {} + | ------ this pattern doesn't introduce a new catch-all binding, but rather pattern matches against the value of constant `CONST1` | = note: the matched value is of type `&[bool; 1]` +note: constant `CONST1` defined here + --> $DIR/slice-patterns-exhaustiveness.rs:124:5 + | +LL | const CONST1: &[bool; 1] = &[true]; + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: if you meant to introduce a binding, use a different name + | +LL | CONST1_var => {} + | ++++ help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ CONST1 => {}, diff --git a/tests/ui/proc-macro/auxiliary/helper-attr.rs b/tests/ui/proc-macro/auxiliary/helper-attr.rs new file mode 100644 index 000000000000..79ccefd98440 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/helper-attr.rs @@ -0,0 +1,12 @@ +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +// Doesn't do anything, but has a helper attribute. +#[proc_macro_derive(WithHelperAttr, attributes(x))] +pub fn derive(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { + proc_macro::TokenStream::new() +} diff --git a/tests/ui/proc-macro/helper-attr-builtin-derive.rs b/tests/ui/proc-macro/helper-attr-builtin-derive.rs new file mode 100644 index 000000000000..eb7292e093c3 --- /dev/null +++ b/tests/ui/proc-macro/helper-attr-builtin-derive.rs @@ -0,0 +1,19 @@ +// This test checks that helper attributes of a derive proc macro can be used together with +// other built-in derive macros. +// issue: rust-lang/rust#132561 +//@ check-pass +//@ aux-build:helper-attr.rs +//@ edition:2021 + +#[macro_use] +extern crate helper_attr; + +use helper_attr::WithHelperAttr; + +#[derive(WithHelperAttr, Debug, Clone, PartialEq)] +struct MyStruct<#[x] 'a, #[x] const A: usize, #[x] B> { + #[x] + field: &'a [B; A], +} + +fn main() {} 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 000000000000..c1785051e5a5 --- /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 000000000000..d7ce52eab80f --- /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 + = 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 094c89930b75..9e3af26e9c46 100644 --- a/tests/ui/simd-abi-checks.rs +++ b/tests/ui/simd-abi-checks.rs @@ -12,19 +12,19 @@ use std::arch::x86_64::*; 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 aa7e94001698..7d2915f7dea6 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 @@ LL | f(g()); = 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 @@ LL | f(g()); = note: for more information, see issue #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 @@ LL | gavx(favx()); = note: for more information, see issue #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 @@ LL | gavx(favx()); = note: for more information, see issue #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 @@ LL | w(Wrapper(g())); = note: for more information, see issue #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 @@ LL | w(Wrapper(g())); = note: for more information, see issue #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 @@ LL | unsafe extern "C" fn g() -> __m256 { = note: for more information, see issue #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 @@ LL | unsafe extern "C" fn f(_: __m256) { = note: for more information, see issue #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 d2afd38fcc85..c453e91d11b2 100644 --- a/tests/ui/sse-abi-checks.rs +++ b/tests/ui/sse-abi-checks.rs @@ -19,6 +19,6 @@ pub struct SseVector([i64; 2]); #[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 77c4e1fc07ab..7dd13af5091a 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/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs index af47ba8baa3f..1a440a90cd73 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs @@ -2,9 +2,9 @@ fn main() { let A = 3; //~^ ERROR refutable pattern in local binding //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered - //~| missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable //~| HELP introduce a variable instead //~| SUGGESTION A_var const A: i32 = 2; + //~^ missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable } diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr index b6c286128023..a275d8e4e839 100644 --- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr +++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr @@ -2,15 +2,18 @@ error[E0005]: refutable pattern in local binding --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9 | LL | let A = 3; - | ^ - | | - | patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered - | missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable - | help: introduce a variable instead: `A_var` + | ^ patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered +... +LL | const A: i32 = 2; + | ------------ missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` +help: introduce a variable instead + | +LL | let A_var = 3; + | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/no-method-found-suggest-trait-args.rs b/tests/ui/suggestions/no-method-found-suggest-trait-args.rs new file mode 100644 index 000000000000..d51f86b29e81 --- /dev/null +++ b/tests/ui/suggestions/no-method-found-suggest-trait-args.rs @@ -0,0 +1,30 @@ +/// Tests that suggestions to add trait bounds that would enable using a method include appropriate +/// placeholder arguments for that trait. + +trait Trait { + fn method(&self) {} +} + +trait Trait2<'a, A, const B: u8, C = (), const D: u8 = 0> { + fn method2(&self) {} +} + +fn foo(value: T) { + //~^ SUGGESTION : Trait + //~| SUGGESTION : Trait2 + value.method(); + //~^ ERROR no method named `method` found for type parameter `T` in the current scope [E0599] + value.method2(); + //~^ ERROR no method named `method2` found for type parameter `T` in the current scope [E0599] +} + +fn bar(value: impl Copy) { + //~^ SUGGESTION + Trait + //~| SUGGESTION + Trait2 + value.method(); + //~^ ERROR no method named `method` found for type parameter `impl Copy` in the current scope [E0599] + value.method2(); + //~^ ERROR no method named `method2` found for type parameter `impl Copy` in the current scope [E0599] +} + +fn main() {} diff --git a/tests/ui/suggestions/no-method-found-suggest-trait-args.stderr b/tests/ui/suggestions/no-method-found-suggest-trait-args.stderr new file mode 100644 index 000000000000..3dcd4667fa09 --- /dev/null +++ b/tests/ui/suggestions/no-method-found-suggest-trait-args.stderr @@ -0,0 +1,63 @@ +error[E0599]: no method named `method` found for type parameter `T` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:15:11 + | +LL | fn foo(value: T) { + | - method `method` not found for this type parameter +... +LL | value.method(); + | ^^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn foo>(value: T) { + | ++++++++++++++++ + +error[E0599]: no method named `method2` found for type parameter `T` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:17:11 + | +LL | fn foo(value: T) { + | - method `method2` not found for this type parameter +... +LL | value.method2(); + | ^^^^^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method2`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn foo>(value: T) { + | ++++++++++++++++++++++++ + +error[E0599]: no method named `method` found for type parameter `impl Copy` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:24:11 + | +LL | fn bar(value: impl Copy) { + | --------- method `method` not found for this type parameter +... +LL | value.method(); + | ^^^^^^ method not found in `impl Copy` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method`, perhaps you need to restrict type parameter `impl Copy` with it: + | +LL | fn bar(value: impl Copy + Trait) { + | ++++++++++++++++ + +error[E0599]: no method named `method2` found for type parameter `impl Copy` in the current scope + --> $DIR/no-method-found-suggest-trait-args.rs:26:11 + | +LL | fn bar(value: impl Copy) { + | --------- method `method2` not found for this type parameter +... +LL | value.method2(); + | ^^^^^^^ method not found in `impl Copy` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `method2`, perhaps you need to restrict type parameter `impl Copy` with it: + | +LL | fn bar(value: impl Copy + Trait2) { + | ++++++++++++++++++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/const-traits/const-trait-bounds.rs b/tests/ui/traits/const-traits/const-trait-bounds.rs deleted file mode 100644 index 8722d9909edd..000000000000 --- a/tests/ui/traits/const-traits/const-trait-bounds.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@ known-bug: #110395 -//@ compile-flags: -Znext-solver -// FIXME(const_trait_impl): check-pass -#![feature(const_trait_impl, generic_const_exprs)] -#![allow(incomplete_features)] - -fn main() { - let _ = process::<()>([()]); - let _ = Struct::<(), 4> { field: [1, 0] }; -} - -fn process(input: [(); T::make(2)]) -> [(); T::make(2)] { - input -} - -struct Struct -where - [u32; T::make(P)]:, -{ - field: [u32; T::make(P)], -} - -#[const_trait] -trait Trait { - fn make(input: usize) -> usize; -} - -impl const Trait for () { - fn make(input: usize) -> usize { - input / 2 - } -} diff --git a/tests/ui/traits/const-traits/const-trait-bounds.stderr b/tests/ui/traits/const-traits/const-trait-bounds.stderr deleted file mode 100644 index 29a01b9d7dce..000000000000 --- a/tests/ui/traits/const-traits/const-trait-bounds.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed - --> $DIR/const-trait-bounds.rs:4:30 - | -LL | #![feature(const_trait_impl, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ - | - = help: remove one of these features - -error[E0284]: type annotations needed: cannot normalize `process::{constant#0}` - --> $DIR/const-trait-bounds.rs:12:35 - | -LL | fn process(input: [(); T::make(2)]) -> [(); T::make(2)] { - | ^^^^^^^^^^^^^^^^ cannot normalize `process::{constant#0}` - -error[E0284]: type annotations needed: cannot normalize `Struct::field::{constant#0}` - --> $DIR/const-trait-bounds.rs:20:12 - | -LL | field: [u32; T::make(P)], - | ^^^^^^^^^^^^^^^^^ cannot normalize `Struct::field::{constant#0}` - -error[E0284]: type annotations needed: cannot normalize `process::{constant#1}` - --> $DIR/const-trait-bounds.rs:13:5 - | -LL | input - | ^^^^^ cannot normalize `process::{constant#1}` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0284`. 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 5554f0ccc0aa..ef636811fd57 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.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr new file mode 100644 index 000000000000..ef636811fd57 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.next.stderr @@ -0,0 +1,11 @@ +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:8:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + 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 0ece8f8321ce..c2a016713463 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/tests/ui/wasm/wasm-stable-target-features.rs b/tests/ui/wasm/wasm-stable-target-features.rs new file mode 100644 index 000000000000..b6d4b67d0703 --- /dev/null +++ b/tests/ui/wasm/wasm-stable-target-features.rs @@ -0,0 +1,49 @@ +//@ only-wasm32 +//@ build-pass + +// Test that a variety of WebAssembly features are all stable and can be used in +// `#[target_feature]`. That should mean they're also available via +// `#[cfg(target_feature)]` as well. + +#[target_feature(enable = "multivalue")] +fn foo1() {} + +#[target_feature(enable = "reference-types")] +fn foo2() {} + +#[target_feature(enable = "bulk-memory")] +fn foo3() {} + +#[target_feature(enable = "extended-const")] +fn foo4() {} + +#[target_feature(enable = "mutable-globals")] +fn foo5() {} + +#[target_feature(enable = "nontrapping-fptoint")] +fn foo6() {} + +#[target_feature(enable = "simd128")] +fn foo7() {} + +#[target_feature(enable = "relaxed-simd")] +fn foo8() {} + +#[target_feature(enable = "sign-ext")] +fn foo9() {} + +#[target_feature(enable = "tail-call")] +fn foo10() {} + +fn main() { + foo1(); + foo2(); + foo3(); + foo4(); + foo5(); + foo6(); + foo7(); + foo8(); + foo9(); + foo10(); +} diff --git a/triagebot.toml b/triagebot.toml index 95538dd7ee37..d5bc549ca9ff 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -212,6 +212,10 @@ trigger_files = [ "src/tools/rustdoc-gui", "src/tools/rustdoc-js", "src/tools/rustdoc-themes", + + # Docs + "src/doc/rustdoc.md", + "src/doc/rustdoc/", ] exclude_labels = [ "T-*", @@ -971,36 +975,30 @@ cc = ["@kobzol"] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ - "fmease", "jyn514", "oli-obk", + "onur-ozkan", ] [assign.adhoc_groups] -compiler-team = [ - "@cjgillot", - "@compiler-errors", - "@petrochenkov", - "@davidtwco", - "@estebank", - "@lcnr", - "@oli-obk", - "@pnkfelix", - "@wesleywiser", -] -compiler-team-contributors = [ - "@TaKO8Ki", - "@Nadrieril", - "@nnethercote", - "@fmease", - "@fee1-dead", - "@jieyouxu", +compiler = [ "@BoxyUwU", "@chenyukang", -] -compiler = [ - "compiler-team", - "compiler-team-contributors", + "@cjgillot", + "@compiler-errors", + "@davidtwco", + "@estebank", + "@fee1-dead", + "@fmease", + "@jieyouxu", + "@lcnr", + "@Nadrieril", + "@nnethercote", + "@oli-obk", + "@petrochenkov", + "@pnkfelix", + "@TaKO8Ki", + "@wesleywiser", ] libs = [ "@cuviper", @@ -1034,6 +1032,11 @@ docs = [ "@ehuss", "@GuillaumeGomez", ] + +codegen = [ + "@saethlin", + "@workingjubilee", +] query-system = [ "@cjgillot", ] @@ -1129,6 +1132,7 @@ project-exploit-mitigations = [ "/Cargo.lock" = ["@Mark-Simulacrum"] "/Cargo.toml" = ["@Mark-Simulacrum"] "/compiler" = ["compiler"] +"/compiler/rustc_abi" = ["compiler", "codegen"] "/compiler/rustc_arena" = ["compiler", "arena"] "/compiler/rustc_ast" = ["compiler", "parser"] "/compiler/rustc_ast_lowering" = ["compiler", "ast_lowering"] @@ -1139,7 +1143,7 @@ project-exploit-mitigations = [ "/compiler/rustc_lexer" = ["compiler", "lexer"] "/compiler/rustc_llvm" = ["@cuviper"] "/compiler/rustc_codegen_llvm/src/debuginfo" = ["compiler", "debuginfo"] -"/compiler/rustc_codegen_ssa" = ["compiler", "@saethlin"] +"/compiler/rustc_codegen_ssa" = ["compiler", "codegen"] "/compiler/rustc_middle/src/mir" = ["compiler", "mir"] "/compiler/rustc_middle/src/traits" = ["compiler", "types"] "/compiler/rustc_middle/src/ty" = ["compiler", "types"] @@ -1185,6 +1189,12 @@ project-exploit-mitigations = [ "/src/rustdoc-json-types" = ["rustdoc"] "/src/stage0" = ["bootstrap"] "/tests/run-make" = ["@jieyouxu"] +"/tests/rustdoc" = ["rustdoc"] +"/tests/rustdoc-gui" = ["rustdoc"] +"/tests/rustdoc-js-std" = ["rustdoc"] +"/tests/rustdoc-js" = ["rustdoc"] +"/tests/rustdoc-json" = ["@aDotInTheVoid"] +"/tests/rustdoc-ui" = ["rustdoc"] "/tests/ui" = ["compiler"] "/src/tools/cargo" = ["@ehuss"] "/src/tools/compiletest" = ["bootstrap", "@wesleywiser", "@oli-obk", "@compiler-errors", "@jieyouxu"]